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