D-Bus 1.6.12
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-sysdeps.c Wrappers around system/libc features (internal to D-BUS implementation) 00003 * 00004 * Copyright (C) 2002, 2003 Red Hat, Inc. 00005 * Copyright (C) 2003 CodeFactory AB 00006 * Copyright (C) 2005 Novell, Inc. 00007 * Copyright (C) 2006 Peter Kümmel <syntheticpp@gmx.net> 00008 * Copyright (C) 2006 Christian Ehrlicher <ch.ehrlicher@gmx.de> 00009 * Copyright (C) 2006-2010 Ralf Habacker <ralf.habacker@freenet.de> 00010 * 00011 * Licensed under the Academic Free License version 2.1 00012 * 00013 * This program is free software; you can redistribute it and/or modify 00014 * it under the terms of the GNU General Public License as published by 00015 * the Free Software Foundation; either version 2 of the License, or 00016 * (at your option) any later version. 00017 * 00018 * This program is distributed in the hope that it will be useful, 00019 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00020 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00021 * GNU General Public License for more details. 00022 * 00023 * You should have received a copy of the GNU General Public License 00024 * along with this program; if not, write to the Free Software 00025 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00026 * 00027 */ 00028 00029 #include <config.h> 00030 00031 #define STRSAFE_NO_DEPRECATE 00032 00033 #ifndef DBUS_WINCE 00034 #ifndef _WIN32_WINNT 00035 #define _WIN32_WINNT 0x0501 00036 #endif 00037 #endif 00038 00039 #include "dbus-internals.h" 00040 #include "dbus-sha.h" 00041 #include "dbus-sysdeps.h" 00042 #include "dbus-threads.h" 00043 #include "dbus-protocol.h" 00044 #include "dbus-string.h" 00045 #include "dbus-sysdeps.h" 00046 #include "dbus-sysdeps-win.h" 00047 #include "dbus-protocol.h" 00048 #include "dbus-hash.h" 00049 #include "dbus-sockets-win.h" 00050 #include "dbus-list.h" 00051 #include "dbus-nonce.h" 00052 #include "dbus-credentials.h" 00053 00054 #include <windows.h> 00055 #include <ws2tcpip.h> 00056 #include <wincrypt.h> 00057 00058 /* Declarations missing in mingw's headers */ 00059 extern BOOL WINAPI ConvertStringSidToSidA (LPCSTR StringSid, PSID *Sid); 00060 extern BOOL WINAPI ConvertSidToStringSidA (PSID Sid, LPSTR *StringSid); 00061 00062 #include <stdio.h> 00063 00064 #include <string.h> 00065 #if HAVE_ERRNO_H 00066 #include <errno.h> 00067 #endif 00068 #ifndef DBUS_WINCE 00069 #include <mbstring.h> 00070 #include <sys/stat.h> 00071 #include <sys/types.h> 00072 #endif 00073 00074 #ifdef HAVE_WS2TCPIP_H 00075 /* getaddrinfo for Windows CE (and Windows). */ 00076 #include <ws2tcpip.h> 00077 #endif 00078 00079 #ifdef HAVE_WSPIAPI_H 00080 // needed for w2k compatibility (getaddrinfo/freeaddrinfo/getnameinfo) 00081 #ifdef __GNUC__ 00082 #define _inline 00083 #include "wspiapi.h" 00084 #else 00085 #include <wspiapi.h> 00086 #endif 00087 #endif // HAVE_WSPIAPI_H 00088 00089 #ifndef O_BINARY 00090 #define O_BINARY 0 00091 #endif 00092 00093 typedef int socklen_t; 00094 00095 00096 void 00097 _dbus_win_set_errno (int err) 00098 { 00099 #ifdef DBUS_WINCE 00100 SetLastError (err); 00101 #else 00102 errno = err; 00103 #endif 00104 } 00105 00106 00107 /* Convert GetLastError() to a dbus error. */ 00108 const char* 00109 _dbus_win_error_from_last_error (void) 00110 { 00111 switch (GetLastError()) 00112 { 00113 case 0: 00114 return DBUS_ERROR_FAILED; 00115 00116 case ERROR_NO_MORE_FILES: 00117 case ERROR_TOO_MANY_OPEN_FILES: 00118 return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */ 00119 00120 case ERROR_ACCESS_DENIED: 00121 case ERROR_CANNOT_MAKE: 00122 return DBUS_ERROR_ACCESS_DENIED; 00123 00124 case ERROR_NOT_ENOUGH_MEMORY: 00125 return DBUS_ERROR_NO_MEMORY; 00126 00127 case ERROR_FILE_EXISTS: 00128 return DBUS_ERROR_FILE_EXISTS; 00129 00130 case ERROR_FILE_NOT_FOUND: 00131 case ERROR_PATH_NOT_FOUND: 00132 return DBUS_ERROR_FILE_NOT_FOUND; 00133 } 00134 00135 return DBUS_ERROR_FAILED; 00136 } 00137 00138 00139 char* 00140 _dbus_win_error_string (int error_number) 00141 { 00142 char *msg; 00143 00144 FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER | 00145 FORMAT_MESSAGE_IGNORE_INSERTS | 00146 FORMAT_MESSAGE_FROM_SYSTEM, 00147 NULL, error_number, 0, 00148 (LPSTR) &msg, 0, NULL); 00149 00150 if (msg[strlen (msg) - 1] == '\n') 00151 msg[strlen (msg) - 1] = '\0'; 00152 if (msg[strlen (msg) - 1] == '\r') 00153 msg[strlen (msg) - 1] = '\0'; 00154 00155 return msg; 00156 } 00157 00158 void 00159 _dbus_win_free_error_string (char *string) 00160 { 00161 LocalFree (string); 00162 } 00163 00184 int 00185 _dbus_read_socket (int fd, 00186 DBusString *buffer, 00187 int count) 00188 { 00189 int bytes_read; 00190 int start; 00191 char *data; 00192 00193 _dbus_assert (count >= 0); 00194 00195 start = _dbus_string_get_length (buffer); 00196 00197 if (!_dbus_string_lengthen (buffer, count)) 00198 { 00199 _dbus_win_set_errno (ENOMEM); 00200 return -1; 00201 } 00202 00203 data = _dbus_string_get_data_len (buffer, start, count); 00204 00205 again: 00206 00207 _dbus_verbose ("recv: count=%d fd=%d\n", count, fd); 00208 bytes_read = recv (fd, data, count, 0); 00209 00210 if (bytes_read == SOCKET_ERROR) 00211 { 00212 DBUS_SOCKET_SET_ERRNO(); 00213 _dbus_verbose ("recv: failed: %s (%d)\n", _dbus_strerror (errno), errno); 00214 bytes_read = -1; 00215 } 00216 else 00217 _dbus_verbose ("recv: = %d\n", bytes_read); 00218 00219 if (bytes_read < 0) 00220 { 00221 if (errno == EINTR) 00222 goto again; 00223 else 00224 { 00225 /* put length back (note that this doesn't actually realloc anything) */ 00226 _dbus_string_set_length (buffer, start); 00227 return -1; 00228 } 00229 } 00230 else 00231 { 00232 /* put length back (doesn't actually realloc) */ 00233 _dbus_string_set_length (buffer, start + bytes_read); 00234 00235 #if 0 00236 if (bytes_read > 0) 00237 _dbus_verbose_bytes_of_string (buffer, start, bytes_read); 00238 #endif 00239 00240 return bytes_read; 00241 } 00242 } 00243 00254 int 00255 _dbus_write_socket (int fd, 00256 const DBusString *buffer, 00257 int start, 00258 int len) 00259 { 00260 const char *data; 00261 int bytes_written; 00262 00263 data = _dbus_string_get_const_data_len (buffer, start, len); 00264 00265 again: 00266 00267 _dbus_verbose ("send: len=%d fd=%d\n", len, fd); 00268 bytes_written = send (fd, data, len, 0); 00269 00270 if (bytes_written == SOCKET_ERROR) 00271 { 00272 DBUS_SOCKET_SET_ERRNO(); 00273 _dbus_verbose ("send: failed: %s\n", _dbus_strerror_from_errno ()); 00274 bytes_written = -1; 00275 } 00276 else 00277 _dbus_verbose ("send: = %d\n", bytes_written); 00278 00279 if (bytes_written < 0 && errno == EINTR) 00280 goto again; 00281 00282 #if 0 00283 if (bytes_written > 0) 00284 _dbus_verbose_bytes_of_string (buffer, start, bytes_written); 00285 #endif 00286 00287 return bytes_written; 00288 } 00289 00290 00298 dbus_bool_t 00299 _dbus_close_socket (int fd, 00300 DBusError *error) 00301 { 00302 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00303 00304 again: 00305 if (closesocket (fd) == SOCKET_ERROR) 00306 { 00307 DBUS_SOCKET_SET_ERRNO (); 00308 00309 if (errno == EINTR) 00310 goto again; 00311 00312 dbus_set_error (error, _dbus_error_from_errno (errno), 00313 "Could not close socket: socket=%d, , %s", 00314 fd, _dbus_strerror_from_errno ()); 00315 return FALSE; 00316 } 00317 _dbus_verbose ("_dbus_close_socket: socket=%d, \n", fd); 00318 00319 return TRUE; 00320 } 00321 00329 void 00330 _dbus_fd_set_close_on_exec (intptr_t handle) 00331 { 00332 if ( !SetHandleInformation( (HANDLE) handle, 00333 HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE, 00334 0 /*disable both flags*/ ) ) 00335 { 00336 _dbus_win_warn_win_error ("Disabling socket handle inheritance failed:", GetLastError()); 00337 } 00338 } 00339 00347 dbus_bool_t 00348 _dbus_set_fd_nonblocking (int handle, 00349 DBusError *error) 00350 { 00351 u_long one = 1; 00352 00353 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00354 00355 if (ioctlsocket (handle, FIONBIO, &one) == SOCKET_ERROR) 00356 { 00357 DBUS_SOCKET_SET_ERRNO (); 00358 dbus_set_error (error, _dbus_error_from_errno (errno), 00359 "Failed to set socket %d:%d to nonblocking: %s", handle, 00360 _dbus_strerror_from_errno ()); 00361 return FALSE; 00362 } 00363 00364 return TRUE; 00365 } 00366 00367 00388 int 00389 _dbus_write_socket_two (int fd, 00390 const DBusString *buffer1, 00391 int start1, 00392 int len1, 00393 const DBusString *buffer2, 00394 int start2, 00395 int len2) 00396 { 00397 WSABUF vectors[2]; 00398 const char *data1; 00399 const char *data2; 00400 int rc; 00401 DWORD bytes_written; 00402 00403 _dbus_assert (buffer1 != NULL); 00404 _dbus_assert (start1 >= 0); 00405 _dbus_assert (start2 >= 0); 00406 _dbus_assert (len1 >= 0); 00407 _dbus_assert (len2 >= 0); 00408 00409 00410 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1); 00411 00412 if (buffer2 != NULL) 00413 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2); 00414 else 00415 { 00416 data2 = NULL; 00417 start2 = 0; 00418 len2 = 0; 00419 } 00420 00421 vectors[0].buf = (char*) data1; 00422 vectors[0].len = len1; 00423 vectors[1].buf = (char*) data2; 00424 vectors[1].len = len2; 00425 00426 again: 00427 00428 _dbus_verbose ("WSASend: len1+2=%d+%d fd=%d\n", len1, len2, fd); 00429 rc = WSASend (fd, 00430 vectors, 00431 data2 ? 2 : 1, 00432 &bytes_written, 00433 0, 00434 NULL, 00435 NULL); 00436 00437 if (rc == SOCKET_ERROR) 00438 { 00439 DBUS_SOCKET_SET_ERRNO (); 00440 _dbus_verbose ("WSASend: failed: %s\n", _dbus_strerror_from_errno ()); 00441 bytes_written = -1; 00442 } 00443 else 00444 _dbus_verbose ("WSASend: = %ld\n", bytes_written); 00445 00446 if (bytes_written < 0 && errno == EINTR) 00447 goto again; 00448 00449 return bytes_written; 00450 } 00451 00452 dbus_bool_t 00453 _dbus_socket_is_invalid (int fd) 00454 { 00455 return fd == INVALID_SOCKET ? TRUE : FALSE; 00456 } 00457 00458 #if 0 00459 00468 int 00469 _dbus_connect_named_pipe (const char *path, 00470 DBusError *error) 00471 { 00472 _dbus_assert_not_reached ("not implemented"); 00473 } 00474 00475 #endif 00476 00477 00478 00479 void 00480 _dbus_win_startup_winsock (void) 00481 { 00482 /* Straight from MSDN, deuglified */ 00483 00484 static dbus_bool_t beenhere = FALSE; 00485 00486 WORD wVersionRequested; 00487 WSADATA wsaData; 00488 int err; 00489 00490 if (beenhere) 00491 return; 00492 00493 wVersionRequested = MAKEWORD (2, 0); 00494 00495 err = WSAStartup (wVersionRequested, &wsaData); 00496 if (err != 0) 00497 { 00498 _dbus_assert_not_reached ("Could not initialize WinSock"); 00499 _dbus_abort (); 00500 } 00501 00502 /* Confirm that the WinSock DLL supports 2.0. Note that if the DLL 00503 * supports versions greater than 2.0 in addition to 2.0, it will 00504 * still return 2.0 in wVersion since that is the version we 00505 * requested. 00506 */ 00507 if (LOBYTE (wsaData.wVersion) != 2 || 00508 HIBYTE (wsaData.wVersion) != 0) 00509 { 00510 _dbus_assert_not_reached ("No usable WinSock found"); 00511 _dbus_abort (); 00512 } 00513 00514 beenhere = TRUE; 00515 } 00516 00517 00518 00519 00520 00521 00522 00523 00524 00525 /************************************************************************ 00526 00527 UTF / string code 00528 00529 ************************************************************************/ 00530 00534 int _dbus_printf_string_upper_bound (const char *format, 00535 va_list args) 00536 { 00537 /* MSVCRT's vsnprintf semantics are a bit different */ 00538 char buf[1024]; 00539 int bufsize; 00540 int len; 00541 va_list args_copy; 00542 00543 bufsize = sizeof (buf); 00544 DBUS_VA_COPY (args_copy, args); 00545 len = _vsnprintf (buf, bufsize - 1, format, args_copy); 00546 va_end (args_copy); 00547 00548 while (len == -1) /* try again */ 00549 { 00550 char *p; 00551 00552 bufsize *= 2; 00553 00554 p = malloc (bufsize); 00555 00556 if (p == NULL) 00557 return -1; 00558 00559 DBUS_VA_COPY (args_copy, args); 00560 len = _vsnprintf (p, bufsize - 1, format, args_copy); 00561 va_end (args_copy); 00562 free (p); 00563 } 00564 00565 return len; 00566 } 00567 00568 00576 wchar_t * 00577 _dbus_win_utf8_to_utf16 (const char *str, 00578 DBusError *error) 00579 { 00580 DBusString s; 00581 int n; 00582 wchar_t *retval; 00583 00584 _dbus_string_init_const (&s, str); 00585 00586 if (!_dbus_string_validate_utf8 (&s, 0, _dbus_string_get_length (&s))) 00587 { 00588 dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid UTF-8"); 00589 return NULL; 00590 } 00591 00592 n = MultiByteToWideChar (CP_UTF8, 0, str, -1, NULL, 0); 00593 00594 if (n == 0) 00595 { 00596 _dbus_win_set_error_from_win_error (error, GetLastError ()); 00597 return NULL; 00598 } 00599 00600 retval = dbus_new (wchar_t, n); 00601 00602 if (!retval) 00603 { 00604 _DBUS_SET_OOM (error); 00605 return NULL; 00606 } 00607 00608 if (MultiByteToWideChar (CP_UTF8, 0, str, -1, retval, n) != n) 00609 { 00610 dbus_free (retval); 00611 dbus_set_error_const (error, DBUS_ERROR_FAILED, "MultiByteToWideChar inconsistency"); 00612 return NULL; 00613 } 00614 00615 return retval; 00616 } 00617 00625 char * 00626 _dbus_win_utf16_to_utf8 (const wchar_t *str, 00627 DBusError *error) 00628 { 00629 int n; 00630 char *retval; 00631 00632 n = WideCharToMultiByte (CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL); 00633 00634 if (n == 0) 00635 { 00636 _dbus_win_set_error_from_win_error (error, GetLastError ()); 00637 return NULL; 00638 } 00639 00640 retval = dbus_malloc (n); 00641 00642 if (!retval) 00643 { 00644 _DBUS_SET_OOM (error); 00645 return NULL; 00646 } 00647 00648 if (WideCharToMultiByte (CP_UTF8, 0, str, -1, retval, n, NULL, NULL) != n) 00649 { 00650 dbus_free (retval); 00651 dbus_set_error_const (error, DBUS_ERROR_FAILED, "WideCharToMultiByte inconsistency"); 00652 return NULL; 00653 } 00654 00655 return retval; 00656 } 00657 00658 00659 00660 00661 00662 00663 /************************************************************************ 00664 00665 00666 ************************************************************************/ 00667 00668 dbus_bool_t 00669 _dbus_win_account_to_sid (const wchar_t *waccount, 00670 void **ppsid, 00671 DBusError *error) 00672 { 00673 dbus_bool_t retval = FALSE; 00674 DWORD sid_length, wdomain_length; 00675 SID_NAME_USE use; 00676 wchar_t *wdomain; 00677 00678 *ppsid = NULL; 00679 00680 sid_length = 0; 00681 wdomain_length = 0; 00682 if (!LookupAccountNameW (NULL, waccount, NULL, &sid_length, 00683 NULL, &wdomain_length, &use) && 00684 GetLastError () != ERROR_INSUFFICIENT_BUFFER) 00685 { 00686 _dbus_win_set_error_from_win_error (error, GetLastError ()); 00687 return FALSE; 00688 } 00689 00690 *ppsid = dbus_malloc (sid_length); 00691 if (!*ppsid) 00692 { 00693 _DBUS_SET_OOM (error); 00694 return FALSE; 00695 } 00696 00697 wdomain = dbus_new (wchar_t, wdomain_length); 00698 if (!wdomain) 00699 { 00700 _DBUS_SET_OOM (error); 00701 goto out1; 00702 } 00703 00704 if (!LookupAccountNameW (NULL, waccount, (PSID) *ppsid, &sid_length, 00705 wdomain, &wdomain_length, &use)) 00706 { 00707 _dbus_win_set_error_from_win_error (error, GetLastError ()); 00708 goto out2; 00709 } 00710 00711 if (!IsValidSid ((PSID) *ppsid)) 00712 { 00713 dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid SID"); 00714 goto out2; 00715 } 00716 00717 retval = TRUE; 00718 00719 out2: 00720 dbus_free (wdomain); 00721 out1: 00722 if (!retval) 00723 { 00724 dbus_free (*ppsid); 00725 *ppsid = NULL; 00726 } 00727 00728 return retval; 00729 } 00730 00740 unsigned long 00741 _dbus_pid_for_log (void) 00742 { 00743 return _dbus_getpid (); 00744 } 00745 00746 00747 #ifndef DBUS_WINCE 00748 00752 static dbus_bool_t 00753 _dbus_getsid(char **sid) 00754 { 00755 HANDLE process_token = INVALID_HANDLE_VALUE; 00756 TOKEN_USER *token_user = NULL; 00757 DWORD n; 00758 PSID psid; 00759 int retval = FALSE; 00760 00761 if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &process_token)) 00762 { 00763 _dbus_win_warn_win_error ("OpenProcessToken failed", GetLastError ()); 00764 goto failed; 00765 } 00766 if ((!GetTokenInformation (process_token, TokenUser, NULL, 0, &n) 00767 && GetLastError () != ERROR_INSUFFICIENT_BUFFER) 00768 || (token_user = alloca (n)) == NULL 00769 || !GetTokenInformation (process_token, TokenUser, token_user, n, &n)) 00770 { 00771 _dbus_win_warn_win_error ("GetTokenInformation failed", GetLastError ()); 00772 goto failed; 00773 } 00774 psid = token_user->User.Sid; 00775 if (!IsValidSid (psid)) 00776 { 00777 _dbus_verbose("%s invalid sid\n",__FUNCTION__); 00778 goto failed; 00779 } 00780 if (!ConvertSidToStringSidA (psid, sid)) 00781 { 00782 _dbus_verbose("%s invalid sid\n",__FUNCTION__); 00783 goto failed; 00784 } 00785 //okay: 00786 retval = TRUE; 00787 00788 failed: 00789 if (process_token != INVALID_HANDLE_VALUE) 00790 CloseHandle (process_token); 00791 00792 _dbus_verbose("_dbus_getsid() returns %d\n",retval); 00793 return retval; 00794 } 00795 #endif 00796 00797 /************************************************************************ 00798 00799 pipes 00800 00801 ************************************************************************/ 00802 00813 dbus_bool_t 00814 _dbus_full_duplex_pipe (int *fd1, 00815 int *fd2, 00816 dbus_bool_t blocking, 00817 DBusError *error) 00818 { 00819 SOCKET temp, socket1 = -1, socket2 = -1; 00820 struct sockaddr_in saddr; 00821 int len; 00822 u_long arg; 00823 00824 _dbus_win_startup_winsock (); 00825 00826 temp = socket (AF_INET, SOCK_STREAM, 0); 00827 if (temp == INVALID_SOCKET) 00828 { 00829 DBUS_SOCKET_SET_ERRNO (); 00830 goto out0; 00831 } 00832 00833 _DBUS_ZERO (saddr); 00834 saddr.sin_family = AF_INET; 00835 saddr.sin_port = 0; 00836 saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); 00837 00838 if (bind (temp, (struct sockaddr *)&saddr, sizeof (saddr)) == SOCKET_ERROR) 00839 { 00840 DBUS_SOCKET_SET_ERRNO (); 00841 goto out0; 00842 } 00843 00844 if (listen (temp, 1) == SOCKET_ERROR) 00845 { 00846 DBUS_SOCKET_SET_ERRNO (); 00847 goto out0; 00848 } 00849 00850 len = sizeof (saddr); 00851 if (getsockname (temp, (struct sockaddr *)&saddr, &len) == SOCKET_ERROR) 00852 { 00853 DBUS_SOCKET_SET_ERRNO (); 00854 goto out0; 00855 } 00856 00857 socket1 = socket (AF_INET, SOCK_STREAM, 0); 00858 if (socket1 == INVALID_SOCKET) 00859 { 00860 DBUS_SOCKET_SET_ERRNO (); 00861 goto out0; 00862 } 00863 00864 if (connect (socket1, (struct sockaddr *)&saddr, len) == SOCKET_ERROR) 00865 { 00866 DBUS_SOCKET_SET_ERRNO (); 00867 goto out1; 00868 } 00869 00870 socket2 = accept (temp, (struct sockaddr *) &saddr, &len); 00871 if (socket2 == INVALID_SOCKET) 00872 { 00873 DBUS_SOCKET_SET_ERRNO (); 00874 goto out1; 00875 } 00876 00877 if (!blocking) 00878 { 00879 arg = 1; 00880 if (ioctlsocket (socket1, FIONBIO, &arg) == SOCKET_ERROR) 00881 { 00882 DBUS_SOCKET_SET_ERRNO (); 00883 goto out2; 00884 } 00885 00886 arg = 1; 00887 if (ioctlsocket (socket2, FIONBIO, &arg) == SOCKET_ERROR) 00888 { 00889 DBUS_SOCKET_SET_ERRNO (); 00890 goto out2; 00891 } 00892 } 00893 00894 *fd1 = socket1; 00895 *fd2 = socket2; 00896 00897 _dbus_verbose ("full-duplex pipe %d:%d <-> %d:%d\n", 00898 *fd1, socket1, *fd2, socket2); 00899 00900 closesocket (temp); 00901 00902 return TRUE; 00903 00904 out2: 00905 closesocket (socket2); 00906 out1: 00907 closesocket (socket1); 00908 out0: 00909 closesocket (temp); 00910 00911 dbus_set_error (error, _dbus_error_from_errno (errno), 00912 "Could not setup socket pair: %s", 00913 _dbus_strerror_from_errno ()); 00914 00915 return FALSE; 00916 } 00917 00926 int 00927 _dbus_poll (DBusPollFD *fds, 00928 int n_fds, 00929 int timeout_milliseconds) 00930 { 00931 #define USE_CHRIS_IMPL 0 00932 00933 #if USE_CHRIS_IMPL 00934 00935 #define DBUS_POLL_CHAR_BUFFER_SIZE 2000 00936 char msg[DBUS_POLL_CHAR_BUFFER_SIZE]; 00937 char *msgp; 00938 00939 int ret = 0; 00940 int i; 00941 struct timeval tv; 00942 int ready; 00943 00944 #define DBUS_STACK_WSAEVENTS 256 00945 WSAEVENT eventsOnStack[DBUS_STACK_WSAEVENTS]; 00946 WSAEVENT *pEvents = NULL; 00947 if (n_fds > DBUS_STACK_WSAEVENTS) 00948 pEvents = calloc(sizeof(WSAEVENT), n_fds); 00949 else 00950 pEvents = eventsOnStack; 00951 00952 00953 #ifdef DBUS_ENABLE_VERBOSE_MODE 00954 msgp = msg; 00955 msgp += sprintf (msgp, "WSAEventSelect: to=%d\n\t", timeout_milliseconds); 00956 for (i = 0; i < n_fds; i++) 00957 { 00958 DBusPollFD *fdp = &fds[i]; 00959 00960 00961 if (fdp->events & _DBUS_POLLIN) 00962 msgp += sprintf (msgp, "R:%d ", fdp->fd); 00963 00964 if (fdp->events & _DBUS_POLLOUT) 00965 msgp += sprintf (msgp, "W:%d ", fdp->fd); 00966 00967 msgp += sprintf (msgp, "E:%d\n\t", fdp->fd); 00968 00969 // FIXME: more robust code for long msg 00970 // create on heap when msg[] becomes too small 00971 if (msgp >= msg + DBUS_POLL_CHAR_BUFFER_SIZE) 00972 { 00973 _dbus_assert_not_reached ("buffer overflow in _dbus_poll"); 00974 } 00975 } 00976 00977 msgp += sprintf (msgp, "\n"); 00978 _dbus_verbose ("%s",msg); 00979 #endif 00980 for (i = 0; i < n_fds; i++) 00981 { 00982 DBusPollFD *fdp = &fds[i]; 00983 WSAEVENT ev; 00984 long lNetworkEvents = FD_OOB; 00985 00986 ev = WSACreateEvent(); 00987 00988 if (fdp->events & _DBUS_POLLIN) 00989 lNetworkEvents |= FD_READ | FD_ACCEPT | FD_CLOSE; 00990 00991 if (fdp->events & _DBUS_POLLOUT) 00992 lNetworkEvents |= FD_WRITE | FD_CONNECT; 00993 00994 WSAEventSelect(fdp->fd, ev, lNetworkEvents); 00995 00996 pEvents[i] = ev; 00997 } 00998 00999 01000 ready = WSAWaitForMultipleEvents (n_fds, pEvents, FALSE, timeout_milliseconds, FALSE); 01001 01002 if (DBUS_SOCKET_API_RETURNS_ERROR (ready)) 01003 { 01004 DBUS_SOCKET_SET_ERRNO (); 01005 if (errno != WSAEWOULDBLOCK) 01006 _dbus_verbose ("WSAWaitForMultipleEvents: failed: %s\n", _dbus_strerror_from_errno ()); 01007 ret = -1; 01008 } 01009 else if (ready == WSA_WAIT_TIMEOUT) 01010 { 01011 _dbus_verbose ("WSAWaitForMultipleEvents: WSA_WAIT_TIMEOUT\n"); 01012 ret = 0; 01013 } 01014 else if (ready >= WSA_WAIT_EVENT_0 && ready < (int)(WSA_WAIT_EVENT_0 + n_fds)) 01015 { 01016 msgp = msg; 01017 msgp += sprintf (msgp, "WSAWaitForMultipleEvents: =%d\n\t", ready); 01018 01019 for (i = 0; i < n_fds; i++) 01020 { 01021 DBusPollFD *fdp = &fds[i]; 01022 WSANETWORKEVENTS ne; 01023 01024 fdp->revents = 0; 01025 01026 WSAEnumNetworkEvents(fdp->fd, pEvents[i], &ne); 01027 01028 if (ne.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) 01029 fdp->revents |= _DBUS_POLLIN; 01030 01031 if (ne.lNetworkEvents & (FD_WRITE | FD_CONNECT)) 01032 fdp->revents |= _DBUS_POLLOUT; 01033 01034 if (ne.lNetworkEvents & (FD_OOB)) 01035 fdp->revents |= _DBUS_POLLERR; 01036 01037 if (ne.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) 01038 msgp += sprintf (msgp, "R:%d ", fdp->fd); 01039 01040 if (ne.lNetworkEvents & (FD_WRITE | FD_CONNECT)) 01041 msgp += sprintf (msgp, "W:%d ", fdp->fd); 01042 01043 if (ne.lNetworkEvents & (FD_OOB)) 01044 msgp += sprintf (msgp, "E:%d ", fdp->fd); 01045 01046 msgp += sprintf (msgp, "lNetworkEvents:%d ", ne.lNetworkEvents); 01047 01048 if(ne.lNetworkEvents) 01049 ret++; 01050 01051 WSAEventSelect(fdp->fd, pEvents[i], 0); 01052 } 01053 01054 msgp += sprintf (msgp, "\n"); 01055 _dbus_verbose ("%s",msg); 01056 } 01057 else 01058 { 01059 _dbus_verbose ("WSAWaitForMultipleEvents: failed for unknown reason!"); 01060 ret = -1; 01061 } 01062 01063 for(i = 0; i < n_fds; i++) 01064 { 01065 WSACloseEvent(pEvents[i]); 01066 } 01067 01068 if (n_fds > DBUS_STACK_WSAEVENTS) 01069 free(pEvents); 01070 01071 return ret; 01072 01073 #else /* USE_CHRIS_IMPL */ 01074 01075 #define DBUS_POLL_CHAR_BUFFER_SIZE 2000 01076 char msg[DBUS_POLL_CHAR_BUFFER_SIZE]; 01077 char *msgp; 01078 01079 fd_set read_set, write_set, err_set; 01080 int max_fd = 0; 01081 int i; 01082 struct timeval tv; 01083 int ready; 01084 01085 FD_ZERO (&read_set); 01086 FD_ZERO (&write_set); 01087 FD_ZERO (&err_set); 01088 01089 01090 #ifdef DBUS_ENABLE_VERBOSE_MODE 01091 msgp = msg; 01092 msgp += sprintf (msgp, "select: to=%d\n\t", timeout_milliseconds); 01093 for (i = 0; i < n_fds; i++) 01094 { 01095 DBusPollFD *fdp = &fds[i]; 01096 01097 01098 if (fdp->events & _DBUS_POLLIN) 01099 msgp += sprintf (msgp, "R:%d ", fdp->fd); 01100 01101 if (fdp->events & _DBUS_POLLOUT) 01102 msgp += sprintf (msgp, "W:%d ", fdp->fd); 01103 01104 msgp += sprintf (msgp, "E:%d\n\t", fdp->fd); 01105 01106 // FIXME: more robust code for long msg 01107 // create on heap when msg[] becomes too small 01108 if (msgp >= msg + DBUS_POLL_CHAR_BUFFER_SIZE) 01109 { 01110 _dbus_assert_not_reached ("buffer overflow in _dbus_poll"); 01111 } 01112 } 01113 01114 msgp += sprintf (msgp, "\n"); 01115 _dbus_verbose ("%s",msg); 01116 #endif 01117 for (i = 0; i < n_fds; i++) 01118 { 01119 DBusPollFD *fdp = &fds[i]; 01120 01121 if (fdp->events & _DBUS_POLLIN) 01122 FD_SET (fdp->fd, &read_set); 01123 01124 if (fdp->events & _DBUS_POLLOUT) 01125 FD_SET (fdp->fd, &write_set); 01126 01127 FD_SET (fdp->fd, &err_set); 01128 01129 max_fd = MAX (max_fd, fdp->fd); 01130 } 01131 01132 // Avoid random lockups with send(), for lack of a better solution so far 01133 tv.tv_sec = timeout_milliseconds < 0 ? 1 : timeout_milliseconds / 1000; 01134 tv.tv_usec = timeout_milliseconds < 0 ? 0 : (timeout_milliseconds % 1000) * 1000; 01135 01136 ready = select (max_fd + 1, &read_set, &write_set, &err_set, &tv); 01137 01138 if (DBUS_SOCKET_API_RETURNS_ERROR (ready)) 01139 { 01140 DBUS_SOCKET_SET_ERRNO (); 01141 if (errno != WSAEWOULDBLOCK) 01142 _dbus_verbose ("select: failed: %s\n", _dbus_strerror_from_errno ()); 01143 } 01144 else if (ready == 0) 01145 _dbus_verbose ("select: = 0\n"); 01146 else 01147 if (ready > 0) 01148 { 01149 #ifdef DBUS_ENABLE_VERBOSE_MODE 01150 msgp = msg; 01151 msgp += sprintf (msgp, "select: = %d:\n\t", ready); 01152 01153 for (i = 0; i < n_fds; i++) 01154 { 01155 DBusPollFD *fdp = &fds[i]; 01156 01157 if (FD_ISSET (fdp->fd, &read_set)) 01158 msgp += sprintf (msgp, "R:%d ", fdp->fd); 01159 01160 if (FD_ISSET (fdp->fd, &write_set)) 01161 msgp += sprintf (msgp, "W:%d ", fdp->fd); 01162 01163 if (FD_ISSET (fdp->fd, &err_set)) 01164 msgp += sprintf (msgp, "E:%d\n\t", fdp->fd); 01165 } 01166 msgp += sprintf (msgp, "\n"); 01167 _dbus_verbose ("%s",msg); 01168 #endif 01169 01170 for (i = 0; i < n_fds; i++) 01171 { 01172 DBusPollFD *fdp = &fds[i]; 01173 01174 fdp->revents = 0; 01175 01176 if (FD_ISSET (fdp->fd, &read_set)) 01177 fdp->revents |= _DBUS_POLLIN; 01178 01179 if (FD_ISSET (fdp->fd, &write_set)) 01180 fdp->revents |= _DBUS_POLLOUT; 01181 01182 if (FD_ISSET (fdp->fd, &err_set)) 01183 fdp->revents |= _DBUS_POLLERR; 01184 } 01185 } 01186 return ready; 01187 #endif /* USE_CHRIS_IMPL */ 01188 } 01189 01190 01191 01192 01193 /****************************************************************************** 01194 01195 Original CVS version of dbus-sysdeps.c 01196 01197 ******************************************************************************/ 01198 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 01199 /* dbus-sysdeps.c Wrappers around system/libc features (internal to D-Bus implementation) 01200 * 01201 * Copyright (C) 2002, 2003 Red Hat, Inc. 01202 * Copyright (C) 2003 CodeFactory AB 01203 * Copyright (C) 2005 Novell, Inc. 01204 * 01205 * Licensed under the Academic Free License version 2.1 01206 * 01207 * This program is free software; you can redistribute it and/or modify 01208 * it under the terms of the GNU General Public License as published by 01209 * the Free Software Foundation; either version 2 of the License, or 01210 * (at your option) any later version. 01211 * 01212 * This program is distributed in the hope that it will be useful, 01213 * but WITHOUT ANY WARRANTY; without even the implied warranty of 01214 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 01215 * GNU General Public License for more details. 01216 * 01217 * You should have received a copy of the GNU General Public License 01218 * along with this program; if not, write to the Free Software 01219 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 01220 * 01221 */ 01222 01223 01229 void 01230 _dbus_exit (int code) 01231 { 01232 _exit (code); 01233 } 01234 01246 int 01247 _dbus_connect_tcp_socket (const char *host, 01248 const char *port, 01249 const char *family, 01250 DBusError *error) 01251 { 01252 return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error); 01253 } 01254 01255 int 01256 _dbus_connect_tcp_socket_with_nonce (const char *host, 01257 const char *port, 01258 const char *family, 01259 const char *noncefile, 01260 DBusError *error) 01261 { 01262 int fd = -1, res; 01263 struct addrinfo hints; 01264 struct addrinfo *ai, *tmp; 01265 01266 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01267 01268 _dbus_win_startup_winsock (); 01269 01270 _DBUS_ZERO (hints); 01271 01272 if (!family) 01273 hints.ai_family = AF_UNSPEC; 01274 else if (!strcmp(family, "ipv4")) 01275 hints.ai_family = AF_INET; 01276 else if (!strcmp(family, "ipv6")) 01277 hints.ai_family = AF_INET6; 01278 else 01279 { 01280 dbus_set_error (error, 01281 DBUS_ERROR_INVALID_ARGS, 01282 "Unknown address family %s", family); 01283 return -1; 01284 } 01285 hints.ai_protocol = IPPROTO_TCP; 01286 hints.ai_socktype = SOCK_STREAM; 01287 #ifdef AI_ADDRCONFIG 01288 hints.ai_flags = AI_ADDRCONFIG; 01289 #else 01290 hints.ai_flags = 0; 01291 #endif 01292 01293 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai) 01294 { 01295 dbus_set_error (error, 01296 _dbus_error_from_errno (res), 01297 "Failed to lookup host/port: \"%s:%s\": %s (%d)", 01298 host, port, _dbus_strerror(res), res); 01299 return -1; 01300 } 01301 01302 tmp = ai; 01303 while (tmp) 01304 { 01305 if ((fd = socket (tmp->ai_family, SOCK_STREAM, 0)) == INVALID_SOCKET) 01306 { 01307 DBUS_SOCKET_SET_ERRNO (); 01308 dbus_set_error (error, 01309 _dbus_error_from_errno (errno), 01310 "Failed to open socket: %s", 01311 _dbus_strerror_from_errno ()); 01312 freeaddrinfo(ai); 01313 return -1; 01314 } 01315 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01316 01317 if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) == SOCKET_ERROR) 01318 { 01319 DBUS_SOCKET_SET_ERRNO (); 01320 closesocket(fd); 01321 fd = -1; 01322 tmp = tmp->ai_next; 01323 continue; 01324 } 01325 01326 break; 01327 } 01328 freeaddrinfo(ai); 01329 01330 if (fd == -1) 01331 { 01332 dbus_set_error (error, 01333 _dbus_error_from_errno (errno), 01334 "Failed to connect to socket \"%s:%s\" %s", 01335 host, port, _dbus_strerror_from_errno ()); 01336 return -1; 01337 } 01338 01339 if (noncefile != NULL) 01340 { 01341 DBusString noncefileStr; 01342 dbus_bool_t ret; 01343 if (!_dbus_string_init (&noncefileStr) || 01344 !_dbus_string_append(&noncefileStr, noncefile)) 01345 { 01346 closesocket (fd); 01347 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01348 return -1; 01349 } 01350 01351 ret = _dbus_send_nonce (fd, &noncefileStr, error); 01352 01353 _dbus_string_free (&noncefileStr); 01354 01355 if (!ret) 01356 { 01357 closesocket (fd); 01358 return -1; 01359 } 01360 } 01361 01362 _dbus_fd_set_close_on_exec (fd); 01363 01364 if (!_dbus_set_fd_nonblocking (fd, error)) 01365 { 01366 closesocket (fd); 01367 return -1; 01368 } 01369 01370 return fd; 01371 } 01372 01388 int 01389 _dbus_listen_tcp_socket (const char *host, 01390 const char *port, 01391 const char *family, 01392 DBusString *retport, 01393 int **fds_p, 01394 DBusError *error) 01395 { 01396 int nlisten_fd = 0, *listen_fd = NULL, res, i, port_num = -1; 01397 struct addrinfo hints; 01398 struct addrinfo *ai, *tmp; 01399 01400 // On Vista, sockaddr_gen must be a sockaddr_in6, and not a sockaddr_in6_old 01401 //That's required for family == IPv6(which is the default on Vista if family is not given) 01402 //So we use our own union instead of sockaddr_gen: 01403 01404 typedef union { 01405 struct sockaddr Address; 01406 struct sockaddr_in AddressIn; 01407 struct sockaddr_in6 AddressIn6; 01408 } mysockaddr_gen; 01409 01410 *fds_p = NULL; 01411 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01412 01413 _dbus_win_startup_winsock (); 01414 01415 _DBUS_ZERO (hints); 01416 01417 if (!family) 01418 hints.ai_family = AF_UNSPEC; 01419 else if (!strcmp(family, "ipv4")) 01420 hints.ai_family = AF_INET; 01421 else if (!strcmp(family, "ipv6")) 01422 hints.ai_family = AF_INET6; 01423 else 01424 { 01425 dbus_set_error (error, 01426 DBUS_ERROR_INVALID_ARGS, 01427 "Unknown address family %s", family); 01428 return -1; 01429 } 01430 01431 hints.ai_protocol = IPPROTO_TCP; 01432 hints.ai_socktype = SOCK_STREAM; 01433 #ifdef AI_ADDRCONFIG 01434 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE; 01435 #else 01436 hints.ai_flags = AI_PASSIVE; 01437 #endif 01438 01439 redo_lookup_with_port: 01440 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai) 01441 { 01442 dbus_set_error (error, 01443 _dbus_error_from_errno (res), 01444 "Failed to lookup host/port: \"%s:%s\": %s (%d)", 01445 host ? host : "*", port, _dbus_strerror(res), res); 01446 return -1; 01447 } 01448 01449 tmp = ai; 01450 while (tmp) 01451 { 01452 int fd = -1, *newlisten_fd; 01453 if ((fd = socket (tmp->ai_family, SOCK_STREAM, 0)) == INVALID_SOCKET) 01454 { 01455 DBUS_SOCKET_SET_ERRNO (); 01456 dbus_set_error (error, 01457 _dbus_error_from_errno (errno), 01458 "Failed to open socket: %s", 01459 _dbus_strerror_from_errno ()); 01460 goto failed; 01461 } 01462 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01463 01464 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) == SOCKET_ERROR) 01465 { 01466 DBUS_SOCKET_SET_ERRNO (); 01467 dbus_set_error (error, _dbus_error_from_errno (errno), 01468 "Failed to bind socket \"%s:%s\": %s", 01469 host ? host : "*", port, _dbus_strerror_from_errno ()); 01470 closesocket (fd); 01471 goto failed; 01472 } 01473 01474 if (listen (fd, 30 /* backlog */) == SOCKET_ERROR) 01475 { 01476 DBUS_SOCKET_SET_ERRNO (); 01477 dbus_set_error (error, _dbus_error_from_errno (errno), 01478 "Failed to listen on socket \"%s:%s\": %s", 01479 host ? host : "*", port, _dbus_strerror_from_errno ()); 01480 closesocket (fd); 01481 goto failed; 01482 } 01483 01484 newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1)); 01485 if (!newlisten_fd) 01486 { 01487 closesocket (fd); 01488 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, 01489 "Failed to allocate file handle array"); 01490 goto failed; 01491 } 01492 listen_fd = newlisten_fd; 01493 listen_fd[nlisten_fd] = fd; 01494 nlisten_fd++; 01495 01496 if (!_dbus_string_get_length(retport)) 01497 { 01498 /* If the user didn't specify a port, or used 0, then 01499 the kernel chooses a port. After the first address 01500 is bound to, we need to force all remaining addresses 01501 to use the same port */ 01502 if (!port || !strcmp(port, "0")) 01503 { 01504 mysockaddr_gen addr; 01505 socklen_t addrlen = sizeof(addr); 01506 char portbuf[10]; 01507 01508 if (getsockname(fd, &addr.Address, &addrlen) == SOCKET_ERROR) 01509 { 01510 DBUS_SOCKET_SET_ERRNO (); 01511 dbus_set_error (error, _dbus_error_from_errno (errno), 01512 "Failed to resolve port \"%s:%s\": %s", 01513 host ? host : "*", port, _dbus_strerror_from_errno()); 01514 goto failed; 01515 } 01516 snprintf( portbuf, sizeof( portbuf ) - 1, "%d", addr.AddressIn.sin_port ); 01517 if (!_dbus_string_append(retport, portbuf)) 01518 { 01519 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01520 goto failed; 01521 } 01522 01523 /* Release current address list & redo lookup */ 01524 port = _dbus_string_get_const_data(retport); 01525 freeaddrinfo(ai); 01526 goto redo_lookup_with_port; 01527 } 01528 else 01529 { 01530 if (!_dbus_string_append(retport, port)) 01531 { 01532 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01533 goto failed; 01534 } 01535 } 01536 } 01537 01538 tmp = tmp->ai_next; 01539 } 01540 freeaddrinfo(ai); 01541 ai = NULL; 01542 01543 if (!nlisten_fd) 01544 { 01545 _dbus_win_set_errno (WSAEADDRINUSE); 01546 dbus_set_error (error, _dbus_error_from_errno (errno), 01547 "Failed to bind socket \"%s:%s\": %s", 01548 host ? host : "*", port, _dbus_strerror_from_errno ()); 01549 return -1; 01550 } 01551 01552 sscanf(_dbus_string_get_const_data(retport), "%d", &port_num); 01553 01554 for (i = 0 ; i < nlisten_fd ; i++) 01555 { 01556 _dbus_fd_set_close_on_exec (listen_fd[i]); 01557 if (!_dbus_set_fd_nonblocking (listen_fd[i], error)) 01558 { 01559 goto failed; 01560 } 01561 } 01562 01563 *fds_p = listen_fd; 01564 01565 return nlisten_fd; 01566 01567 failed: 01568 if (ai) 01569 freeaddrinfo(ai); 01570 for (i = 0 ; i < nlisten_fd ; i++) 01571 closesocket (listen_fd[i]); 01572 dbus_free(listen_fd); 01573 return -1; 01574 } 01575 01576 01584 int 01585 _dbus_accept (int listen_fd) 01586 { 01587 int client_fd; 01588 01589 retry: 01590 client_fd = accept (listen_fd, NULL, NULL); 01591 01592 if (DBUS_SOCKET_IS_INVALID (client_fd)) 01593 { 01594 DBUS_SOCKET_SET_ERRNO (); 01595 if (errno == EINTR) 01596 goto retry; 01597 } 01598 01599 _dbus_verbose ("client fd %d accepted\n", client_fd); 01600 01601 return client_fd; 01602 } 01603 01604 01605 01606 01607 dbus_bool_t 01608 _dbus_send_credentials_socket (int handle, 01609 DBusError *error) 01610 { 01611 /* FIXME: for the session bus credentials shouldn't matter (?), but 01612 * for the system bus they are presumably essential. A rough outline 01613 * of a way to implement the credential transfer would be this: 01614 * 01615 * client waits to *read* a byte. 01616 * 01617 * server creates a named pipe with a random name, sends a byte 01618 * contining its length, and its name. 01619 * 01620 * client reads the name, connects to it (using Win32 API). 01621 * 01622 * server waits for connection to the named pipe, then calls 01623 * ImpersonateNamedPipeClient(), notes its now-current credentials, 01624 * calls RevertToSelf(), closes its handles to the named pipe, and 01625 * is done. (Maybe there is some other way to get the SID of a named 01626 * pipe client without having to use impersonation?) 01627 * 01628 * client closes its handles and is done. 01629 * 01630 * Ralf: Why not sending credentials over the given this connection ? 01631 * Using named pipes makes it impossible to be connected from a unix client. 01632 * 01633 */ 01634 int bytes_written; 01635 DBusString buf; 01636 01637 _dbus_string_init_const_len (&buf, "\0", 1); 01638 again: 01639 bytes_written = _dbus_write_socket (handle, &buf, 0, 1 ); 01640 01641 if (bytes_written < 0 && errno == EINTR) 01642 goto again; 01643 01644 if (bytes_written < 0) 01645 { 01646 dbus_set_error (error, _dbus_error_from_errno (errno), 01647 "Failed to write credentials byte: %s", 01648 _dbus_strerror_from_errno ()); 01649 return FALSE; 01650 } 01651 else if (bytes_written == 0) 01652 { 01653 dbus_set_error (error, DBUS_ERROR_IO_ERROR, 01654 "wrote zero bytes writing credentials byte"); 01655 return FALSE; 01656 } 01657 else 01658 { 01659 _dbus_assert (bytes_written == 1); 01660 _dbus_verbose ("wrote 1 zero byte, credential sending isn't implemented yet\n"); 01661 return TRUE; 01662 } 01663 return TRUE; 01664 } 01665 01684 dbus_bool_t 01685 _dbus_read_credentials_socket (int handle, 01686 DBusCredentials *credentials, 01687 DBusError *error) 01688 { 01689 int bytes_read = 0; 01690 DBusString buf; 01691 01692 // could fail due too OOM 01693 if (_dbus_string_init(&buf)) 01694 { 01695 bytes_read = _dbus_read_socket(handle, &buf, 1 ); 01696 01697 if (bytes_read > 0) 01698 _dbus_verbose("got one zero byte from server"); 01699 01700 _dbus_string_free(&buf); 01701 } 01702 01703 _dbus_credentials_add_from_current_process (credentials); 01704 _dbus_verbose("FIXME: get faked credentials from current process"); 01705 01706 return TRUE; 01707 } 01708 01717 dbus_bool_t 01718 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error) 01719 { 01720 /* TODO */ 01721 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01722 return TRUE; 01723 } 01724 01725 01736 dbus_bool_t 01737 _dbus_concat_dir_and_file (DBusString *dir, 01738 const DBusString *next_component) 01739 { 01740 dbus_bool_t dir_ends_in_slash; 01741 dbus_bool_t file_starts_with_slash; 01742 01743 if (_dbus_string_get_length (dir) == 0 || 01744 _dbus_string_get_length (next_component) == 0) 01745 return TRUE; 01746 01747 dir_ends_in_slash = 01748 ('/' == _dbus_string_get_byte (dir, _dbus_string_get_length (dir) - 1) || 01749 '\\' == _dbus_string_get_byte (dir, _dbus_string_get_length (dir) - 1)); 01750 01751 file_starts_with_slash = 01752 ('/' == _dbus_string_get_byte (next_component, 0) || 01753 '\\' == _dbus_string_get_byte (next_component, 0)); 01754 01755 if (dir_ends_in_slash && file_starts_with_slash) 01756 { 01757 _dbus_string_shorten (dir, 1); 01758 } 01759 else if (!(dir_ends_in_slash || file_starts_with_slash)) 01760 { 01761 if (!_dbus_string_append_byte (dir, '\\')) 01762 return FALSE; 01763 } 01764 01765 return _dbus_string_copy (next_component, 0, dir, 01766 _dbus_string_get_length (dir)); 01767 } 01768 01769 /*---------------- DBusCredentials ----------------------------------*/ 01770 01778 dbus_bool_t 01779 _dbus_credentials_add_from_user (DBusCredentials *credentials, 01780 const DBusString *username) 01781 { 01782 return _dbus_credentials_add_windows_sid (credentials, 01783 _dbus_string_get_const_data(username)); 01784 } 01785 01794 dbus_bool_t 01795 _dbus_credentials_add_from_current_process (DBusCredentials *credentials) 01796 { 01797 dbus_bool_t retval = FALSE; 01798 char *sid = NULL; 01799 01800 if (!_dbus_getsid(&sid)) 01801 goto failed; 01802 01803 if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid())) 01804 goto failed; 01805 01806 if (!_dbus_credentials_add_windows_sid (credentials,sid)) 01807 goto failed; 01808 01809 retval = TRUE; 01810 goto end; 01811 failed: 01812 retval = FALSE; 01813 end: 01814 if (sid) 01815 LocalFree(sid); 01816 01817 return retval; 01818 } 01819 01832 dbus_bool_t 01833 _dbus_append_user_from_current_process (DBusString *str) 01834 { 01835 dbus_bool_t retval = FALSE; 01836 char *sid = NULL; 01837 01838 if (!_dbus_getsid(&sid)) 01839 return FALSE; 01840 01841 retval = _dbus_string_append (str,sid); 01842 01843 LocalFree(sid); 01844 return retval; 01845 } 01846 01851 dbus_pid_t 01852 _dbus_getpid (void) 01853 { 01854 return GetCurrentProcessId (); 01855 } 01856 01858 #define NANOSECONDS_PER_SECOND 1000000000 01859 01860 #define MICROSECONDS_PER_SECOND 1000000 01861 01862 #define MILLISECONDS_PER_SECOND 1000 01863 01864 #define NANOSECONDS_PER_MILLISECOND 1000000 01865 01866 #define MICROSECONDS_PER_MILLISECOND 1000 01867 01872 void 01873 _dbus_sleep_milliseconds (int milliseconds) 01874 { 01875 Sleep (milliseconds); 01876 } 01877 01878 01886 void 01887 _dbus_get_real_time (long *tv_sec, 01888 long *tv_usec) 01889 { 01890 FILETIME ft; 01891 dbus_uint64_t time64; 01892 01893 GetSystemTimeAsFileTime (&ft); 01894 01895 memcpy (&time64, &ft, sizeof (time64)); 01896 01897 /* Convert from 100s of nanoseconds since 1601-01-01 01898 * to Unix epoch. Yes, this is Y2038 unsafe. 01899 */ 01900 time64 -= DBUS_INT64_CONSTANT (116444736000000000); 01901 time64 /= 10; 01902 01903 if (tv_sec) 01904 *tv_sec = time64 / 1000000; 01905 01906 if (tv_usec) 01907 *tv_usec = time64 % 1000000; 01908 } 01909 01917 void 01918 _dbus_get_monotonic_time (long *tv_sec, 01919 long *tv_usec) 01920 { 01921 /* no implementation yet, fall back to wall-clock time */ 01922 _dbus_get_real_time (tv_sec, tv_usec); 01923 } 01924 01928 void 01929 _dbus_disable_sigpipe (void) 01930 { 01931 } 01932 01941 dbus_bool_t 01942 _dbus_create_directory (const DBusString *filename, 01943 DBusError *error) 01944 { 01945 const char *filename_c; 01946 01947 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01948 01949 filename_c = _dbus_string_get_const_data (filename); 01950 01951 if (!CreateDirectoryA (filename_c, NULL)) 01952 { 01953 if (GetLastError () == ERROR_ALREADY_EXISTS) 01954 return TRUE; 01955 01956 dbus_set_error (error, DBUS_ERROR_FAILED, 01957 "Failed to create directory %s: %s\n", 01958 filename_c, _dbus_strerror_from_errno ()); 01959 return FALSE; 01960 } 01961 else 01962 return TRUE; 01963 } 01964 01965 01974 dbus_bool_t 01975 _dbus_generate_random_bytes (DBusString *str, 01976 int n_bytes) 01977 { 01978 int old_len; 01979 char *p; 01980 HCRYPTPROV hprov; 01981 01982 old_len = _dbus_string_get_length (str); 01983 01984 if (!_dbus_string_lengthen (str, n_bytes)) 01985 return FALSE; 01986 01987 p = _dbus_string_get_data_len (str, old_len, n_bytes); 01988 01989 if (!CryptAcquireContext (&hprov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) 01990 return FALSE; 01991 01992 if (!CryptGenRandom (hprov, n_bytes, p)) 01993 { 01994 CryptReleaseContext (hprov, 0); 01995 return FALSE; 01996 } 01997 01998 CryptReleaseContext (hprov, 0); 01999 02000 return TRUE; 02001 } 02002 02009 const char* 02010 _dbus_get_tmpdir(void) 02011 { 02012 static const char* tmpdir = NULL; 02013 static char buf[1000]; 02014 02015 if (tmpdir == NULL) 02016 { 02017 char *last_slash; 02018 02019 if (!GetTempPathA (sizeof (buf), buf)) 02020 { 02021 _dbus_warn ("GetTempPath failed\n"); 02022 _dbus_abort (); 02023 } 02024 02025 /* Drop terminating backslash or slash */ 02026 last_slash = _mbsrchr (buf, '\\'); 02027 if (last_slash > buf && last_slash[1] == '\0') 02028 last_slash[0] = '\0'; 02029 last_slash = _mbsrchr (buf, '/'); 02030 if (last_slash > buf && last_slash[1] == '\0') 02031 last_slash[0] = '\0'; 02032 02033 tmpdir = buf; 02034 } 02035 02036 _dbus_assert(tmpdir != NULL); 02037 02038 return tmpdir; 02039 } 02040 02041 02050 dbus_bool_t 02051 _dbus_delete_file (const DBusString *filename, 02052 DBusError *error) 02053 { 02054 const char *filename_c; 02055 02056 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02057 02058 filename_c = _dbus_string_get_const_data (filename); 02059 02060 if (DeleteFileA (filename_c) == 0) 02061 { 02062 dbus_set_error (error, DBUS_ERROR_FAILED, 02063 "Failed to delete file %s: %s\n", 02064 filename_c, _dbus_strerror_from_errno ()); 02065 return FALSE; 02066 } 02067 else 02068 return TRUE; 02069 } 02070 02071 /* 02072 * replaces the term DBUS_PREFIX in configure_time_path by the 02073 * current dbus installation directory. On unix this function is a noop 02074 * 02075 * @param configure_time_path 02076 * @return real path 02077 */ 02078 const char * 02079 _dbus_replace_install_prefix (const char *configure_time_path) 02080 { 02081 #ifndef DBUS_PREFIX 02082 return configure_time_path; 02083 #else 02084 static char retval[1000]; 02085 static char runtime_prefix[1000]; 02086 int len = 1000; 02087 int i; 02088 02089 if (!configure_time_path) 02090 return NULL; 02091 02092 if ((!_dbus_get_install_root(runtime_prefix, len) || 02093 strncmp (configure_time_path, DBUS_PREFIX "/", 02094 strlen (DBUS_PREFIX) + 1))) { 02095 strcat (retval, configure_time_path); 02096 return retval; 02097 } 02098 02099 strcpy (retval, runtime_prefix); 02100 strcat (retval, configure_time_path + strlen (DBUS_PREFIX) + 1); 02101 02102 /* Somehow, in some situations, backslashes get collapsed in the string. 02103 * Since windows C library accepts both forward and backslashes as 02104 * path separators, convert all backslashes to forward slashes. 02105 */ 02106 02107 for(i = 0; retval[i] != '\0'; i++) { 02108 if(retval[i] == '\\') 02109 retval[i] = '/'; 02110 } 02111 return retval; 02112 #endif 02113 } 02114 02115 #if !defined (DBUS_DISABLE_ASSERTS) || defined(DBUS_BUILD_TESTS) 02116 02117 #if defined(_MSC_VER) || defined(DBUS_WINCE) 02118 # ifdef BACKTRACES 02119 # undef BACKTRACES 02120 # endif 02121 #else 02122 # define BACKTRACES 02123 #endif 02124 02125 #ifdef BACKTRACES 02126 /* 02127 * Backtrace Generator 02128 * 02129 * Copyright 2004 Eric Poech 02130 * Copyright 2004 Robert Shearman 02131 * 02132 * This library is free software; you can redistribute it and/or 02133 * modify it under the terms of the GNU Lesser General Public 02134 * License as published by the Free Software Foundation; either 02135 * version 2.1 of the License, or (at your option) any later version. 02136 * 02137 * This library is distributed in the hope that it will be useful, 02138 * but WITHOUT ANY WARRANTY; without even the implied warranty of 02139 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 02140 * Lesser General Public License for more details. 02141 * 02142 * You should have received a copy of the GNU Lesser General Public 02143 * License along with this library; if not, write to the Free Software 02144 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 02145 */ 02146 02147 #include <winver.h> 02148 #include <imagehlp.h> 02149 #include <stdio.h> 02150 02151 #define DPRINTF _dbus_warn 02152 02153 #ifdef _MSC_VER 02154 #define BOOL int 02155 02156 #define __i386__ 02157 #endif 02158 02159 //#define MAKE_FUNCPTR(f) static typeof(f) * p##f 02160 02161 //MAKE_FUNCPTR(StackWalk); 02162 //MAKE_FUNCPTR(SymGetModuleBase); 02163 //MAKE_FUNCPTR(SymFunctionTableAccess); 02164 //MAKE_FUNCPTR(SymInitialize); 02165 //MAKE_FUNCPTR(SymGetSymFromAddr); 02166 //MAKE_FUNCPTR(SymGetModuleInfo); 02167 static BOOL (WINAPI *pStackWalk)( 02168 DWORD MachineType, 02169 HANDLE hProcess, 02170 HANDLE hThread, 02171 LPSTACKFRAME StackFrame, 02172 PVOID ContextRecord, 02173 PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine, 02174 PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine, 02175 PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine, 02176 PTRANSLATE_ADDRESS_ROUTINE TranslateAddress 02177 ); 02178 #ifdef _WIN64 02179 static DWORD64 (WINAPI *pSymGetModuleBase)( 02180 HANDLE hProcess, 02181 DWORD64 dwAddr 02182 ); 02183 static PVOID (WINAPI *pSymFunctionTableAccess)( 02184 HANDLE hProcess, 02185 DWORD64 AddrBase 02186 ); 02187 #else 02188 static DWORD (WINAPI *pSymGetModuleBase)( 02189 HANDLE hProcess, 02190 DWORD dwAddr 02191 ); 02192 static PVOID (WINAPI *pSymFunctionTableAccess)( 02193 HANDLE hProcess, 02194 DWORD AddrBase 02195 ); 02196 #endif 02197 static BOOL (WINAPI *pSymInitialize)( 02198 HANDLE hProcess, 02199 PSTR UserSearchPath, 02200 BOOL fInvadeProcess 02201 ); 02202 static BOOL (WINAPI *pSymGetSymFromAddr)( 02203 HANDLE hProcess, 02204 DWORD Address, 02205 PDWORD Displacement, 02206 PIMAGEHLP_SYMBOL Symbol 02207 ); 02208 static BOOL (WINAPI *pSymGetModuleInfo)( 02209 HANDLE hProcess, 02210 DWORD dwAddr, 02211 PIMAGEHLP_MODULE ModuleInfo 02212 ); 02213 static DWORD (WINAPI *pSymSetOptions)( 02214 DWORD SymOptions 02215 ); 02216 02217 02218 static BOOL init_backtrace() 02219 { 02220 HMODULE hmodDbgHelp = LoadLibraryA("dbghelp"); 02221 /* 02222 #define GETFUNC(x) \ 02223 p##x = (typeof(x)*)GetProcAddress(hmodDbgHelp, #x); \ 02224 if (!p##x) \ 02225 { \ 02226 return FALSE; \ 02227 } 02228 */ 02229 02230 02231 // GETFUNC(StackWalk); 02232 // GETFUNC(SymGetModuleBase); 02233 // GETFUNC(SymFunctionTableAccess); 02234 // GETFUNC(SymInitialize); 02235 // GETFUNC(SymGetSymFromAddr); 02236 // GETFUNC(SymGetModuleInfo); 02237 02238 #define FUNC(x) #x 02239 02240 pStackWalk = (BOOL (WINAPI *)( 02241 DWORD MachineType, 02242 HANDLE hProcess, 02243 HANDLE hThread, 02244 LPSTACKFRAME StackFrame, 02245 PVOID ContextRecord, 02246 PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine, 02247 PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine, 02248 PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine, 02249 PTRANSLATE_ADDRESS_ROUTINE TranslateAddress 02250 ))GetProcAddress (hmodDbgHelp, FUNC(StackWalk)); 02251 #ifdef _WIN64 02252 pSymGetModuleBase=(DWORD64 (WINAPI *)( 02253 HANDLE hProcess, 02254 DWORD64 dwAddr 02255 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleBase)); 02256 pSymFunctionTableAccess=(PVOID (WINAPI *)( 02257 HANDLE hProcess, 02258 DWORD64 AddrBase 02259 ))GetProcAddress (hmodDbgHelp, FUNC(SymFunctionTableAccess)); 02260 #else 02261 pSymGetModuleBase=(DWORD (WINAPI *)( 02262 HANDLE hProcess, 02263 DWORD dwAddr 02264 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleBase)); 02265 pSymFunctionTableAccess=(PVOID (WINAPI *)( 02266 HANDLE hProcess, 02267 DWORD AddrBase 02268 ))GetProcAddress (hmodDbgHelp, FUNC(SymFunctionTableAccess)); 02269 #endif 02270 pSymInitialize = (BOOL (WINAPI *)( 02271 HANDLE hProcess, 02272 PSTR UserSearchPath, 02273 BOOL fInvadeProcess 02274 ))GetProcAddress (hmodDbgHelp, FUNC(SymInitialize)); 02275 pSymGetSymFromAddr = (BOOL (WINAPI *)( 02276 HANDLE hProcess, 02277 DWORD Address, 02278 PDWORD Displacement, 02279 PIMAGEHLP_SYMBOL Symbol 02280 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetSymFromAddr)); 02281 pSymGetModuleInfo = (BOOL (WINAPI *)( 02282 HANDLE hProcess, 02283 DWORD dwAddr, 02284 PIMAGEHLP_MODULE ModuleInfo 02285 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleInfo)); 02286 pSymSetOptions = (DWORD (WINAPI *)( 02287 DWORD SymOptions 02288 ))GetProcAddress (hmodDbgHelp, FUNC(SymSetOptions)); 02289 02290 02291 pSymSetOptions(SYMOPT_UNDNAME); 02292 02293 pSymInitialize(GetCurrentProcess(), NULL, TRUE); 02294 02295 return TRUE; 02296 } 02297 02298 static void dump_backtrace_for_thread(HANDLE hThread) 02299 { 02300 STACKFRAME sf; 02301 CONTEXT context; 02302 DWORD dwImageType; 02303 02304 if (!pStackWalk) 02305 if (!init_backtrace()) 02306 return; 02307 02308 /* can't use this function for current thread as GetThreadContext 02309 * doesn't support getting context from current thread */ 02310 if (hThread == GetCurrentThread()) 02311 return; 02312 02313 DPRINTF("Backtrace:\n"); 02314 02315 _DBUS_ZERO(context); 02316 context.ContextFlags = CONTEXT_FULL; 02317 02318 SuspendThread(hThread); 02319 02320 if (!GetThreadContext(hThread, &context)) 02321 { 02322 DPRINTF("Couldn't get thread context (error %ld)\n", GetLastError()); 02323 ResumeThread(hThread); 02324 return; 02325 } 02326 02327 _DBUS_ZERO(sf); 02328 02329 #ifdef __i386__ 02330 sf.AddrFrame.Offset = context.Ebp; 02331 sf.AddrFrame.Mode = AddrModeFlat; 02332 sf.AddrPC.Offset = context.Eip; 02333 sf.AddrPC.Mode = AddrModeFlat; 02334 dwImageType = IMAGE_FILE_MACHINE_I386; 02335 #elif _M_X64 02336 dwImageType = IMAGE_FILE_MACHINE_AMD64; 02337 sf.AddrPC.Offset = context.Rip; 02338 sf.AddrPC.Mode = AddrModeFlat; 02339 sf.AddrFrame.Offset = context.Rsp; 02340 sf.AddrFrame.Mode = AddrModeFlat; 02341 sf.AddrStack.Offset = context.Rsp; 02342 sf.AddrStack.Mode = AddrModeFlat; 02343 #elif _M_IA64 02344 dwImageType = IMAGE_FILE_MACHINE_IA64; 02345 sf.AddrPC.Offset = context.StIIP; 02346 sf.AddrPC.Mode = AddrModeFlat; 02347 sf.AddrFrame.Offset = context.IntSp; 02348 sf.AddrFrame.Mode = AddrModeFlat; 02349 sf.AddrBStore.Offset= context.RsBSP; 02350 sf.AddrBStore.Mode = AddrModeFlat; 02351 sf.AddrStack.Offset = context.IntSp; 02352 sf.AddrStack.Mode = AddrModeFlat; 02353 #else 02354 # error You need to fill in the STACKFRAME structure for your architecture 02355 #endif 02356 02357 while (pStackWalk(dwImageType, GetCurrentProcess(), 02358 hThread, &sf, &context, NULL, pSymFunctionTableAccess, 02359 pSymGetModuleBase, NULL)) 02360 { 02361 BYTE buffer[256]; 02362 IMAGEHLP_SYMBOL * pSymbol = (IMAGEHLP_SYMBOL *)buffer; 02363 DWORD dwDisplacement; 02364 02365 pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); 02366 pSymbol->MaxNameLength = sizeof(buffer) - sizeof(IMAGEHLP_SYMBOL) + 1; 02367 02368 if (!pSymGetSymFromAddr(GetCurrentProcess(), sf.AddrPC.Offset, 02369 &dwDisplacement, pSymbol)) 02370 { 02371 IMAGEHLP_MODULE ModuleInfo; 02372 ModuleInfo.SizeOfStruct = sizeof(ModuleInfo); 02373 02374 if (!pSymGetModuleInfo(GetCurrentProcess(), sf.AddrPC.Offset, 02375 &ModuleInfo)) 02376 DPRINTF("1\t%p\n", (void*)sf.AddrPC.Offset); 02377 else 02378 DPRINTF("2\t%s+0x%lx\n", ModuleInfo.ImageName, 02379 sf.AddrPC.Offset - ModuleInfo.BaseOfImage); 02380 } 02381 else if (dwDisplacement) 02382 DPRINTF("3\t%s+0x%lx\n", pSymbol->Name, dwDisplacement); 02383 else 02384 DPRINTF("4\t%s\n", pSymbol->Name); 02385 } 02386 02387 ResumeThread(hThread); 02388 } 02389 02390 static DWORD WINAPI dump_thread_proc(LPVOID lpParameter) 02391 { 02392 dump_backtrace_for_thread((HANDLE)lpParameter); 02393 return 0; 02394 } 02395 02396 /* cannot get valid context from current thread, so we have to execute 02397 * backtrace from another thread */ 02398 static void dump_backtrace() 02399 { 02400 HANDLE hCurrentThread; 02401 HANDLE hThread; 02402 DWORD dwThreadId; 02403 DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), 02404 GetCurrentProcess(), &hCurrentThread, 0, FALSE, DUPLICATE_SAME_ACCESS); 02405 hThread = CreateThread(NULL, 0, dump_thread_proc, (LPVOID)hCurrentThread, 02406 0, &dwThreadId); 02407 WaitForSingleObject(hThread, INFINITE); 02408 CloseHandle(hThread); 02409 CloseHandle(hCurrentThread); 02410 } 02411 #endif 02412 #endif /* asserts or tests enabled */ 02413 02414 #ifdef BACKTRACES 02415 void _dbus_print_backtrace(void) 02416 { 02417 init_backtrace(); 02418 dump_backtrace(); 02419 } 02420 #else 02421 void _dbus_print_backtrace(void) 02422 { 02423 _dbus_verbose (" D-Bus not compiled with backtrace support\n"); 02424 } 02425 #endif 02426 02427 static dbus_uint32_t fromAscii(char ascii) 02428 { 02429 if(ascii >= '0' && ascii <= '9') 02430 return ascii - '0'; 02431 if(ascii >= 'A' && ascii <= 'F') 02432 return ascii - 'A' + 10; 02433 if(ascii >= 'a' && ascii <= 'f') 02434 return ascii - 'a' + 10; 02435 return 0; 02436 } 02437 02438 dbus_bool_t _dbus_read_local_machine_uuid (DBusGUID *machine_id, 02439 dbus_bool_t create_if_not_found, 02440 DBusError *error) 02441 { 02442 #ifdef DBUS_WINCE 02443 return TRUE; 02444 // TODO 02445 #else 02446 HW_PROFILE_INFOA info; 02447 char *lpc = &info.szHwProfileGuid[0]; 02448 dbus_uint32_t u; 02449 02450 // the hw-profile guid lives long enough 02451 if(!GetCurrentHwProfileA(&info)) 02452 { 02453 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); // FIXME 02454 return FALSE; 02455 } 02456 02457 // Form: {12340001-4980-1920-6788-123456789012} 02458 lpc++; 02459 // 12340001 02460 u = ((fromAscii(lpc[0]) << 0) | 02461 (fromAscii(lpc[1]) << 4) | 02462 (fromAscii(lpc[2]) << 8) | 02463 (fromAscii(lpc[3]) << 12) | 02464 (fromAscii(lpc[4]) << 16) | 02465 (fromAscii(lpc[5]) << 20) | 02466 (fromAscii(lpc[6]) << 24) | 02467 (fromAscii(lpc[7]) << 28)); 02468 machine_id->as_uint32s[0] = u; 02469 02470 lpc += 9; 02471 // 4980-1920 02472 u = ((fromAscii(lpc[0]) << 0) | 02473 (fromAscii(lpc[1]) << 4) | 02474 (fromAscii(lpc[2]) << 8) | 02475 (fromAscii(lpc[3]) << 12) | 02476 (fromAscii(lpc[5]) << 16) | 02477 (fromAscii(lpc[6]) << 20) | 02478 (fromAscii(lpc[7]) << 24) | 02479 (fromAscii(lpc[8]) << 28)); 02480 machine_id->as_uint32s[1] = u; 02481 02482 lpc += 10; 02483 // 6788-1234 02484 u = ((fromAscii(lpc[0]) << 0) | 02485 (fromAscii(lpc[1]) << 4) | 02486 (fromAscii(lpc[2]) << 8) | 02487 (fromAscii(lpc[3]) << 12) | 02488 (fromAscii(lpc[5]) << 16) | 02489 (fromAscii(lpc[6]) << 20) | 02490 (fromAscii(lpc[7]) << 24) | 02491 (fromAscii(lpc[8]) << 28)); 02492 machine_id->as_uint32s[2] = u; 02493 02494 lpc += 9; 02495 // 56789012 02496 u = ((fromAscii(lpc[0]) << 0) | 02497 (fromAscii(lpc[1]) << 4) | 02498 (fromAscii(lpc[2]) << 8) | 02499 (fromAscii(lpc[3]) << 12) | 02500 (fromAscii(lpc[4]) << 16) | 02501 (fromAscii(lpc[5]) << 20) | 02502 (fromAscii(lpc[6]) << 24) | 02503 (fromAscii(lpc[7]) << 28)); 02504 machine_id->as_uint32s[3] = u; 02505 #endif 02506 return TRUE; 02507 } 02508 02509 static 02510 HANDLE _dbus_global_lock (const char *mutexname) 02511 { 02512 HANDLE mutex; 02513 DWORD gotMutex; 02514 02515 mutex = CreateMutexA( NULL, FALSE, mutexname ); 02516 if( !mutex ) 02517 { 02518 return FALSE; 02519 } 02520 02521 gotMutex = WaitForSingleObject( mutex, INFINITE ); 02522 switch( gotMutex ) 02523 { 02524 case WAIT_ABANDONED: 02525 ReleaseMutex (mutex); 02526 CloseHandle (mutex); 02527 return 0; 02528 case WAIT_FAILED: 02529 case WAIT_TIMEOUT: 02530 return 0; 02531 } 02532 02533 return mutex; 02534 } 02535 02536 static 02537 void _dbus_global_unlock (HANDLE mutex) 02538 { 02539 ReleaseMutex (mutex); 02540 CloseHandle (mutex); 02541 } 02542 02543 // for proper cleanup in dbus-daemon 02544 static HANDLE hDBusDaemonMutex = NULL; 02545 static HANDLE hDBusSharedMem = NULL; 02546 // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs 02547 static const char *cUniqueDBusInitMutex = "UniqueDBusInitMutex"; 02548 // sync _dbus_get_autolaunch_address 02549 static const char *cDBusAutolaunchMutex = "DBusAutolaunchMutex"; 02550 // mutex to determine if dbus-daemon is already started (per user) 02551 static const char *cDBusDaemonMutex = "DBusDaemonMutex"; 02552 // named shm for dbus adress info (per user) 02553 static const char *cDBusDaemonAddressInfo = "DBusDaemonAddressInfo"; 02554 02555 static dbus_bool_t 02556 _dbus_get_install_root_as_hash(DBusString *out) 02557 { 02558 DBusString install_path; 02559 02560 char path[MAX_PATH*2]; 02561 int path_size = sizeof(path); 02562 02563 if (!_dbus_get_install_root(path,path_size)) 02564 return FALSE; 02565 02566 _dbus_string_init(&install_path); 02567 _dbus_string_append(&install_path,path); 02568 02569 _dbus_string_init(out); 02570 _dbus_string_tolower_ascii(&install_path,0,_dbus_string_get_length(&install_path)); 02571 02572 if (!_dbus_sha_compute (&install_path, out)) 02573 return FALSE; 02574 02575 return TRUE; 02576 } 02577 02578 static dbus_bool_t 02579 _dbus_get_address_string (DBusString *out, const char *basestring, const char *scope) 02580 { 02581 _dbus_string_init(out); 02582 _dbus_string_append(out,basestring); 02583 02584 if (!scope) 02585 { 02586 return TRUE; 02587 } 02588 else if (strcmp(scope,"*install-path") == 0 02589 // for 1.3 compatibility 02590 || strcmp(scope,"install-path") == 0) 02591 { 02592 DBusString temp; 02593 if (!_dbus_get_install_root_as_hash(&temp)) 02594 { 02595 _dbus_string_free(out); 02596 return FALSE; 02597 } 02598 _dbus_string_append(out,"-"); 02599 _dbus_string_append(out,_dbus_string_get_const_data(&temp)); 02600 _dbus_string_free(&temp); 02601 } 02602 else if (strcmp(scope,"*user") == 0) 02603 { 02604 _dbus_string_append(out,"-"); 02605 if (!_dbus_append_user_from_current_process(out)) 02606 { 02607 _dbus_string_free(out); 02608 return FALSE; 02609 } 02610 } 02611 else if (strlen(scope) > 0) 02612 { 02613 _dbus_string_append(out,"-"); 02614 _dbus_string_append(out,scope); 02615 return TRUE; 02616 } 02617 return TRUE; 02618 } 02619 02620 static dbus_bool_t 02621 _dbus_get_shm_name (DBusString *out,const char *scope) 02622 { 02623 return _dbus_get_address_string (out,cDBusDaemonAddressInfo,scope); 02624 } 02625 02626 static dbus_bool_t 02627 _dbus_get_mutex_name (DBusString *out,const char *scope) 02628 { 02629 return _dbus_get_address_string (out,cDBusDaemonMutex,scope); 02630 } 02631 02632 dbus_bool_t 02633 _dbus_daemon_is_session_bus_address_published (const char *scope) 02634 { 02635 HANDLE lock; 02636 DBusString mutex_name; 02637 02638 if (!_dbus_get_mutex_name(&mutex_name,scope)) 02639 { 02640 _dbus_string_free( &mutex_name ); 02641 return FALSE; 02642 } 02643 02644 if (hDBusDaemonMutex) 02645 return TRUE; 02646 02647 // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs 02648 lock = _dbus_global_lock( cUniqueDBusInitMutex ); 02649 02650 // we use CreateMutex instead of OpenMutex because of possible race conditions, 02651 // see http://msdn.microsoft.com/en-us/library/ms684315%28VS.85%29.aspx 02652 hDBusDaemonMutex = CreateMutexA( NULL, FALSE, _dbus_string_get_const_data(&mutex_name) ); 02653 02654 /* The client uses mutex ownership to detect a running server, so the server should do so too. 02655 Fortunally the client deletes the mutex in the lock protected area, so checking presence 02656 will work too. */ 02657 02658 _dbus_global_unlock( lock ); 02659 02660 _dbus_string_free( &mutex_name ); 02661 02662 if (hDBusDaemonMutex == NULL) 02663 return FALSE; 02664 if (GetLastError() == ERROR_ALREADY_EXISTS) 02665 { 02666 CloseHandle(hDBusDaemonMutex); 02667 hDBusDaemonMutex = NULL; 02668 return TRUE; 02669 } 02670 // mutex wasn't created before, so return false. 02671 // We leave the mutex name allocated for later reusage 02672 // in _dbus_daemon_publish_session_bus_address. 02673 return FALSE; 02674 } 02675 02676 dbus_bool_t 02677 _dbus_daemon_publish_session_bus_address (const char* address, const char *scope) 02678 { 02679 HANDLE lock; 02680 char *shared_addr = NULL; 02681 DBusString shm_name; 02682 DBusString mutex_name; 02683 02684 _dbus_assert (address); 02685 02686 if (!_dbus_get_mutex_name(&mutex_name,scope)) 02687 { 02688 _dbus_string_free( &mutex_name ); 02689 return FALSE; 02690 } 02691 02692 // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs 02693 lock = _dbus_global_lock( cUniqueDBusInitMutex ); 02694 02695 if (!hDBusDaemonMutex) 02696 { 02697 hDBusDaemonMutex = CreateMutexA( NULL, FALSE, _dbus_string_get_const_data(&mutex_name) ); 02698 } 02699 _dbus_string_free( &mutex_name ); 02700 02701 // acquire the mutex 02702 if (WaitForSingleObject( hDBusDaemonMutex, 10 ) != WAIT_OBJECT_0) 02703 { 02704 _dbus_global_unlock( lock ); 02705 CloseHandle( hDBusDaemonMutex ); 02706 return FALSE; 02707 } 02708 02709 if (!_dbus_get_shm_name(&shm_name,scope)) 02710 { 02711 _dbus_string_free( &shm_name ); 02712 _dbus_global_unlock( lock ); 02713 return FALSE; 02714 } 02715 02716 // create shm 02717 hDBusSharedMem = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 02718 0, strlen( address ) + 1, _dbus_string_get_const_data(&shm_name) ); 02719 _dbus_assert( hDBusSharedMem ); 02720 02721 shared_addr = MapViewOfFile( hDBusSharedMem, FILE_MAP_WRITE, 0, 0, 0 ); 02722 02723 _dbus_assert (shared_addr); 02724 02725 strcpy( shared_addr, address); 02726 02727 // cleanup 02728 UnmapViewOfFile( shared_addr ); 02729 02730 _dbus_global_unlock( lock ); 02731 _dbus_verbose( "published session bus address at %s\n",_dbus_string_get_const_data (&shm_name) ); 02732 02733 _dbus_string_free( &shm_name ); 02734 return TRUE; 02735 } 02736 02737 void 02738 _dbus_daemon_unpublish_session_bus_address (void) 02739 { 02740 HANDLE lock; 02741 02742 // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs 02743 lock = _dbus_global_lock( cUniqueDBusInitMutex ); 02744 02745 CloseHandle( hDBusSharedMem ); 02746 02747 hDBusSharedMem = NULL; 02748 02749 ReleaseMutex( hDBusDaemonMutex ); 02750 02751 CloseHandle( hDBusDaemonMutex ); 02752 02753 hDBusDaemonMutex = NULL; 02754 02755 _dbus_global_unlock( lock ); 02756 } 02757 02758 static dbus_bool_t 02759 _dbus_get_autolaunch_shm (DBusString *address, DBusString *shm_name) 02760 { 02761 HANDLE sharedMem; 02762 char *shared_addr; 02763 int i; 02764 02765 // read shm 02766 for(i=0;i<20;++i) { 02767 // we know that dbus-daemon is available, so we wait until shm is available 02768 sharedMem = OpenFileMappingA( FILE_MAP_READ, FALSE, _dbus_string_get_const_data(shm_name)); 02769 if( sharedMem == 0 ) 02770 Sleep( 100 ); 02771 if ( sharedMem != 0) 02772 break; 02773 } 02774 02775 if( sharedMem == 0 ) 02776 return FALSE; 02777 02778 shared_addr = MapViewOfFile( sharedMem, FILE_MAP_READ, 0, 0, 0 ); 02779 02780 if( !shared_addr ) 02781 return FALSE; 02782 02783 _dbus_string_init( address ); 02784 02785 _dbus_string_append( address, shared_addr ); 02786 02787 // cleanup 02788 UnmapViewOfFile( shared_addr ); 02789 02790 CloseHandle( sharedMem ); 02791 02792 return TRUE; 02793 } 02794 02795 static dbus_bool_t 02796 _dbus_daemon_already_runs (DBusString *address, DBusString *shm_name, const char *scope) 02797 { 02798 HANDLE lock; 02799 HANDLE daemon; 02800 DBusString mutex_name; 02801 dbus_bool_t bRet = TRUE; 02802 02803 if (!_dbus_get_mutex_name(&mutex_name,scope)) 02804 { 02805 _dbus_string_free( &mutex_name ); 02806 return FALSE; 02807 } 02808 02809 // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs 02810 lock = _dbus_global_lock( cUniqueDBusInitMutex ); 02811 02812 // do checks 02813 daemon = CreateMutexA( NULL, FALSE, _dbus_string_get_const_data(&mutex_name) ); 02814 if(WaitForSingleObject( daemon, 10 ) != WAIT_TIMEOUT) 02815 { 02816 ReleaseMutex (daemon); 02817 CloseHandle (daemon); 02818 02819 _dbus_global_unlock( lock ); 02820 _dbus_string_free( &mutex_name ); 02821 return FALSE; 02822 } 02823 02824 // read shm 02825 bRet = _dbus_get_autolaunch_shm( address, shm_name ); 02826 02827 // cleanup 02828 CloseHandle ( daemon ); 02829 02830 _dbus_global_unlock( lock ); 02831 _dbus_string_free( &mutex_name ); 02832 02833 return bRet; 02834 } 02835 02836 dbus_bool_t 02837 _dbus_get_autolaunch_address (const char *scope, DBusString *address, 02838 DBusError *error) 02839 { 02840 HANDLE mutex; 02841 STARTUPINFOA si; 02842 PROCESS_INFORMATION pi; 02843 dbus_bool_t retval = FALSE; 02844 LPSTR lpFile; 02845 char dbus_exe_path[MAX_PATH]; 02846 char dbus_args[MAX_PATH * 2]; 02847 const char * daemon_name = DBUS_DAEMON_NAME ".exe"; 02848 DBusString shm_name; 02849 02850 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02851 02852 if (!_dbus_get_shm_name(&shm_name,scope)) 02853 { 02854 dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not determine shm name"); 02855 return FALSE; 02856 } 02857 02858 mutex = _dbus_global_lock ( cDBusAutolaunchMutex ); 02859 02860 if (_dbus_daemon_already_runs(address,&shm_name,scope)) 02861 { 02862 _dbus_verbose( "found running dbus daemon at %s\n", 02863 _dbus_string_get_const_data (&shm_name) ); 02864 retval = TRUE; 02865 goto out; 02866 } 02867 02868 if (!SearchPathA(NULL, daemon_name, NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile)) 02869 { 02870 // Look in directory containing dbus shared library 02871 HMODULE hmod; 02872 char dbus_module_path[MAX_PATH]; 02873 DWORD rc; 02874 02875 _dbus_verbose( "did not found dbus daemon executable on default search path, " 02876 "trying path where dbus shared library is located"); 02877 02878 hmod = _dbus_win_get_dll_hmodule(); 02879 rc = GetModuleFileNameA(hmod, dbus_module_path, sizeof(dbus_module_path)); 02880 if (rc <= 0) 02881 { 02882 dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not retrieve dbus shared library file name"); 02883 retval = FALSE; 02884 goto out; 02885 } 02886 else 02887 { 02888 char *ext_idx = strrchr(dbus_module_path, '\\'); 02889 if (ext_idx) 02890 *ext_idx = '\0'; 02891 if (!SearchPathA(dbus_module_path, daemon_name, NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile)) 02892 { 02893 dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not find dbus-daemon executable"); 02894 retval = FALSE; 02895 printf ("please add the path to %s to your PATH environment variable\n", daemon_name); 02896 printf ("or start the daemon manually\n\n"); 02897 goto out; 02898 } 02899 _dbus_verbose( "found dbus daemon executable at %s",dbus_module_path); 02900 } 02901 } 02902 02903 02904 // Create process 02905 ZeroMemory( &si, sizeof(si) ); 02906 si.cb = sizeof(si); 02907 ZeroMemory( &pi, sizeof(pi) ); 02908 02909 _snprintf(dbus_args, sizeof(dbus_args) - 1, "\"%s\" %s", dbus_exe_path, " --session"); 02910 02911 // argv[i] = "--config-file=bus\\session.conf"; 02912 // printf("create process \"%s\" %s\n", dbus_exe_path, dbus_args); 02913 if(CreateProcessA(dbus_exe_path, dbus_args, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) 02914 { 02915 CloseHandle (pi.hThread); 02916 CloseHandle (pi.hProcess); 02917 retval = _dbus_get_autolaunch_shm( address, &shm_name ); 02918 if (retval == FALSE) 02919 dbus_set_error_const (error, DBUS_ERROR_FAILED, "Failed to get autolaunch address from launched dbus-daemon"); 02920 } 02921 else 02922 { 02923 dbus_set_error_const (error, DBUS_ERROR_FAILED, "Failed to launch dbus-daemon"); 02924 retval = FALSE; 02925 } 02926 02927 out: 02928 if (retval) 02929 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02930 else 02931 _DBUS_ASSERT_ERROR_IS_SET (error); 02932 02933 _dbus_global_unlock (mutex); 02934 02935 return retval; 02936 } 02937 02938 02945 dbus_bool_t 02946 _dbus_make_file_world_readable(const DBusString *filename, 02947 DBusError *error) 02948 { 02949 // TODO 02950 return TRUE; 02951 } 02952 02959 static const char * 02960 _dbus_windows_get_datadir (void) 02961 { 02962 return _dbus_replace_install_prefix(DBUS_DATADIR); 02963 } 02964 02965 #undef DBUS_DATADIR 02966 #define DBUS_DATADIR _dbus_windows_get_datadir () 02967 02968 02969 #define DBUS_STANDARD_SESSION_SERVICEDIR "/dbus-1/services" 02970 #define DBUS_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services" 02971 02988 dbus_bool_t 02989 _dbus_get_standard_session_servicedirs (DBusList **dirs) 02990 { 02991 const char *common_progs; 02992 DBusString servicedir_path; 02993 02994 if (!_dbus_string_init (&servicedir_path)) 02995 return FALSE; 02996 02997 #ifdef DBUS_WINCE 02998 { 02999 /* On Windows CE, we adjust datadir dynamically to installation location. */ 03000 const char *data_dir = _dbus_getenv ("DBUS_DATADIR"); 03001 03002 if (data_dir != NULL) 03003 { 03004 if (!_dbus_string_append (&servicedir_path, data_dir)) 03005 goto oom; 03006 03007 if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR)) 03008 goto oom; 03009 } 03010 } 03011 #else 03012 /* 03013 the code for accessing services requires absolute base pathes 03014 in case DBUS_DATADIR is relative make it absolute 03015 */ 03016 #ifdef DBUS_WIN 03017 { 03018 DBusString p; 03019 03020 _dbus_string_init_const (&p, DBUS_DATADIR); 03021 03022 if (!_dbus_path_is_absolute (&p)) 03023 { 03024 char install_root[1000]; 03025 if (_dbus_get_install_root (install_root, sizeof(install_root))) 03026 if (!_dbus_string_append (&servicedir_path, install_root)) 03027 goto oom; 03028 } 03029 } 03030 #endif 03031 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR)) 03032 goto oom; 03033 03034 if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR)) 03035 goto oom; 03036 #endif 03037 03038 common_progs = _dbus_getenv ("CommonProgramFiles"); 03039 03040 if (common_progs != NULL) 03041 { 03042 if (!_dbus_string_append (&servicedir_path, common_progs)) 03043 goto oom; 03044 03045 if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR)) 03046 goto oom; 03047 } 03048 03049 if (!_dbus_split_paths_and_append (&servicedir_path, 03050 DBUS_STANDARD_SESSION_SERVICEDIR, 03051 dirs)) 03052 goto oom; 03053 03054 _dbus_string_free (&servicedir_path); 03055 return TRUE; 03056 03057 oom: 03058 _dbus_string_free (&servicedir_path); 03059 return FALSE; 03060 } 03061 03080 dbus_bool_t 03081 _dbus_get_standard_system_servicedirs (DBusList **dirs) 03082 { 03083 *dirs = NULL; 03084 return TRUE; 03085 } 03086 03087 _DBUS_DEFINE_GLOBAL_LOCK (atomic); 03088 03096 dbus_int32_t 03097 _dbus_atomic_inc (DBusAtomic *atomic) 03098 { 03099 // +/- 1 is needed here! 03100 // no volatile argument with mingw 03101 return InterlockedIncrement (&atomic->value) - 1; 03102 } 03103 03111 dbus_int32_t 03112 _dbus_atomic_dec (DBusAtomic *atomic) 03113 { 03114 // +/- 1 is needed here! 03115 // no volatile argument with mingw 03116 return InterlockedDecrement (&atomic->value) + 1; 03117 } 03118 03126 dbus_int32_t 03127 _dbus_atomic_get (DBusAtomic *atomic) 03128 { 03129 /* this is what GLib does, hopefully it's right... */ 03130 MemoryBarrier (); 03131 return atomic->value; 03132 } 03133 03141 void 03142 _dbus_flush_caches (void) 03143 { 03144 } 03145 03152 dbus_bool_t 03153 _dbus_get_is_errno_eagain_or_ewouldblock (void) 03154 { 03155 return errno == WSAEWOULDBLOCK; 03156 } 03157 03165 dbus_bool_t 03166 _dbus_get_install_root(char *prefix, int len) 03167 { 03168 //To find the prefix, we cut the filename and also \bin\ if present 03169 DWORD pathLength; 03170 char *lastSlash; 03171 SetLastError( 0 ); 03172 pathLength = GetModuleFileNameA(_dbus_win_get_dll_hmodule(), prefix, len); 03173 if ( pathLength == 0 || GetLastError() != 0 ) { 03174 *prefix = '\0'; 03175 return FALSE; 03176 } 03177 lastSlash = _mbsrchr(prefix, '\\'); 03178 if (lastSlash == NULL) { 03179 *prefix = '\0'; 03180 return FALSE; 03181 } 03182 //cut off binary name 03183 lastSlash[1] = 0; 03184 03185 //cut possible "\\bin" 03186 03187 //this fails if we are in a double-byte system codepage and the 03188 //folder's name happens to end with the *bytes* 03189 //"\\bin"... (I.e. the second byte of some Han character and then 03190 //the Latin "bin", but that is not likely I think... 03191 if (lastSlash - prefix >= 4 && strnicmp(lastSlash - 4, "\\bin", 4) == 0) 03192 lastSlash[-3] = 0; 03193 else if (lastSlash - prefix >= 10 && strnicmp(lastSlash - 10, "\\bin\\debug", 10) == 0) 03194 lastSlash[-9] = 0; 03195 else if (lastSlash - prefix >= 12 && strnicmp(lastSlash - 12, "\\bin\\release", 12) == 0) 03196 lastSlash[-11] = 0; 03197 03198 return TRUE; 03199 } 03200 03214 dbus_bool_t 03215 _dbus_get_config_file_name(DBusString *config_file, char *s) 03216 { 03217 char path[MAX_PATH*2]; 03218 int path_size = sizeof(path); 03219 03220 if (!_dbus_get_install_root(path,path_size)) 03221 return FALSE; 03222 03223 if(strlen(s) + 4 + strlen(path) > sizeof(path)-2) 03224 return FALSE; 03225 strcat(path,"etc\\"); 03226 strcat(path,s); 03227 if (_dbus_file_exists(path)) 03228 { 03229 // find path from executable 03230 if (!_dbus_string_append (config_file, path)) 03231 return FALSE; 03232 } 03233 else 03234 { 03235 if (!_dbus_get_install_root(path,path_size)) 03236 return FALSE; 03237 if(strlen(s) + 11 + strlen(path) > sizeof(path)-2) 03238 return FALSE; 03239 strcat(path,"etc\\dbus-1\\"); 03240 strcat(path,s); 03241 03242 if (_dbus_file_exists(path)) 03243 { 03244 if (!_dbus_string_append (config_file, path)) 03245 return FALSE; 03246 } 03247 else 03248 { 03249 if (!_dbus_get_install_root(path,path_size)) 03250 return FALSE; 03251 if(strlen(s) + 4 + strlen(path) > sizeof(path)-2) 03252 return FALSE; 03253 strcat(path,"bus\\"); 03254 strcat(path,s); 03255 03256 if (_dbus_file_exists(path)) 03257 { 03258 if (!_dbus_string_append (config_file, path)) 03259 return FALSE; 03260 } 03261 } 03262 } 03263 return TRUE; 03264 } 03265 03274 dbus_bool_t 03275 _dbus_append_system_config_file (DBusString *str) 03276 { 03277 return _dbus_get_config_file_name(str, "system.conf"); 03278 } 03279 03286 dbus_bool_t 03287 _dbus_append_session_config_file (DBusString *str) 03288 { 03289 return _dbus_get_config_file_name(str, "session.conf"); 03290 } 03291 03292 /* See comment in dbus-sysdeps-unix.c */ 03293 dbus_bool_t 03294 _dbus_lookup_session_address (dbus_bool_t *supported, 03295 DBusString *address, 03296 DBusError *error) 03297 { 03298 /* Probably fill this in with something based on COM? */ 03299 *supported = FALSE; 03300 return TRUE; 03301 } 03302 03316 dbus_bool_t 03317 _dbus_append_keyring_directory_for_credentials (DBusString *directory, 03318 DBusCredentials *credentials) 03319 { 03320 DBusString homedir; 03321 DBusString dotdir; 03322 const char *homepath; 03323 const char *homedrive; 03324 03325 _dbus_assert (credentials != NULL); 03326 _dbus_assert (!_dbus_credentials_are_anonymous (credentials)); 03327 03328 if (!_dbus_string_init (&homedir)) 03329 return FALSE; 03330 03331 homedrive = _dbus_getenv("HOMEDRIVE"); 03332 if (homedrive != NULL && *homedrive != '\0') 03333 { 03334 _dbus_string_append(&homedir,homedrive); 03335 } 03336 03337 homepath = _dbus_getenv("HOMEPATH"); 03338 if (homepath != NULL && *homepath != '\0') 03339 { 03340 _dbus_string_append(&homedir,homepath); 03341 } 03342 03343 #ifdef DBUS_BUILD_TESTS 03344 { 03345 const char *override; 03346 03347 override = _dbus_getenv ("DBUS_TEST_HOMEDIR"); 03348 if (override != NULL && *override != '\0') 03349 { 03350 _dbus_string_set_length (&homedir, 0); 03351 if (!_dbus_string_append (&homedir, override)) 03352 goto failed; 03353 03354 _dbus_verbose ("Using fake homedir for testing: %s\n", 03355 _dbus_string_get_const_data (&homedir)); 03356 } 03357 else 03358 { 03359 static dbus_bool_t already_warned = FALSE; 03360 if (!already_warned) 03361 { 03362 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n"); 03363 already_warned = TRUE; 03364 } 03365 } 03366 } 03367 #endif 03368 03369 #ifdef DBUS_WINCE 03370 /* It's not possible to create a .something directory in Windows CE 03371 using the file explorer. */ 03372 #define KEYRING_DIR "dbus-keyrings" 03373 #else 03374 #define KEYRING_DIR ".dbus-keyrings" 03375 #endif 03376 03377 _dbus_string_init_const (&dotdir, KEYRING_DIR); 03378 if (!_dbus_concat_dir_and_file (&homedir, 03379 &dotdir)) 03380 goto failed; 03381 03382 if (!_dbus_string_copy (&homedir, 0, 03383 directory, _dbus_string_get_length (directory))) { 03384 goto failed; 03385 } 03386 03387 _dbus_string_free (&homedir); 03388 return TRUE; 03389 03390 failed: 03391 _dbus_string_free (&homedir); 03392 return FALSE; 03393 } 03394 03400 dbus_bool_t 03401 _dbus_file_exists (const char *file) 03402 { 03403 DWORD attributes = GetFileAttributesA (file); 03404 03405 if (attributes != INVALID_FILE_ATTRIBUTES && GetLastError() != ERROR_PATH_NOT_FOUND) 03406 return TRUE; 03407 else 03408 return FALSE; 03409 } 03410 03418 const char* 03419 _dbus_strerror (int error_number) 03420 { 03421 #ifdef DBUS_WINCE 03422 // TODO 03423 return "unknown"; 03424 #else 03425 const char *msg; 03426 03427 switch (error_number) 03428 { 03429 case WSAEINTR: 03430 return "Interrupted function call"; 03431 case WSAEACCES: 03432 return "Permission denied"; 03433 case WSAEFAULT: 03434 return "Bad address"; 03435 case WSAEINVAL: 03436 return "Invalid argument"; 03437 case WSAEMFILE: 03438 return "Too many open files"; 03439 case WSAEWOULDBLOCK: 03440 return "Resource temporarily unavailable"; 03441 case WSAEINPROGRESS: 03442 return "Operation now in progress"; 03443 case WSAEALREADY: 03444 return "Operation already in progress"; 03445 case WSAENOTSOCK: 03446 return "Socket operation on nonsocket"; 03447 case WSAEDESTADDRREQ: 03448 return "Destination address required"; 03449 case WSAEMSGSIZE: 03450 return "Message too long"; 03451 case WSAEPROTOTYPE: 03452 return "Protocol wrong type for socket"; 03453 case WSAENOPROTOOPT: 03454 return "Bad protocol option"; 03455 case WSAEPROTONOSUPPORT: 03456 return "Protocol not supported"; 03457 case WSAESOCKTNOSUPPORT: 03458 return "Socket type not supported"; 03459 case WSAEOPNOTSUPP: 03460 return "Operation not supported"; 03461 case WSAEPFNOSUPPORT: 03462 return "Protocol family not supported"; 03463 case WSAEAFNOSUPPORT: 03464 return "Address family not supported by protocol family"; 03465 case WSAEADDRINUSE: 03466 return "Address already in use"; 03467 case WSAEADDRNOTAVAIL: 03468 return "Cannot assign requested address"; 03469 case WSAENETDOWN: 03470 return "Network is down"; 03471 case WSAENETUNREACH: 03472 return "Network is unreachable"; 03473 case WSAENETRESET: 03474 return "Network dropped connection on reset"; 03475 case WSAECONNABORTED: 03476 return "Software caused connection abort"; 03477 case WSAECONNRESET: 03478 return "Connection reset by peer"; 03479 case WSAENOBUFS: 03480 return "No buffer space available"; 03481 case WSAEISCONN: 03482 return "Socket is already connected"; 03483 case WSAENOTCONN: 03484 return "Socket is not connected"; 03485 case WSAESHUTDOWN: 03486 return "Cannot send after socket shutdown"; 03487 case WSAETIMEDOUT: 03488 return "Connection timed out"; 03489 case WSAECONNREFUSED: 03490 return "Connection refused"; 03491 case WSAEHOSTDOWN: 03492 return "Host is down"; 03493 case WSAEHOSTUNREACH: 03494 return "No route to host"; 03495 case WSAEPROCLIM: 03496 return "Too many processes"; 03497 case WSAEDISCON: 03498 return "Graceful shutdown in progress"; 03499 case WSATYPE_NOT_FOUND: 03500 return "Class type not found"; 03501 case WSAHOST_NOT_FOUND: 03502 return "Host not found"; 03503 case WSATRY_AGAIN: 03504 return "Nonauthoritative host not found"; 03505 case WSANO_RECOVERY: 03506 return "This is a nonrecoverable error"; 03507 case WSANO_DATA: 03508 return "Valid name, no data record of requested type"; 03509 case WSA_INVALID_HANDLE: 03510 return "Specified event object handle is invalid"; 03511 case WSA_INVALID_PARAMETER: 03512 return "One or more parameters are invalid"; 03513 case WSA_IO_INCOMPLETE: 03514 return "Overlapped I/O event object not in signaled state"; 03515 case WSA_IO_PENDING: 03516 return "Overlapped operations will complete later"; 03517 case WSA_NOT_ENOUGH_MEMORY: 03518 return "Insufficient memory available"; 03519 case WSA_OPERATION_ABORTED: 03520 return "Overlapped operation aborted"; 03521 #ifdef WSAINVALIDPROCTABLE 03522 03523 case WSAINVALIDPROCTABLE: 03524 return "Invalid procedure table from service provider"; 03525 #endif 03526 #ifdef WSAINVALIDPROVIDER 03527 03528 case WSAINVALIDPROVIDER: 03529 return "Invalid service provider version number"; 03530 #endif 03531 #ifdef WSAPROVIDERFAILEDINIT 03532 03533 case WSAPROVIDERFAILEDINIT: 03534 return "Unable to initialize a service provider"; 03535 #endif 03536 03537 case WSASYSCALLFAILURE: 03538 return "System call failure"; 03539 } 03540 msg = strerror (error_number); 03541 if (msg == NULL) 03542 msg = "unknown"; 03543 03544 return msg; 03545 #endif //DBUS_WINCE 03546 } 03547 03555 void 03556 _dbus_win_set_error_from_win_error (DBusError *error, 03557 int code) 03558 { 03559 char *msg; 03560 03561 /* As we want the English message, use the A API */ 03562 FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER | 03563 FORMAT_MESSAGE_IGNORE_INSERTS | 03564 FORMAT_MESSAGE_FROM_SYSTEM, 03565 NULL, code, MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US), 03566 (LPSTR) &msg, 0, NULL); 03567 if (msg) 03568 { 03569 char *msg_copy; 03570 03571 msg_copy = dbus_malloc (strlen (msg)); 03572 strcpy (msg_copy, msg); 03573 LocalFree (msg); 03574 03575 dbus_set_error (error, "win32.error", "%s", msg_copy); 03576 } 03577 else 03578 dbus_set_error (error, "win32.error", "Unknown error code %d or FormatMessage failed", code); 03579 } 03580 03581 void 03582 _dbus_win_warn_win_error (const char *message, 03583 int code) 03584 { 03585 DBusError error; 03586 03587 dbus_error_init (&error); 03588 _dbus_win_set_error_from_win_error (&error, code); 03589 _dbus_warn ("%s: %s\n", message, error.message); 03590 dbus_error_free (&error); 03591 } 03592 03600 dbus_bool_t 03601 _dbus_delete_directory (const DBusString *filename, 03602 DBusError *error) 03603 { 03604 const char *filename_c; 03605 03606 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03607 03608 filename_c = _dbus_string_get_const_data (filename); 03609 03610 if (RemoveDirectoryA (filename_c) == 0) 03611 { 03612 char *emsg = _dbus_win_error_string (GetLastError ()); 03613 dbus_set_error (error, _dbus_win_error_from_last_error (), 03614 "Failed to remove directory %s: %s", 03615 filename_c, emsg); 03616 _dbus_win_free_error_string (emsg); 03617 return FALSE; 03618 } 03619 03620 return TRUE; 03621 } 03622 03629 dbus_bool_t 03630 _dbus_path_is_absolute (const DBusString *filename) 03631 { 03632 if (_dbus_string_get_length (filename) > 0) 03633 return _dbus_string_get_byte (filename, 1) == ':' 03634 || _dbus_string_get_byte (filename, 0) == '\\' 03635 || _dbus_string_get_byte (filename, 0) == '/'; 03636 else 03637 return FALSE; 03638 } 03639 03640 dbus_bool_t 03641 _dbus_check_setuid (void) 03642 { 03643 return FALSE; 03644 } 03645 03647 /* tests in dbus-sysdeps-util.c */ 03648