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