D-Bus 1.4.20
|
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 00542 bufsize = sizeof (buf); 00543 len = _vsnprintf (buf, bufsize - 1, format, args); 00544 00545 while (len == -1) /* try again */ 00546 { 00547 char *p; 00548 00549 bufsize *= 2; 00550 00551 p = malloc (bufsize); 00552 00553 if (p == NULL) 00554 return -1; 00555 00556 len = _vsnprintf (p, bufsize - 1, format, args); 00557 free (p); 00558 } 00559 00560 return len; 00561 } 00562 00563 00571 wchar_t * 00572 _dbus_win_utf8_to_utf16 (const char *str, 00573 DBusError *error) 00574 { 00575 DBusString s; 00576 int n; 00577 wchar_t *retval; 00578 00579 _dbus_string_init_const (&s, str); 00580 00581 if (!_dbus_string_validate_utf8 (&s, 0, _dbus_string_get_length (&s))) 00582 { 00583 dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid UTF-8"); 00584 return NULL; 00585 } 00586 00587 n = MultiByteToWideChar (CP_UTF8, 0, str, -1, NULL, 0); 00588 00589 if (n == 0) 00590 { 00591 _dbus_win_set_error_from_win_error (error, GetLastError ()); 00592 return NULL; 00593 } 00594 00595 retval = dbus_new (wchar_t, n); 00596 00597 if (!retval) 00598 { 00599 _DBUS_SET_OOM (error); 00600 return NULL; 00601 } 00602 00603 if (MultiByteToWideChar (CP_UTF8, 0, str, -1, retval, n) != n) 00604 { 00605 dbus_free (retval); 00606 dbus_set_error_const (error, DBUS_ERROR_FAILED, "MultiByteToWideChar inconsistency"); 00607 return NULL; 00608 } 00609 00610 return retval; 00611 } 00612 00620 char * 00621 _dbus_win_utf16_to_utf8 (const wchar_t *str, 00622 DBusError *error) 00623 { 00624 int n; 00625 char *retval; 00626 00627 n = WideCharToMultiByte (CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL); 00628 00629 if (n == 0) 00630 { 00631 _dbus_win_set_error_from_win_error (error, GetLastError ()); 00632 return NULL; 00633 } 00634 00635 retval = dbus_malloc (n); 00636 00637 if (!retval) 00638 { 00639 _DBUS_SET_OOM (error); 00640 return NULL; 00641 } 00642 00643 if (WideCharToMultiByte (CP_UTF8, 0, str, -1, retval, n, NULL, NULL) != n) 00644 { 00645 dbus_free (retval); 00646 dbus_set_error_const (error, DBUS_ERROR_FAILED, "WideCharToMultiByte inconsistency"); 00647 return NULL; 00648 } 00649 00650 return retval; 00651 } 00652 00653 00654 00655 00656 00657 00658 /************************************************************************ 00659 00660 00661 ************************************************************************/ 00662 00663 dbus_bool_t 00664 _dbus_win_account_to_sid (const wchar_t *waccount, 00665 void **ppsid, 00666 DBusError *error) 00667 { 00668 dbus_bool_t retval = FALSE; 00669 DWORD sid_length, wdomain_length; 00670 SID_NAME_USE use; 00671 wchar_t *wdomain; 00672 00673 *ppsid = NULL; 00674 00675 sid_length = 0; 00676 wdomain_length = 0; 00677 if (!LookupAccountNameW (NULL, waccount, NULL, &sid_length, 00678 NULL, &wdomain_length, &use) && 00679 GetLastError () != ERROR_INSUFFICIENT_BUFFER) 00680 { 00681 _dbus_win_set_error_from_win_error (error, GetLastError ()); 00682 return FALSE; 00683 } 00684 00685 *ppsid = dbus_malloc (sid_length); 00686 if (!*ppsid) 00687 { 00688 _DBUS_SET_OOM (error); 00689 return FALSE; 00690 } 00691 00692 wdomain = dbus_new (wchar_t, wdomain_length); 00693 if (!wdomain) 00694 { 00695 _DBUS_SET_OOM (error); 00696 goto out1; 00697 } 00698 00699 if (!LookupAccountNameW (NULL, waccount, (PSID) *ppsid, &sid_length, 00700 wdomain, &wdomain_length, &use)) 00701 { 00702 _dbus_win_set_error_from_win_error (error, GetLastError ()); 00703 goto out2; 00704 } 00705 00706 if (!IsValidSid ((PSID) *ppsid)) 00707 { 00708 dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid SID"); 00709 goto out2; 00710 } 00711 00712 retval = TRUE; 00713 00714 out2: 00715 dbus_free (wdomain); 00716 out1: 00717 if (!retval) 00718 { 00719 dbus_free (*ppsid); 00720 *ppsid = NULL; 00721 } 00722 00723 return retval; 00724 } 00725 00735 unsigned long 00736 _dbus_pid_for_log (void) 00737 { 00738 return _dbus_getpid (); 00739 } 00740 00741 00742 #ifndef DBUS_WINCE 00743 00747 static dbus_bool_t 00748 _dbus_getsid(char **sid) 00749 { 00750 HANDLE process_token = INVALID_HANDLE_VALUE; 00751 TOKEN_USER *token_user = NULL; 00752 DWORD n; 00753 PSID psid; 00754 int retval = FALSE; 00755 00756 if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &process_token)) 00757 { 00758 _dbus_win_warn_win_error ("OpenProcessToken failed", GetLastError ()); 00759 goto failed; 00760 } 00761 if ((!GetTokenInformation (process_token, TokenUser, NULL, 0, &n) 00762 && GetLastError () != ERROR_INSUFFICIENT_BUFFER) 00763 || (token_user = alloca (n)) == NULL 00764 || !GetTokenInformation (process_token, TokenUser, token_user, n, &n)) 00765 { 00766 _dbus_win_warn_win_error ("GetTokenInformation failed", GetLastError ()); 00767 goto failed; 00768 } 00769 psid = token_user->User.Sid; 00770 if (!IsValidSid (psid)) 00771 { 00772 _dbus_verbose("%s invalid sid\n",__FUNCTION__); 00773 goto failed; 00774 } 00775 if (!ConvertSidToStringSidA (psid, sid)) 00776 { 00777 _dbus_verbose("%s invalid sid\n",__FUNCTION__); 00778 goto failed; 00779 } 00780 //okay: 00781 retval = TRUE; 00782 00783 failed: 00784 if (process_token != INVALID_HANDLE_VALUE) 00785 CloseHandle (process_token); 00786 00787 _dbus_verbose("_dbus_getsid() returns %d\n",retval); 00788 return retval; 00789 } 00790 #endif 00791 00792 /************************************************************************ 00793 00794 pipes 00795 00796 ************************************************************************/ 00797 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 fd_set read_set, write_set; 00824 struct timeval tv; 00825 int res; 00826 00827 _dbus_win_startup_winsock (); 00828 00829 temp = socket (AF_INET, SOCK_STREAM, 0); 00830 if (temp == INVALID_SOCKET) 00831 { 00832 DBUS_SOCKET_SET_ERRNO (); 00833 goto out0; 00834 } 00835 00836 _DBUS_ZERO (saddr); 00837 saddr.sin_family = AF_INET; 00838 saddr.sin_port = 0; 00839 saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); 00840 00841 if (bind (temp, (struct sockaddr *)&saddr, sizeof (saddr)) == SOCKET_ERROR) 00842 { 00843 DBUS_SOCKET_SET_ERRNO (); 00844 goto out0; 00845 } 00846 00847 if (listen (temp, 1) == SOCKET_ERROR) 00848 { 00849 DBUS_SOCKET_SET_ERRNO (); 00850 goto out0; 00851 } 00852 00853 len = sizeof (saddr); 00854 if (getsockname (temp, (struct sockaddr *)&saddr, &len) == SOCKET_ERROR) 00855 { 00856 DBUS_SOCKET_SET_ERRNO (); 00857 goto out0; 00858 } 00859 00860 socket1 = socket (AF_INET, SOCK_STREAM, 0); 00861 if (socket1 == INVALID_SOCKET) 00862 { 00863 DBUS_SOCKET_SET_ERRNO (); 00864 goto out0; 00865 } 00866 00867 if (connect (socket1, (struct sockaddr *)&saddr, len) == SOCKET_ERROR) 00868 { 00869 DBUS_SOCKET_SET_ERRNO (); 00870 goto out1; 00871 } 00872 00873 socket2 = accept (temp, (struct sockaddr *) &saddr, &len); 00874 if (socket2 == INVALID_SOCKET) 00875 { 00876 DBUS_SOCKET_SET_ERRNO (); 00877 goto out1; 00878 } 00879 00880 if (!blocking) 00881 { 00882 arg = 1; 00883 if (ioctlsocket (socket1, FIONBIO, &arg) == SOCKET_ERROR) 00884 { 00885 DBUS_SOCKET_SET_ERRNO (); 00886 goto out2; 00887 } 00888 00889 arg = 1; 00890 if (ioctlsocket (socket2, FIONBIO, &arg) == SOCKET_ERROR) 00891 { 00892 DBUS_SOCKET_SET_ERRNO (); 00893 goto out2; 00894 } 00895 } 00896 00897 *fd1 = socket1; 00898 *fd2 = socket2; 00899 00900 _dbus_verbose ("full-duplex pipe %d:%d <-> %d:%d\n", 00901 *fd1, socket1, *fd2, socket2); 00902 00903 closesocket (temp); 00904 00905 return TRUE; 00906 00907 out2: 00908 closesocket (socket2); 00909 out1: 00910 closesocket (socket1); 00911 out0: 00912 closesocket (temp); 00913 00914 dbus_set_error (error, _dbus_error_from_errno (errno), 00915 "Could not setup socket pair: %s", 00916 _dbus_strerror_from_errno ()); 00917 00918 return FALSE; 00919 } 00920 00929 int 00930 _dbus_poll (DBusPollFD *fds, 00931 int n_fds, 00932 int timeout_milliseconds) 00933 { 00934 #define USE_CHRIS_IMPL 0 00935 00936 #if USE_CHRIS_IMPL 00937 00938 #define DBUS_POLL_CHAR_BUFFER_SIZE 2000 00939 char msg[DBUS_POLL_CHAR_BUFFER_SIZE]; 00940 char *msgp; 00941 00942 int ret = 0; 00943 int i; 00944 struct timeval tv; 00945 int ready; 00946 00947 #define DBUS_STACK_WSAEVENTS 256 00948 WSAEVENT eventsOnStack[DBUS_STACK_WSAEVENTS]; 00949 WSAEVENT *pEvents = NULL; 00950 if (n_fds > DBUS_STACK_WSAEVENTS) 00951 pEvents = calloc(sizeof(WSAEVENT), n_fds); 00952 else 00953 pEvents = eventsOnStack; 00954 00955 00956 #ifdef DBUS_ENABLE_VERBOSE_MODE 00957 msgp = msg; 00958 msgp += sprintf (msgp, "WSAEventSelect: to=%d\n\t", timeout_milliseconds); 00959 for (i = 0; i < n_fds; i++) 00960 { 00961 static dbus_bool_t warned = FALSE; 00962 DBusPollFD *fdp = &fds[i]; 00963 00964 00965 if (fdp->events & _DBUS_POLLIN) 00966 msgp += sprintf (msgp, "R:%d ", fdp->fd); 00967 00968 if (fdp->events & _DBUS_POLLOUT) 00969 msgp += sprintf (msgp, "W:%d ", fdp->fd); 00970 00971 msgp += sprintf (msgp, "E:%d\n\t", fdp->fd); 00972 00973 // FIXME: more robust code for long msg 00974 // create on heap when msg[] becomes too small 00975 if (msgp >= msg + DBUS_POLL_CHAR_BUFFER_SIZE) 00976 { 00977 _dbus_assert_not_reached ("buffer overflow in _dbus_poll"); 00978 } 00979 } 00980 00981 msgp += sprintf (msgp, "\n"); 00982 _dbus_verbose ("%s",msg); 00983 #endif 00984 for (i = 0; i < n_fds; i++) 00985 { 00986 DBusPollFD *fdp = &fds[i]; 00987 WSAEVENT ev; 00988 long lNetworkEvents = FD_OOB; 00989 00990 ev = WSACreateEvent(); 00991 00992 if (fdp->events & _DBUS_POLLIN) 00993 lNetworkEvents |= FD_READ | FD_ACCEPT | FD_CLOSE; 00994 00995 if (fdp->events & _DBUS_POLLOUT) 00996 lNetworkEvents |= FD_WRITE | FD_CONNECT; 00997 00998 WSAEventSelect(fdp->fd, ev, lNetworkEvents); 00999 01000 pEvents[i] = ev; 01001 } 01002 01003 01004 ready = WSAWaitForMultipleEvents (n_fds, pEvents, FALSE, timeout_milliseconds, FALSE); 01005 01006 if (DBUS_SOCKET_API_RETURNS_ERROR (ready)) 01007 { 01008 DBUS_SOCKET_SET_ERRNO (); 01009 if (errno != WSAEWOULDBLOCK) 01010 _dbus_verbose ("WSAWaitForMultipleEvents: failed: %s\n", _dbus_strerror_from_errno ()); 01011 ret = -1; 01012 } 01013 else if (ready == WSA_WAIT_TIMEOUT) 01014 { 01015 _dbus_verbose ("WSAWaitForMultipleEvents: WSA_WAIT_TIMEOUT\n"); 01016 ret = 0; 01017 } 01018 else if (ready >= WSA_WAIT_EVENT_0 && ready < (int)(WSA_WAIT_EVENT_0 + n_fds)) 01019 { 01020 msgp = msg; 01021 msgp += sprintf (msgp, "WSAWaitForMultipleEvents: =%d\n\t", ready); 01022 01023 for (i = 0; i < n_fds; i++) 01024 { 01025 DBusPollFD *fdp = &fds[i]; 01026 WSANETWORKEVENTS ne; 01027 01028 fdp->revents = 0; 01029 01030 WSAEnumNetworkEvents(fdp->fd, pEvents[i], &ne); 01031 01032 if (ne.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) 01033 fdp->revents |= _DBUS_POLLIN; 01034 01035 if (ne.lNetworkEvents & (FD_WRITE | FD_CONNECT)) 01036 fdp->revents |= _DBUS_POLLOUT; 01037 01038 if (ne.lNetworkEvents & (FD_OOB)) 01039 fdp->revents |= _DBUS_POLLERR; 01040 01041 if (ne.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) 01042 msgp += sprintf (msgp, "R:%d ", fdp->fd); 01043 01044 if (ne.lNetworkEvents & (FD_WRITE | FD_CONNECT)) 01045 msgp += sprintf (msgp, "W:%d ", fdp->fd); 01046 01047 if (ne.lNetworkEvents & (FD_OOB)) 01048 msgp += sprintf (msgp, "E:%d ", fdp->fd); 01049 01050 msgp += sprintf (msgp, "lNetworkEvents:%d ", ne.lNetworkEvents); 01051 01052 if(ne.lNetworkEvents) 01053 ret++; 01054 01055 WSAEventSelect(fdp->fd, pEvents[i], 0); 01056 } 01057 01058 msgp += sprintf (msgp, "\n"); 01059 _dbus_verbose ("%s",msg); 01060 } 01061 else 01062 { 01063 _dbus_verbose ("WSAWaitForMultipleEvents: failed for unknown reason!"); 01064 ret = -1; 01065 } 01066 01067 for(i = 0; i < n_fds; i++) 01068 { 01069 WSACloseEvent(pEvents[i]); 01070 } 01071 01072 if (n_fds > DBUS_STACK_WSAEVENTS) 01073 free(pEvents); 01074 01075 return ret; 01076 01077 #else /* USE_CHRIS_IMPL */ 01078 01079 #define DBUS_POLL_CHAR_BUFFER_SIZE 2000 01080 char msg[DBUS_POLL_CHAR_BUFFER_SIZE]; 01081 char *msgp; 01082 01083 fd_set read_set, write_set, err_set; 01084 int max_fd = 0; 01085 int i; 01086 struct timeval tv; 01087 int ready; 01088 01089 FD_ZERO (&read_set); 01090 FD_ZERO (&write_set); 01091 FD_ZERO (&err_set); 01092 01093 01094 #ifdef DBUS_ENABLE_VERBOSE_MODE 01095 msgp = msg; 01096 msgp += sprintf (msgp, "select: to=%d\n\t", timeout_milliseconds); 01097 for (i = 0; i < n_fds; i++) 01098 { 01099 static dbus_bool_t warned = FALSE; 01100 DBusPollFD *fdp = &fds[i]; 01101 01102 01103 if (fdp->events & _DBUS_POLLIN) 01104 msgp += sprintf (msgp, "R:%d ", fdp->fd); 01105 01106 if (fdp->events & _DBUS_POLLOUT) 01107 msgp += sprintf (msgp, "W:%d ", fdp->fd); 01108 01109 msgp += sprintf (msgp, "E:%d\n\t", fdp->fd); 01110 01111 // FIXME: more robust code for long msg 01112 // create on heap when msg[] becomes too small 01113 if (msgp >= msg + DBUS_POLL_CHAR_BUFFER_SIZE) 01114 { 01115 _dbus_assert_not_reached ("buffer overflow in _dbus_poll"); 01116 } 01117 } 01118 01119 msgp += sprintf (msgp, "\n"); 01120 _dbus_verbose ("%s",msg); 01121 #endif 01122 for (i = 0; i < n_fds; i++) 01123 { 01124 DBusPollFD *fdp = &fds[i]; 01125 01126 if (fdp->events & _DBUS_POLLIN) 01127 FD_SET (fdp->fd, &read_set); 01128 01129 if (fdp->events & _DBUS_POLLOUT) 01130 FD_SET (fdp->fd, &write_set); 01131 01132 FD_SET (fdp->fd, &err_set); 01133 01134 max_fd = MAX (max_fd, fdp->fd); 01135 } 01136 01137 // Avoid random lockups with send(), for lack of a better solution so far 01138 tv.tv_sec = timeout_milliseconds < 0 ? 1 : timeout_milliseconds / 1000; 01139 tv.tv_usec = timeout_milliseconds < 0 ? 0 : (timeout_milliseconds % 1000) * 1000; 01140 01141 ready = select (max_fd + 1, &read_set, &write_set, &err_set, &tv); 01142 01143 if (DBUS_SOCKET_API_RETURNS_ERROR (ready)) 01144 { 01145 DBUS_SOCKET_SET_ERRNO (); 01146 if (errno != WSAEWOULDBLOCK) 01147 _dbus_verbose ("select: failed: %s\n", _dbus_strerror_from_errno ()); 01148 } 01149 else if (ready == 0) 01150 _dbus_verbose ("select: = 0\n"); 01151 else 01152 if (ready > 0) 01153 { 01154 #ifdef DBUS_ENABLE_VERBOSE_MODE 01155 msgp = msg; 01156 msgp += sprintf (msgp, "select: = %d:\n\t", ready); 01157 01158 for (i = 0; i < n_fds; i++) 01159 { 01160 DBusPollFD *fdp = &fds[i]; 01161 01162 if (FD_ISSET (fdp->fd, &read_set)) 01163 msgp += sprintf (msgp, "R:%d ", fdp->fd); 01164 01165 if (FD_ISSET (fdp->fd, &write_set)) 01166 msgp += sprintf (msgp, "W:%d ", fdp->fd); 01167 01168 if (FD_ISSET (fdp->fd, &err_set)) 01169 msgp += sprintf (msgp, "E:%d\n\t", fdp->fd); 01170 } 01171 msgp += sprintf (msgp, "\n"); 01172 _dbus_verbose ("%s",msg); 01173 #endif 01174 01175 for (i = 0; i < n_fds; i++) 01176 { 01177 DBusPollFD *fdp = &fds[i]; 01178 01179 fdp->revents = 0; 01180 01181 if (FD_ISSET (fdp->fd, &read_set)) 01182 fdp->revents |= _DBUS_POLLIN; 01183 01184 if (FD_ISSET (fdp->fd, &write_set)) 01185 fdp->revents |= _DBUS_POLLOUT; 01186 01187 if (FD_ISSET (fdp->fd, &err_set)) 01188 fdp->revents |= _DBUS_POLLERR; 01189 } 01190 } 01191 return ready; 01192 #endif /* USE_CHRIS_IMPL */ 01193 } 01194 01195 01196 01197 01198 /****************************************************************************** 01199 01200 Original CVS version of dbus-sysdeps.c 01201 01202 ******************************************************************************/ 01203 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 01204 /* dbus-sysdeps.c Wrappers around system/libc features (internal to D-Bus implementation) 01205 * 01206 * Copyright (C) 2002, 2003 Red Hat, Inc. 01207 * Copyright (C) 2003 CodeFactory AB 01208 * Copyright (C) 2005 Novell, Inc. 01209 * 01210 * Licensed under the Academic Free License version 2.1 01211 * 01212 * This program is free software; you can redistribute it and/or modify 01213 * it under the terms of the GNU General Public License as published by 01214 * the Free Software Foundation; either version 2 of the License, or 01215 * (at your option) any later version. 01216 * 01217 * This program is distributed in the hope that it will be useful, 01218 * but WITHOUT ANY WARRANTY; without even the implied warranty of 01219 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 01220 * GNU General Public License for more details. 01221 * 01222 * You should have received a copy of the GNU General Public License 01223 * along with this program; if not, write to the Free Software 01224 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 01225 * 01226 */ 01227 01228 01234 void 01235 _dbus_exit (int code) 01236 { 01237 _exit (code); 01238 } 01239 01251 int 01252 _dbus_connect_tcp_socket (const char *host, 01253 const char *port, 01254 const char *family, 01255 DBusError *error) 01256 { 01257 return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error); 01258 } 01259 01260 int 01261 _dbus_connect_tcp_socket_with_nonce (const char *host, 01262 const char *port, 01263 const char *family, 01264 const char *noncefile, 01265 DBusError *error) 01266 { 01267 int fd = -1, res; 01268 struct addrinfo hints; 01269 struct addrinfo *ai, *tmp; 01270 01271 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01272 01273 _dbus_win_startup_winsock (); 01274 01275 _DBUS_ZERO (hints); 01276 01277 if (!family) 01278 hints.ai_family = AF_UNSPEC; 01279 else if (!strcmp(family, "ipv4")) 01280 hints.ai_family = AF_INET; 01281 else if (!strcmp(family, "ipv6")) 01282 hints.ai_family = AF_INET6; 01283 else 01284 { 01285 dbus_set_error (error, 01286 DBUS_ERROR_INVALID_ARGS, 01287 "Unknown address family %s", family); 01288 return -1; 01289 } 01290 hints.ai_protocol = IPPROTO_TCP; 01291 hints.ai_socktype = SOCK_STREAM; 01292 #ifdef AI_ADDRCONFIG 01293 hints.ai_flags = AI_ADDRCONFIG; 01294 #else 01295 hints.ai_flags = 0; 01296 #endif 01297 01298 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai) 01299 { 01300 dbus_set_error (error, 01301 _dbus_error_from_errno (res), 01302 "Failed to lookup host/port: \"%s:%s\": %s (%d)", 01303 host, port, _dbus_strerror(res), res); 01304 return -1; 01305 } 01306 01307 tmp = ai; 01308 while (tmp) 01309 { 01310 if ((fd = socket (tmp->ai_family, SOCK_STREAM, 0)) == INVALID_SOCKET) 01311 { 01312 DBUS_SOCKET_SET_ERRNO (); 01313 dbus_set_error (error, 01314 _dbus_error_from_errno (errno), 01315 "Failed to open socket: %s", 01316 _dbus_strerror_from_errno ()); 01317 freeaddrinfo(ai); 01318 return -1; 01319 } 01320 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01321 01322 if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) == SOCKET_ERROR) 01323 { 01324 DBUS_SOCKET_SET_ERRNO (); 01325 closesocket(fd); 01326 fd = -1; 01327 tmp = tmp->ai_next; 01328 continue; 01329 } 01330 01331 break; 01332 } 01333 freeaddrinfo(ai); 01334 01335 if (fd == -1) 01336 { 01337 dbus_set_error (error, 01338 _dbus_error_from_errno (errno), 01339 "Failed to connect to socket \"%s:%s\" %s", 01340 host, port, _dbus_strerror_from_errno ()); 01341 return -1; 01342 } 01343 01344 if (noncefile != NULL) 01345 { 01346 DBusString noncefileStr; 01347 dbus_bool_t ret; 01348 if (!_dbus_string_init (&noncefileStr) || 01349 !_dbus_string_append(&noncefileStr, noncefile)) 01350 { 01351 closesocket (fd); 01352 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01353 return -1; 01354 } 01355 01356 ret = _dbus_send_nonce (fd, &noncefileStr, error); 01357 01358 _dbus_string_free (&noncefileStr); 01359 01360 if (!ret) 01361 { 01362 closesocket (fd); 01363 return -1; 01364 } 01365 } 01366 01367 _dbus_fd_set_close_on_exec (fd); 01368 01369 if (!_dbus_set_fd_nonblocking (fd, error)) 01370 { 01371 closesocket (fd); 01372 return -1; 01373 } 01374 01375 return fd; 01376 } 01377 01393 int 01394 _dbus_listen_tcp_socket (const char *host, 01395 const char *port, 01396 const char *family, 01397 DBusString *retport, 01398 int **fds_p, 01399 DBusError *error) 01400 { 01401 int nlisten_fd = 0, *listen_fd = NULL, res, i, port_num = -1; 01402 struct addrinfo hints; 01403 struct addrinfo *ai, *tmp; 01404 01405 // On Vista, sockaddr_gen must be a sockaddr_in6, and not a sockaddr_in6_old 01406 //That's required for family == IPv6(which is the default on Vista if family is not given) 01407 //So we use our own union instead of sockaddr_gen: 01408 01409 typedef union { 01410 struct sockaddr Address; 01411 struct sockaddr_in AddressIn; 01412 struct sockaddr_in6 AddressIn6; 01413 } mysockaddr_gen; 01414 01415 *fds_p = NULL; 01416 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01417 01418 _dbus_win_startup_winsock (); 01419 01420 _DBUS_ZERO (hints); 01421 01422 if (!family) 01423 hints.ai_family = AF_UNSPEC; 01424 else if (!strcmp(family, "ipv4")) 01425 hints.ai_family = AF_INET; 01426 else if (!strcmp(family, "ipv6")) 01427 hints.ai_family = AF_INET6; 01428 else 01429 { 01430 dbus_set_error (error, 01431 DBUS_ERROR_INVALID_ARGS, 01432 "Unknown address family %s", family); 01433 return -1; 01434 } 01435 01436 hints.ai_protocol = IPPROTO_TCP; 01437 hints.ai_socktype = SOCK_STREAM; 01438 #ifdef AI_ADDRCONFIG 01439 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE; 01440 #else 01441 hints.ai_flags = AI_PASSIVE; 01442 #endif 01443 01444 redo_lookup_with_port: 01445 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai) 01446 { 01447 dbus_set_error (error, 01448 _dbus_error_from_errno (res), 01449 "Failed to lookup host/port: \"%s:%s\": %s (%d)", 01450 host ? host : "*", port, _dbus_strerror(res), res); 01451 return -1; 01452 } 01453 01454 tmp = ai; 01455 while (tmp) 01456 { 01457 int fd = -1, *newlisten_fd; 01458 if ((fd = socket (tmp->ai_family, SOCK_STREAM, 0)) == INVALID_SOCKET) 01459 { 01460 DBUS_SOCKET_SET_ERRNO (); 01461 dbus_set_error (error, 01462 _dbus_error_from_errno (errno), 01463 "Failed to open socket: %s", 01464 _dbus_strerror_from_errno ()); 01465 goto failed; 01466 } 01467 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01468 01469 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) == SOCKET_ERROR) 01470 { 01471 DBUS_SOCKET_SET_ERRNO (); 01472 dbus_set_error (error, _dbus_error_from_errno (errno), 01473 "Failed to bind socket \"%s:%s\": %s", 01474 host ? host : "*", port, _dbus_strerror_from_errno ()); 01475 closesocket (fd); 01476 goto failed; 01477 } 01478 01479 if (listen (fd, 30 /* backlog */) == SOCKET_ERROR) 01480 { 01481 DBUS_SOCKET_SET_ERRNO (); 01482 dbus_set_error (error, _dbus_error_from_errno (errno), 01483 "Failed to listen on socket \"%s:%s\": %s", 01484 host ? host : "*", port, _dbus_strerror_from_errno ()); 01485 closesocket (fd); 01486 goto failed; 01487 } 01488 01489 newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1)); 01490 if (!newlisten_fd) 01491 { 01492 closesocket (fd); 01493 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, 01494 "Failed to allocate file handle array"); 01495 goto failed; 01496 } 01497 listen_fd = newlisten_fd; 01498 listen_fd[nlisten_fd] = fd; 01499 nlisten_fd++; 01500 01501 if (!_dbus_string_get_length(retport)) 01502 { 01503 /* If the user didn't specify a port, or used 0, then 01504 the kernel chooses a port. After the first address 01505 is bound to, we need to force all remaining addresses 01506 to use the same port */ 01507 if (!port || !strcmp(port, "0")) 01508 { 01509 mysockaddr_gen addr; 01510 socklen_t addrlen = sizeof(addr); 01511 char portbuf[10]; 01512 01513 if (getsockname(fd, &addr.Address, &addrlen) == SOCKET_ERROR) 01514 { 01515 DBUS_SOCKET_SET_ERRNO (); 01516 dbus_set_error (error, _dbus_error_from_errno (errno), 01517 "Failed to resolve port \"%s:%s\": %s", 01518 host ? host : "*", port, _dbus_strerror_from_errno()); 01519 goto failed; 01520 } 01521 snprintf( portbuf, sizeof( portbuf ) - 1, "%d", addr.AddressIn.sin_port ); 01522 if (!_dbus_string_append(retport, portbuf)) 01523 { 01524 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01525 goto failed; 01526 } 01527 01528 /* Release current address list & redo lookup */ 01529 port = _dbus_string_get_const_data(retport); 01530 freeaddrinfo(ai); 01531 goto redo_lookup_with_port; 01532 } 01533 else 01534 { 01535 if (!_dbus_string_append(retport, port)) 01536 { 01537 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01538 goto failed; 01539 } 01540 } 01541 } 01542 01543 tmp = tmp->ai_next; 01544 } 01545 freeaddrinfo(ai); 01546 ai = NULL; 01547 01548 if (!nlisten_fd) 01549 { 01550 _dbus_win_set_errno (WSAEADDRINUSE); 01551 dbus_set_error (error, _dbus_error_from_errno (errno), 01552 "Failed to bind socket \"%s:%s\": %s", 01553 host ? host : "*", port, _dbus_strerror_from_errno ()); 01554 return -1; 01555 } 01556 01557 sscanf(_dbus_string_get_const_data(retport), "%d", &port_num); 01558 01559 for (i = 0 ; i < nlisten_fd ; i++) 01560 { 01561 _dbus_fd_set_close_on_exec (listen_fd[i]); 01562 if (!_dbus_set_fd_nonblocking (listen_fd[i], error)) 01563 { 01564 goto failed; 01565 } 01566 } 01567 01568 *fds_p = listen_fd; 01569 01570 return nlisten_fd; 01571 01572 failed: 01573 if (ai) 01574 freeaddrinfo(ai); 01575 for (i = 0 ; i < nlisten_fd ; i++) 01576 closesocket (listen_fd[i]); 01577 dbus_free(listen_fd); 01578 return -1; 01579 } 01580 01581 01589 int 01590 _dbus_accept (int listen_fd) 01591 { 01592 int client_fd; 01593 01594 retry: 01595 client_fd = accept (listen_fd, NULL, NULL); 01596 01597 if (DBUS_SOCKET_IS_INVALID (client_fd)) 01598 { 01599 DBUS_SOCKET_SET_ERRNO (); 01600 if (errno == EINTR) 01601 goto retry; 01602 } 01603 01604 _dbus_verbose ("client fd %d accepted\n", client_fd); 01605 01606 return client_fd; 01607 } 01608 01609 01610 01611 01612 dbus_bool_t 01613 _dbus_send_credentials_socket (int handle, 01614 DBusError *error) 01615 { 01616 /* FIXME: for the session bus credentials shouldn't matter (?), but 01617 * for the system bus they are presumably essential. A rough outline 01618 * of a way to implement the credential transfer would be this: 01619 * 01620 * client waits to *read* a byte. 01621 * 01622 * server creates a named pipe with a random name, sends a byte 01623 * contining its length, and its name. 01624 * 01625 * client reads the name, connects to it (using Win32 API). 01626 * 01627 * server waits for connection to the named pipe, then calls 01628 * ImpersonateNamedPipeClient(), notes its now-current credentials, 01629 * calls RevertToSelf(), closes its handles to the named pipe, and 01630 * is done. (Maybe there is some other way to get the SID of a named 01631 * pipe client without having to use impersonation?) 01632 * 01633 * client closes its handles and is done. 01634 * 01635 * Ralf: Why not sending credentials over the given this connection ? 01636 * Using named pipes makes it impossible to be connected from a unix client. 01637 * 01638 */ 01639 int bytes_written; 01640 DBusString buf; 01641 01642 _dbus_string_init_const_len (&buf, "\0", 1); 01643 again: 01644 bytes_written = _dbus_write_socket (handle, &buf, 0, 1 ); 01645 01646 if (bytes_written < 0 && errno == EINTR) 01647 goto again; 01648 01649 if (bytes_written < 0) 01650 { 01651 dbus_set_error (error, _dbus_error_from_errno (errno), 01652 "Failed to write credentials byte: %s", 01653 _dbus_strerror_from_errno ()); 01654 return FALSE; 01655 } 01656 else if (bytes_written == 0) 01657 { 01658 dbus_set_error (error, DBUS_ERROR_IO_ERROR, 01659 "wrote zero bytes writing credentials byte"); 01660 return FALSE; 01661 } 01662 else 01663 { 01664 _dbus_assert (bytes_written == 1); 01665 _dbus_verbose ("wrote 1 zero byte, credential sending isn't implemented yet\n"); 01666 return TRUE; 01667 } 01668 return TRUE; 01669 } 01670 01689 dbus_bool_t 01690 _dbus_read_credentials_socket (int handle, 01691 DBusCredentials *credentials, 01692 DBusError *error) 01693 { 01694 int bytes_read = 0; 01695 DBusString buf; 01696 01697 // could fail due too OOM 01698 if (_dbus_string_init(&buf)) 01699 { 01700 bytes_read = _dbus_read_socket(handle, &buf, 1 ); 01701 01702 if (bytes_read > 0) 01703 _dbus_verbose("got one zero byte from server"); 01704 01705 _dbus_string_free(&buf); 01706 } 01707 01708 _dbus_credentials_add_from_current_process (credentials); 01709 _dbus_verbose("FIXME: get faked credentials from current process"); 01710 01711 return TRUE; 01712 } 01713 01722 dbus_bool_t 01723 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error) 01724 { 01725 /* TODO */ 01726 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01727 return TRUE; 01728 } 01729 01730 01741 dbus_bool_t 01742 _dbus_concat_dir_and_file (DBusString *dir, 01743 const DBusString *next_component) 01744 { 01745 dbus_bool_t dir_ends_in_slash; 01746 dbus_bool_t file_starts_with_slash; 01747 01748 if (_dbus_string_get_length (dir) == 0 || 01749 _dbus_string_get_length (next_component) == 0) 01750 return TRUE; 01751 01752 dir_ends_in_slash = 01753 ('/' == _dbus_string_get_byte (dir, _dbus_string_get_length (dir) - 1) || 01754 '\\' == _dbus_string_get_byte (dir, _dbus_string_get_length (dir) - 1)); 01755 01756 file_starts_with_slash = 01757 ('/' == _dbus_string_get_byte (next_component, 0) || 01758 '\\' == _dbus_string_get_byte (next_component, 0)); 01759 01760 if (dir_ends_in_slash && file_starts_with_slash) 01761 { 01762 _dbus_string_shorten (dir, 1); 01763 } 01764 else if (!(dir_ends_in_slash || file_starts_with_slash)) 01765 { 01766 if (!_dbus_string_append_byte (dir, '\\')) 01767 return FALSE; 01768 } 01769 01770 return _dbus_string_copy (next_component, 0, dir, 01771 _dbus_string_get_length (dir)); 01772 } 01773 01774 /*---------------- DBusCredentials ----------------------------------*/ 01775 01783 dbus_bool_t 01784 _dbus_credentials_add_from_user (DBusCredentials *credentials, 01785 const DBusString *username) 01786 { 01787 return _dbus_credentials_add_windows_sid (credentials, 01788 _dbus_string_get_const_data(username)); 01789 } 01790 01799 dbus_bool_t 01800 _dbus_credentials_add_from_current_process (DBusCredentials *credentials) 01801 { 01802 dbus_bool_t retval = FALSE; 01803 char *sid = NULL; 01804 01805 if (!_dbus_getsid(&sid)) 01806 goto failed; 01807 01808 if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid())) 01809 goto failed; 01810 01811 if (!_dbus_credentials_add_windows_sid (credentials,sid)) 01812 goto failed; 01813 01814 retval = TRUE; 01815 goto end; 01816 failed: 01817 retval = FALSE; 01818 end: 01819 if (sid) 01820 LocalFree(sid); 01821 01822 return retval; 01823 } 01824 01837 dbus_bool_t 01838 _dbus_append_user_from_current_process (DBusString *str) 01839 { 01840 dbus_bool_t retval = FALSE; 01841 char *sid = NULL; 01842 01843 if (!_dbus_getsid(&sid)) 01844 return FALSE; 01845 01846 retval = _dbus_string_append (str,sid); 01847 01848 LocalFree(sid); 01849 return retval; 01850 } 01851 01856 dbus_pid_t 01857 _dbus_getpid (void) 01858 { 01859 return GetCurrentProcessId (); 01860 } 01861 01863 #define NANOSECONDS_PER_SECOND 1000000000 01864 01865 #define MICROSECONDS_PER_SECOND 1000000 01866 01867 #define MILLISECONDS_PER_SECOND 1000 01868 01869 #define NANOSECONDS_PER_MILLISECOND 1000000 01870 01871 #define MICROSECONDS_PER_MILLISECOND 1000 01872 01877 void 01878 _dbus_sleep_milliseconds (int milliseconds) 01879 { 01880 Sleep (milliseconds); 01881 } 01882 01883 01890 void 01891 _dbus_get_current_time (long *tv_sec, 01892 long *tv_usec) 01893 { 01894 FILETIME ft; 01895 dbus_uint64_t time64; 01896 01897 GetSystemTimeAsFileTime (&ft); 01898 01899 memcpy (&time64, &ft, sizeof (time64)); 01900 01901 /* Convert from 100s of nanoseconds since 1601-01-01 01902 * to Unix epoch. Yes, this is Y2038 unsafe. 01903 */ 01904 time64 -= DBUS_INT64_CONSTANT (116444736000000000); 01905 time64 /= 10; 01906 01907 if (tv_sec) 01908 *tv_sec = time64 / 1000000; 01909 01910 if (tv_usec) 01911 *tv_usec = time64 % 1000000; 01912 } 01913 01914 01918 void 01919 _dbus_disable_sigpipe (void) 01920 { 01921 } 01922 01931 dbus_bool_t 01932 _dbus_create_directory (const DBusString *filename, 01933 DBusError *error) 01934 { 01935 const char *filename_c; 01936 01937 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01938 01939 filename_c = _dbus_string_get_const_data (filename); 01940 01941 if (!CreateDirectoryA (filename_c, NULL)) 01942 { 01943 if (GetLastError () == ERROR_ALREADY_EXISTS) 01944 return TRUE; 01945 01946 dbus_set_error (error, DBUS_ERROR_FAILED, 01947 "Failed to create directory %s: %s\n", 01948 filename_c, _dbus_strerror_from_errno ()); 01949 return FALSE; 01950 } 01951 else 01952 return TRUE; 01953 } 01954 01955 01964 dbus_bool_t 01965 _dbus_generate_random_bytes (DBusString *str, 01966 int n_bytes) 01967 { 01968 int old_len; 01969 char *p; 01970 HCRYPTPROV hprov; 01971 01972 old_len = _dbus_string_get_length (str); 01973 01974 if (!_dbus_string_lengthen (str, n_bytes)) 01975 return FALSE; 01976 01977 p = _dbus_string_get_data_len (str, old_len, n_bytes); 01978 01979 if (!CryptAcquireContext (&hprov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) 01980 return FALSE; 01981 01982 if (!CryptGenRandom (hprov, n_bytes, p)) 01983 { 01984 CryptReleaseContext (hprov, 0); 01985 return FALSE; 01986 } 01987 01988 CryptReleaseContext (hprov, 0); 01989 01990 return TRUE; 01991 } 01992 01999 const char* 02000 _dbus_get_tmpdir(void) 02001 { 02002 static const char* tmpdir = NULL; 02003 static char buf[1000]; 02004 02005 if (tmpdir == NULL) 02006 { 02007 char *last_slash; 02008 02009 if (!GetTempPathA (sizeof (buf), buf)) 02010 { 02011 _dbus_warn ("GetTempPath failed\n"); 02012 _dbus_abort (); 02013 } 02014 02015 /* Drop terminating backslash or slash */ 02016 last_slash = _mbsrchr (buf, '\\'); 02017 if (last_slash > buf && last_slash[1] == '\0') 02018 last_slash[0] = '\0'; 02019 last_slash = _mbsrchr (buf, '/'); 02020 if (last_slash > buf && last_slash[1] == '\0') 02021 last_slash[0] = '\0'; 02022 02023 tmpdir = buf; 02024 } 02025 02026 _dbus_assert(tmpdir != NULL); 02027 02028 return tmpdir; 02029 } 02030 02031 02040 dbus_bool_t 02041 _dbus_delete_file (const DBusString *filename, 02042 DBusError *error) 02043 { 02044 const char *filename_c; 02045 02046 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02047 02048 filename_c = _dbus_string_get_const_data (filename); 02049 02050 if (DeleteFileA (filename_c) == 0) 02051 { 02052 dbus_set_error (error, DBUS_ERROR_FAILED, 02053 "Failed to delete file %s: %s\n", 02054 filename_c, _dbus_strerror_from_errno ()); 02055 return FALSE; 02056 } 02057 else 02058 return TRUE; 02059 } 02060 02061 /* 02062 * replaces the term DBUS_PREFIX in configure_time_path by the 02063 * current dbus installation directory. On unix this function is a noop 02064 * 02065 * @param configure_time_path 02066 * @return real path 02067 */ 02068 const char * 02069 _dbus_replace_install_prefix (const char *configure_time_path) 02070 { 02071 #ifndef DBUS_PREFIX 02072 return configure_time_path; 02073 #else 02074 static char retval[1000]; 02075 static char runtime_prefix[1000]; 02076 int len = 1000; 02077 int i; 02078 02079 if (!configure_time_path) 02080 return NULL; 02081 02082 if ((!_dbus_get_install_root(runtime_prefix, len) || 02083 strncmp (configure_time_path, DBUS_PREFIX "/", 02084 strlen (DBUS_PREFIX) + 1))) { 02085 strcat (retval, configure_time_path); 02086 return retval; 02087 } 02088 02089 strcpy (retval, runtime_prefix); 02090 strcat (retval, configure_time_path + strlen (DBUS_PREFIX) + 1); 02091 02092 /* Somehow, in some situations, backslashes get collapsed in the string. 02093 * Since windows C library accepts both forward and backslashes as 02094 * path separators, convert all backslashes to forward slashes. 02095 */ 02096 02097 for(i = 0; retval[i] != '\0'; i++) { 02098 if(retval[i] == '\\') 02099 retval[i] = '/'; 02100 } 02101 return retval; 02102 #endif 02103 } 02104 02105 #if !defined (DBUS_DISABLE_ASSERTS) || defined(DBUS_BUILD_TESTS) 02106 02107 #if defined(_MSC_VER) || defined(DBUS_WINCE) 02108 # ifdef BACKTRACES 02109 # undef BACKTRACES 02110 # endif 02111 #else 02112 # define BACKTRACES 02113 #endif 02114 02115 #ifdef BACKTRACES 02116 /* 02117 * Backtrace Generator 02118 * 02119 * Copyright 2004 Eric Poech 02120 * Copyright 2004 Robert Shearman 02121 * 02122 * This library is free software; you can redistribute it and/or 02123 * modify it under the terms of the GNU Lesser General Public 02124 * License as published by the Free Software Foundation; either 02125 * version 2.1 of the License, or (at your option) any later version. 02126 * 02127 * This library is distributed in the hope that it will be useful, 02128 * but WITHOUT ANY WARRANTY; without even the implied warranty of 02129 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 02130 * Lesser General Public License for more details. 02131 * 02132 * You should have received a copy of the GNU Lesser General Public 02133 * License along with this library; if not, write to the Free Software 02134 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 02135 */ 02136 02137 #include <winver.h> 02138 #include <imagehlp.h> 02139 #include <stdio.h> 02140 02141 #define DPRINTF _dbus_warn 02142 02143 #ifdef _MSC_VER 02144 #define BOOL int 02145 02146 #define __i386__ 02147 #endif 02148 02149 //#define MAKE_FUNCPTR(f) static typeof(f) * p##f 02150 02151 //MAKE_FUNCPTR(StackWalk); 02152 //MAKE_FUNCPTR(SymGetModuleBase); 02153 //MAKE_FUNCPTR(SymFunctionTableAccess); 02154 //MAKE_FUNCPTR(SymInitialize); 02155 //MAKE_FUNCPTR(SymGetSymFromAddr); 02156 //MAKE_FUNCPTR(SymGetModuleInfo); 02157 static BOOL (WINAPI *pStackWalk)( 02158 DWORD MachineType, 02159 HANDLE hProcess, 02160 HANDLE hThread, 02161 LPSTACKFRAME StackFrame, 02162 PVOID ContextRecord, 02163 PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine, 02164 PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine, 02165 PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine, 02166 PTRANSLATE_ADDRESS_ROUTINE TranslateAddress 02167 ); 02168 #ifdef _WIN64 02169 static DWORD64 (WINAPI *pSymGetModuleBase)( 02170 HANDLE hProcess, 02171 DWORD64 dwAddr 02172 ); 02173 static PVOID (WINAPI *pSymFunctionTableAccess)( 02174 HANDLE hProcess, 02175 DWORD64 AddrBase 02176 ); 02177 #else 02178 static DWORD (WINAPI *pSymGetModuleBase)( 02179 HANDLE hProcess, 02180 DWORD dwAddr 02181 ); 02182 static PVOID (WINAPI *pSymFunctionTableAccess)( 02183 HANDLE hProcess, 02184 DWORD AddrBase 02185 ); 02186 #endif 02187 static BOOL (WINAPI *pSymInitialize)( 02188 HANDLE hProcess, 02189 PSTR UserSearchPath, 02190 BOOL fInvadeProcess 02191 ); 02192 static BOOL (WINAPI *pSymGetSymFromAddr)( 02193 HANDLE hProcess, 02194 DWORD Address, 02195 PDWORD Displacement, 02196 PIMAGEHLP_SYMBOL Symbol 02197 ); 02198 static BOOL (WINAPI *pSymGetModuleInfo)( 02199 HANDLE hProcess, 02200 DWORD dwAddr, 02201 PIMAGEHLP_MODULE ModuleInfo 02202 ); 02203 static DWORD (WINAPI *pSymSetOptions)( 02204 DWORD SymOptions 02205 ); 02206 02207 02208 static BOOL init_backtrace() 02209 { 02210 HMODULE hmodDbgHelp = LoadLibraryA("dbghelp"); 02211 /* 02212 #define GETFUNC(x) \ 02213 p##x = (typeof(x)*)GetProcAddress(hmodDbgHelp, #x); \ 02214 if (!p##x) \ 02215 { \ 02216 return FALSE; \ 02217 } 02218 */ 02219 02220 02221 // GETFUNC(StackWalk); 02222 // GETFUNC(SymGetModuleBase); 02223 // GETFUNC(SymFunctionTableAccess); 02224 // GETFUNC(SymInitialize); 02225 // GETFUNC(SymGetSymFromAddr); 02226 // GETFUNC(SymGetModuleInfo); 02227 02228 #define FUNC(x) #x 02229 02230 pStackWalk = (BOOL (WINAPI *)( 02231 DWORD MachineType, 02232 HANDLE hProcess, 02233 HANDLE hThread, 02234 LPSTACKFRAME StackFrame, 02235 PVOID ContextRecord, 02236 PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine, 02237 PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine, 02238 PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine, 02239 PTRANSLATE_ADDRESS_ROUTINE TranslateAddress 02240 ))GetProcAddress (hmodDbgHelp, FUNC(StackWalk)); 02241 #ifdef _WIN64 02242 pSymGetModuleBase=(DWORD64 (WINAPI *)( 02243 HANDLE hProcess, 02244 DWORD64 dwAddr 02245 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleBase)); 02246 pSymFunctionTableAccess=(PVOID (WINAPI *)( 02247 HANDLE hProcess, 02248 DWORD64 AddrBase 02249 ))GetProcAddress (hmodDbgHelp, FUNC(SymFunctionTableAccess)); 02250 #else 02251 pSymGetModuleBase=(DWORD (WINAPI *)( 02252 HANDLE hProcess, 02253 DWORD dwAddr 02254 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleBase)); 02255 pSymFunctionTableAccess=(PVOID (WINAPI *)( 02256 HANDLE hProcess, 02257 DWORD AddrBase 02258 ))GetProcAddress (hmodDbgHelp, FUNC(SymFunctionTableAccess)); 02259 #endif 02260 pSymInitialize = (BOOL (WINAPI *)( 02261 HANDLE hProcess, 02262 PSTR UserSearchPath, 02263 BOOL fInvadeProcess 02264 ))GetProcAddress (hmodDbgHelp, FUNC(SymInitialize)); 02265 pSymGetSymFromAddr = (BOOL (WINAPI *)( 02266 HANDLE hProcess, 02267 DWORD Address, 02268 PDWORD Displacement, 02269 PIMAGEHLP_SYMBOL Symbol 02270 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetSymFromAddr)); 02271 pSymGetModuleInfo = (BOOL (WINAPI *)( 02272 HANDLE hProcess, 02273 DWORD dwAddr, 02274 PIMAGEHLP_MODULE ModuleInfo 02275 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleInfo)); 02276 pSymSetOptions = (DWORD (WINAPI *)( 02277 DWORD SymOptions 02278 ))GetProcAddress (hmodDbgHelp, FUNC(SymSetOptions)); 02279 02280 02281 pSymSetOptions(SYMOPT_UNDNAME); 02282 02283 pSymInitialize(GetCurrentProcess(), NULL, TRUE); 02284 02285 return TRUE; 02286 } 02287 02288 static void dump_backtrace_for_thread(HANDLE hThread) 02289 { 02290 STACKFRAME sf; 02291 CONTEXT context; 02292 DWORD dwImageType; 02293 02294 if (!pStackWalk) 02295 if (!init_backtrace()) 02296 return; 02297 02298 /* can't use this function for current thread as GetThreadContext 02299 * doesn't support getting context from current thread */ 02300 if (hThread == GetCurrentThread()) 02301 return; 02302 02303 DPRINTF("Backtrace:\n"); 02304 02305 _DBUS_ZERO(context); 02306 context.ContextFlags = CONTEXT_FULL; 02307 02308 SuspendThread(hThread); 02309 02310 if (!GetThreadContext(hThread, &context)) 02311 { 02312 DPRINTF("Couldn't get thread context (error %ld)\n", GetLastError()); 02313 ResumeThread(hThread); 02314 return; 02315 } 02316 02317 _DBUS_ZERO(sf); 02318 02319 #ifdef __i386__ 02320 sf.AddrFrame.Offset = context.Ebp; 02321 sf.AddrFrame.Mode = AddrModeFlat; 02322 sf.AddrPC.Offset = context.Eip; 02323 sf.AddrPC.Mode = AddrModeFlat; 02324 dwImageType = IMAGE_FILE_MACHINE_I386; 02325 #elif _M_X64 02326 dwImageType = IMAGE_FILE_MACHINE_AMD64; 02327 sf.AddrPC.Offset = context.Rip; 02328 sf.AddrPC.Mode = AddrModeFlat; 02329 sf.AddrFrame.Offset = context.Rsp; 02330 sf.AddrFrame.Mode = AddrModeFlat; 02331 sf.AddrStack.Offset = context.Rsp; 02332 sf.AddrStack.Mode = AddrModeFlat; 02333 #elif _M_IA64 02334 dwImageType = IMAGE_FILE_MACHINE_IA64; 02335 sf.AddrPC.Offset = context.StIIP; 02336 sf.AddrPC.Mode = AddrModeFlat; 02337 sf.AddrFrame.Offset = context.IntSp; 02338 sf.AddrFrame.Mode = AddrModeFlat; 02339 sf.AddrBStore.Offset= context.RsBSP; 02340 sf.AddrBStore.Mode = AddrModeFlat; 02341 sf.AddrStack.Offset = context.IntSp; 02342 sf.AddrStack.Mode = AddrModeFlat; 02343 #else 02344 # error You need to fill in the STACKFRAME structure for your architecture 02345 #endif 02346 02347 while (pStackWalk(dwImageType, GetCurrentProcess(), 02348 hThread, &sf, &context, NULL, pSymFunctionTableAccess, 02349 pSymGetModuleBase, NULL)) 02350 { 02351 BYTE buffer[256]; 02352 IMAGEHLP_SYMBOL * pSymbol = (IMAGEHLP_SYMBOL *)buffer; 02353 DWORD dwDisplacement; 02354 02355 pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); 02356 pSymbol->MaxNameLength = sizeof(buffer) - sizeof(IMAGEHLP_SYMBOL) + 1; 02357 02358 if (!pSymGetSymFromAddr(GetCurrentProcess(), sf.AddrPC.Offset, 02359 &dwDisplacement, pSymbol)) 02360 { 02361 IMAGEHLP_MODULE ModuleInfo; 02362 ModuleInfo.SizeOfStruct = sizeof(ModuleInfo); 02363 02364 if (!pSymGetModuleInfo(GetCurrentProcess(), sf.AddrPC.Offset, 02365 &ModuleInfo)) 02366 DPRINTF("1\t%p\n", (void*)sf.AddrPC.Offset); 02367 else 02368 DPRINTF("2\t%s+0x%lx\n", ModuleInfo.ImageName, 02369 sf.AddrPC.Offset - ModuleInfo.BaseOfImage); 02370 } 02371 else if (dwDisplacement) 02372 DPRINTF("3\t%s+0x%lx\n", pSymbol->Name, dwDisplacement); 02373 else 02374 DPRINTF("4\t%s\n", pSymbol->Name); 02375 } 02376 02377 ResumeThread(hThread); 02378 } 02379 02380 static DWORD WINAPI dump_thread_proc(LPVOID lpParameter) 02381 { 02382 dump_backtrace_for_thread((HANDLE)lpParameter); 02383 return 0; 02384 } 02385 02386 /* cannot get valid context from current thread, so we have to execute 02387 * backtrace from another thread */ 02388 static void dump_backtrace() 02389 { 02390 HANDLE hCurrentThread; 02391 HANDLE hThread; 02392 DWORD dwThreadId; 02393 DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), 02394 GetCurrentProcess(), &hCurrentThread, 0, FALSE, DUPLICATE_SAME_ACCESS); 02395 hThread = CreateThread(NULL, 0, dump_thread_proc, (LPVOID)hCurrentThread, 02396 0, &dwThreadId); 02397 WaitForSingleObject(hThread, INFINITE); 02398 CloseHandle(hThread); 02399 CloseHandle(hCurrentThread); 02400 } 02401 #endif 02402 #endif /* asserts or tests enabled */ 02403 02404 #ifdef BACKTRACES 02405 void _dbus_print_backtrace(void) 02406 { 02407 init_backtrace(); 02408 dump_backtrace(); 02409 } 02410 #else 02411 void _dbus_print_backtrace(void) 02412 { 02413 _dbus_verbose (" D-Bus not compiled with backtrace support\n"); 02414 } 02415 #endif 02416 02417 static dbus_uint32_t fromAscii(char ascii) 02418 { 02419 if(ascii >= '0' && ascii <= '9') 02420 return ascii - '0'; 02421 if(ascii >= 'A' && ascii <= 'F') 02422 return ascii - 'A' + 10; 02423 if(ascii >= 'a' && ascii <= 'f') 02424 return ascii - 'a' + 10; 02425 return 0; 02426 } 02427 02428 dbus_bool_t _dbus_read_local_machine_uuid (DBusGUID *machine_id, 02429 dbus_bool_t create_if_not_found, 02430 DBusError *error) 02431 { 02432 #ifdef DBUS_WINCE 02433 return TRUE; 02434 // TODO 02435 #else 02436 HW_PROFILE_INFOA info; 02437 char *lpc = &info.szHwProfileGuid[0]; 02438 dbus_uint32_t u; 02439 02440 // the hw-profile guid lives long enough 02441 if(!GetCurrentHwProfileA(&info)) 02442 { 02443 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); // FIXME 02444 return FALSE; 02445 } 02446 02447 // Form: {12340001-4980-1920-6788-123456789012} 02448 lpc++; 02449 // 12340001 02450 u = ((fromAscii(lpc[0]) << 0) | 02451 (fromAscii(lpc[1]) << 4) | 02452 (fromAscii(lpc[2]) << 8) | 02453 (fromAscii(lpc[3]) << 12) | 02454 (fromAscii(lpc[4]) << 16) | 02455 (fromAscii(lpc[5]) << 20) | 02456 (fromAscii(lpc[6]) << 24) | 02457 (fromAscii(lpc[7]) << 28)); 02458 machine_id->as_uint32s[0] = u; 02459 02460 lpc += 9; 02461 // 4980-1920 02462 u = ((fromAscii(lpc[0]) << 0) | 02463 (fromAscii(lpc[1]) << 4) | 02464 (fromAscii(lpc[2]) << 8) | 02465 (fromAscii(lpc[3]) << 12) | 02466 (fromAscii(lpc[5]) << 16) | 02467 (fromAscii(lpc[6]) << 20) | 02468 (fromAscii(lpc[7]) << 24) | 02469 (fromAscii(lpc[8]) << 28)); 02470 machine_id->as_uint32s[1] = u; 02471 02472 lpc += 10; 02473 // 6788-1234 02474 u = ((fromAscii(lpc[0]) << 0) | 02475 (fromAscii(lpc[1]) << 4) | 02476 (fromAscii(lpc[2]) << 8) | 02477 (fromAscii(lpc[3]) << 12) | 02478 (fromAscii(lpc[5]) << 16) | 02479 (fromAscii(lpc[6]) << 20) | 02480 (fromAscii(lpc[7]) << 24) | 02481 (fromAscii(lpc[8]) << 28)); 02482 machine_id->as_uint32s[2] = u; 02483 02484 lpc += 9; 02485 // 56789012 02486 u = ((fromAscii(lpc[0]) << 0) | 02487 (fromAscii(lpc[1]) << 4) | 02488 (fromAscii(lpc[2]) << 8) | 02489 (fromAscii(lpc[3]) << 12) | 02490 (fromAscii(lpc[4]) << 16) | 02491 (fromAscii(lpc[5]) << 20) | 02492 (fromAscii(lpc[6]) << 24) | 02493 (fromAscii(lpc[7]) << 28)); 02494 machine_id->as_uint32s[3] = u; 02495 #endif 02496 return TRUE; 02497 } 02498 02499 static 02500 HANDLE _dbus_global_lock (const char *mutexname) 02501 { 02502 HANDLE mutex; 02503 DWORD gotMutex; 02504 02505 mutex = CreateMutexA( NULL, FALSE, mutexname ); 02506 if( !mutex ) 02507 { 02508 return FALSE; 02509 } 02510 02511 gotMutex = WaitForSingleObject( mutex, INFINITE ); 02512 switch( gotMutex ) 02513 { 02514 case WAIT_ABANDONED: 02515 ReleaseMutex (mutex); 02516 CloseHandle (mutex); 02517 return 0; 02518 case WAIT_FAILED: 02519 case WAIT_TIMEOUT: 02520 return 0; 02521 } 02522 02523 return mutex; 02524 } 02525 02526 static 02527 void _dbus_global_unlock (HANDLE mutex) 02528 { 02529 ReleaseMutex (mutex); 02530 CloseHandle (mutex); 02531 } 02532 02533 // for proper cleanup in dbus-daemon 02534 static HANDLE hDBusDaemonMutex = NULL; 02535 static HANDLE hDBusSharedMem = NULL; 02536 // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs 02537 static const char *cUniqueDBusInitMutex = "UniqueDBusInitMutex"; 02538 // sync _dbus_get_autolaunch_address 02539 static const char *cDBusAutolaunchMutex = "DBusAutolaunchMutex"; 02540 // mutex to determine if dbus-daemon is already started (per user) 02541 static const char *cDBusDaemonMutex = "DBusDaemonMutex"; 02542 // named shm for dbus adress info (per user) 02543 static const char *cDBusDaemonAddressInfo = "DBusDaemonAddressInfo"; 02544 02545 static dbus_bool_t 02546 _dbus_get_install_root_as_hash(DBusString *out) 02547 { 02548 DBusString install_path; 02549 02550 char path[MAX_PATH*2]; 02551 int path_size = sizeof(path); 02552 02553 if (!_dbus_get_install_root(path,path_size)) 02554 return FALSE; 02555 02556 _dbus_string_init(&install_path); 02557 _dbus_string_append(&install_path,path); 02558 02559 _dbus_string_init(out); 02560 _dbus_string_tolower_ascii(&install_path,0,_dbus_string_get_length(&install_path)); 02561 02562 if (!_dbus_sha_compute (&install_path, out)) 02563 return FALSE; 02564 02565 return TRUE; 02566 } 02567 02568 static dbus_bool_t 02569 _dbus_get_address_string (DBusString *out, const char *basestring, const char *scope) 02570 { 02571 _dbus_string_init(out); 02572 _dbus_string_append(out,basestring); 02573 02574 if (!scope) 02575 { 02576 return TRUE; 02577 } 02578 else if (strcmp(scope,"*install-path") == 0 02579 // for 1.3 compatibility 02580 || strcmp(scope,"install-path") == 0) 02581 { 02582 DBusString temp; 02583 if (!_dbus_get_install_root_as_hash(&temp)) 02584 { 02585 _dbus_string_free(out); 02586 return FALSE; 02587 } 02588 _dbus_string_append(out,"-"); 02589 _dbus_string_append(out,_dbus_string_get_const_data(&temp)); 02590 _dbus_string_free(&temp); 02591 } 02592 else if (strcmp(scope,"*user") == 0) 02593 { 02594 _dbus_string_append(out,"-"); 02595 if (!_dbus_append_user_from_current_process(out)) 02596 { 02597 _dbus_string_free(out); 02598 return FALSE; 02599 } 02600 } 02601 else if (strlen(scope) > 0) 02602 { 02603 _dbus_string_append(out,"-"); 02604 _dbus_string_append(out,scope); 02605 return TRUE; 02606 } 02607 return TRUE; 02608 } 02609 02610 static dbus_bool_t 02611 _dbus_get_shm_name (DBusString *out,const char *scope) 02612 { 02613 return _dbus_get_address_string (out,cDBusDaemonAddressInfo,scope); 02614 } 02615 02616 static dbus_bool_t 02617 _dbus_get_mutex_name (DBusString *out,const char *scope) 02618 { 02619 return _dbus_get_address_string (out,cDBusDaemonMutex,scope); 02620 } 02621 02622 dbus_bool_t 02623 _dbus_daemon_is_session_bus_address_published (const char *scope) 02624 { 02625 HANDLE lock; 02626 HANDLE mutex; 02627 DBusString mutex_name; 02628 DWORD ret; 02629 02630 if (!_dbus_get_mutex_name(&mutex_name,scope)) 02631 { 02632 _dbus_string_free( &mutex_name ); 02633 return FALSE; 02634 } 02635 02636 if (hDBusDaemonMutex) 02637 return TRUE; 02638 02639 // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs 02640 lock = _dbus_global_lock( cUniqueDBusInitMutex ); 02641 02642 // we use CreateMutex instead of OpenMutex because of possible race conditions, 02643 // see http://msdn.microsoft.com/en-us/library/ms684315%28VS.85%29.aspx 02644 hDBusDaemonMutex = CreateMutexA( NULL, FALSE, _dbus_string_get_const_data(&mutex_name) ); 02645 02646 /* The client uses mutex ownership to detect a running server, so the server should do so too. 02647 Fortunally the client deletes the mutex in the lock protected area, so checking presence 02648 will work too. */ 02649 02650 _dbus_global_unlock( lock ); 02651 02652 _dbus_string_free( &mutex_name ); 02653 02654 if (hDBusDaemonMutex == NULL) 02655 return FALSE; 02656 if (GetLastError() == ERROR_ALREADY_EXISTS) 02657 { 02658 CloseHandle(hDBusDaemonMutex); 02659 hDBusDaemonMutex = NULL; 02660 return TRUE; 02661 } 02662 // mutex wasn't created before, so return false. 02663 // We leave the mutex name allocated for later reusage 02664 // in _dbus_daemon_publish_session_bus_address. 02665 return FALSE; 02666 } 02667 02668 dbus_bool_t 02669 _dbus_daemon_publish_session_bus_address (const char* address, const char *scope) 02670 { 02671 HANDLE lock; 02672 char *shared_addr = NULL; 02673 DWORD ret; 02674 char addressInfo[1024]; 02675 DBusString shm_name; 02676 DBusString mutex_name; 02677 02678 _dbus_assert (address); 02679 02680 if (!_dbus_get_mutex_name(&mutex_name,scope)) 02681 { 02682 _dbus_string_free( &mutex_name ); 02683 return FALSE; 02684 } 02685 02686 // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs 02687 lock = _dbus_global_lock( cUniqueDBusInitMutex ); 02688 02689 if (!hDBusDaemonMutex) 02690 { 02691 hDBusDaemonMutex = CreateMutexA( NULL, FALSE, _dbus_string_get_const_data(&mutex_name) ); 02692 } 02693 _dbus_string_free( &mutex_name ); 02694 02695 // acquire the mutex 02696 if (WaitForSingleObject( hDBusDaemonMutex, 10 ) != WAIT_OBJECT_0) 02697 { 02698 _dbus_global_unlock( lock ); 02699 CloseHandle( hDBusDaemonMutex ); 02700 return FALSE; 02701 } 02702 02703 if (!_dbus_get_shm_name(&shm_name,scope)) 02704 { 02705 _dbus_string_free( &shm_name ); 02706 _dbus_global_unlock( lock ); 02707 return FALSE; 02708 } 02709 02710 // create shm 02711 hDBusSharedMem = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 02712 0, strlen( address ) + 1, _dbus_string_get_const_data(&shm_name) ); 02713 _dbus_assert( hDBusSharedMem ); 02714 02715 shared_addr = MapViewOfFile( hDBusSharedMem, FILE_MAP_WRITE, 0, 0, 0 ); 02716 02717 _dbus_assert (shared_addr); 02718 02719 strcpy( shared_addr, address); 02720 02721 // cleanup 02722 UnmapViewOfFile( shared_addr ); 02723 02724 _dbus_global_unlock( lock ); 02725 _dbus_verbose( "published session bus address at %s\n",_dbus_string_get_const_data (&shm_name) ); 02726 02727 _dbus_string_free( &shm_name ); 02728 return TRUE; 02729 } 02730 02731 void 02732 _dbus_daemon_unpublish_session_bus_address (void) 02733 { 02734 HANDLE lock; 02735 02736 // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs 02737 lock = _dbus_global_lock( cUniqueDBusInitMutex ); 02738 02739 CloseHandle( hDBusSharedMem ); 02740 02741 hDBusSharedMem = NULL; 02742 02743 ReleaseMutex( hDBusDaemonMutex ); 02744 02745 CloseHandle( hDBusDaemonMutex ); 02746 02747 hDBusDaemonMutex = NULL; 02748 02749 _dbus_global_unlock( lock ); 02750 } 02751 02752 static dbus_bool_t 02753 _dbus_get_autolaunch_shm (DBusString *address, DBusString *shm_name) 02754 { 02755 HANDLE sharedMem; 02756 char *shared_addr; 02757 int i; 02758 02759 // read shm 02760 for(i=0;i<20;++i) { 02761 // we know that dbus-daemon is available, so we wait until shm is available 02762 sharedMem = OpenFileMappingA( FILE_MAP_READ, FALSE, _dbus_string_get_const_data(shm_name)); 02763 if( sharedMem == 0 ) 02764 Sleep( 100 ); 02765 if ( sharedMem != 0) 02766 break; 02767 } 02768 02769 if( sharedMem == 0 ) 02770 return FALSE; 02771 02772 shared_addr = MapViewOfFile( sharedMem, FILE_MAP_READ, 0, 0, 0 ); 02773 02774 if( !shared_addr ) 02775 return FALSE; 02776 02777 _dbus_string_init( address ); 02778 02779 _dbus_string_append( address, shared_addr ); 02780 02781 // cleanup 02782 UnmapViewOfFile( shared_addr ); 02783 02784 CloseHandle( sharedMem ); 02785 02786 return TRUE; 02787 } 02788 02789 static dbus_bool_t 02790 _dbus_daemon_already_runs (DBusString *address, DBusString *shm_name, const char *scope) 02791 { 02792 HANDLE lock; 02793 HANDLE daemon; 02794 DBusString mutex_name; 02795 dbus_bool_t bRet = TRUE; 02796 02797 if (!_dbus_get_mutex_name(&mutex_name,scope)) 02798 { 02799 _dbus_string_free( &mutex_name ); 02800 return FALSE; 02801 } 02802 02803 // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs 02804 lock = _dbus_global_lock( cUniqueDBusInitMutex ); 02805 02806 // do checks 02807 daemon = CreateMutexA( NULL, FALSE, _dbus_string_get_const_data(&mutex_name) ); 02808 if(WaitForSingleObject( daemon, 10 ) != WAIT_TIMEOUT) 02809 { 02810 ReleaseMutex (daemon); 02811 CloseHandle (daemon); 02812 02813 _dbus_global_unlock( lock ); 02814 _dbus_string_free( &mutex_name ); 02815 return FALSE; 02816 } 02817 02818 // read shm 02819 bRet = _dbus_get_autolaunch_shm( address, shm_name ); 02820 02821 // cleanup 02822 CloseHandle ( daemon ); 02823 02824 _dbus_global_unlock( lock ); 02825 _dbus_string_free( &mutex_name ); 02826 02827 return bRet; 02828 } 02829 02830 dbus_bool_t 02831 _dbus_get_autolaunch_address (const char *scope, DBusString *address, 02832 DBusError *error) 02833 { 02834 HANDLE mutex; 02835 STARTUPINFOA si; 02836 PROCESS_INFORMATION pi; 02837 dbus_bool_t retval = FALSE; 02838 LPSTR lpFile; 02839 char dbus_exe_path[MAX_PATH]; 02840 char dbus_args[MAX_PATH * 2]; 02841 const char * daemon_name = DBUS_DAEMON_NAME ".exe"; 02842 DBusString shm_name; 02843 02844 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02845 02846 if (!_dbus_get_shm_name(&shm_name,scope)) 02847 { 02848 dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not determine shm name"); 02849 return FALSE; 02850 } 02851 02852 mutex = _dbus_global_lock ( cDBusAutolaunchMutex ); 02853 02854 if (_dbus_daemon_already_runs(address,&shm_name,scope)) 02855 { 02856 _dbus_verbose( "found running dbus daemon at %s\n", 02857 _dbus_string_get_const_data (&shm_name) ); 02858 retval = TRUE; 02859 goto out; 02860 } 02861 02862 if (!SearchPathA(NULL, daemon_name, NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile)) 02863 { 02864 // Look in directory containing dbus shared library 02865 HMODULE hmod; 02866 char dbus_module_path[MAX_PATH]; 02867 DWORD rc; 02868 02869 _dbus_verbose( "did not found dbus daemon executable on default search path, " 02870 "trying path where dbus shared library is located"); 02871 02872 hmod = _dbus_win_get_dll_hmodule(); 02873 rc = GetModuleFileNameA(hmod, dbus_module_path, sizeof(dbus_module_path)); 02874 if (rc <= 0) 02875 { 02876 dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not retrieve dbus shared library file name"); 02877 retval = FALSE; 02878 goto out; 02879 } 02880 else 02881 { 02882 char *ext_idx = strrchr(dbus_module_path, '\\'); 02883 if (ext_idx) 02884 *ext_idx = '\0'; 02885 if (!SearchPathA(dbus_module_path, daemon_name, NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile)) 02886 { 02887 dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not find dbus-daemon executable"); 02888 retval = FALSE; 02889 printf ("please add the path to %s to your PATH environment variable\n", daemon_name); 02890 printf ("or start the daemon manually\n\n"); 02891 goto out; 02892 } 02893 _dbus_verbose( "found dbus daemon executable at %s",dbus_module_path); 02894 } 02895 } 02896 02897 02898 // Create process 02899 ZeroMemory( &si, sizeof(si) ); 02900 si.cb = sizeof(si); 02901 ZeroMemory( &pi, sizeof(pi) ); 02902 02903 _snprintf(dbus_args, sizeof(dbus_args) - 1, "\"%s\" %s", dbus_exe_path, " --session"); 02904 02905 // argv[i] = "--config-file=bus\\session.conf"; 02906 // printf("create process \"%s\" %s\n", dbus_exe_path, dbus_args); 02907 if(CreateProcessA(dbus_exe_path, dbus_args, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) 02908 { 02909 CloseHandle (pi.hThread); 02910 CloseHandle (pi.hProcess); 02911 retval = _dbus_get_autolaunch_shm( address, &shm_name ); 02912 if (retval == FALSE) 02913 dbus_set_error_const (error, DBUS_ERROR_FAILED, "Failed to get autolaunch address from launched dbus-daemon"); 02914 } 02915 else 02916 { 02917 dbus_set_error_const (error, DBUS_ERROR_FAILED, "Failed to launch dbus-daemon"); 02918 retval = FALSE; 02919 } 02920 02921 out: 02922 if (retval) 02923 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02924 else 02925 _DBUS_ASSERT_ERROR_IS_SET (error); 02926 02927 _dbus_global_unlock (mutex); 02928 02929 return retval; 02930 } 02931 02932 02939 dbus_bool_t 02940 _dbus_make_file_world_readable(const DBusString *filename, 02941 DBusError *error) 02942 { 02943 // TODO 02944 return TRUE; 02945 } 02946 02953 static const char * 02954 _dbus_windows_get_datadir (void) 02955 { 02956 return _dbus_replace_install_prefix(DBUS_DATADIR); 02957 } 02958 02959 #undef DBUS_DATADIR 02960 #define DBUS_DATADIR _dbus_windows_get_datadir () 02961 02962 02963 #define DBUS_STANDARD_SESSION_SERVICEDIR "/dbus-1/services" 02964 #define DBUS_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services" 02965 02982 dbus_bool_t 02983 _dbus_get_standard_session_servicedirs (DBusList **dirs) 02984 { 02985 const char *common_progs; 02986 DBusString servicedir_path; 02987 02988 if (!_dbus_string_init (&servicedir_path)) 02989 return FALSE; 02990 02991 #ifdef DBUS_WINCE 02992 { 02993 /* On Windows CE, we adjust datadir dynamically to installation location. */ 02994 const char *data_dir = _dbus_getenv ("DBUS_DATADIR"); 02995 02996 if (data_dir != NULL) 02997 { 02998 if (!_dbus_string_append (&servicedir_path, data_dir)) 02999 goto oom; 03000 03001 if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR)) 03002 goto oom; 03003 } 03004 } 03005 #else 03006 /* 03007 the code for accessing services requires absolute base pathes 03008 in case DBUS_DATADIR is relative make it absolute 03009 */ 03010 #ifdef DBUS_WIN 03011 { 03012 DBusString p; 03013 03014 _dbus_string_init_const (&p, DBUS_DATADIR); 03015 03016 if (!_dbus_path_is_absolute (&p)) 03017 { 03018 char install_root[1000]; 03019 if (_dbus_get_install_root (install_root, sizeof(install_root))) 03020 if (!_dbus_string_append (&servicedir_path, install_root)) 03021 goto oom; 03022 } 03023 } 03024 #endif 03025 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR)) 03026 goto oom; 03027 03028 if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR)) 03029 goto oom; 03030 #endif 03031 03032 common_progs = _dbus_getenv ("CommonProgramFiles"); 03033 03034 if (common_progs != NULL) 03035 { 03036 if (!_dbus_string_append (&servicedir_path, common_progs)) 03037 goto oom; 03038 03039 if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR)) 03040 goto oom; 03041 } 03042 03043 if (!_dbus_split_paths_and_append (&servicedir_path, 03044 DBUS_STANDARD_SESSION_SERVICEDIR, 03045 dirs)) 03046 goto oom; 03047 03048 _dbus_string_free (&servicedir_path); 03049 return TRUE; 03050 03051 oom: 03052 _dbus_string_free (&servicedir_path); 03053 return FALSE; 03054 } 03055 03074 dbus_bool_t 03075 _dbus_get_standard_system_servicedirs (DBusList **dirs) 03076 { 03077 *dirs = NULL; 03078 return TRUE; 03079 } 03080 03081 _DBUS_DEFINE_GLOBAL_LOCK (atomic); 03082 03090 dbus_int32_t 03091 _dbus_atomic_inc (DBusAtomic *atomic) 03092 { 03093 // +/- 1 is needed here! 03094 // no volatile argument with mingw 03095 return InterlockedIncrement (&atomic->value) - 1; 03096 } 03097 03105 dbus_int32_t 03106 _dbus_atomic_dec (DBusAtomic *atomic) 03107 { 03108 // +/- 1 is needed here! 03109 // no volatile argument with mingw 03110 return InterlockedDecrement (&atomic->value) + 1; 03111 } 03112 03120 dbus_int32_t 03121 _dbus_atomic_get (DBusAtomic *atomic) 03122 { 03123 /* this is what GLib does, hopefully it's right... */ 03124 MemoryBarrier (); 03125 return atomic->value; 03126 } 03127 03135 void 03136 _dbus_flush_caches (void) 03137 { 03138 } 03139 03146 dbus_bool_t 03147 _dbus_get_is_errno_eagain_or_ewouldblock (void) 03148 { 03149 return errno == WSAEWOULDBLOCK; 03150 } 03151 03159 dbus_bool_t 03160 _dbus_get_install_root(char *prefix, int len) 03161 { 03162 //To find the prefix, we cut the filename and also \bin\ if present 03163 char* p = 0; 03164 int i; 03165 DWORD pathLength; 03166 char *lastSlash; 03167 SetLastError( 0 ); 03168 pathLength = GetModuleFileNameA(_dbus_win_get_dll_hmodule(), prefix, len); 03169 if ( pathLength == 0 || GetLastError() != 0 ) { 03170 *prefix = '\0'; 03171 return FALSE; 03172 } 03173 lastSlash = _mbsrchr(prefix, '\\'); 03174 if (lastSlash == NULL) { 03175 *prefix = '\0'; 03176 return FALSE; 03177 } 03178 //cut off binary name 03179 lastSlash[1] = 0; 03180 03181 //cut possible "\\bin" 03182 03183 //this fails if we are in a double-byte system codepage and the 03184 //folder's name happens to end with the *bytes* 03185 //"\\bin"... (I.e. the second byte of some Han character and then 03186 //the Latin "bin", but that is not likely I think... 03187 if (lastSlash - prefix >= 4 && strnicmp(lastSlash - 4, "\\bin", 4) == 0) 03188 lastSlash[-3] = 0; 03189 else if (lastSlash - prefix >= 10 && strnicmp(lastSlash - 10, "\\bin\\debug", 10) == 0) 03190 lastSlash[-9] = 0; 03191 else if (lastSlash - prefix >= 12 && strnicmp(lastSlash - 12, "\\bin\\release", 12) == 0) 03192 lastSlash[-11] = 0; 03193 03194 return TRUE; 03195 } 03196 03210 dbus_bool_t 03211 _dbus_get_config_file_name(DBusString *config_file, char *s) 03212 { 03213 char path[MAX_PATH*2]; 03214 int path_size = sizeof(path); 03215 03216 if (!_dbus_get_install_root(path,path_size)) 03217 return FALSE; 03218 03219 if(strlen(s) + 4 + strlen(path) > sizeof(path)-2) 03220 return FALSE; 03221 strcat(path,"etc\\"); 03222 strcat(path,s); 03223 if (_dbus_file_exists(path)) 03224 { 03225 // find path from executable 03226 if (!_dbus_string_append (config_file, path)) 03227 return FALSE; 03228 } 03229 else 03230 { 03231 if (!_dbus_get_install_root(path,path_size)) 03232 return FALSE; 03233 if(strlen(s) + 11 + strlen(path) > sizeof(path)-2) 03234 return FALSE; 03235 strcat(path,"etc\\dbus-1\\"); 03236 strcat(path,s); 03237 03238 if (_dbus_file_exists(path)) 03239 { 03240 if (!_dbus_string_append (config_file, path)) 03241 return FALSE; 03242 } 03243 else 03244 { 03245 if (!_dbus_get_install_root(path,path_size)) 03246 return FALSE; 03247 if(strlen(s) + 4 + strlen(path) > sizeof(path)-2) 03248 return FALSE; 03249 strcat(path,"bus\\"); 03250 strcat(path,s); 03251 03252 if (_dbus_file_exists(path)) 03253 { 03254 if (!_dbus_string_append (config_file, path)) 03255 return FALSE; 03256 } 03257 } 03258 } 03259 return TRUE; 03260 } 03261 03270 dbus_bool_t 03271 _dbus_append_system_config_file (DBusString *str) 03272 { 03273 return _dbus_get_config_file_name(str, "system.conf"); 03274 } 03275 03282 dbus_bool_t 03283 _dbus_append_session_config_file (DBusString *str) 03284 { 03285 return _dbus_get_config_file_name(str, "session.conf"); 03286 } 03287 03288 /* See comment in dbus-sysdeps-unix.c */ 03289 dbus_bool_t 03290 _dbus_lookup_session_address (dbus_bool_t *supported, 03291 DBusString *address, 03292 DBusError *error) 03293 { 03294 /* Probably fill this in with something based on COM? */ 03295 *supported = FALSE; 03296 return TRUE; 03297 } 03298 03312 dbus_bool_t 03313 _dbus_append_keyring_directory_for_credentials (DBusString *directory, 03314 DBusCredentials *credentials) 03315 { 03316 DBusString homedir; 03317 DBusString dotdir; 03318 dbus_uid_t uid; 03319 const char *homepath; 03320 const char *homedrive; 03321 03322 _dbus_assert (credentials != NULL); 03323 _dbus_assert (!_dbus_credentials_are_anonymous (credentials)); 03324 03325 if (!_dbus_string_init (&homedir)) 03326 return FALSE; 03327 03328 homedrive = _dbus_getenv("HOMEDRIVE"); 03329 if (homedrive != NULL && *homedrive != '\0') 03330 { 03331 _dbus_string_append(&homedir,homedrive); 03332 } 03333 03334 homepath = _dbus_getenv("HOMEPATH"); 03335 if (homepath != NULL && *homepath != '\0') 03336 { 03337 _dbus_string_append(&homedir,homepath); 03338 } 03339 03340 #ifdef DBUS_BUILD_TESTS 03341 { 03342 const char *override; 03343 03344 override = _dbus_getenv ("DBUS_TEST_HOMEDIR"); 03345 if (override != NULL && *override != '\0') 03346 { 03347 _dbus_string_set_length (&homedir, 0); 03348 if (!_dbus_string_append (&homedir, override)) 03349 goto failed; 03350 03351 _dbus_verbose ("Using fake homedir for testing: %s\n", 03352 _dbus_string_get_const_data (&homedir)); 03353 } 03354 else 03355 { 03356 static dbus_bool_t already_warned = FALSE; 03357 if (!already_warned) 03358 { 03359 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n"); 03360 already_warned = TRUE; 03361 } 03362 } 03363 } 03364 #endif 03365 03366 #ifdef DBUS_WINCE 03367 /* It's not possible to create a .something directory in Windows CE 03368 using the file explorer. */ 03369 #define KEYRING_DIR "dbus-keyrings" 03370 #else 03371 #define KEYRING_DIR ".dbus-keyrings" 03372 #endif 03373 03374 _dbus_string_init_const (&dotdir, KEYRING_DIR); 03375 if (!_dbus_concat_dir_and_file (&homedir, 03376 &dotdir)) 03377 goto failed; 03378 03379 if (!_dbus_string_copy (&homedir, 0, 03380 directory, _dbus_string_get_length (directory))) { 03381 goto failed; 03382 } 03383 03384 _dbus_string_free (&homedir); 03385 return TRUE; 03386 03387 failed: 03388 _dbus_string_free (&homedir); 03389 return FALSE; 03390 } 03391 03397 dbus_bool_t 03398 _dbus_file_exists (const char *file) 03399 { 03400 DWORD attributes = GetFileAttributesA (file); 03401 03402 if (attributes != INVALID_FILE_ATTRIBUTES && GetLastError() != ERROR_PATH_NOT_FOUND) 03403 return TRUE; 03404 else 03405 return FALSE; 03406 } 03407 03415 const char* 03416 _dbus_strerror (int error_number) 03417 { 03418 #ifdef DBUS_WINCE 03419 // TODO 03420 return "unknown"; 03421 #else 03422 const char *msg; 03423 03424 switch (error_number) 03425 { 03426 case WSAEINTR: 03427 return "Interrupted function call"; 03428 case WSAEACCES: 03429 return "Permission denied"; 03430 case WSAEFAULT: 03431 return "Bad address"; 03432 case WSAEINVAL: 03433 return "Invalid argument"; 03434 case WSAEMFILE: 03435 return "Too many open files"; 03436 case WSAEWOULDBLOCK: 03437 return "Resource temporarily unavailable"; 03438 case WSAEINPROGRESS: 03439 return "Operation now in progress"; 03440 case WSAEALREADY: 03441 return "Operation already in progress"; 03442 case WSAENOTSOCK: 03443 return "Socket operation on nonsocket"; 03444 case WSAEDESTADDRREQ: 03445 return "Destination address required"; 03446 case WSAEMSGSIZE: 03447 return "Message too long"; 03448 case WSAEPROTOTYPE: 03449 return "Protocol wrong type for socket"; 03450 case WSAENOPROTOOPT: 03451 return "Bad protocol option"; 03452 case WSAEPROTONOSUPPORT: 03453 return "Protocol not supported"; 03454 case WSAESOCKTNOSUPPORT: 03455 return "Socket type not supported"; 03456 case WSAEOPNOTSUPP: 03457 return "Operation not supported"; 03458 case WSAEPFNOSUPPORT: 03459 return "Protocol family not supported"; 03460 case WSAEAFNOSUPPORT: 03461 return "Address family not supported by protocol family"; 03462 case WSAEADDRINUSE: 03463 return "Address already in use"; 03464 case WSAEADDRNOTAVAIL: 03465 return "Cannot assign requested address"; 03466 case WSAENETDOWN: 03467 return "Network is down"; 03468 case WSAENETUNREACH: 03469 return "Network is unreachable"; 03470 case WSAENETRESET: 03471 return "Network dropped connection on reset"; 03472 case WSAECONNABORTED: 03473 return "Software caused connection abort"; 03474 case WSAECONNRESET: 03475 return "Connection reset by peer"; 03476 case WSAENOBUFS: 03477 return "No buffer space available"; 03478 case WSAEISCONN: 03479 return "Socket is already connected"; 03480 case WSAENOTCONN: 03481 return "Socket is not connected"; 03482 case WSAESHUTDOWN: 03483 return "Cannot send after socket shutdown"; 03484 case WSAETIMEDOUT: 03485 return "Connection timed out"; 03486 case WSAECONNREFUSED: 03487 return "Connection refused"; 03488 case WSAEHOSTDOWN: 03489 return "Host is down"; 03490 case WSAEHOSTUNREACH: 03491 return "No route to host"; 03492 case WSAEPROCLIM: 03493 return "Too many processes"; 03494 case WSAEDISCON: 03495 return "Graceful shutdown in progress"; 03496 case WSATYPE_NOT_FOUND: 03497 return "Class type not found"; 03498 case WSAHOST_NOT_FOUND: 03499 return "Host not found"; 03500 case WSATRY_AGAIN: 03501 return "Nonauthoritative host not found"; 03502 case WSANO_RECOVERY: 03503 return "This is a nonrecoverable error"; 03504 case WSANO_DATA: 03505 return "Valid name, no data record of requested type"; 03506 case WSA_INVALID_HANDLE: 03507 return "Specified event object handle is invalid"; 03508 case WSA_INVALID_PARAMETER: 03509 return "One or more parameters are invalid"; 03510 case WSA_IO_INCOMPLETE: 03511 return "Overlapped I/O event object not in signaled state"; 03512 case WSA_IO_PENDING: 03513 return "Overlapped operations will complete later"; 03514 case WSA_NOT_ENOUGH_MEMORY: 03515 return "Insufficient memory available"; 03516 case WSA_OPERATION_ABORTED: 03517 return "Overlapped operation aborted"; 03518 #ifdef WSAINVALIDPROCTABLE 03519 03520 case WSAINVALIDPROCTABLE: 03521 return "Invalid procedure table from service provider"; 03522 #endif 03523 #ifdef WSAINVALIDPROVIDER 03524 03525 case WSAINVALIDPROVIDER: 03526 return "Invalid service provider version number"; 03527 #endif 03528 #ifdef WSAPROVIDERFAILEDINIT 03529 03530 case WSAPROVIDERFAILEDINIT: 03531 return "Unable to initialize a service provider"; 03532 #endif 03533 03534 case WSASYSCALLFAILURE: 03535 return "System call failure"; 03536 } 03537 msg = strerror (error_number); 03538 if (msg == NULL) 03539 msg = "unknown"; 03540 03541 return msg; 03542 #endif //DBUS_WINCE 03543 } 03544 03552 void 03553 _dbus_win_set_error_from_win_error (DBusError *error, 03554 int code) 03555 { 03556 char *msg; 03557 03558 /* As we want the English message, use the A API */ 03559 FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER | 03560 FORMAT_MESSAGE_IGNORE_INSERTS | 03561 FORMAT_MESSAGE_FROM_SYSTEM, 03562 NULL, code, MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US), 03563 (LPSTR) &msg, 0, NULL); 03564 if (msg) 03565 { 03566 char *msg_copy; 03567 03568 msg_copy = dbus_malloc (strlen (msg)); 03569 strcpy (msg_copy, msg); 03570 LocalFree (msg); 03571 03572 dbus_set_error (error, "win32.error", "%s", msg_copy); 03573 } 03574 else 03575 dbus_set_error (error, "win32.error", "Unknown error code %d or FormatMessage failed", code); 03576 } 03577 03578 void 03579 _dbus_win_warn_win_error (const char *message, 03580 int code) 03581 { 03582 DBusError error; 03583 03584 dbus_error_init (&error); 03585 _dbus_win_set_error_from_win_error (&error, code); 03586 _dbus_warn ("%s: %s\n", message, error.message); 03587 dbus_error_free (&error); 03588 } 03589 03597 dbus_bool_t 03598 _dbus_delete_directory (const DBusString *filename, 03599 DBusError *error) 03600 { 03601 const char *filename_c; 03602 03603 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03604 03605 filename_c = _dbus_string_get_const_data (filename); 03606 03607 if (RemoveDirectoryA (filename_c) == 0) 03608 { 03609 char *emsg = _dbus_win_error_string (GetLastError ()); 03610 dbus_set_error (error, _dbus_win_error_from_last_error (), 03611 "Failed to remove directory %s: %s", 03612 filename_c, emsg); 03613 _dbus_win_free_error_string (emsg); 03614 return FALSE; 03615 } 03616 03617 return TRUE; 03618 } 03619 03626 dbus_bool_t 03627 _dbus_path_is_absolute (const DBusString *filename) 03628 { 03629 if (_dbus_string_get_length (filename) > 0) 03630 return _dbus_string_get_byte (filename, 1) == ':' 03631 || _dbus_string_get_byte (filename, 0) == '\\' 03632 || _dbus_string_get_byte (filename, 0) == '/'; 03633 else 03634 return FALSE; 03635 } 03636 03638 /* tests in dbus-sysdeps-util.c */ 03639