|
D-Bus
1.8.20
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-sysdeps.c Wrappers around system/libc features (internal to D-BUS implementation) 00003 * 00004 * Copyright (C) 2002, 2003 Red Hat, Inc. 00005 * Copyright (C) 2003 CodeFactory AB 00006 * Copyright (C) 2005 Novell, Inc. 00007 * Copyright (C) 2006 Peter Kümmel <syntheticpp@gmx.net> 00008 * Copyright (C) 2006 Christian Ehrlicher <ch.ehrlicher@gmx.de> 00009 * Copyright (C) 2006-2013 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 #include <iphlpapi.h> 00058 00059 /* Declarations missing in mingw's and windows sdk 7.0 headers */ 00060 extern BOOL WINAPI ConvertStringSidToSidA (LPCSTR StringSid, PSID *Sid); 00061 extern BOOL WINAPI ConvertSidToStringSidA (PSID Sid, LPSTR *StringSid); 00062 00063 #include <stdio.h> 00064 #include <stdlib.h> 00065 00066 #include <string.h> 00067 #if HAVE_ERRNO_H 00068 #include <errno.h> 00069 #endif 00070 #ifndef DBUS_WINCE 00071 #include <mbstring.h> 00072 #include <sys/stat.h> 00073 #include <sys/types.h> 00074 #endif 00075 00076 #ifdef HAVE_WS2TCPIP_H 00077 /* getaddrinfo for Windows CE (and Windows). */ 00078 #include <ws2tcpip.h> 00079 #endif 00080 00081 #ifndef O_BINARY 00082 #define O_BINARY 0 00083 #endif 00084 00085 #ifndef PROCESS_QUERY_LIMITED_INFORMATION 00086 /* MinGW32 < 4 does not define this value in its headers */ 00087 #define PROCESS_QUERY_LIMITED_INFORMATION (0x1000) 00088 #endif 00089 00090 typedef int socklen_t; 00091 00092 00093 void 00094 _dbus_win_set_errno (int err) 00095 { 00096 #ifdef DBUS_WINCE 00097 SetLastError (err); 00098 #else 00099 errno = err; 00100 #endif 00101 } 00102 00103 static BOOL is_winxp_sp3_or_lower(); 00104 00105 /* 00106 * _MIB_TCPROW_EX and friends are not available in system headers 00107 * and are mapped to attribute identical ...OWNER_PID typedefs. 00108 */ 00109 typedef MIB_TCPROW_OWNER_PID _MIB_TCPROW_EX; 00110 typedef MIB_TCPTABLE_OWNER_PID MIB_TCPTABLE_EX; 00111 typedef PMIB_TCPTABLE_OWNER_PID PMIB_TCPTABLE_EX; 00112 typedef DWORD (WINAPI *ProcAllocateAndGetTcpExtTableFromStack)(PMIB_TCPTABLE_EX*,BOOL,HANDLE,DWORD,DWORD); 00113 static ProcAllocateAndGetTcpExtTableFromStack lpfnAllocateAndGetTcpExTableFromStack = NULL; 00114 00120 static BOOL 00121 load_ex_ip_helper_procedures(void) 00122 { 00123 HMODULE hModule = LoadLibrary ("iphlpapi.dll"); 00124 if (hModule == NULL) 00125 { 00126 _dbus_verbose ("could not load iphlpapi.dll\n"); 00127 return FALSE; 00128 } 00129 00130 lpfnAllocateAndGetTcpExTableFromStack = (ProcAllocateAndGetTcpExtTableFromStack)GetProcAddress (hModule, "AllocateAndGetTcpExTableFromStack"); 00131 if (lpfnAllocateAndGetTcpExTableFromStack == NULL) 00132 { 00133 _dbus_verbose ("could not find function AllocateAndGetTcpExTableFromStack in iphlpapi.dll\n"); 00134 return FALSE; 00135 } 00136 return TRUE; 00137 } 00138 00145 static dbus_pid_t 00146 get_pid_from_extended_tcp_table(int peer_port) 00147 { 00148 dbus_pid_t result; 00149 DWORD errorCode, size = 0, i; 00150 MIB_TCPTABLE_OWNER_PID *tcp_table; 00151 00152 if ((errorCode = 00153 GetExtendedTcpTable (NULL, &size, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0)) == ERROR_INSUFFICIENT_BUFFER) 00154 { 00155 tcp_table = (MIB_TCPTABLE_OWNER_PID *) dbus_malloc (size); 00156 if (tcp_table == NULL) 00157 { 00158 _dbus_verbose ("Error allocating memory\n"); 00159 return 0; 00160 } 00161 } 00162 else 00163 { 00164 _dbus_win_warn_win_error ("unexpected error returned from GetExtendedTcpTable", errorCode); 00165 return 0; 00166 } 00167 00168 if ((errorCode = GetExtendedTcpTable (tcp_table, &size, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0)) != NO_ERROR) 00169 { 00170 _dbus_verbose ("Error fetching tcp table %d\n", (int)errorCode); 00171 dbus_free (tcp_table); 00172 return 0; 00173 } 00174 00175 result = 0; 00176 for (i = 0; i < tcp_table->dwNumEntries; i++) 00177 { 00178 MIB_TCPROW_OWNER_PID *p = &tcp_table->table[i]; 00179 int local_address = ntohl (p->dwLocalAddr); 00180 int local_port = ntohs (p->dwLocalPort); 00181 if (p->dwState == MIB_TCP_STATE_ESTAB 00182 && local_address == INADDR_LOOPBACK && local_port == peer_port) 00183 result = p->dwOwningPid; 00184 } 00185 00186 dbus_free (tcp_table); 00187 _dbus_verbose ("got pid %lu\n", result); 00188 return result; 00189 } 00190 00198 static dbus_pid_t 00199 get_pid_from_tcp_ex_table(int peer_port) 00200 { 00201 dbus_pid_t result; 00202 DWORD errorCode, i; 00203 PMIB_TCPTABLE_EX tcp_table = NULL; 00204 00205 if (!load_ex_ip_helper_procedures ()) 00206 { 00207 _dbus_verbose 00208 ("Error not been able to load iphelper procedures\n"); 00209 return 0; 00210 } 00211 00212 errorCode = lpfnAllocateAndGetTcpExTableFromStack (&tcp_table, TRUE, GetProcessHeap(), 0, 2); 00213 00214 if (errorCode != NO_ERROR) 00215 { 00216 _dbus_verbose 00217 ("Error not been able to call AllocateAndGetTcpExTableFromStack()\n"); 00218 return 0; 00219 } 00220 00221 result = 0; 00222 for (i = 0; i < tcp_table->dwNumEntries; i++) 00223 { 00224 _MIB_TCPROW_EX *p = &tcp_table->table[i]; 00225 int local_port = ntohs (p->dwLocalPort); 00226 int local_address = ntohl (p->dwLocalAddr); 00227 if (local_address == INADDR_LOOPBACK && local_port == peer_port) 00228 { 00229 result = p->dwOwningPid; 00230 break; 00231 } 00232 } 00233 00234 HeapFree (GetProcessHeap(), 0, tcp_table); 00235 _dbus_verbose ("got pid %lu\n", result); 00236 return result; 00237 } 00238 00244 static dbus_pid_t 00245 _dbus_get_peer_pid_from_tcp_handle (int handle) 00246 { 00247 struct sockaddr_storage addr; 00248 socklen_t len = sizeof (addr); 00249 int peer_port; 00250 00251 dbus_pid_t result; 00252 dbus_bool_t is_localhost = FALSE; 00253 00254 getpeername (handle, (struct sockaddr *) &addr, &len); 00255 00256 if (addr.ss_family == AF_INET) 00257 { 00258 struct sockaddr_in *s = (struct sockaddr_in *) &addr; 00259 peer_port = ntohs (s->sin_port); 00260 is_localhost = (ntohl (s->sin_addr.s_addr) == INADDR_LOOPBACK); 00261 } 00262 else if (addr.ss_family == AF_INET6) 00263 { 00264 _dbus_verbose ("FIXME [61922]: IPV6 support not working on windows\n"); 00265 return 0; 00266 /* 00267 struct sockaddr_in6 *s = (struct sockaddr_in6 * )&addr; 00268 peer_port = ntohs (s->sin6_port); 00269 is_localhost = (memcmp(s->sin6_addr.s6_addr, in6addr_loopback.s6_addr, 16) == 0); 00270 _dbus_verbose ("IPV6 %08x %08x\n", s->sin6_addr.s6_addr, in6addr_loopback.s6_addr); 00271 */ 00272 } 00273 else 00274 { 00275 _dbus_verbose ("no idea what address family %d is\n", addr.ss_family); 00276 return 0; 00277 } 00278 00279 if (!is_localhost) 00280 { 00281 _dbus_verbose ("could not fetch process id from remote process\n"); 00282 return 0; 00283 } 00284 00285 if (peer_port == 0) 00286 { 00287 _dbus_verbose 00288 ("Error not been able to fetch tcp peer port from connection\n"); 00289 return 0; 00290 } 00291 00292 _dbus_verbose ("trying to get peers pid"); 00293 00294 result = get_pid_from_extended_tcp_table (peer_port); 00295 if (result > 0) 00296 return result; 00297 result = get_pid_from_tcp_ex_table (peer_port); 00298 return result; 00299 } 00300 00301 /* Convert GetLastError() to a dbus error. */ 00302 const char* 00303 _dbus_win_error_from_last_error (void) 00304 { 00305 switch (GetLastError()) 00306 { 00307 case 0: 00308 return DBUS_ERROR_FAILED; 00309 00310 case ERROR_NO_MORE_FILES: 00311 case ERROR_TOO_MANY_OPEN_FILES: 00312 return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */ 00313 00314 case ERROR_ACCESS_DENIED: 00315 case ERROR_CANNOT_MAKE: 00316 return DBUS_ERROR_ACCESS_DENIED; 00317 00318 case ERROR_NOT_ENOUGH_MEMORY: 00319 return DBUS_ERROR_NO_MEMORY; 00320 00321 case ERROR_FILE_EXISTS: 00322 return DBUS_ERROR_FILE_EXISTS; 00323 00324 case ERROR_FILE_NOT_FOUND: 00325 case ERROR_PATH_NOT_FOUND: 00326 return DBUS_ERROR_FILE_NOT_FOUND; 00327 } 00328 00329 return DBUS_ERROR_FAILED; 00330 } 00331 00332 00333 char* 00334 _dbus_win_error_string (int error_number) 00335 { 00336 char *msg; 00337 00338 FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER | 00339 FORMAT_MESSAGE_IGNORE_INSERTS | 00340 FORMAT_MESSAGE_FROM_SYSTEM, 00341 NULL, error_number, 0, 00342 (LPSTR) &msg, 0, NULL); 00343 00344 if (msg[strlen (msg) - 1] == '\n') 00345 msg[strlen (msg) - 1] = '\0'; 00346 if (msg[strlen (msg) - 1] == '\r') 00347 msg[strlen (msg) - 1] = '\0'; 00348 00349 return msg; 00350 } 00351 00352 void 00353 _dbus_win_free_error_string (char *string) 00354 { 00355 LocalFree (string); 00356 } 00357 00378 int 00379 _dbus_read_socket (int fd, 00380 DBusString *buffer, 00381 int count) 00382 { 00383 int bytes_read; 00384 int start; 00385 char *data; 00386 00387 _dbus_assert (count >= 0); 00388 00389 start = _dbus_string_get_length (buffer); 00390 00391 if (!_dbus_string_lengthen (buffer, count)) 00392 { 00393 _dbus_win_set_errno (ENOMEM); 00394 return -1; 00395 } 00396 00397 data = _dbus_string_get_data_len (buffer, start, count); 00398 00399 again: 00400 00401 _dbus_verbose ("recv: count=%d fd=%d\n", count, fd); 00402 bytes_read = recv (fd, data, count, 0); 00403 00404 if (bytes_read == SOCKET_ERROR) 00405 { 00406 DBUS_SOCKET_SET_ERRNO(); 00407 _dbus_verbose ("recv: failed: %s (%d)\n", _dbus_strerror (errno), errno); 00408 bytes_read = -1; 00409 } 00410 else 00411 _dbus_verbose ("recv: = %d\n", bytes_read); 00412 00413 if (bytes_read < 0) 00414 { 00415 if (errno == EINTR) 00416 goto again; 00417 else 00418 { 00419 /* put length back (note that this doesn't actually realloc anything) */ 00420 _dbus_string_set_length (buffer, start); 00421 return -1; 00422 } 00423 } 00424 else 00425 { 00426 /* put length back (doesn't actually realloc) */ 00427 _dbus_string_set_length (buffer, start + bytes_read); 00428 00429 #if 0 00430 if (bytes_read > 0) 00431 _dbus_verbose_bytes_of_string (buffer, start, bytes_read); 00432 #endif 00433 00434 return bytes_read; 00435 } 00436 } 00437 00448 int 00449 _dbus_write_socket (int fd, 00450 const DBusString *buffer, 00451 int start, 00452 int len) 00453 { 00454 const char *data; 00455 int bytes_written; 00456 00457 data = _dbus_string_get_const_data_len (buffer, start, len); 00458 00459 again: 00460 00461 _dbus_verbose ("send: len=%d fd=%d\n", len, fd); 00462 bytes_written = send (fd, data, len, 0); 00463 00464 if (bytes_written == SOCKET_ERROR) 00465 { 00466 DBUS_SOCKET_SET_ERRNO(); 00467 _dbus_verbose ("send: failed: %s\n", _dbus_strerror_from_errno ()); 00468 bytes_written = -1; 00469 } 00470 else 00471 _dbus_verbose ("send: = %d\n", bytes_written); 00472 00473 if (bytes_written < 0 && errno == EINTR) 00474 goto again; 00475 00476 #if 0 00477 if (bytes_written > 0) 00478 _dbus_verbose_bytes_of_string (buffer, start, bytes_written); 00479 #endif 00480 00481 return bytes_written; 00482 } 00483 00484 00492 dbus_bool_t 00493 _dbus_close_socket (int fd, 00494 DBusError *error) 00495 { 00496 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00497 00498 again: 00499 if (closesocket (fd) == SOCKET_ERROR) 00500 { 00501 DBUS_SOCKET_SET_ERRNO (); 00502 00503 if (errno == EINTR) 00504 goto again; 00505 00506 dbus_set_error (error, _dbus_error_from_errno (errno), 00507 "Could not close socket: socket=%d, , %s", 00508 fd, _dbus_strerror_from_errno ()); 00509 return FALSE; 00510 } 00511 _dbus_verbose ("_dbus_close_socket: socket=%d, \n", fd); 00512 00513 return TRUE; 00514 } 00515 00523 void 00524 _dbus_fd_set_close_on_exec (intptr_t handle) 00525 { 00526 if ( !SetHandleInformation( (HANDLE) handle, 00527 HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE, 00528 0 /*disable both flags*/ ) ) 00529 { 00530 _dbus_win_warn_win_error ("Disabling socket handle inheritance failed:", GetLastError()); 00531 } 00532 } 00533 00541 dbus_bool_t 00542 _dbus_set_fd_nonblocking (int handle, 00543 DBusError *error) 00544 { 00545 u_long one = 1; 00546 00547 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00548 00549 if (ioctlsocket (handle, FIONBIO, &one) == SOCKET_ERROR) 00550 { 00551 DBUS_SOCKET_SET_ERRNO (); 00552 dbus_set_error (error, _dbus_error_from_errno (errno), 00553 "Failed to set socket %d:%d to nonblocking: %s", handle, 00554 _dbus_strerror_from_errno ()); 00555 return FALSE; 00556 } 00557 00558 return TRUE; 00559 } 00560 00561 00582 int 00583 _dbus_write_socket_two (int fd, 00584 const DBusString *buffer1, 00585 int start1, 00586 int len1, 00587 const DBusString *buffer2, 00588 int start2, 00589 int len2) 00590 { 00591 WSABUF vectors[2]; 00592 const char *data1; 00593 const char *data2; 00594 int rc; 00595 DWORD bytes_written; 00596 00597 _dbus_assert (buffer1 != NULL); 00598 _dbus_assert (start1 >= 0); 00599 _dbus_assert (start2 >= 0); 00600 _dbus_assert (len1 >= 0); 00601 _dbus_assert (len2 >= 0); 00602 00603 00604 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1); 00605 00606 if (buffer2 != NULL) 00607 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2); 00608 else 00609 { 00610 data2 = NULL; 00611 start2 = 0; 00612 len2 = 0; 00613 } 00614 00615 vectors[0].buf = (char*) data1; 00616 vectors[0].len = len1; 00617 vectors[1].buf = (char*) data2; 00618 vectors[1].len = len2; 00619 00620 again: 00621 00622 _dbus_verbose ("WSASend: len1+2=%d+%d fd=%d\n", len1, len2, fd); 00623 rc = WSASend (fd, 00624 vectors, 00625 data2 ? 2 : 1, 00626 &bytes_written, 00627 0, 00628 NULL, 00629 NULL); 00630 00631 if (rc == SOCKET_ERROR) 00632 { 00633 DBUS_SOCKET_SET_ERRNO (); 00634 _dbus_verbose ("WSASend: failed: %s\n", _dbus_strerror_from_errno ()); 00635 bytes_written = -1; 00636 } 00637 else 00638 _dbus_verbose ("WSASend: = %ld\n", bytes_written); 00639 00640 if (bytes_written < 0 && errno == EINTR) 00641 goto again; 00642 00643 return bytes_written; 00644 } 00645 00646 dbus_bool_t 00647 _dbus_socket_is_invalid (int fd) 00648 { 00649 return fd == INVALID_SOCKET ? TRUE : FALSE; 00650 } 00651 00652 #if 0 00653 00662 int 00663 _dbus_connect_named_pipe (const char *path, 00664 DBusError *error) 00665 { 00666 _dbus_assert_not_reached ("not implemented"); 00667 } 00668 00669 #endif 00670 00674 dbus_bool_t 00675 _dbus_win_startup_winsock (void) 00676 { 00677 /* Straight from MSDN, deuglified */ 00678 00679 /* Protected by _DBUS_LOCK_sysdeps */ 00680 static dbus_bool_t beenhere = FALSE; 00681 00682 WORD wVersionRequested; 00683 WSADATA wsaData; 00684 int err; 00685 00686 if (!_DBUS_LOCK (sysdeps)) 00687 return FALSE; 00688 00689 if (beenhere) 00690 goto out; 00691 00692 wVersionRequested = MAKEWORD (2, 0); 00693 00694 err = WSAStartup (wVersionRequested, &wsaData); 00695 if (err != 0) 00696 { 00697 _dbus_assert_not_reached ("Could not initialize WinSock"); 00698 _dbus_abort (); 00699 } 00700 00701 /* Confirm that the WinSock DLL supports 2.0. Note that if the DLL 00702 * supports versions greater than 2.0 in addition to 2.0, it will 00703 * still return 2.0 in wVersion since that is the version we 00704 * requested. 00705 */ 00706 if (LOBYTE (wsaData.wVersion) != 2 || 00707 HIBYTE (wsaData.wVersion) != 0) 00708 { 00709 _dbus_assert_not_reached ("No usable WinSock found"); 00710 _dbus_abort (); 00711 } 00712 00713 beenhere = TRUE; 00714 00715 out: 00716 _DBUS_UNLOCK (sysdeps); 00717 return TRUE; 00718 } 00719 00720 00721 00722 00723 00724 00725 00726 00727 00728 /************************************************************************ 00729 00730 UTF / string code 00731 00732 ************************************************************************/ 00733 00737 int _dbus_printf_string_upper_bound (const char *format, 00738 va_list args) 00739 { 00740 /* MSVCRT's vsnprintf semantics are a bit different */ 00741 char buf[1024]; 00742 int bufsize; 00743 int len; 00744 va_list args_copy; 00745 00746 bufsize = sizeof (buf); 00747 DBUS_VA_COPY (args_copy, args); 00748 len = _vsnprintf (buf, bufsize - 1, format, args_copy); 00749 va_end (args_copy); 00750 00751 while (len == -1) /* try again */ 00752 { 00753 char *p; 00754 00755 bufsize *= 2; 00756 00757 p = malloc (bufsize); 00758 00759 if (p == NULL) 00760 return -1; 00761 00762 DBUS_VA_COPY (args_copy, args); 00763 len = _vsnprintf (p, bufsize - 1, format, args_copy); 00764 va_end (args_copy); 00765 free (p); 00766 } 00767 00768 return len; 00769 } 00770 00771 00779 wchar_t * 00780 _dbus_win_utf8_to_utf16 (const char *str, 00781 DBusError *error) 00782 { 00783 DBusString s; 00784 int n; 00785 wchar_t *retval; 00786 00787 _dbus_string_init_const (&s, str); 00788 00789 if (!_dbus_string_validate_utf8 (&s, 0, _dbus_string_get_length (&s))) 00790 { 00791 dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid UTF-8"); 00792 return NULL; 00793 } 00794 00795 n = MultiByteToWideChar (CP_UTF8, 0, str, -1, NULL, 0); 00796 00797 if (n == 0) 00798 { 00799 _dbus_win_set_error_from_win_error (error, GetLastError ()); 00800 return NULL; 00801 } 00802 00803 retval = dbus_new (wchar_t, n); 00804 00805 if (!retval) 00806 { 00807 _DBUS_SET_OOM (error); 00808 return NULL; 00809 } 00810 00811 if (MultiByteToWideChar (CP_UTF8, 0, str, -1, retval, n) != n) 00812 { 00813 dbus_free (retval); 00814 dbus_set_error_const (error, DBUS_ERROR_FAILED, "MultiByteToWideChar inconsistency"); 00815 return NULL; 00816 } 00817 00818 return retval; 00819 } 00820 00828 char * 00829 _dbus_win_utf16_to_utf8 (const wchar_t *str, 00830 DBusError *error) 00831 { 00832 int n; 00833 char *retval; 00834 00835 n = WideCharToMultiByte (CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL); 00836 00837 if (n == 0) 00838 { 00839 _dbus_win_set_error_from_win_error (error, GetLastError ()); 00840 return NULL; 00841 } 00842 00843 retval = dbus_malloc (n); 00844 00845 if (!retval) 00846 { 00847 _DBUS_SET_OOM (error); 00848 return NULL; 00849 } 00850 00851 if (WideCharToMultiByte (CP_UTF8, 0, str, -1, retval, n, NULL, NULL) != n) 00852 { 00853 dbus_free (retval); 00854 dbus_set_error_const (error, DBUS_ERROR_FAILED, "WideCharToMultiByte inconsistency"); 00855 return NULL; 00856 } 00857 00858 return retval; 00859 } 00860 00861 00862 00863 00864 00865 00866 /************************************************************************ 00867 00868 00869 ************************************************************************/ 00870 00871 dbus_bool_t 00872 _dbus_win_account_to_sid (const wchar_t *waccount, 00873 void **ppsid, 00874 DBusError *error) 00875 { 00876 dbus_bool_t retval = FALSE; 00877 DWORD sid_length, wdomain_length; 00878 SID_NAME_USE use; 00879 wchar_t *wdomain; 00880 00881 *ppsid = NULL; 00882 00883 sid_length = 0; 00884 wdomain_length = 0; 00885 if (!LookupAccountNameW (NULL, waccount, NULL, &sid_length, 00886 NULL, &wdomain_length, &use) && 00887 GetLastError () != ERROR_INSUFFICIENT_BUFFER) 00888 { 00889 _dbus_win_set_error_from_win_error (error, GetLastError ()); 00890 return FALSE; 00891 } 00892 00893 *ppsid = dbus_malloc (sid_length); 00894 if (!*ppsid) 00895 { 00896 _DBUS_SET_OOM (error); 00897 return FALSE; 00898 } 00899 00900 wdomain = dbus_new (wchar_t, wdomain_length); 00901 if (!wdomain) 00902 { 00903 _DBUS_SET_OOM (error); 00904 goto out1; 00905 } 00906 00907 if (!LookupAccountNameW (NULL, waccount, (PSID) *ppsid, &sid_length, 00908 wdomain, &wdomain_length, &use)) 00909 { 00910 _dbus_win_set_error_from_win_error (error, GetLastError ()); 00911 goto out2; 00912 } 00913 00914 if (!IsValidSid ((PSID) *ppsid)) 00915 { 00916 dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid SID"); 00917 goto out2; 00918 } 00919 00920 retval = TRUE; 00921 00922 out2: 00923 dbus_free (wdomain); 00924 out1: 00925 if (!retval) 00926 { 00927 dbus_free (*ppsid); 00928 *ppsid = NULL; 00929 } 00930 00931 return retval; 00932 } 00933 00943 unsigned long 00944 _dbus_pid_for_log (void) 00945 { 00946 return _dbus_getpid (); 00947 } 00948 00949 #ifndef DBUS_WINCE 00950 00951 static BOOL is_winxp_sp3_or_lower() 00952 { 00953 OSVERSIONINFOEX osvi; 00954 DWORDLONG dwlConditionMask = 0; 00955 int op=VER_LESS_EQUAL; 00956 00957 // Initialize the OSVERSIONINFOEX structure. 00958 00959 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); 00960 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); 00961 osvi.dwMajorVersion = 5; 00962 osvi.dwMinorVersion = 1; 00963 osvi.wServicePackMajor = 3; 00964 osvi.wServicePackMinor = 0; 00965 00966 // Initialize the condition mask. 00967 00968 VER_SET_CONDITION( dwlConditionMask, VER_MAJORVERSION, op ); 00969 VER_SET_CONDITION( dwlConditionMask, VER_MINORVERSION, op ); 00970 VER_SET_CONDITION( dwlConditionMask, VER_SERVICEPACKMAJOR, op ); 00971 VER_SET_CONDITION( dwlConditionMask, VER_SERVICEPACKMINOR, op ); 00972 00973 // Perform the test. 00974 00975 return VerifyVersionInfo( 00976 &osvi, 00977 VER_MAJORVERSION | VER_MINORVERSION | 00978 VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, 00979 dwlConditionMask); 00980 } 00981 00987 static dbus_bool_t 00988 _dbus_getsid(char **sid, dbus_pid_t process_id) 00989 { 00990 HANDLE process_token = INVALID_HANDLE_VALUE; 00991 TOKEN_USER *token_user = NULL; 00992 DWORD n; 00993 PSID psid; 00994 int retval = FALSE; 00995 00996 HANDLE process_handle = OpenProcess(is_winxp_sp3_or_lower() ? PROCESS_QUERY_INFORMATION : PROCESS_QUERY_LIMITED_INFORMATION, FALSE, process_id); 00997 00998 if (!OpenProcessToken (process_handle, TOKEN_QUERY, &process_token)) 00999 { 01000 _dbus_win_warn_win_error ("OpenProcessToken failed", GetLastError ()); 01001 goto failed; 01002 } 01003 if ((!GetTokenInformation (process_token, TokenUser, NULL, 0, &n) 01004 && GetLastError () != ERROR_INSUFFICIENT_BUFFER) 01005 || (token_user = alloca (n)) == NULL 01006 || !GetTokenInformation (process_token, TokenUser, token_user, n, &n)) 01007 { 01008 _dbus_win_warn_win_error ("GetTokenInformation failed", GetLastError ()); 01009 goto failed; 01010 } 01011 psid = token_user->User.Sid; 01012 if (!IsValidSid (psid)) 01013 { 01014 _dbus_verbose("%s invalid sid\n",__FUNCTION__); 01015 goto failed; 01016 } 01017 if (!ConvertSidToStringSidA (psid, sid)) 01018 { 01019 _dbus_verbose("%s invalid sid\n",__FUNCTION__); 01020 goto failed; 01021 } 01022 //okay: 01023 retval = TRUE; 01024 01025 failed: 01026 CloseHandle (process_handle); 01027 if (process_token != INVALID_HANDLE_VALUE) 01028 CloseHandle (process_token); 01029 01030 _dbus_verbose("_dbus_getsid() got '%s' and returns %d\n", *sid, retval); 01031 return retval; 01032 } 01033 #endif 01034 01035 /************************************************************************ 01036 01037 pipes 01038 01039 ************************************************************************/ 01040 01051 dbus_bool_t 01052 _dbus_full_duplex_pipe (int *fd1, 01053 int *fd2, 01054 dbus_bool_t blocking, 01055 DBusError *error) 01056 { 01057 SOCKET temp, socket1 = -1, socket2 = -1; 01058 struct sockaddr_in saddr; 01059 int len; 01060 u_long arg; 01061 01062 if (!_dbus_win_startup_winsock ()) 01063 { 01064 _DBUS_SET_OOM (error); 01065 return FALSE; 01066 } 01067 01068 temp = socket (AF_INET, SOCK_STREAM, 0); 01069 if (temp == INVALID_SOCKET) 01070 { 01071 DBUS_SOCKET_SET_ERRNO (); 01072 goto out0; 01073 } 01074 01075 _DBUS_ZERO (saddr); 01076 saddr.sin_family = AF_INET; 01077 saddr.sin_port = 0; 01078 saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); 01079 01080 if (bind (temp, (struct sockaddr *)&saddr, sizeof (saddr)) == SOCKET_ERROR) 01081 { 01082 DBUS_SOCKET_SET_ERRNO (); 01083 goto out0; 01084 } 01085 01086 if (listen (temp, 1) == SOCKET_ERROR) 01087 { 01088 DBUS_SOCKET_SET_ERRNO (); 01089 goto out0; 01090 } 01091 01092 len = sizeof (saddr); 01093 if (getsockname (temp, (struct sockaddr *)&saddr, &len) == SOCKET_ERROR) 01094 { 01095 DBUS_SOCKET_SET_ERRNO (); 01096 goto out0; 01097 } 01098 01099 socket1 = socket (AF_INET, SOCK_STREAM, 0); 01100 if (socket1 == INVALID_SOCKET) 01101 { 01102 DBUS_SOCKET_SET_ERRNO (); 01103 goto out0; 01104 } 01105 01106 if (connect (socket1, (struct sockaddr *)&saddr, len) == SOCKET_ERROR) 01107 { 01108 DBUS_SOCKET_SET_ERRNO (); 01109 goto out1; 01110 } 01111 01112 socket2 = accept (temp, (struct sockaddr *) &saddr, &len); 01113 if (socket2 == INVALID_SOCKET) 01114 { 01115 DBUS_SOCKET_SET_ERRNO (); 01116 goto out1; 01117 } 01118 01119 if (!blocking) 01120 { 01121 arg = 1; 01122 if (ioctlsocket (socket1, FIONBIO, &arg) == SOCKET_ERROR) 01123 { 01124 DBUS_SOCKET_SET_ERRNO (); 01125 goto out2; 01126 } 01127 01128 arg = 1; 01129 if (ioctlsocket (socket2, FIONBIO, &arg) == SOCKET_ERROR) 01130 { 01131 DBUS_SOCKET_SET_ERRNO (); 01132 goto out2; 01133 } 01134 } 01135 01136 *fd1 = socket1; 01137 *fd2 = socket2; 01138 01139 _dbus_verbose ("full-duplex pipe %d:%d <-> %d:%d\n", 01140 *fd1, socket1, *fd2, socket2); 01141 01142 closesocket (temp); 01143 01144 return TRUE; 01145 01146 out2: 01147 closesocket (socket2); 01148 out1: 01149 closesocket (socket1); 01150 out0: 01151 closesocket (temp); 01152 01153 dbus_set_error (error, _dbus_error_from_errno (errno), 01154 "Could not setup socket pair: %s", 01155 _dbus_strerror_from_errno ()); 01156 01157 return FALSE; 01158 } 01159 01168 int 01169 _dbus_poll (DBusPollFD *fds, 01170 int n_fds, 01171 int timeout_milliseconds) 01172 { 01173 #define USE_CHRIS_IMPL 0 01174 01175 #if USE_CHRIS_IMPL 01176 01177 #define DBUS_POLL_CHAR_BUFFER_SIZE 2000 01178 char msg[DBUS_POLL_CHAR_BUFFER_SIZE]; 01179 char *msgp; 01180 01181 int ret = 0; 01182 int i; 01183 struct timeval tv; 01184 int ready; 01185 01186 #define DBUS_STACK_WSAEVENTS 256 01187 WSAEVENT eventsOnStack[DBUS_STACK_WSAEVENTS]; 01188 WSAEVENT *pEvents = NULL; 01189 if (n_fds > DBUS_STACK_WSAEVENTS) 01190 pEvents = calloc(sizeof(WSAEVENT), n_fds); 01191 else 01192 pEvents = eventsOnStack; 01193 01194 01195 #ifdef DBUS_ENABLE_VERBOSE_MODE 01196 msgp = msg; 01197 msgp += sprintf (msgp, "WSAEventSelect: to=%d\n\t", timeout_milliseconds); 01198 for (i = 0; i < n_fds; i++) 01199 { 01200 DBusPollFD *fdp = &fds[i]; 01201 01202 01203 if (fdp->events & _DBUS_POLLIN) 01204 msgp += sprintf (msgp, "R:%d ", fdp->fd); 01205 01206 if (fdp->events & _DBUS_POLLOUT) 01207 msgp += sprintf (msgp, "W:%d ", fdp->fd); 01208 01209 msgp += sprintf (msgp, "E:%d\n\t", fdp->fd); 01210 01211 // FIXME: more robust code for long msg 01212 // create on heap when msg[] becomes too small 01213 if (msgp >= msg + DBUS_POLL_CHAR_BUFFER_SIZE) 01214 { 01215 _dbus_assert_not_reached ("buffer overflow in _dbus_poll"); 01216 } 01217 } 01218 01219 msgp += sprintf (msgp, "\n"); 01220 _dbus_verbose ("%s",msg); 01221 #endif 01222 for (i = 0; i < n_fds; i++) 01223 { 01224 DBusPollFD *fdp = &fds[i]; 01225 WSAEVENT ev; 01226 long lNetworkEvents = FD_OOB; 01227 01228 ev = WSACreateEvent(); 01229 01230 if (fdp->events & _DBUS_POLLIN) 01231 lNetworkEvents |= FD_READ | FD_ACCEPT | FD_CLOSE; 01232 01233 if (fdp->events & _DBUS_POLLOUT) 01234 lNetworkEvents |= FD_WRITE | FD_CONNECT; 01235 01236 WSAEventSelect(fdp->fd, ev, lNetworkEvents); 01237 01238 pEvents[i] = ev; 01239 } 01240 01241 01242 ready = WSAWaitForMultipleEvents (n_fds, pEvents, FALSE, timeout_milliseconds, FALSE); 01243 01244 if (DBUS_SOCKET_API_RETURNS_ERROR (ready)) 01245 { 01246 DBUS_SOCKET_SET_ERRNO (); 01247 if (errno != WSAEWOULDBLOCK) 01248 _dbus_verbose ("WSAWaitForMultipleEvents: failed: %s\n", _dbus_strerror_from_errno ()); 01249 ret = -1; 01250 } 01251 else if (ready == WSA_WAIT_TIMEOUT) 01252 { 01253 _dbus_verbose ("WSAWaitForMultipleEvents: WSA_WAIT_TIMEOUT\n"); 01254 ret = 0; 01255 } 01256 else if (ready >= WSA_WAIT_EVENT_0 && ready < (int)(WSA_WAIT_EVENT_0 + n_fds)) 01257 { 01258 msgp = msg; 01259 msgp += sprintf (msgp, "WSAWaitForMultipleEvents: =%d\n\t", ready); 01260 01261 for (i = 0; i < n_fds; i++) 01262 { 01263 DBusPollFD *fdp = &fds[i]; 01264 WSANETWORKEVENTS ne; 01265 01266 fdp->revents = 0; 01267 01268 WSAEnumNetworkEvents(fdp->fd, pEvents[i], &ne); 01269 01270 if (ne.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) 01271 fdp->revents |= _DBUS_POLLIN; 01272 01273 if (ne.lNetworkEvents & (FD_WRITE | FD_CONNECT)) 01274 fdp->revents |= _DBUS_POLLOUT; 01275 01276 if (ne.lNetworkEvents & (FD_OOB)) 01277 fdp->revents |= _DBUS_POLLERR; 01278 01279 if (ne.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) 01280 msgp += sprintf (msgp, "R:%d ", fdp->fd); 01281 01282 if (ne.lNetworkEvents & (FD_WRITE | FD_CONNECT)) 01283 msgp += sprintf (msgp, "W:%d ", fdp->fd); 01284 01285 if (ne.lNetworkEvents & (FD_OOB)) 01286 msgp += sprintf (msgp, "E:%d ", fdp->fd); 01287 01288 msgp += sprintf (msgp, "lNetworkEvents:%d ", ne.lNetworkEvents); 01289 01290 if(ne.lNetworkEvents) 01291 ret++; 01292 01293 WSAEventSelect(fdp->fd, pEvents[i], 0); 01294 } 01295 01296 msgp += sprintf (msgp, "\n"); 01297 _dbus_verbose ("%s",msg); 01298 } 01299 else 01300 { 01301 _dbus_verbose ("WSAWaitForMultipleEvents: failed for unknown reason!"); 01302 ret = -1; 01303 } 01304 01305 for(i = 0; i < n_fds; i++) 01306 { 01307 WSACloseEvent(pEvents[i]); 01308 } 01309 01310 if (n_fds > DBUS_STACK_WSAEVENTS) 01311 free(pEvents); 01312 01313 return ret; 01314 01315 #else /* USE_CHRIS_IMPL */ 01316 01317 #define DBUS_POLL_CHAR_BUFFER_SIZE 2000 01318 char msg[DBUS_POLL_CHAR_BUFFER_SIZE]; 01319 char *msgp; 01320 01321 fd_set read_set, write_set, err_set; 01322 int max_fd = 0; 01323 int i; 01324 struct timeval tv; 01325 int ready; 01326 01327 FD_ZERO (&read_set); 01328 FD_ZERO (&write_set); 01329 FD_ZERO (&err_set); 01330 01331 01332 #ifdef DBUS_ENABLE_VERBOSE_MODE 01333 msgp = msg; 01334 msgp += sprintf (msgp, "select: to=%d\n\t", timeout_milliseconds); 01335 for (i = 0; i < n_fds; i++) 01336 { 01337 DBusPollFD *fdp = &fds[i]; 01338 01339 01340 if (fdp->events & _DBUS_POLLIN) 01341 msgp += sprintf (msgp, "R:%d ", fdp->fd); 01342 01343 if (fdp->events & _DBUS_POLLOUT) 01344 msgp += sprintf (msgp, "W:%d ", fdp->fd); 01345 01346 msgp += sprintf (msgp, "E:%d\n\t", fdp->fd); 01347 01348 // FIXME: more robust code for long msg 01349 // create on heap when msg[] becomes too small 01350 if (msgp >= msg + DBUS_POLL_CHAR_BUFFER_SIZE) 01351 { 01352 _dbus_assert_not_reached ("buffer overflow in _dbus_poll"); 01353 } 01354 } 01355 01356 msgp += sprintf (msgp, "\n"); 01357 _dbus_verbose ("%s",msg); 01358 #endif 01359 for (i = 0; i < n_fds; i++) 01360 { 01361 DBusPollFD *fdp = &fds[i]; 01362 01363 if (fdp->events & _DBUS_POLLIN) 01364 FD_SET (fdp->fd, &read_set); 01365 01366 if (fdp->events & _DBUS_POLLOUT) 01367 FD_SET (fdp->fd, &write_set); 01368 01369 FD_SET (fdp->fd, &err_set); 01370 01371 max_fd = MAX (max_fd, fdp->fd); 01372 } 01373 01374 // Avoid random lockups with send(), for lack of a better solution so far 01375 tv.tv_sec = timeout_milliseconds < 0 ? 1 : timeout_milliseconds / 1000; 01376 tv.tv_usec = timeout_milliseconds < 0 ? 0 : (timeout_milliseconds % 1000) * 1000; 01377 01378 ready = select (max_fd + 1, &read_set, &write_set, &err_set, &tv); 01379 01380 if (DBUS_SOCKET_API_RETURNS_ERROR (ready)) 01381 { 01382 DBUS_SOCKET_SET_ERRNO (); 01383 if (errno != WSAEWOULDBLOCK) 01384 _dbus_verbose ("select: failed: %s\n", _dbus_strerror_from_errno ()); 01385 } 01386 else if (ready == 0) 01387 _dbus_verbose ("select: = 0\n"); 01388 else 01389 if (ready > 0) 01390 { 01391 #ifdef DBUS_ENABLE_VERBOSE_MODE 01392 msgp = msg; 01393 msgp += sprintf (msgp, "select: = %d:\n\t", ready); 01394 01395 for (i = 0; i < n_fds; i++) 01396 { 01397 DBusPollFD *fdp = &fds[i]; 01398 01399 if (FD_ISSET (fdp->fd, &read_set)) 01400 msgp += sprintf (msgp, "R:%d ", fdp->fd); 01401 01402 if (FD_ISSET (fdp->fd, &write_set)) 01403 msgp += sprintf (msgp, "W:%d ", fdp->fd); 01404 01405 if (FD_ISSET (fdp->fd, &err_set)) 01406 msgp += sprintf (msgp, "E:%d\n\t", fdp->fd); 01407 } 01408 msgp += sprintf (msgp, "\n"); 01409 _dbus_verbose ("%s",msg); 01410 #endif 01411 01412 for (i = 0; i < n_fds; i++) 01413 { 01414 DBusPollFD *fdp = &fds[i]; 01415 01416 fdp->revents = 0; 01417 01418 if (FD_ISSET (fdp->fd, &read_set)) 01419 fdp->revents |= _DBUS_POLLIN; 01420 01421 if (FD_ISSET (fdp->fd, &write_set)) 01422 fdp->revents |= _DBUS_POLLOUT; 01423 01424 if (FD_ISSET (fdp->fd, &err_set)) 01425 fdp->revents |= _DBUS_POLLERR; 01426 } 01427 } 01428 return ready; 01429 #endif /* USE_CHRIS_IMPL */ 01430 } 01431 01432 01433 01434 01435 /****************************************************************************** 01436 01437 Original CVS version of dbus-sysdeps.c 01438 01439 ******************************************************************************/ 01440 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 01441 /* dbus-sysdeps.c Wrappers around system/libc features (internal to D-Bus implementation) 01442 * 01443 * Copyright (C) 2002, 2003 Red Hat, Inc. 01444 * Copyright (C) 2003 CodeFactory AB 01445 * Copyright (C) 2005 Novell, Inc. 01446 * 01447 * Licensed under the Academic Free License version 2.1 01448 * 01449 * This program is free software; you can redistribute it and/or modify 01450 * it under the terms of the GNU General Public License as published by 01451 * the Free Software Foundation; either version 2 of the License, or 01452 * (at your option) any later version. 01453 * 01454 * This program is distributed in the hope that it will be useful, 01455 * but WITHOUT ANY WARRANTY; without even the implied warranty of 01456 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 01457 * GNU General Public License for more details. 01458 * 01459 * You should have received a copy of the GNU General Public License 01460 * along with this program; if not, write to the Free Software 01461 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 01462 * 01463 */ 01464 01465 01471 void 01472 _dbus_exit (int code) 01473 { 01474 _exit (code); 01475 } 01476 01488 int 01489 _dbus_connect_tcp_socket (const char *host, 01490 const char *port, 01491 const char *family, 01492 DBusError *error) 01493 { 01494 return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error); 01495 } 01496 01497 int 01498 _dbus_connect_tcp_socket_with_nonce (const char *host, 01499 const char *port, 01500 const char *family, 01501 const char *noncefile, 01502 DBusError *error) 01503 { 01504 int fd = -1, res; 01505 struct addrinfo hints; 01506 struct addrinfo *ai, *tmp; 01507 01508 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01509 01510 if (!_dbus_win_startup_winsock ()) 01511 { 01512 _DBUS_SET_OOM (error); 01513 return -1; 01514 } 01515 01516 _DBUS_ZERO (hints); 01517 01518 if (!family) 01519 hints.ai_family = AF_UNSPEC; 01520 else if (!strcmp(family, "ipv4")) 01521 hints.ai_family = AF_INET; 01522 else if (!strcmp(family, "ipv6")) 01523 hints.ai_family = AF_INET6; 01524 else 01525 { 01526 dbus_set_error (error, 01527 DBUS_ERROR_INVALID_ARGS, 01528 "Unknown address family %s", family); 01529 return -1; 01530 } 01531 hints.ai_protocol = IPPROTO_TCP; 01532 hints.ai_socktype = SOCK_STREAM; 01533 #ifdef AI_ADDRCONFIG 01534 hints.ai_flags = AI_ADDRCONFIG; 01535 #else 01536 hints.ai_flags = 0; 01537 #endif 01538 01539 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai) 01540 { 01541 dbus_set_error (error, 01542 _dbus_error_from_errno (res), 01543 "Failed to lookup host/port: \"%s:%s\": %s (%d)", 01544 host, port, _dbus_strerror(res), res); 01545 return -1; 01546 } 01547 01548 tmp = ai; 01549 while (tmp) 01550 { 01551 if ((fd = socket (tmp->ai_family, SOCK_STREAM, 0)) == INVALID_SOCKET) 01552 { 01553 DBUS_SOCKET_SET_ERRNO (); 01554 dbus_set_error (error, 01555 _dbus_error_from_errno (errno), 01556 "Failed to open socket: %s", 01557 _dbus_strerror_from_errno ()); 01558 freeaddrinfo(ai); 01559 return -1; 01560 } 01561 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01562 01563 if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) == SOCKET_ERROR) 01564 { 01565 DBUS_SOCKET_SET_ERRNO (); 01566 closesocket(fd); 01567 fd = -1; 01568 tmp = tmp->ai_next; 01569 continue; 01570 } 01571 01572 break; 01573 } 01574 freeaddrinfo(ai); 01575 01576 if (fd == -1) 01577 { 01578 dbus_set_error (error, 01579 _dbus_error_from_errno (errno), 01580 "Failed to connect to socket \"%s:%s\" %s", 01581 host, port, _dbus_strerror_from_errno ()); 01582 return -1; 01583 } 01584 01585 if (noncefile != NULL) 01586 { 01587 DBusString noncefileStr; 01588 dbus_bool_t ret; 01589 if (!_dbus_string_init (&noncefileStr) || 01590 !_dbus_string_append(&noncefileStr, noncefile)) 01591 { 01592 closesocket (fd); 01593 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01594 return -1; 01595 } 01596 01597 ret = _dbus_send_nonce (fd, &noncefileStr, error); 01598 01599 _dbus_string_free (&noncefileStr); 01600 01601 if (!ret) 01602 { 01603 closesocket (fd); 01604 return -1; 01605 } 01606 } 01607 01608 _dbus_fd_set_close_on_exec (fd); 01609 01610 if (!_dbus_set_fd_nonblocking (fd, error)) 01611 { 01612 closesocket (fd); 01613 return -1; 01614 } 01615 01616 return fd; 01617 } 01618 01634 int 01635 _dbus_listen_tcp_socket (const char *host, 01636 const char *port, 01637 const char *family, 01638 DBusString *retport, 01639 int **fds_p, 01640 DBusError *error) 01641 { 01642 int nlisten_fd = 0, *listen_fd = NULL, res, i, port_num = -1; 01643 struct addrinfo hints; 01644 struct addrinfo *ai, *tmp; 01645 01646 // On Vista, sockaddr_gen must be a sockaddr_in6, and not a sockaddr_in6_old 01647 //That's required for family == IPv6(which is the default on Vista if family is not given) 01648 //So we use our own union instead of sockaddr_gen: 01649 01650 typedef union { 01651 struct sockaddr Address; 01652 struct sockaddr_in AddressIn; 01653 struct sockaddr_in6 AddressIn6; 01654 } mysockaddr_gen; 01655 01656 *fds_p = NULL; 01657 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01658 01659 if (!_dbus_win_startup_winsock ()) 01660 { 01661 _DBUS_SET_OOM (error); 01662 return -1; 01663 } 01664 01665 _DBUS_ZERO (hints); 01666 01667 if (!family) 01668 hints.ai_family = AF_UNSPEC; 01669 else if (!strcmp(family, "ipv4")) 01670 hints.ai_family = AF_INET; 01671 else if (!strcmp(family, "ipv6")) 01672 hints.ai_family = AF_INET6; 01673 else 01674 { 01675 dbus_set_error (error, 01676 DBUS_ERROR_INVALID_ARGS, 01677 "Unknown address family %s", family); 01678 return -1; 01679 } 01680 01681 hints.ai_protocol = IPPROTO_TCP; 01682 hints.ai_socktype = SOCK_STREAM; 01683 #ifdef AI_ADDRCONFIG 01684 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE; 01685 #else 01686 hints.ai_flags = AI_PASSIVE; 01687 #endif 01688 01689 redo_lookup_with_port: 01690 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai) 01691 { 01692 dbus_set_error (error, 01693 _dbus_error_from_errno (res), 01694 "Failed to lookup host/port: \"%s:%s\": %s (%d)", 01695 host ? host : "*", port, _dbus_strerror(res), res); 01696 return -1; 01697 } 01698 01699 tmp = ai; 01700 while (tmp) 01701 { 01702 int fd = -1, *newlisten_fd; 01703 if ((fd = socket (tmp->ai_family, SOCK_STREAM, 0)) == INVALID_SOCKET) 01704 { 01705 DBUS_SOCKET_SET_ERRNO (); 01706 dbus_set_error (error, 01707 _dbus_error_from_errno (errno), 01708 "Failed to open socket: %s", 01709 _dbus_strerror_from_errno ()); 01710 goto failed; 01711 } 01712 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01713 01714 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) == SOCKET_ERROR) 01715 { 01716 DBUS_SOCKET_SET_ERRNO (); 01717 closesocket (fd); 01718 if (errno == WSAEADDRINUSE) 01719 { 01720 /* Calling this function with port=0 tries to 01721 * bind the same port twice, so we should 01722 * ignore the second bind. 01723 */ 01724 tmp = tmp->ai_next; 01725 continue; 01726 } 01727 dbus_set_error (error, _dbus_error_from_errno (errno), 01728 "Failed to bind socket \"%s:%s\": %s", 01729 host ? host : "*", port, _dbus_strerror_from_errno ()); 01730 goto failed; 01731 } 01732 01733 if (listen (fd, 30 /* backlog */) == SOCKET_ERROR) 01734 { 01735 DBUS_SOCKET_SET_ERRNO (); 01736 dbus_set_error (error, _dbus_error_from_errno (errno), 01737 "Failed to listen on socket \"%s:%s\": %s", 01738 host ? host : "*", port, _dbus_strerror_from_errno ()); 01739 closesocket (fd); 01740 goto failed; 01741 } 01742 01743 newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1)); 01744 if (!newlisten_fd) 01745 { 01746 closesocket (fd); 01747 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, 01748 "Failed to allocate file handle array"); 01749 goto failed; 01750 } 01751 listen_fd = newlisten_fd; 01752 listen_fd[nlisten_fd] = fd; 01753 nlisten_fd++; 01754 01755 if (!_dbus_string_get_length(retport)) 01756 { 01757 /* If the user didn't specify a port, or used 0, then 01758 the kernel chooses a port. After the first address 01759 is bound to, we need to force all remaining addresses 01760 to use the same port */ 01761 if (!port || !strcmp(port, "0")) 01762 { 01763 mysockaddr_gen addr; 01764 socklen_t addrlen = sizeof(addr); 01765 char portbuf[10]; 01766 01767 if (getsockname(fd, &addr.Address, &addrlen) == SOCKET_ERROR) 01768 { 01769 DBUS_SOCKET_SET_ERRNO (); 01770 dbus_set_error (error, _dbus_error_from_errno (errno), 01771 "Failed to resolve port \"%s:%s\": %s", 01772 host ? host : "*", port, _dbus_strerror_from_errno()); 01773 goto failed; 01774 } 01775 if (addr.AddressIn.sin_family = AF_INET) 01776 snprintf( portbuf, sizeof( portbuf ) - 1, "%d", ntohs(addr.AddressIn.sin_port) ); 01777 else 01778 snprintf( portbuf, sizeof( portbuf ) - 1, "%d", ntohs(addr.AddressIn6.sin6_port) ); 01779 if (!_dbus_string_append(retport, portbuf)) 01780 { 01781 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01782 goto failed; 01783 } 01784 01785 /* Release current address list & redo lookup */ 01786 port = _dbus_string_get_const_data(retport); 01787 freeaddrinfo(ai); 01788 goto redo_lookup_with_port; 01789 } 01790 else 01791 { 01792 if (!_dbus_string_append(retport, port)) 01793 { 01794 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01795 goto failed; 01796 } 01797 } 01798 } 01799 01800 tmp = tmp->ai_next; 01801 } 01802 freeaddrinfo(ai); 01803 ai = NULL; 01804 01805 if (!nlisten_fd) 01806 { 01807 _dbus_win_set_errno (WSAEADDRINUSE); 01808 dbus_set_error (error, _dbus_error_from_errno (errno), 01809 "Failed to bind socket \"%s:%s\": %s", 01810 host ? host : "*", port, _dbus_strerror_from_errno ()); 01811 return -1; 01812 } 01813 01814 sscanf(_dbus_string_get_const_data(retport), "%d", &port_num); 01815 01816 for (i = 0 ; i < nlisten_fd ; i++) 01817 { 01818 _dbus_fd_set_close_on_exec (listen_fd[i]); 01819 if (!_dbus_set_fd_nonblocking (listen_fd[i], error)) 01820 { 01821 goto failed; 01822 } 01823 } 01824 01825 *fds_p = listen_fd; 01826 01827 return nlisten_fd; 01828 01829 failed: 01830 if (ai) 01831 freeaddrinfo(ai); 01832 for (i = 0 ; i < nlisten_fd ; i++) 01833 closesocket (listen_fd[i]); 01834 dbus_free(listen_fd); 01835 return -1; 01836 } 01837 01838 01846 int 01847 _dbus_accept (int listen_fd) 01848 { 01849 int client_fd; 01850 01851 retry: 01852 client_fd = accept (listen_fd, NULL, NULL); 01853 01854 if (DBUS_SOCKET_IS_INVALID (client_fd)) 01855 { 01856 DBUS_SOCKET_SET_ERRNO (); 01857 if (errno == EINTR) 01858 goto retry; 01859 } 01860 01861 _dbus_verbose ("client fd %d accepted\n", client_fd); 01862 01863 return client_fd; 01864 } 01865 01866 01867 01868 01869 dbus_bool_t 01870 _dbus_send_credentials_socket (int handle, 01871 DBusError *error) 01872 { 01873 /* FIXME: for the session bus credentials shouldn't matter (?), but 01874 * for the system bus they are presumably essential. A rough outline 01875 * of a way to implement the credential transfer would be this: 01876 * 01877 * client waits to *read* a byte. 01878 * 01879 * server creates a named pipe with a random name, sends a byte 01880 * contining its length, and its name. 01881 * 01882 * client reads the name, connects to it (using Win32 API). 01883 * 01884 * server waits for connection to the named pipe, then calls 01885 * ImpersonateNamedPipeClient(), notes its now-current credentials, 01886 * calls RevertToSelf(), closes its handles to the named pipe, and 01887 * is done. (Maybe there is some other way to get the SID of a named 01888 * pipe client without having to use impersonation?) 01889 * 01890 * client closes its handles and is done. 01891 * 01892 * Ralf: Why not sending credentials over the given this connection ? 01893 * Using named pipes makes it impossible to be connected from a unix client. 01894 * 01895 */ 01896 int bytes_written; 01897 DBusString buf; 01898 01899 _dbus_string_init_const_len (&buf, "\0", 1); 01900 again: 01901 bytes_written = _dbus_write_socket (handle, &buf, 0, 1 ); 01902 01903 if (bytes_written < 0 && errno == EINTR) 01904 goto again; 01905 01906 if (bytes_written < 0) 01907 { 01908 dbus_set_error (error, _dbus_error_from_errno (errno), 01909 "Failed to write credentials byte: %s", 01910 _dbus_strerror_from_errno ()); 01911 return FALSE; 01912 } 01913 else if (bytes_written == 0) 01914 { 01915 dbus_set_error (error, DBUS_ERROR_IO_ERROR, 01916 "wrote zero bytes writing credentials byte"); 01917 return FALSE; 01918 } 01919 else 01920 { 01921 _dbus_assert (bytes_written == 1); 01922 _dbus_verbose ("wrote 1 zero byte, credential sending isn't implemented yet\n"); 01923 return TRUE; 01924 } 01925 return TRUE; 01926 } 01927 01946 dbus_bool_t 01947 _dbus_read_credentials_socket (int handle, 01948 DBusCredentials *credentials, 01949 DBusError *error) 01950 { 01951 int bytes_read = 0; 01952 DBusString buf; 01953 01954 char *sid = NULL; 01955 dbus_pid_t pid; 01956 int retval = FALSE; 01957 01958 // could fail due too OOM 01959 if (_dbus_string_init (&buf)) 01960 { 01961 bytes_read = _dbus_read_socket (handle, &buf, 1 ); 01962 01963 if (bytes_read > 0) 01964 _dbus_verbose ("got one zero byte from server\n"); 01965 01966 _dbus_string_free (&buf); 01967 } 01968 01969 pid = _dbus_get_peer_pid_from_tcp_handle (handle); 01970 if (pid == 0) 01971 return TRUE; 01972 01973 _dbus_credentials_add_pid (credentials, pid); 01974 01975 if (_dbus_getsid (&sid, pid)) 01976 { 01977 if (!_dbus_credentials_add_windows_sid (credentials, sid)) 01978 goto out; 01979 } 01980 01981 retval = TRUE; 01982 01983 out: 01984 if (sid) 01985 LocalFree (sid); 01986 01987 return retval; 01988 } 01989 01998 dbus_bool_t 01999 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error) 02000 { 02001 /* TODO */ 02002 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02003 return TRUE; 02004 } 02005 02006 02017 dbus_bool_t 02018 _dbus_concat_dir_and_file (DBusString *dir, 02019 const DBusString *next_component) 02020 { 02021 dbus_bool_t dir_ends_in_slash; 02022 dbus_bool_t file_starts_with_slash; 02023 02024 if (_dbus_string_get_length (dir) == 0 || 02025 _dbus_string_get_length (next_component) == 0) 02026 return TRUE; 02027 02028 dir_ends_in_slash = 02029 ('/' == _dbus_string_get_byte (dir, _dbus_string_get_length (dir) - 1) || 02030 '\\' == _dbus_string_get_byte (dir, _dbus_string_get_length (dir) - 1)); 02031 02032 file_starts_with_slash = 02033 ('/' == _dbus_string_get_byte (next_component, 0) || 02034 '\\' == _dbus_string_get_byte (next_component, 0)); 02035 02036 if (dir_ends_in_slash && file_starts_with_slash) 02037 { 02038 _dbus_string_shorten (dir, 1); 02039 } 02040 else if (!(dir_ends_in_slash || file_starts_with_slash)) 02041 { 02042 if (!_dbus_string_append_byte (dir, '\\')) 02043 return FALSE; 02044 } 02045 02046 return _dbus_string_copy (next_component, 0, dir, 02047 _dbus_string_get_length (dir)); 02048 } 02049 02050 /*---------------- DBusCredentials ----------------------------------*/ 02051 02059 dbus_bool_t 02060 _dbus_credentials_add_from_user (DBusCredentials *credentials, 02061 const DBusString *username) 02062 { 02063 return _dbus_credentials_add_windows_sid (credentials, 02064 _dbus_string_get_const_data(username)); 02065 } 02066 02075 dbus_bool_t 02076 _dbus_credentials_add_from_current_process (DBusCredentials *credentials) 02077 { 02078 dbus_bool_t retval = FALSE; 02079 char *sid = NULL; 02080 02081 if (!_dbus_getsid(&sid, _dbus_getpid())) 02082 goto failed; 02083 02084 if (!_dbus_credentials_add_pid (credentials, _dbus_getpid())) 02085 goto failed; 02086 02087 if (!_dbus_credentials_add_windows_sid (credentials,sid)) 02088 goto failed; 02089 02090 retval = TRUE; 02091 goto end; 02092 failed: 02093 retval = FALSE; 02094 end: 02095 if (sid) 02096 LocalFree(sid); 02097 02098 return retval; 02099 } 02100 02113 dbus_bool_t 02114 _dbus_append_user_from_current_process (DBusString *str) 02115 { 02116 dbus_bool_t retval = FALSE; 02117 char *sid = NULL; 02118 02119 if (!_dbus_getsid(&sid, _dbus_getpid())) 02120 return FALSE; 02121 02122 retval = _dbus_string_append (str,sid); 02123 02124 LocalFree(sid); 02125 return retval; 02126 } 02127 02132 dbus_pid_t 02133 _dbus_getpid (void) 02134 { 02135 return GetCurrentProcessId (); 02136 } 02137 02139 #define NANOSECONDS_PER_SECOND 1000000000 02140 02141 #define MICROSECONDS_PER_SECOND 1000000 02142 02143 #define MILLISECONDS_PER_SECOND 1000 02144 02145 #define NANOSECONDS_PER_MILLISECOND 1000000 02146 02147 #define MICROSECONDS_PER_MILLISECOND 1000 02148 02153 void 02154 _dbus_sleep_milliseconds (int milliseconds) 02155 { 02156 Sleep (milliseconds); 02157 } 02158 02159 02167 void 02168 _dbus_get_real_time (long *tv_sec, 02169 long *tv_usec) 02170 { 02171 FILETIME ft; 02172 dbus_uint64_t time64; 02173 02174 GetSystemTimeAsFileTime (&ft); 02175 02176 memcpy (&time64, &ft, sizeof (time64)); 02177 02178 /* Convert from 100s of nanoseconds since 1601-01-01 02179 * to Unix epoch. Yes, this is Y2038 unsafe. 02180 */ 02181 time64 -= DBUS_INT64_CONSTANT (116444736000000000); 02182 time64 /= 10; 02183 02184 if (tv_sec) 02185 *tv_sec = time64 / 1000000; 02186 02187 if (tv_usec) 02188 *tv_usec = time64 % 1000000; 02189 } 02190 02198 void 02199 _dbus_get_monotonic_time (long *tv_sec, 02200 long *tv_usec) 02201 { 02202 /* no implementation yet, fall back to wall-clock time */ 02203 _dbus_get_real_time (tv_sec, tv_usec); 02204 } 02205 02209 void 02210 _dbus_disable_sigpipe (void) 02211 { 02212 } 02213 02222 dbus_bool_t 02223 _dbus_create_directory (const DBusString *filename, 02224 DBusError *error) 02225 { 02226 const char *filename_c; 02227 02228 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02229 02230 filename_c = _dbus_string_get_const_data (filename); 02231 02232 if (!CreateDirectoryA (filename_c, NULL)) 02233 { 02234 if (GetLastError () == ERROR_ALREADY_EXISTS) 02235 return TRUE; 02236 02237 dbus_set_error (error, DBUS_ERROR_FAILED, 02238 "Failed to create directory %s: %s\n", 02239 filename_c, _dbus_strerror_from_errno ()); 02240 return FALSE; 02241 } 02242 else 02243 return TRUE; 02244 } 02245 02246 02255 dbus_bool_t 02256 _dbus_generate_random_bytes (DBusString *str, 02257 int n_bytes) 02258 { 02259 int old_len; 02260 char *p; 02261 HCRYPTPROV hprov; 02262 02263 old_len = _dbus_string_get_length (str); 02264 02265 if (!_dbus_string_lengthen (str, n_bytes)) 02266 return FALSE; 02267 02268 p = _dbus_string_get_data_len (str, old_len, n_bytes); 02269 02270 if (!CryptAcquireContext (&hprov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) 02271 return FALSE; 02272 02273 if (!CryptGenRandom (hprov, n_bytes, p)) 02274 { 02275 CryptReleaseContext (hprov, 0); 02276 return FALSE; 02277 } 02278 02279 CryptReleaseContext (hprov, 0); 02280 02281 return TRUE; 02282 } 02283 02290 const char* 02291 _dbus_get_tmpdir(void) 02292 { 02293 /* Protected by _DBUS_LOCK_sysdeps */ 02294 static const char* tmpdir = NULL; 02295 static char buf[1000]; 02296 02297 if (!_DBUS_LOCK (sysdeps)) 02298 return NULL; 02299 02300 if (tmpdir == NULL) 02301 { 02302 char *last_slash; 02303 02304 if (!GetTempPathA (sizeof (buf), buf)) 02305 { 02306 _dbus_warn ("GetTempPath failed\n"); 02307 _dbus_abort (); 02308 } 02309 02310 /* Drop terminating backslash or slash */ 02311 last_slash = _mbsrchr (buf, '\\'); 02312 if (last_slash > buf && last_slash[1] == '\0') 02313 last_slash[0] = '\0'; 02314 last_slash = _mbsrchr (buf, '/'); 02315 if (last_slash > buf && last_slash[1] == '\0') 02316 last_slash[0] = '\0'; 02317 02318 tmpdir = buf; 02319 } 02320 02321 _DBUS_UNLOCK (sysdeps); 02322 02323 _dbus_assert(tmpdir != NULL); 02324 02325 return tmpdir; 02326 } 02327 02328 02337 dbus_bool_t 02338 _dbus_delete_file (const DBusString *filename, 02339 DBusError *error) 02340 { 02341 const char *filename_c; 02342 02343 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02344 02345 filename_c = _dbus_string_get_const_data (filename); 02346 02347 if (DeleteFileA (filename_c) == 0) 02348 { 02349 dbus_set_error (error, DBUS_ERROR_FAILED, 02350 "Failed to delete file %s: %s\n", 02351 filename_c, _dbus_strerror_from_errno ()); 02352 return FALSE; 02353 } 02354 else 02355 return TRUE; 02356 } 02357 02358 #if !defined (DBUS_DISABLE_ASSERT) || defined(DBUS_ENABLE_EMBEDDED_TESTS) 02359 02360 #if defined(_MSC_VER) || defined(DBUS_WINCE) 02361 # ifdef BACKTRACES 02362 # undef BACKTRACES 02363 # endif 02364 #else 02365 # define BACKTRACES 02366 #endif 02367 02368 #ifdef BACKTRACES 02369 /* 02370 * Backtrace Generator 02371 * 02372 * Copyright 2004 Eric Poech 02373 * Copyright 2004 Robert Shearman 02374 * 02375 * This library is free software; you can redistribute it and/or 02376 * modify it under the terms of the GNU Lesser General Public 02377 * License as published by the Free Software Foundation; either 02378 * version 2.1 of the License, or (at your option) any later version. 02379 * 02380 * This library is distributed in the hope that it will be useful, 02381 * but WITHOUT ANY WARRANTY; without even the implied warranty of 02382 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 02383 * Lesser General Public License for more details. 02384 * 02385 * You should have received a copy of the GNU Lesser General Public 02386 * License along with this library; if not, write to the Free Software 02387 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 02388 */ 02389 02390 #include <winver.h> 02391 #include <imagehlp.h> 02392 #include <stdio.h> 02393 02394 #define DPRINTF _dbus_warn 02395 02396 #ifdef _MSC_VER 02397 #define BOOL int 02398 02399 #define __i386__ 02400 #endif 02401 02402 //#define MAKE_FUNCPTR(f) static typeof(f) * p##f 02403 02404 //MAKE_FUNCPTR(StackWalk); 02405 //MAKE_FUNCPTR(SymGetModuleBase); 02406 //MAKE_FUNCPTR(SymFunctionTableAccess); 02407 //MAKE_FUNCPTR(SymInitialize); 02408 //MAKE_FUNCPTR(SymGetSymFromAddr); 02409 //MAKE_FUNCPTR(SymGetModuleInfo); 02410 static BOOL (WINAPI *pStackWalk)( 02411 DWORD MachineType, 02412 HANDLE hProcess, 02413 HANDLE hThread, 02414 LPSTACKFRAME StackFrame, 02415 PVOID ContextRecord, 02416 PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine, 02417 PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine, 02418 PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine, 02419 PTRANSLATE_ADDRESS_ROUTINE TranslateAddress 02420 ); 02421 #ifdef _WIN64 02422 static DWORD64 (WINAPI *pSymGetModuleBase)( 02423 HANDLE hProcess, 02424 DWORD64 dwAddr 02425 ); 02426 static PVOID (WINAPI *pSymFunctionTableAccess)( 02427 HANDLE hProcess, 02428 DWORD64 AddrBase 02429 ); 02430 #else 02431 static DWORD (WINAPI *pSymGetModuleBase)( 02432 HANDLE hProcess, 02433 DWORD dwAddr 02434 ); 02435 static PVOID (WINAPI *pSymFunctionTableAccess)( 02436 HANDLE hProcess, 02437 DWORD AddrBase 02438 ); 02439 #endif 02440 static BOOL (WINAPI *pSymInitialize)( 02441 HANDLE hProcess, 02442 PSTR UserSearchPath, 02443 BOOL fInvadeProcess 02444 ); 02445 static BOOL (WINAPI *pSymGetSymFromAddr)( 02446 HANDLE hProcess, 02447 DWORD Address, 02448 PDWORD Displacement, 02449 PIMAGEHLP_SYMBOL Symbol 02450 ); 02451 static BOOL (WINAPI *pSymGetModuleInfo)( 02452 HANDLE hProcess, 02453 DWORD dwAddr, 02454 PIMAGEHLP_MODULE ModuleInfo 02455 ); 02456 static DWORD (WINAPI *pSymSetOptions)( 02457 DWORD SymOptions 02458 ); 02459 02460 02461 static BOOL init_backtrace() 02462 { 02463 HMODULE hmodDbgHelp = LoadLibraryA("dbghelp"); 02464 /* 02465 #define GETFUNC(x) \ 02466 p##x = (typeof(x)*)GetProcAddress(hmodDbgHelp, #x); \ 02467 if (!p##x) \ 02468 { \ 02469 return FALSE; \ 02470 } 02471 */ 02472 02473 02474 // GETFUNC(StackWalk); 02475 // GETFUNC(SymGetModuleBase); 02476 // GETFUNC(SymFunctionTableAccess); 02477 // GETFUNC(SymInitialize); 02478 // GETFUNC(SymGetSymFromAddr); 02479 // GETFUNC(SymGetModuleInfo); 02480 02481 #define FUNC(x) #x 02482 02483 pStackWalk = (BOOL (WINAPI *)( 02484 DWORD MachineType, 02485 HANDLE hProcess, 02486 HANDLE hThread, 02487 LPSTACKFRAME StackFrame, 02488 PVOID ContextRecord, 02489 PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine, 02490 PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine, 02491 PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine, 02492 PTRANSLATE_ADDRESS_ROUTINE TranslateAddress 02493 ))GetProcAddress (hmodDbgHelp, FUNC(StackWalk)); 02494 #ifdef _WIN64 02495 pSymGetModuleBase=(DWORD64 (WINAPI *)( 02496 HANDLE hProcess, 02497 DWORD64 dwAddr 02498 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleBase)); 02499 pSymFunctionTableAccess=(PVOID (WINAPI *)( 02500 HANDLE hProcess, 02501 DWORD64 AddrBase 02502 ))GetProcAddress (hmodDbgHelp, FUNC(SymFunctionTableAccess)); 02503 #else 02504 pSymGetModuleBase=(DWORD (WINAPI *)( 02505 HANDLE hProcess, 02506 DWORD dwAddr 02507 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleBase)); 02508 pSymFunctionTableAccess=(PVOID (WINAPI *)( 02509 HANDLE hProcess, 02510 DWORD AddrBase 02511 ))GetProcAddress (hmodDbgHelp, FUNC(SymFunctionTableAccess)); 02512 #endif 02513 pSymInitialize = (BOOL (WINAPI *)( 02514 HANDLE hProcess, 02515 PSTR UserSearchPath, 02516 BOOL fInvadeProcess 02517 ))GetProcAddress (hmodDbgHelp, FUNC(SymInitialize)); 02518 pSymGetSymFromAddr = (BOOL (WINAPI *)( 02519 HANDLE hProcess, 02520 DWORD Address, 02521 PDWORD Displacement, 02522 PIMAGEHLP_SYMBOL Symbol 02523 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetSymFromAddr)); 02524 pSymGetModuleInfo = (BOOL (WINAPI *)( 02525 HANDLE hProcess, 02526 DWORD dwAddr, 02527 PIMAGEHLP_MODULE ModuleInfo 02528 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleInfo)); 02529 pSymSetOptions = (DWORD (WINAPI *)( 02530 DWORD SymOptions 02531 ))GetProcAddress (hmodDbgHelp, FUNC(SymSetOptions)); 02532 02533 02534 pSymSetOptions(SYMOPT_UNDNAME); 02535 02536 pSymInitialize(GetCurrentProcess(), NULL, TRUE); 02537 02538 return TRUE; 02539 } 02540 02541 static void dump_backtrace_for_thread(HANDLE hThread) 02542 { 02543 STACKFRAME sf; 02544 CONTEXT context; 02545 DWORD dwImageType; 02546 02547 if (!pStackWalk) 02548 if (!init_backtrace()) 02549 return; 02550 02551 /* can't use this function for current thread as GetThreadContext 02552 * doesn't support getting context from current thread */ 02553 if (hThread == GetCurrentThread()) 02554 return; 02555 02556 DPRINTF("Backtrace:\n"); 02557 02558 _DBUS_ZERO(context); 02559 context.ContextFlags = CONTEXT_FULL; 02560 02561 SuspendThread(hThread); 02562 02563 if (!GetThreadContext(hThread, &context)) 02564 { 02565 DPRINTF("Couldn't get thread context (error %ld)\n", GetLastError()); 02566 ResumeThread(hThread); 02567 return; 02568 } 02569 02570 _DBUS_ZERO(sf); 02571 02572 #ifdef __i386__ 02573 sf.AddrFrame.Offset = context.Ebp; 02574 sf.AddrFrame.Mode = AddrModeFlat; 02575 sf.AddrPC.Offset = context.Eip; 02576 sf.AddrPC.Mode = AddrModeFlat; 02577 dwImageType = IMAGE_FILE_MACHINE_I386; 02578 #elif _M_X64 02579 dwImageType = IMAGE_FILE_MACHINE_AMD64; 02580 sf.AddrPC.Offset = context.Rip; 02581 sf.AddrPC.Mode = AddrModeFlat; 02582 sf.AddrFrame.Offset = context.Rsp; 02583 sf.AddrFrame.Mode = AddrModeFlat; 02584 sf.AddrStack.Offset = context.Rsp; 02585 sf.AddrStack.Mode = AddrModeFlat; 02586 #elif _M_IA64 02587 dwImageType = IMAGE_FILE_MACHINE_IA64; 02588 sf.AddrPC.Offset = context.StIIP; 02589 sf.AddrPC.Mode = AddrModeFlat; 02590 sf.AddrFrame.Offset = context.IntSp; 02591 sf.AddrFrame.Mode = AddrModeFlat; 02592 sf.AddrBStore.Offset= context.RsBSP; 02593 sf.AddrBStore.Mode = AddrModeFlat; 02594 sf.AddrStack.Offset = context.IntSp; 02595 sf.AddrStack.Mode = AddrModeFlat; 02596 #else 02597 # error You need to fill in the STACKFRAME structure for your architecture 02598 #endif 02599 02600 while (pStackWalk(dwImageType, GetCurrentProcess(), 02601 hThread, &sf, &context, NULL, pSymFunctionTableAccess, 02602 pSymGetModuleBase, NULL)) 02603 { 02604 BYTE buffer[256]; 02605 IMAGEHLP_SYMBOL * pSymbol = (IMAGEHLP_SYMBOL *)buffer; 02606 DWORD dwDisplacement; 02607 02608 pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); 02609 pSymbol->MaxNameLength = sizeof(buffer) - sizeof(IMAGEHLP_SYMBOL) + 1; 02610 02611 if (!pSymGetSymFromAddr(GetCurrentProcess(), sf.AddrPC.Offset, 02612 &dwDisplacement, pSymbol)) 02613 { 02614 IMAGEHLP_MODULE ModuleInfo; 02615 ModuleInfo.SizeOfStruct = sizeof(ModuleInfo); 02616 02617 if (!pSymGetModuleInfo(GetCurrentProcess(), sf.AddrPC.Offset, 02618 &ModuleInfo)) 02619 DPRINTF("1\t%p\n", (void*)sf.AddrPC.Offset); 02620 else 02621 DPRINTF("2\t%s+0x%lx\n", ModuleInfo.ImageName, 02622 sf.AddrPC.Offset - ModuleInfo.BaseOfImage); 02623 } 02624 else if (dwDisplacement) 02625 DPRINTF("3\t%s+0x%lx\n", pSymbol->Name, dwDisplacement); 02626 else 02627 DPRINTF("4\t%s\n", pSymbol->Name); 02628 } 02629 02630 ResumeThread(hThread); 02631 } 02632 02633 static DWORD WINAPI dump_thread_proc(LPVOID lpParameter) 02634 { 02635 dump_backtrace_for_thread((HANDLE)lpParameter); 02636 return 0; 02637 } 02638 02639 /* cannot get valid context from current thread, so we have to execute 02640 * backtrace from another thread */ 02641 static void dump_backtrace() 02642 { 02643 HANDLE hCurrentThread; 02644 HANDLE hThread; 02645 DWORD dwThreadId; 02646 DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), 02647 GetCurrentProcess(), &hCurrentThread, 0, FALSE, DUPLICATE_SAME_ACCESS); 02648 hThread = CreateThread(NULL, 0, dump_thread_proc, (LPVOID)hCurrentThread, 02649 0, &dwThreadId); 02650 WaitForSingleObject(hThread, INFINITE); 02651 CloseHandle(hThread); 02652 CloseHandle(hCurrentThread); 02653 } 02654 #endif 02655 #endif /* asserts or tests enabled */ 02656 02657 #ifdef BACKTRACES 02658 void _dbus_print_backtrace(void) 02659 { 02660 init_backtrace(); 02661 dump_backtrace(); 02662 } 02663 #else 02664 void _dbus_print_backtrace(void) 02665 { 02666 _dbus_verbose (" D-Bus not compiled with backtrace support\n"); 02667 } 02668 #endif 02669 02670 static dbus_uint32_t fromAscii(char ascii) 02671 { 02672 if(ascii >= '0' && ascii <= '9') 02673 return ascii - '0'; 02674 if(ascii >= 'A' && ascii <= 'F') 02675 return ascii - 'A' + 10; 02676 if(ascii >= 'a' && ascii <= 'f') 02677 return ascii - 'a' + 10; 02678 return 0; 02679 } 02680 02681 dbus_bool_t _dbus_read_local_machine_uuid (DBusGUID *machine_id, 02682 dbus_bool_t create_if_not_found, 02683 DBusError *error) 02684 { 02685 #ifdef DBUS_WINCE 02686 return TRUE; 02687 // TODO 02688 #else 02689 HW_PROFILE_INFOA info; 02690 char *lpc = &info.szHwProfileGuid[0]; 02691 dbus_uint32_t u; 02692 02693 // the hw-profile guid lives long enough 02694 if(!GetCurrentHwProfileA(&info)) 02695 { 02696 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); // FIXME 02697 return FALSE; 02698 } 02699 02700 // Form: {12340001-4980-1920-6788-123456789012} 02701 lpc++; 02702 // 12340001 02703 u = ((fromAscii(lpc[0]) << 0) | 02704 (fromAscii(lpc[1]) << 4) | 02705 (fromAscii(lpc[2]) << 8) | 02706 (fromAscii(lpc[3]) << 12) | 02707 (fromAscii(lpc[4]) << 16) | 02708 (fromAscii(lpc[5]) << 20) | 02709 (fromAscii(lpc[6]) << 24) | 02710 (fromAscii(lpc[7]) << 28)); 02711 machine_id->as_uint32s[0] = u; 02712 02713 lpc += 9; 02714 // 4980-1920 02715 u = ((fromAscii(lpc[0]) << 0) | 02716 (fromAscii(lpc[1]) << 4) | 02717 (fromAscii(lpc[2]) << 8) | 02718 (fromAscii(lpc[3]) << 12) | 02719 (fromAscii(lpc[5]) << 16) | 02720 (fromAscii(lpc[6]) << 20) | 02721 (fromAscii(lpc[7]) << 24) | 02722 (fromAscii(lpc[8]) << 28)); 02723 machine_id->as_uint32s[1] = u; 02724 02725 lpc += 10; 02726 // 6788-1234 02727 u = ((fromAscii(lpc[0]) << 0) | 02728 (fromAscii(lpc[1]) << 4) | 02729 (fromAscii(lpc[2]) << 8) | 02730 (fromAscii(lpc[3]) << 12) | 02731 (fromAscii(lpc[5]) << 16) | 02732 (fromAscii(lpc[6]) << 20) | 02733 (fromAscii(lpc[7]) << 24) | 02734 (fromAscii(lpc[8]) << 28)); 02735 machine_id->as_uint32s[2] = u; 02736 02737 lpc += 9; 02738 // 56789012 02739 u = ((fromAscii(lpc[0]) << 0) | 02740 (fromAscii(lpc[1]) << 4) | 02741 (fromAscii(lpc[2]) << 8) | 02742 (fromAscii(lpc[3]) << 12) | 02743 (fromAscii(lpc[4]) << 16) | 02744 (fromAscii(lpc[5]) << 20) | 02745 (fromAscii(lpc[6]) << 24) | 02746 (fromAscii(lpc[7]) << 28)); 02747 machine_id->as_uint32s[3] = u; 02748 #endif 02749 return TRUE; 02750 } 02751 02752 static 02753 HANDLE _dbus_global_lock (const char *mutexname) 02754 { 02755 HANDLE mutex; 02756 DWORD gotMutex; 02757 02758 mutex = CreateMutexA( NULL, FALSE, mutexname ); 02759 if( !mutex ) 02760 { 02761 return FALSE; 02762 } 02763 02764 gotMutex = WaitForSingleObject( mutex, INFINITE ); 02765 switch( gotMutex ) 02766 { 02767 case WAIT_ABANDONED: 02768 ReleaseMutex (mutex); 02769 CloseHandle (mutex); 02770 return 0; 02771 case WAIT_FAILED: 02772 case WAIT_TIMEOUT: 02773 return 0; 02774 } 02775 02776 return mutex; 02777 } 02778 02779 static 02780 void _dbus_global_unlock (HANDLE mutex) 02781 { 02782 ReleaseMutex (mutex); 02783 CloseHandle (mutex); 02784 } 02785 02786 // for proper cleanup in dbus-daemon 02787 static HANDLE hDBusDaemonMutex = NULL; 02788 static HANDLE hDBusSharedMem = NULL; 02789 // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs 02790 static const char *cUniqueDBusInitMutex = "UniqueDBusInitMutex"; 02791 // sync _dbus_get_autolaunch_address 02792 static const char *cDBusAutolaunchMutex = "DBusAutolaunchMutex"; 02793 // mutex to determine if dbus-daemon is already started (per user) 02794 static const char *cDBusDaemonMutex = "DBusDaemonMutex"; 02795 // named shm for dbus adress info (per user) 02796 static const char *cDBusDaemonAddressInfo = "DBusDaemonAddressInfo"; 02797 02798 static dbus_bool_t 02799 _dbus_get_install_root_as_hash(DBusString *out) 02800 { 02801 DBusString install_path; 02802 02803 char path[MAX_PATH*2]; 02804 int path_size = sizeof(path); 02805 02806 if (!_dbus_get_install_root(path,path_size)) 02807 return FALSE; 02808 02809 _dbus_string_init(&install_path); 02810 _dbus_string_append(&install_path,path); 02811 02812 _dbus_string_init(out); 02813 _dbus_string_tolower_ascii(&install_path,0,_dbus_string_get_length(&install_path)); 02814 02815 if (!_dbus_sha_compute (&install_path, out)) 02816 return FALSE; 02817 02818 return TRUE; 02819 } 02820 02821 static dbus_bool_t 02822 _dbus_get_address_string (DBusString *out, const char *basestring, const char *scope) 02823 { 02824 _dbus_string_init(out); 02825 _dbus_string_append(out,basestring); 02826 02827 if (!scope) 02828 { 02829 return TRUE; 02830 } 02831 else if (strcmp(scope,"*install-path") == 0 02832 // for 1.3 compatibility 02833 || strcmp(scope,"install-path") == 0) 02834 { 02835 DBusString temp; 02836 if (!_dbus_get_install_root_as_hash(&temp)) 02837 { 02838 _dbus_string_free(out); 02839 return FALSE; 02840 } 02841 _dbus_string_append(out,"-"); 02842 _dbus_string_append(out,_dbus_string_get_const_data(&temp)); 02843 _dbus_string_free(&temp); 02844 } 02845 else if (strcmp(scope,"*user") == 0) 02846 { 02847 _dbus_string_append(out,"-"); 02848 if (!_dbus_append_user_from_current_process(out)) 02849 { 02850 _dbus_string_free(out); 02851 return FALSE; 02852 } 02853 } 02854 else if (strlen(scope) > 0) 02855 { 02856 _dbus_string_append(out,"-"); 02857 _dbus_string_append(out,scope); 02858 return TRUE; 02859 } 02860 return TRUE; 02861 } 02862 02863 static dbus_bool_t 02864 _dbus_get_shm_name (DBusString *out,const char *scope) 02865 { 02866 return _dbus_get_address_string (out,cDBusDaemonAddressInfo,scope); 02867 } 02868 02869 static dbus_bool_t 02870 _dbus_get_mutex_name (DBusString *out,const char *scope) 02871 { 02872 return _dbus_get_address_string (out,cDBusDaemonMutex,scope); 02873 } 02874 02875 dbus_bool_t 02876 _dbus_daemon_is_session_bus_address_published (const char *scope) 02877 { 02878 HANDLE lock; 02879 DBusString mutex_name; 02880 02881 if (!_dbus_get_mutex_name(&mutex_name,scope)) 02882 { 02883 _dbus_string_free( &mutex_name ); 02884 return FALSE; 02885 } 02886 02887 if (hDBusDaemonMutex) 02888 return TRUE; 02889 02890 // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs 02891 lock = _dbus_global_lock( cUniqueDBusInitMutex ); 02892 02893 // we use CreateMutex instead of OpenMutex because of possible race conditions, 02894 // see http://msdn.microsoft.com/en-us/library/ms684315%28VS.85%29.aspx 02895 hDBusDaemonMutex = CreateMutexA( NULL, FALSE, _dbus_string_get_const_data(&mutex_name) ); 02896 02897 /* The client uses mutex ownership to detect a running server, so the server should do so too. 02898 Fortunally the client deletes the mutex in the lock protected area, so checking presence 02899 will work too. */ 02900 02901 _dbus_global_unlock( lock ); 02902 02903 _dbus_string_free( &mutex_name ); 02904 02905 if (hDBusDaemonMutex == NULL) 02906 return FALSE; 02907 if (GetLastError() == ERROR_ALREADY_EXISTS) 02908 { 02909 CloseHandle(hDBusDaemonMutex); 02910 hDBusDaemonMutex = NULL; 02911 return TRUE; 02912 } 02913 // mutex wasn't created before, so return false. 02914 // We leave the mutex name allocated for later reusage 02915 // in _dbus_daemon_publish_session_bus_address. 02916 return FALSE; 02917 } 02918 02919 dbus_bool_t 02920 _dbus_daemon_publish_session_bus_address (const char* address, const char *scope) 02921 { 02922 HANDLE lock; 02923 char *shared_addr = NULL; 02924 DBusString shm_name; 02925 DBusString mutex_name; 02926 02927 _dbus_assert (address); 02928 02929 if (!_dbus_get_mutex_name(&mutex_name,scope)) 02930 { 02931 _dbus_string_free( &mutex_name ); 02932 return FALSE; 02933 } 02934 02935 // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs 02936 lock = _dbus_global_lock( cUniqueDBusInitMutex ); 02937 02938 if (!hDBusDaemonMutex) 02939 { 02940 hDBusDaemonMutex = CreateMutexA( NULL, FALSE, _dbus_string_get_const_data(&mutex_name) ); 02941 } 02942 _dbus_string_free( &mutex_name ); 02943 02944 // acquire the mutex 02945 if (WaitForSingleObject( hDBusDaemonMutex, 10 ) != WAIT_OBJECT_0) 02946 { 02947 _dbus_global_unlock( lock ); 02948 CloseHandle( hDBusDaemonMutex ); 02949 return FALSE; 02950 } 02951 02952 if (!_dbus_get_shm_name(&shm_name,scope)) 02953 { 02954 _dbus_string_free( &shm_name ); 02955 _dbus_global_unlock( lock ); 02956 return FALSE; 02957 } 02958 02959 // create shm 02960 hDBusSharedMem = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 02961 0, strlen( address ) + 1, _dbus_string_get_const_data(&shm_name) ); 02962 _dbus_assert( hDBusSharedMem ); 02963 02964 shared_addr = MapViewOfFile( hDBusSharedMem, FILE_MAP_WRITE, 0, 0, 0 ); 02965 02966 _dbus_assert (shared_addr); 02967 02968 strcpy( shared_addr, address); 02969 02970 // cleanup 02971 UnmapViewOfFile( shared_addr ); 02972 02973 _dbus_global_unlock( lock ); 02974 _dbus_verbose( "published session bus address at %s\n",_dbus_string_get_const_data (&shm_name) ); 02975 02976 _dbus_string_free( &shm_name ); 02977 return TRUE; 02978 } 02979 02980 void 02981 _dbus_daemon_unpublish_session_bus_address (void) 02982 { 02983 HANDLE lock; 02984 02985 // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs 02986 lock = _dbus_global_lock( cUniqueDBusInitMutex ); 02987 02988 CloseHandle( hDBusSharedMem ); 02989 02990 hDBusSharedMem = NULL; 02991 02992 ReleaseMutex( hDBusDaemonMutex ); 02993 02994 CloseHandle( hDBusDaemonMutex ); 02995 02996 hDBusDaemonMutex = NULL; 02997 02998 _dbus_global_unlock( lock ); 02999 } 03000 03001 static dbus_bool_t 03002 _dbus_get_autolaunch_shm (DBusString *address, DBusString *shm_name) 03003 { 03004 HANDLE sharedMem; 03005 char *shared_addr; 03006 int i; 03007 03008 // read shm 03009 for(i=0;i<20;++i) { 03010 // we know that dbus-daemon is available, so we wait until shm is available 03011 sharedMem = OpenFileMappingA( FILE_MAP_READ, FALSE, _dbus_string_get_const_data(shm_name)); 03012 if( sharedMem == 0 ) 03013 Sleep( 100 ); 03014 if ( sharedMem != 0) 03015 break; 03016 } 03017 03018 if( sharedMem == 0 ) 03019 return FALSE; 03020 03021 shared_addr = MapViewOfFile( sharedMem, FILE_MAP_READ, 0, 0, 0 ); 03022 03023 if( !shared_addr ) 03024 return FALSE; 03025 03026 _dbus_string_init( address ); 03027 03028 _dbus_string_append( address, shared_addr ); 03029 03030 // cleanup 03031 UnmapViewOfFile( shared_addr ); 03032 03033 CloseHandle( sharedMem ); 03034 03035 return TRUE; 03036 } 03037 03038 static dbus_bool_t 03039 _dbus_daemon_already_runs (DBusString *address, DBusString *shm_name, const char *scope) 03040 { 03041 HANDLE lock; 03042 HANDLE daemon; 03043 DBusString mutex_name; 03044 dbus_bool_t bRet = TRUE; 03045 03046 if (!_dbus_get_mutex_name(&mutex_name,scope)) 03047 { 03048 _dbus_string_free( &mutex_name ); 03049 return FALSE; 03050 } 03051 03052 // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs 03053 lock = _dbus_global_lock( cUniqueDBusInitMutex ); 03054 03055 // do checks 03056 daemon = CreateMutexA( NULL, FALSE, _dbus_string_get_const_data(&mutex_name) ); 03057 if(WaitForSingleObject( daemon, 10 ) != WAIT_TIMEOUT) 03058 { 03059 ReleaseMutex (daemon); 03060 CloseHandle (daemon); 03061 03062 _dbus_global_unlock( lock ); 03063 _dbus_string_free( &mutex_name ); 03064 return FALSE; 03065 } 03066 03067 // read shm 03068 bRet = _dbus_get_autolaunch_shm( address, shm_name ); 03069 03070 // cleanup 03071 CloseHandle ( daemon ); 03072 03073 _dbus_global_unlock( lock ); 03074 _dbus_string_free( &mutex_name ); 03075 03076 return bRet; 03077 } 03078 03079 dbus_bool_t 03080 _dbus_get_autolaunch_address (const char *scope, DBusString *address, 03081 DBusError *error) 03082 { 03083 HANDLE mutex; 03084 STARTUPINFOA si; 03085 PROCESS_INFORMATION pi; 03086 dbus_bool_t retval = FALSE; 03087 LPSTR lpFile; 03088 char dbus_exe_path[MAX_PATH]; 03089 char dbus_args[MAX_PATH * 2]; 03090 const char * daemon_name = DBUS_DAEMON_NAME ".exe"; 03091 DBusString shm_name; 03092 03093 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03094 03095 if (!_dbus_get_shm_name(&shm_name,scope)) 03096 { 03097 dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not determine shm name"); 03098 return FALSE; 03099 } 03100 03101 mutex = _dbus_global_lock ( cDBusAutolaunchMutex ); 03102 03103 if (_dbus_daemon_already_runs(address,&shm_name,scope)) 03104 { 03105 _dbus_verbose( "found running dbus daemon at %s\n", 03106 _dbus_string_get_const_data (&shm_name) ); 03107 retval = TRUE; 03108 goto out; 03109 } 03110 03111 if (!SearchPathA(NULL, daemon_name, NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile)) 03112 { 03113 // Look in directory containing dbus shared library 03114 HMODULE hmod; 03115 char dbus_module_path[MAX_PATH]; 03116 DWORD rc; 03117 03118 _dbus_verbose( "did not found dbus daemon executable on default search path, " 03119 "trying path where dbus shared library is located"); 03120 03121 hmod = _dbus_win_get_dll_hmodule(); 03122 rc = GetModuleFileNameA(hmod, dbus_module_path, sizeof(dbus_module_path)); 03123 if (rc <= 0) 03124 { 03125 dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not retrieve dbus shared library file name"); 03126 retval = FALSE; 03127 goto out; 03128 } 03129 else 03130 { 03131 char *ext_idx = strrchr(dbus_module_path, '\\'); 03132 if (ext_idx) 03133 *ext_idx = '\0'; 03134 if (!SearchPathA(dbus_module_path, daemon_name, NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile)) 03135 { 03136 dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not find dbus-daemon executable"); 03137 retval = FALSE; 03138 printf ("please add the path to %s to your PATH environment variable\n", daemon_name); 03139 printf ("or start the daemon manually\n\n"); 03140 goto out; 03141 } 03142 _dbus_verbose( "found dbus daemon executable at %s",dbus_module_path); 03143 } 03144 } 03145 03146 03147 // Create process 03148 ZeroMemory( &si, sizeof(si) ); 03149 si.cb = sizeof(si); 03150 ZeroMemory( &pi, sizeof(pi) ); 03151 03152 _snprintf(dbus_args, sizeof(dbus_args) - 1, "\"%s\" %s", dbus_exe_path, " --session"); 03153 03154 // argv[i] = "--config-file=bus\\session.conf"; 03155 // printf("create process \"%s\" %s\n", dbus_exe_path, dbus_args); 03156 if(CreateProcessA(dbus_exe_path, dbus_args, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) 03157 { 03158 CloseHandle (pi.hThread); 03159 CloseHandle (pi.hProcess); 03160 retval = _dbus_get_autolaunch_shm( address, &shm_name ); 03161 if (retval == FALSE) 03162 dbus_set_error_const (error, DBUS_ERROR_FAILED, "Failed to get autolaunch address from launched dbus-daemon"); 03163 } 03164 else 03165 { 03166 dbus_set_error_const (error, DBUS_ERROR_FAILED, "Failed to launch dbus-daemon"); 03167 retval = FALSE; 03168 } 03169 03170 out: 03171 if (retval) 03172 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03173 else 03174 _DBUS_ASSERT_ERROR_IS_SET (error); 03175 03176 _dbus_global_unlock (mutex); 03177 03178 return retval; 03179 } 03180 03181 03188 dbus_bool_t 03189 _dbus_make_file_world_readable(const DBusString *filename, 03190 DBusError *error) 03191 { 03192 // TODO 03193 return TRUE; 03194 } 03195 03203 dbus_int32_t 03204 _dbus_atomic_inc (DBusAtomic *atomic) 03205 { 03206 // +/- 1 is needed here! 03207 // no volatile argument with mingw 03208 return InterlockedIncrement (&atomic->value) - 1; 03209 } 03210 03218 dbus_int32_t 03219 _dbus_atomic_dec (DBusAtomic *atomic) 03220 { 03221 // +/- 1 is needed here! 03222 // no volatile argument with mingw 03223 return InterlockedDecrement (&atomic->value) + 1; 03224 } 03225 03233 dbus_int32_t 03234 _dbus_atomic_get (DBusAtomic *atomic) 03235 { 03236 /* In this situation, GLib issues a MemoryBarrier() and then returns 03237 * atomic->value. However, mingw from mingw.org (not to be confused with 03238 * mingw-w64 from mingw-w64.sf.net) does not have MemoryBarrier in its 03239 * headers, so we have to get a memory barrier some other way. 03240 * 03241 * InterlockedIncrement is older, and is documented on MSDN to be a full 03242 * memory barrier, so let's use that. 03243 */ 03244 long dummy = 0; 03245 03246 InterlockedExchange (&dummy, 1); 03247 03248 return atomic->value; 03249 } 03250 03258 void 03259 _dbus_flush_caches (void) 03260 { 03261 } 03262 03269 dbus_bool_t 03270 _dbus_get_is_errno_eagain_or_ewouldblock (void) 03271 { 03272 return errno == WSAEWOULDBLOCK; 03273 } 03274 03282 dbus_bool_t 03283 _dbus_get_install_root(char *prefix, int len) 03284 { 03285 //To find the prefix, we cut the filename and also \bin\ if present 03286 DWORD pathLength; 03287 char *lastSlash; 03288 SetLastError( 0 ); 03289 pathLength = GetModuleFileNameA(_dbus_win_get_dll_hmodule(), prefix, len); 03290 if ( pathLength == 0 || GetLastError() != 0 ) { 03291 *prefix = '\0'; 03292 return FALSE; 03293 } 03294 lastSlash = _mbsrchr(prefix, '\\'); 03295 if (lastSlash == NULL) { 03296 *prefix = '\0'; 03297 return FALSE; 03298 } 03299 //cut off binary name 03300 lastSlash[1] = 0; 03301 03302 //cut possible "\\bin" 03303 03304 //this fails if we are in a double-byte system codepage and the 03305 //folder's name happens to end with the *bytes* 03306 //"\\bin"... (I.e. the second byte of some Han character and then 03307 //the Latin "bin", but that is not likely I think... 03308 if (lastSlash - prefix >= 4 && strnicmp(lastSlash - 4, "\\bin", 4) == 0) 03309 lastSlash[-3] = 0; 03310 else if (lastSlash - prefix >= 10 && strnicmp(lastSlash - 10, "\\bin\\debug", 10) == 0) 03311 lastSlash[-9] = 0; 03312 else if (lastSlash - prefix >= 12 && strnicmp(lastSlash - 12, "\\bin\\release", 12) == 0) 03313 lastSlash[-11] = 0; 03314 03315 return TRUE; 03316 } 03317 03331 dbus_bool_t 03332 _dbus_get_config_file_name(DBusString *config_file, char *s) 03333 { 03334 char path[MAX_PATH*2]; 03335 int path_size = sizeof(path); 03336 03337 if (!_dbus_get_install_root(path,path_size)) 03338 return FALSE; 03339 03340 if(strlen(s) + 4 + strlen(path) > sizeof(path)-2) 03341 return FALSE; 03342 strcat(path,"etc\\"); 03343 strcat(path,s); 03344 if (_dbus_file_exists(path)) 03345 { 03346 // find path from executable 03347 if (!_dbus_string_append (config_file, path)) 03348 return FALSE; 03349 } 03350 else 03351 { 03352 if (!_dbus_get_install_root(path,path_size)) 03353 return FALSE; 03354 if(strlen(s) + 11 + strlen(path) > sizeof(path)-2) 03355 return FALSE; 03356 strcat(path,"etc\\dbus-1\\"); 03357 strcat(path,s); 03358 03359 if (_dbus_file_exists(path)) 03360 { 03361 if (!_dbus_string_append (config_file, path)) 03362 return FALSE; 03363 } 03364 else 03365 { 03366 if (!_dbus_get_install_root(path,path_size)) 03367 return FALSE; 03368 if(strlen(s) + 4 + strlen(path) > sizeof(path)-2) 03369 return FALSE; 03370 strcat(path,"bus\\"); 03371 strcat(path,s); 03372 03373 if (_dbus_file_exists(path)) 03374 { 03375 if (!_dbus_string_append (config_file, path)) 03376 return FALSE; 03377 } 03378 } 03379 } 03380 return TRUE; 03381 } 03382 03383 /* See comment in dbus-sysdeps-unix.c */ 03384 dbus_bool_t 03385 _dbus_lookup_session_address (dbus_bool_t *supported, 03386 DBusString *address, 03387 DBusError *error) 03388 { 03389 /* Probably fill this in with something based on COM? */ 03390 *supported = FALSE; 03391 return TRUE; 03392 } 03393 03407 dbus_bool_t 03408 _dbus_append_keyring_directory_for_credentials (DBusString *directory, 03409 DBusCredentials *credentials) 03410 { 03411 DBusString homedir; 03412 DBusString dotdir; 03413 const char *homepath; 03414 const char *homedrive; 03415 03416 _dbus_assert (credentials != NULL); 03417 _dbus_assert (!_dbus_credentials_are_anonymous (credentials)); 03418 03419 if (!_dbus_string_init (&homedir)) 03420 return FALSE; 03421 03422 homedrive = _dbus_getenv("HOMEDRIVE"); 03423 if (homedrive != NULL && *homedrive != '\0') 03424 { 03425 _dbus_string_append(&homedir,homedrive); 03426 } 03427 03428 homepath = _dbus_getenv("HOMEPATH"); 03429 if (homepath != NULL && *homepath != '\0') 03430 { 03431 _dbus_string_append(&homedir,homepath); 03432 } 03433 03434 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 03435 { 03436 const char *override; 03437 03438 override = _dbus_getenv ("DBUS_TEST_HOMEDIR"); 03439 if (override != NULL && *override != '\0') 03440 { 03441 _dbus_string_set_length (&homedir, 0); 03442 if (!_dbus_string_append (&homedir, override)) 03443 goto failed; 03444 03445 _dbus_verbose ("Using fake homedir for testing: %s\n", 03446 _dbus_string_get_const_data (&homedir)); 03447 } 03448 else 03449 { 03450 /* Not strictly thread-safe, but if we fail at thread-safety here, 03451 * the worst that will happen is some extra warnings. */ 03452 static dbus_bool_t already_warned = FALSE; 03453 if (!already_warned) 03454 { 03455 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n"); 03456 already_warned = TRUE; 03457 } 03458 } 03459 } 03460 #endif 03461 03462 #ifdef DBUS_WINCE 03463 /* It's not possible to create a .something directory in Windows CE 03464 using the file explorer. */ 03465 #define KEYRING_DIR "dbus-keyrings" 03466 #else 03467 #define KEYRING_DIR ".dbus-keyrings" 03468 #endif 03469 03470 _dbus_string_init_const (&dotdir, KEYRING_DIR); 03471 if (!_dbus_concat_dir_and_file (&homedir, 03472 &dotdir)) 03473 goto failed; 03474 03475 if (!_dbus_string_copy (&homedir, 0, 03476 directory, _dbus_string_get_length (directory))) { 03477 goto failed; 03478 } 03479 03480 _dbus_string_free (&homedir); 03481 return TRUE; 03482 03483 failed: 03484 _dbus_string_free (&homedir); 03485 return FALSE; 03486 } 03487 03493 dbus_bool_t 03494 _dbus_file_exists (const char *file) 03495 { 03496 DWORD attributes = GetFileAttributesA (file); 03497 03498 if (attributes != INVALID_FILE_ATTRIBUTES && GetLastError() != ERROR_PATH_NOT_FOUND) 03499 return TRUE; 03500 else 03501 return FALSE; 03502 } 03503 03511 const char* 03512 _dbus_strerror (int error_number) 03513 { 03514 #ifdef DBUS_WINCE 03515 // TODO 03516 return "unknown"; 03517 #else 03518 const char *msg; 03519 03520 switch (error_number) 03521 { 03522 case WSAEINTR: 03523 return "Interrupted function call"; 03524 case WSAEACCES: 03525 return "Permission denied"; 03526 case WSAEFAULT: 03527 return "Bad address"; 03528 case WSAEINVAL: 03529 return "Invalid argument"; 03530 case WSAEMFILE: 03531 return "Too many open files"; 03532 case WSAEWOULDBLOCK: 03533 return "Resource temporarily unavailable"; 03534 case WSAEINPROGRESS: 03535 return "Operation now in progress"; 03536 case WSAEALREADY: 03537 return "Operation already in progress"; 03538 case WSAENOTSOCK: 03539 return "Socket operation on nonsocket"; 03540 case WSAEDESTADDRREQ: 03541 return "Destination address required"; 03542 case WSAEMSGSIZE: 03543 return "Message too long"; 03544 case WSAEPROTOTYPE: 03545 return "Protocol wrong type for socket"; 03546 case WSAENOPROTOOPT: 03547 return "Bad protocol option"; 03548 case WSAEPROTONOSUPPORT: 03549 return "Protocol not supported"; 03550 case WSAESOCKTNOSUPPORT: 03551 return "Socket type not supported"; 03552 case WSAEOPNOTSUPP: 03553 return "Operation not supported"; 03554 case WSAEPFNOSUPPORT: 03555 return "Protocol family not supported"; 03556 case WSAEAFNOSUPPORT: 03557 return "Address family not supported by protocol family"; 03558 case WSAEADDRINUSE: 03559 return "Address already in use"; 03560 case WSAEADDRNOTAVAIL: 03561 return "Cannot assign requested address"; 03562 case WSAENETDOWN: 03563 return "Network is down"; 03564 case WSAENETUNREACH: 03565 return "Network is unreachable"; 03566 case WSAENETRESET: 03567 return "Network dropped connection on reset"; 03568 case WSAECONNABORTED: 03569 return "Software caused connection abort"; 03570 case WSAECONNRESET: 03571 return "Connection reset by peer"; 03572 case WSAENOBUFS: 03573 return "No buffer space available"; 03574 case WSAEISCONN: 03575 return "Socket is already connected"; 03576 case WSAENOTCONN: 03577 return "Socket is not connected"; 03578 case WSAESHUTDOWN: 03579 return "Cannot send after socket shutdown"; 03580 case WSAETIMEDOUT: 03581 return "Connection timed out"; 03582 case WSAECONNREFUSED: 03583 return "Connection refused"; 03584 case WSAEHOSTDOWN: 03585 return "Host is down"; 03586 case WSAEHOSTUNREACH: 03587 return "No route to host"; 03588 case WSAEPROCLIM: 03589 return "Too many processes"; 03590 case WSAEDISCON: 03591 return "Graceful shutdown in progress"; 03592 case WSATYPE_NOT_FOUND: 03593 return "Class type not found"; 03594 case WSAHOST_NOT_FOUND: 03595 return "Host not found"; 03596 case WSATRY_AGAIN: 03597 return "Nonauthoritative host not found"; 03598 case WSANO_RECOVERY: 03599 return "This is a nonrecoverable error"; 03600 case WSANO_DATA: 03601 return "Valid name, no data record of requested type"; 03602 case WSA_INVALID_HANDLE: 03603 return "Specified event object handle is invalid"; 03604 case WSA_INVALID_PARAMETER: 03605 return "One or more parameters are invalid"; 03606 case WSA_IO_INCOMPLETE: 03607 return "Overlapped I/O event object not in signaled state"; 03608 case WSA_IO_PENDING: 03609 return "Overlapped operations will complete later"; 03610 case WSA_NOT_ENOUGH_MEMORY: 03611 return "Insufficient memory available"; 03612 case WSA_OPERATION_ABORTED: 03613 return "Overlapped operation aborted"; 03614 #ifdef WSAINVALIDPROCTABLE 03615 03616 case WSAINVALIDPROCTABLE: 03617 return "Invalid procedure table from service provider"; 03618 #endif 03619 #ifdef WSAINVALIDPROVIDER 03620 03621 case WSAINVALIDPROVIDER: 03622 return "Invalid service provider version number"; 03623 #endif 03624 #ifdef WSAPROVIDERFAILEDINIT 03625 03626 case WSAPROVIDERFAILEDINIT: 03627 return "Unable to initialize a service provider"; 03628 #endif 03629 03630 case WSASYSCALLFAILURE: 03631 return "System call failure"; 03632 } 03633 msg = strerror (error_number); 03634 if (msg == NULL) 03635 msg = "unknown"; 03636 03637 return msg; 03638 #endif //DBUS_WINCE 03639 } 03640 03648 void 03649 _dbus_win_set_error_from_win_error (DBusError *error, 03650 int code) 03651 { 03652 char *msg; 03653 03654 /* As we want the English message, use the A API */ 03655 FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER | 03656 FORMAT_MESSAGE_IGNORE_INSERTS | 03657 FORMAT_MESSAGE_FROM_SYSTEM, 03658 NULL, code, MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US), 03659 (LPSTR) &msg, 0, NULL); 03660 if (msg) 03661 { 03662 char *msg_copy; 03663 03664 msg_copy = dbus_malloc (strlen (msg)); 03665 strcpy (msg_copy, msg); 03666 LocalFree (msg); 03667 03668 dbus_set_error (error, "win32.error", "%s", msg_copy); 03669 } 03670 else 03671 dbus_set_error (error, "win32.error", "Unknown error code %d or FormatMessage failed", code); 03672 } 03673 03674 void 03675 _dbus_win_warn_win_error (const char *message, 03676 unsigned long code) 03677 { 03678 DBusError error; 03679 03680 dbus_error_init (&error); 03681 _dbus_win_set_error_from_win_error (&error, code); 03682 _dbus_warn ("%s: %s\n", message, error.message); 03683 dbus_error_free (&error); 03684 } 03685 03693 dbus_bool_t 03694 _dbus_delete_directory (const DBusString *filename, 03695 DBusError *error) 03696 { 03697 const char *filename_c; 03698 03699 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03700 03701 filename_c = _dbus_string_get_const_data (filename); 03702 03703 if (RemoveDirectoryA (filename_c) == 0) 03704 { 03705 char *emsg = _dbus_win_error_string (GetLastError ()); 03706 dbus_set_error (error, _dbus_win_error_from_last_error (), 03707 "Failed to remove directory %s: %s", 03708 filename_c, emsg); 03709 _dbus_win_free_error_string (emsg); 03710 return FALSE; 03711 } 03712 03713 return TRUE; 03714 } 03715 03722 dbus_bool_t 03723 _dbus_path_is_absolute (const DBusString *filename) 03724 { 03725 if (_dbus_string_get_length (filename) > 0) 03726 return _dbus_string_get_byte (filename, 1) == ':' 03727 || _dbus_string_get_byte (filename, 0) == '\\' 03728 || _dbus_string_get_byte (filename, 0) == '/'; 03729 else 03730 return FALSE; 03731 } 03732 03733 03735 /* tests in dbus-sysdeps-util.c */ 03736
1.7.6.1