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