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