D-Bus 1.4.0
|
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 Ralf Habacker <ralf.habacker@freenet.de> 00008 * Copyright (C) 2006 Peter Kümmel <syntheticpp@gmx.net> 00009 * Copyright (C) 2006 Christian Ehrlicher <ch.ehrlicher@gmx.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-sysdeps.h" 00041 #include "dbus-threads.h" 00042 #include "dbus-protocol.h" 00043 #include "dbus-string.h" 00044 #include "dbus-sysdeps-win.h" 00045 #include "dbus-protocol.h" 00046 #include "dbus-hash.h" 00047 #include "dbus-sockets-win.h" 00048 #include "dbus-list.h" 00049 #include "dbus-nonce.h" 00050 #include "dbus-credentials.h" 00051 00052 #include <windows.h> 00053 #include <ws2tcpip.h> 00054 #include <wincrypt.h> 00055 00056 /* Declarations missing in mingw's headers */ 00057 extern BOOL WINAPI ConvertStringSidToSidA (LPCSTR StringSid, PSID *Sid); 00058 extern BOOL WINAPI ConvertSidToStringSidA (PSID Sid, LPSTR *StringSid); 00059 00060 #include <stdio.h> 00061 00062 #include <string.h> 00063 #if HAVE_ERRNO_H 00064 #include <errno.h> 00065 #endif 00066 #ifndef DBUS_WINCE 00067 #include <mbstring.h> 00068 #include <sys/stat.h> 00069 #include <sys/types.h> 00070 #endif 00071 00072 #ifdef HAVE_WS2TCPIP_H 00073 /* getaddrinfo for Windows CE (and Windows). */ 00074 #include <ws2tcpip.h> 00075 #endif 00076 00077 #ifdef HAVE_WSPIAPI_H 00078 // needed for w2k compatibility (getaddrinfo/freeaddrinfo/getnameinfo) 00079 #ifdef __GNUC__ 00080 #define _inline 00081 #include "wspiapi.h" 00082 #else 00083 #include <wspiapi.h> 00084 #endif 00085 #endif // HAVE_WSPIAPI_H 00086 00087 #ifndef O_BINARY 00088 #define O_BINARY 0 00089 #endif 00090 00091 typedef int socklen_t; 00092 00093 00094 void 00095 _dbus_win_set_errno (int err) 00096 { 00097 #ifdef DBUS_WINCE 00098 SetLastError (err); 00099 #else 00100 errno = err; 00101 #endif 00102 } 00103 00104 00105 /* Convert GetLastError() to a dbus error. */ 00106 const char* 00107 _dbus_win_error_from_last_error (void) 00108 { 00109 switch (GetLastError()) 00110 { 00111 case 0: 00112 return DBUS_ERROR_FAILED; 00113 00114 case ERROR_NO_MORE_FILES: 00115 case ERROR_TOO_MANY_OPEN_FILES: 00116 return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */ 00117 00118 case ERROR_ACCESS_DENIED: 00119 case ERROR_CANNOT_MAKE: 00120 return DBUS_ERROR_ACCESS_DENIED; 00121 00122 case ERROR_NOT_ENOUGH_MEMORY: 00123 return DBUS_ERROR_NO_MEMORY; 00124 00125 case ERROR_FILE_EXISTS: 00126 return DBUS_ERROR_FILE_EXISTS; 00127 00128 case ERROR_FILE_NOT_FOUND: 00129 case ERROR_PATH_NOT_FOUND: 00130 return DBUS_ERROR_FILE_NOT_FOUND; 00131 } 00132 00133 return DBUS_ERROR_FAILED; 00134 } 00135 00136 00137 char* 00138 _dbus_win_error_string (int error_number) 00139 { 00140 char *msg; 00141 00142 FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER | 00143 FORMAT_MESSAGE_IGNORE_INSERTS | 00144 FORMAT_MESSAGE_FROM_SYSTEM, 00145 NULL, error_number, 0, 00146 (LPSTR) &msg, 0, NULL); 00147 00148 if (msg[strlen (msg) - 1] == '\n') 00149 msg[strlen (msg) - 1] = '\0'; 00150 if (msg[strlen (msg) - 1] == '\r') 00151 msg[strlen (msg) - 1] = '\0'; 00152 00153 return msg; 00154 } 00155 00156 void 00157 _dbus_win_free_error_string (char *string) 00158 { 00159 LocalFree (string); 00160 } 00161 00182 int 00183 _dbus_read_socket (int fd, 00184 DBusString *buffer, 00185 int count) 00186 { 00187 int bytes_read; 00188 int start; 00189 char *data; 00190 00191 _dbus_assert (count >= 0); 00192 00193 start = _dbus_string_get_length (buffer); 00194 00195 if (!_dbus_string_lengthen (buffer, count)) 00196 { 00197 _dbus_win_set_errno (ENOMEM); 00198 return -1; 00199 } 00200 00201 data = _dbus_string_get_data_len (buffer, start, count); 00202 00203 again: 00204 00205 _dbus_verbose ("recv: count=%d fd=%d\n", count, fd); 00206 bytes_read = recv (fd, data, count, 0); 00207 00208 if (bytes_read == SOCKET_ERROR) 00209 { 00210 DBUS_SOCKET_SET_ERRNO(); 00211 _dbus_verbose ("recv: failed: %s (%d)\n", _dbus_strerror (errno), errno); 00212 bytes_read = -1; 00213 } 00214 else 00215 _dbus_verbose ("recv: = %d\n", bytes_read); 00216 00217 if (bytes_read < 0) 00218 { 00219 if (errno == EINTR) 00220 goto again; 00221 else 00222 { 00223 /* put length back (note that this doesn't actually realloc anything) */ 00224 _dbus_string_set_length (buffer, start); 00225 return -1; 00226 } 00227 } 00228 else 00229 { 00230 /* put length back (doesn't actually realloc) */ 00231 _dbus_string_set_length (buffer, start + bytes_read); 00232 00233 #if 0 00234 if (bytes_read > 0) 00235 _dbus_verbose_bytes_of_string (buffer, start, bytes_read); 00236 #endif 00237 00238 return bytes_read; 00239 } 00240 } 00241 00252 int 00253 _dbus_write_socket (int fd, 00254 const DBusString *buffer, 00255 int start, 00256 int len) 00257 { 00258 const char *data; 00259 int bytes_written; 00260 00261 data = _dbus_string_get_const_data_len (buffer, start, len); 00262 00263 again: 00264 00265 _dbus_verbose ("send: len=%d fd=%d\n", len, fd); 00266 bytes_written = send (fd, data, len, 0); 00267 00268 if (bytes_written == SOCKET_ERROR) 00269 { 00270 DBUS_SOCKET_SET_ERRNO(); 00271 _dbus_verbose ("send: failed: %s\n", _dbus_strerror_from_errno ()); 00272 bytes_written = -1; 00273 } 00274 else 00275 _dbus_verbose ("send: = %d\n", bytes_written); 00276 00277 if (bytes_written < 0 && errno == EINTR) 00278 goto again; 00279 00280 #if 0 00281 if (bytes_written > 0) 00282 _dbus_verbose_bytes_of_string (buffer, start, bytes_written); 00283 #endif 00284 00285 return bytes_written; 00286 } 00287 00288 00296 dbus_bool_t 00297 _dbus_close_socket (int fd, 00298 DBusError *error) 00299 { 00300 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00301 00302 again: 00303 if (closesocket (fd) == SOCKET_ERROR) 00304 { 00305 DBUS_SOCKET_SET_ERRNO (); 00306 00307 if (errno == EINTR) 00308 goto again; 00309 00310 dbus_set_error (error, _dbus_error_from_errno (errno), 00311 "Could not close socket: socket=%d, , %s", 00312 fd, _dbus_strerror_from_errno ()); 00313 return FALSE; 00314 } 00315 _dbus_verbose ("_dbus_close_socket: socket=%d, \n", fd); 00316 00317 return TRUE; 00318 } 00319 00327 void 00328 _dbus_fd_set_close_on_exec (intptr_t handle) 00329 { 00330 if ( !SetHandleInformation( (HANDLE) handle, 00331 HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE, 00332 0 /*disable both flags*/ ) ) 00333 { 00334 _dbus_win_warn_win_error ("Disabling socket handle inheritance failed:", GetLastError()); 00335 } 00336 } 00337 00345 dbus_bool_t 00346 _dbus_set_fd_nonblocking (int handle, 00347 DBusError *error) 00348 { 00349 u_long one = 1; 00350 00351 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00352 00353 if (ioctlsocket (handle, FIONBIO, &one) == SOCKET_ERROR) 00354 { 00355 DBUS_SOCKET_SET_ERRNO (); 00356 dbus_set_error (error, _dbus_error_from_errno (errno), 00357 "Failed to set socket %d:%d to nonblocking: %s", handle, 00358 _dbus_strerror_from_errno ()); 00359 return FALSE; 00360 } 00361 00362 return TRUE; 00363 } 00364 00365 00386 int 00387 _dbus_write_socket_two (int fd, 00388 const DBusString *buffer1, 00389 int start1, 00390 int len1, 00391 const DBusString *buffer2, 00392 int start2, 00393 int len2) 00394 { 00395 WSABUF vectors[2]; 00396 const char *data1; 00397 const char *data2; 00398 int rc; 00399 DWORD bytes_written; 00400 00401 _dbus_assert (buffer1 != NULL); 00402 _dbus_assert (start1 >= 0); 00403 _dbus_assert (start2 >= 0); 00404 _dbus_assert (len1 >= 0); 00405 _dbus_assert (len2 >= 0); 00406 00407 00408 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1); 00409 00410 if (buffer2 != NULL) 00411 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2); 00412 else 00413 { 00414 data2 = NULL; 00415 start2 = 0; 00416 len2 = 0; 00417 } 00418 00419 vectors[0].buf = (char*) data1; 00420 vectors[0].len = len1; 00421 vectors[1].buf = (char*) data2; 00422 vectors[1].len = len2; 00423 00424 again: 00425 00426 _dbus_verbose ("WSASend: len1+2=%d+%d fd=%d\n", len1, len2, fd); 00427 rc = WSASend (fd, 00428 vectors, 00429 data2 ? 2 : 1, 00430 &bytes_written, 00431 0, 00432 NULL, 00433 NULL); 00434 00435 if (rc == SOCKET_ERROR) 00436 { 00437 DBUS_SOCKET_SET_ERRNO (); 00438 _dbus_verbose ("WSASend: failed: %s\n", _dbus_strerror_from_errno ()); 00439 bytes_written = -1; 00440 } 00441 else 00442 _dbus_verbose ("WSASend: = %ld\n", bytes_written); 00443 00444 if (bytes_written < 0 && errno == EINTR) 00445 goto again; 00446 00447 return bytes_written; 00448 } 00449 00450 dbus_bool_t 00451 _dbus_socket_is_invalid (int fd) 00452 { 00453 return fd == INVALID_SOCKET ? TRUE : FALSE; 00454 } 00455 00456 #if 0 00457 00466 int 00467 _dbus_connect_named_pipe (const char *path, 00468 DBusError *error) 00469 { 00470 _dbus_assert_not_reached ("not implemented"); 00471 } 00472 00473 #endif 00474 00475 00476 00477 void 00478 _dbus_win_startup_winsock (void) 00479 { 00480 /* Straight from MSDN, deuglified */ 00481 00482 static dbus_bool_t beenhere = FALSE; 00483 00484 WORD wVersionRequested; 00485 WSADATA wsaData; 00486 int err; 00487 00488 if (beenhere) 00489 return; 00490 00491 wVersionRequested = MAKEWORD (2, 0); 00492 00493 err = WSAStartup (wVersionRequested, &wsaData); 00494 if (err != 0) 00495 { 00496 _dbus_assert_not_reached ("Could not initialize WinSock"); 00497 _dbus_abort (); 00498 } 00499 00500 /* Confirm that the WinSock DLL supports 2.0. Note that if the DLL 00501 * supports versions greater than 2.0 in addition to 2.0, it will 00502 * still return 2.0 in wVersion since that is the version we 00503 * requested. 00504 */ 00505 if (LOBYTE (wsaData.wVersion) != 2 || 00506 HIBYTE (wsaData.wVersion) != 0) 00507 { 00508 _dbus_assert_not_reached ("No usable WinSock found"); 00509 _dbus_abort (); 00510 } 00511 00512 beenhere = TRUE; 00513 } 00514 00515 00516 00517 00518 00519 00520 00521 00522 00523 /************************************************************************ 00524 00525 UTF / string code 00526 00527 ************************************************************************/ 00528 00532 int _dbus_printf_string_upper_bound (const char *format, 00533 va_list args) 00534 { 00535 /* MSVCRT's vsnprintf semantics are a bit different */ 00536 char buf[1024]; 00537 int bufsize; 00538 int len; 00539 00540 bufsize = sizeof (buf); 00541 len = _vsnprintf (buf, bufsize - 1, format, args); 00542 00543 while (len == -1) /* try again */ 00544 { 00545 char *p; 00546 00547 bufsize *= 2; 00548 00549 p = malloc (bufsize); 00550 len = _vsnprintf (p, bufsize - 1, format, args); 00551 free (p); 00552 } 00553 00554 return len; 00555 } 00556 00557 00565 wchar_t * 00566 _dbus_win_utf8_to_utf16 (const char *str, 00567 DBusError *error) 00568 { 00569 DBusString s; 00570 int n; 00571 wchar_t *retval; 00572 00573 _dbus_string_init_const (&s, str); 00574 00575 if (!_dbus_string_validate_utf8 (&s, 0, _dbus_string_get_length (&s))) 00576 { 00577 dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid UTF-8"); 00578 return NULL; 00579 } 00580 00581 n = MultiByteToWideChar (CP_UTF8, 0, str, -1, NULL, 0); 00582 00583 if (n == 0) 00584 { 00585 _dbus_win_set_error_from_win_error (error, GetLastError ()); 00586 return NULL; 00587 } 00588 00589 retval = dbus_new (wchar_t, n); 00590 00591 if (!retval) 00592 { 00593 _DBUS_SET_OOM (error); 00594 return NULL; 00595 } 00596 00597 if (MultiByteToWideChar (CP_UTF8, 0, str, -1, retval, n) != n) 00598 { 00599 dbus_free (retval); 00600 dbus_set_error_const (error, DBUS_ERROR_FAILED, "MultiByteToWideChar inconsistency"); 00601 return NULL; 00602 } 00603 00604 return retval; 00605 } 00606 00614 char * 00615 _dbus_win_utf16_to_utf8 (const wchar_t *str, 00616 DBusError *error) 00617 { 00618 int n; 00619 char *retval; 00620 00621 n = WideCharToMultiByte (CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL); 00622 00623 if (n == 0) 00624 { 00625 _dbus_win_set_error_from_win_error (error, GetLastError ()); 00626 return NULL; 00627 } 00628 00629 retval = dbus_malloc (n); 00630 00631 if (!retval) 00632 { 00633 _DBUS_SET_OOM (error); 00634 return NULL; 00635 } 00636 00637 if (WideCharToMultiByte (CP_UTF8, 0, str, -1, retval, n, NULL, NULL) != n) 00638 { 00639 dbus_free (retval); 00640 dbus_set_error_const (error, DBUS_ERROR_FAILED, "WideCharToMultiByte inconsistency"); 00641 return NULL; 00642 } 00643 00644 return retval; 00645 } 00646 00647 00648 00649 00650 00651 00652 /************************************************************************ 00653 00654 00655 ************************************************************************/ 00656 00657 dbus_bool_t 00658 _dbus_win_account_to_sid (const wchar_t *waccount, 00659 void **ppsid, 00660 DBusError *error) 00661 { 00662 dbus_bool_t retval = FALSE; 00663 DWORD sid_length, wdomain_length; 00664 SID_NAME_USE use; 00665 wchar_t *wdomain; 00666 00667 *ppsid = NULL; 00668 00669 sid_length = 0; 00670 wdomain_length = 0; 00671 if (!LookupAccountNameW (NULL, waccount, NULL, &sid_length, 00672 NULL, &wdomain_length, &use) && 00673 GetLastError () != ERROR_INSUFFICIENT_BUFFER) 00674 { 00675 _dbus_win_set_error_from_win_error (error, GetLastError ()); 00676 return FALSE; 00677 } 00678 00679 *ppsid = dbus_malloc (sid_length); 00680 if (!*ppsid) 00681 { 00682 _DBUS_SET_OOM (error); 00683 return FALSE; 00684 } 00685 00686 wdomain = dbus_new (wchar_t, wdomain_length); 00687 if (!wdomain) 00688 { 00689 _DBUS_SET_OOM (error); 00690 goto out1; 00691 } 00692 00693 if (!LookupAccountNameW (NULL, waccount, (PSID) *ppsid, &sid_length, 00694 wdomain, &wdomain_length, &use)) 00695 { 00696 _dbus_win_set_error_from_win_error (error, GetLastError ()); 00697 goto out2; 00698 } 00699 00700 if (!IsValidSid ((PSID) *ppsid)) 00701 { 00702 dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid SID"); 00703 goto out2; 00704 } 00705 00706 retval = TRUE; 00707 00708 out2: 00709 dbus_free (wdomain); 00710 out1: 00711 if (!retval) 00712 { 00713 dbus_free (*ppsid); 00714 *ppsid = NULL; 00715 } 00716 00717 return retval; 00718 } 00719 00729 unsigned long 00730 _dbus_pid_for_log (void) 00731 { 00732 return _dbus_getpid (); 00733 } 00734 00735 00736 #ifndef DBUS_WINCE 00737 00741 static dbus_bool_t 00742 _dbus_getsid(char **sid) 00743 { 00744 HANDLE process_token = INVALID_HANDLE_VALUE; 00745 TOKEN_USER *token_user = NULL; 00746 DWORD n; 00747 PSID psid; 00748 int retval = FALSE; 00749 00750 if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &process_token)) 00751 { 00752 _dbus_win_warn_win_error ("OpenProcessToken failed", GetLastError ()); 00753 goto failed; 00754 } 00755 if ((!GetTokenInformation (process_token, TokenUser, NULL, 0, &n) 00756 && GetLastError () != ERROR_INSUFFICIENT_BUFFER) 00757 || (token_user = alloca (n)) == NULL 00758 || !GetTokenInformation (process_token, TokenUser, token_user, n, &n)) 00759 { 00760 _dbus_win_warn_win_error ("GetTokenInformation failed", GetLastError ()); 00761 goto failed; 00762 } 00763 psid = token_user->User.Sid; 00764 if (!IsValidSid (psid)) 00765 { 00766 _dbus_verbose("%s invalid sid\n",__FUNCTION__); 00767 goto failed; 00768 } 00769 if (!ConvertSidToStringSidA (psid, sid)) 00770 { 00771 _dbus_verbose("%s invalid sid\n",__FUNCTION__); 00772 goto failed; 00773 } 00774 //okay: 00775 retval = TRUE; 00776 00777 failed: 00778 if (process_token != INVALID_HANDLE_VALUE) 00779 CloseHandle (process_token); 00780 00781 _dbus_verbose("_dbus_getsid() returns %d\n",retval); 00782 return retval; 00783 } 00784 #endif 00785 00786 /************************************************************************ 00787 00788 pipes 00789 00790 ************************************************************************/ 00791 00807 dbus_bool_t 00808 _dbus_full_duplex_pipe (int *fd1, 00809 int *fd2, 00810 dbus_bool_t blocking, 00811 DBusError *error) 00812 { 00813 SOCKET temp, socket1 = -1, socket2 = -1; 00814 struct sockaddr_in saddr; 00815 int len; 00816 u_long arg; 00817 fd_set read_set, write_set; 00818 struct timeval tv; 00819 int res; 00820 00821 _dbus_win_startup_winsock (); 00822 00823 temp = socket (AF_INET, SOCK_STREAM, 0); 00824 if (temp == INVALID_SOCKET) 00825 { 00826 DBUS_SOCKET_SET_ERRNO (); 00827 goto out0; 00828 } 00829 00830 _DBUS_ZERO (saddr); 00831 saddr.sin_family = AF_INET; 00832 saddr.sin_port = 0; 00833 saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); 00834 00835 if (bind (temp, (struct sockaddr *)&saddr, sizeof (saddr)) == SOCKET_ERROR) 00836 { 00837 DBUS_SOCKET_SET_ERRNO (); 00838 goto out0; 00839 } 00840 00841 if (listen (temp, 1) == SOCKET_ERROR) 00842 { 00843 DBUS_SOCKET_SET_ERRNO (); 00844 goto out0; 00845 } 00846 00847 len = sizeof (saddr); 00848 if (getsockname (temp, (struct sockaddr *)&saddr, &len) == SOCKET_ERROR) 00849 { 00850 DBUS_SOCKET_SET_ERRNO (); 00851 goto out0; 00852 } 00853 00854 socket1 = socket (AF_INET, SOCK_STREAM, 0); 00855 if (socket1 == INVALID_SOCKET) 00856 { 00857 DBUS_SOCKET_SET_ERRNO (); 00858 goto out0; 00859 } 00860 00861 if (connect (socket1, (struct sockaddr *)&saddr, len) == SOCKET_ERROR) 00862 { 00863 DBUS_SOCKET_SET_ERRNO (); 00864 goto out1; 00865 } 00866 00867 socket2 = accept (temp, (struct sockaddr *) &saddr, &len); 00868 if (socket2 == INVALID_SOCKET) 00869 { 00870 DBUS_SOCKET_SET_ERRNO (); 00871 goto out1; 00872 } 00873 00874 if (!blocking) 00875 { 00876 arg = 1; 00877 if (ioctlsocket (socket1, FIONBIO, &arg) == SOCKET_ERROR) 00878 { 00879 DBUS_SOCKET_SET_ERRNO (); 00880 goto out2; 00881 } 00882 00883 arg = 1; 00884 if (ioctlsocket (socket2, FIONBIO, &arg) == SOCKET_ERROR) 00885 { 00886 DBUS_SOCKET_SET_ERRNO (); 00887 goto out2; 00888 } 00889 } 00890 00891 *fd1 = socket1; 00892 *fd2 = socket2; 00893 00894 _dbus_verbose ("full-duplex pipe %d:%d <-> %d:%d\n", 00895 *fd1, socket1, *fd2, socket2); 00896 00897 closesocket (temp); 00898 00899 return TRUE; 00900 00901 out2: 00902 closesocket (socket2); 00903 out1: 00904 closesocket (socket1); 00905 out0: 00906 closesocket (temp); 00907 00908 dbus_set_error (error, _dbus_error_from_errno (errno), 00909 "Could not setup socket pair: %s", 00910 _dbus_strerror_from_errno ()); 00911 00912 return FALSE; 00913 } 00914 00923 int 00924 _dbus_poll (DBusPollFD *fds, 00925 int n_fds, 00926 int timeout_milliseconds) 00927 { 00928 #define USE_CHRIS_IMPL 0 00929 00930 #if USE_CHRIS_IMPL 00931 00932 #define DBUS_POLL_CHAR_BUFFER_SIZE 2000 00933 char msg[DBUS_POLL_CHAR_BUFFER_SIZE]; 00934 char *msgp; 00935 00936 int ret = 0; 00937 int i; 00938 struct timeval tv; 00939 int ready; 00940 00941 #define DBUS_STACK_WSAEVENTS 256 00942 WSAEVENT eventsOnStack[DBUS_STACK_WSAEVENTS]; 00943 WSAEVENT *pEvents = NULL; 00944 if (n_fds > DBUS_STACK_WSAEVENTS) 00945 pEvents = calloc(sizeof(WSAEVENT), n_fds); 00946 else 00947 pEvents = eventsOnStack; 00948 00949 00950 #ifdef DBUS_ENABLE_VERBOSE_MODE 00951 msgp = msg; 00952 msgp += sprintf (msgp, "WSAEventSelect: to=%d\n\t", timeout_milliseconds); 00953 for (i = 0; i < n_fds; i++) 00954 { 00955 static dbus_bool_t warned = FALSE; 00956 DBusPollFD *fdp = &fds[i]; 00957 00958 00959 if (fdp->events & _DBUS_POLLIN) 00960 msgp += sprintf (msgp, "R:%d ", fdp->fd); 00961 00962 if (fdp->events & _DBUS_POLLOUT) 00963 msgp += sprintf (msgp, "W:%d ", fdp->fd); 00964 00965 msgp += sprintf (msgp, "E:%d\n\t", fdp->fd); 00966 00967 // FIXME: more robust code for long msg 00968 // create on heap when msg[] becomes too small 00969 if (msgp >= msg + DBUS_POLL_CHAR_BUFFER_SIZE) 00970 { 00971 _dbus_assert_not_reached ("buffer overflow in _dbus_poll"); 00972 } 00973 } 00974 00975 msgp += sprintf (msgp, "\n"); 00976 _dbus_verbose ("%s",msg); 00977 #endif 00978 for (i = 0; i < n_fds; i++) 00979 { 00980 DBusPollFD *fdp = &fds[i]; 00981 WSAEVENT ev; 00982 long lNetworkEvents = FD_OOB; 00983 00984 ev = WSACreateEvent(); 00985 00986 if (fdp->events & _DBUS_POLLIN) 00987 lNetworkEvents |= FD_READ | FD_ACCEPT | FD_CLOSE; 00988 00989 if (fdp->events & _DBUS_POLLOUT) 00990 lNetworkEvents |= FD_WRITE | FD_CONNECT; 00991 00992 WSAEventSelect(fdp->fd, ev, lNetworkEvents); 00993 00994 pEvents[i] = ev; 00995 } 00996 00997 00998 ready = WSAWaitForMultipleEvents (n_fds, pEvents, FALSE, timeout_milliseconds, FALSE); 00999 01000 if (DBUS_SOCKET_API_RETURNS_ERROR (ready)) 01001 { 01002 DBUS_SOCKET_SET_ERRNO (); 01003 if (errno != WSAEWOULDBLOCK) 01004 _dbus_verbose ("WSAWaitForMultipleEvents: failed: %s\n", _dbus_strerror_from_errno ()); 01005 ret = -1; 01006 } 01007 else if (ready == WSA_WAIT_TIMEOUT) 01008 { 01009 _dbus_verbose ("WSAWaitForMultipleEvents: WSA_WAIT_TIMEOUT\n"); 01010 ret = 0; 01011 } 01012 else if (ready >= WSA_WAIT_EVENT_0 && ready < (int)(WSA_WAIT_EVENT_0 + n_fds)) 01013 { 01014 msgp = msg; 01015 msgp += sprintf (msgp, "WSAWaitForMultipleEvents: =%d\n\t", ready); 01016 01017 for (i = 0; i < n_fds; i++) 01018 { 01019 DBusPollFD *fdp = &fds[i]; 01020 WSANETWORKEVENTS ne; 01021 01022 fdp->revents = 0; 01023 01024 WSAEnumNetworkEvents(fdp->fd, pEvents[i], &ne); 01025 01026 if (ne.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) 01027 fdp->revents |= _DBUS_POLLIN; 01028 01029 if (ne.lNetworkEvents & (FD_WRITE | FD_CONNECT)) 01030 fdp->revents |= _DBUS_POLLOUT; 01031 01032 if (ne.lNetworkEvents & (FD_OOB)) 01033 fdp->revents |= _DBUS_POLLERR; 01034 01035 if (ne.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) 01036 msgp += sprintf (msgp, "R:%d ", fdp->fd); 01037 01038 if (ne.lNetworkEvents & (FD_WRITE | FD_CONNECT)) 01039 msgp += sprintf (msgp, "W:%d ", fdp->fd); 01040 01041 if (ne.lNetworkEvents & (FD_OOB)) 01042 msgp += sprintf (msgp, "E:%d ", fdp->fd); 01043 01044 msgp += sprintf (msgp, "lNetworkEvents:%d ", ne.lNetworkEvents); 01045 01046 if(ne.lNetworkEvents) 01047 ret++; 01048 01049 WSAEventSelect(fdp->fd, pEvents[i], 0); 01050 } 01051 01052 msgp += sprintf (msgp, "\n"); 01053 _dbus_verbose ("%s",msg); 01054 } 01055 else 01056 { 01057 _dbus_verbose ("WSAWaitForMultipleEvents: failed for unknown reason!"); 01058 ret = -1; 01059 } 01060 01061 for(i = 0; i < n_fds; i++) 01062 { 01063 WSACloseEvent(pEvents[i]); 01064 } 01065 01066 if (n_fds > DBUS_STACK_WSAEVENTS) 01067 free(pEvents); 01068 01069 return ret; 01070 01071 #else /* USE_CHRIS_IMPL */ 01072 01073 #define DBUS_POLL_CHAR_BUFFER_SIZE 2000 01074 char msg[DBUS_POLL_CHAR_BUFFER_SIZE]; 01075 char *msgp; 01076 01077 fd_set read_set, write_set, err_set; 01078 int max_fd = 0; 01079 int i; 01080 struct timeval tv; 01081 int ready; 01082 01083 FD_ZERO (&read_set); 01084 FD_ZERO (&write_set); 01085 FD_ZERO (&err_set); 01086 01087 01088 #ifdef DBUS_ENABLE_VERBOSE_MODE 01089 msgp = msg; 01090 msgp += sprintf (msgp, "select: to=%d\n\t", timeout_milliseconds); 01091 for (i = 0; i < n_fds; i++) 01092 { 01093 static dbus_bool_t warned = FALSE; 01094 DBusPollFD *fdp = &fds[i]; 01095 01096 01097 if (fdp->events & _DBUS_POLLIN) 01098 msgp += sprintf (msgp, "R:%d ", fdp->fd); 01099 01100 if (fdp->events & _DBUS_POLLOUT) 01101 msgp += sprintf (msgp, "W:%d ", fdp->fd); 01102 01103 msgp += sprintf (msgp, "E:%d\n\t", fdp->fd); 01104 01105 // FIXME: more robust code for long msg 01106 // create on heap when msg[] becomes too small 01107 if (msgp >= msg + DBUS_POLL_CHAR_BUFFER_SIZE) 01108 { 01109 _dbus_assert_not_reached ("buffer overflow in _dbus_poll"); 01110 } 01111 } 01112 01113 msgp += sprintf (msgp, "\n"); 01114 _dbus_verbose ("%s",msg); 01115 #endif 01116 for (i = 0; i < n_fds; i++) 01117 { 01118 DBusPollFD *fdp = &fds[i]; 01119 01120 if (fdp->events & _DBUS_POLLIN) 01121 FD_SET (fdp->fd, &read_set); 01122 01123 if (fdp->events & _DBUS_POLLOUT) 01124 FD_SET (fdp->fd, &write_set); 01125 01126 FD_SET (fdp->fd, &err_set); 01127 01128 max_fd = MAX (max_fd, fdp->fd); 01129 } 01130 01131 01132 tv.tv_sec = timeout_milliseconds / 1000; 01133 tv.tv_usec = (timeout_milliseconds % 1000) * 1000; 01134 01135 ready = select (max_fd + 1, &read_set, &write_set, &err_set, 01136 timeout_milliseconds < 0 ? NULL : &tv); 01137 01138 if (DBUS_SOCKET_API_RETURNS_ERROR (ready)) 01139 { 01140 DBUS_SOCKET_SET_ERRNO (); 01141 if (errno != WSAEWOULDBLOCK) 01142 _dbus_verbose ("select: failed: %s\n", _dbus_strerror_from_errno ()); 01143 } 01144 else if (ready == 0) 01145 _dbus_verbose ("select: = 0\n"); 01146 else 01147 if (ready > 0) 01148 { 01149 #ifdef DBUS_ENABLE_VERBOSE_MODE 01150 msgp = msg; 01151 msgp += sprintf (msgp, "select: = %d:\n\t", ready); 01152 01153 for (i = 0; i < n_fds; i++) 01154 { 01155 DBusPollFD *fdp = &fds[i]; 01156 01157 if (FD_ISSET (fdp->fd, &read_set)) 01158 msgp += sprintf (msgp, "R:%d ", fdp->fd); 01159 01160 if (FD_ISSET (fdp->fd, &write_set)) 01161 msgp += sprintf (msgp, "W:%d ", fdp->fd); 01162 01163 if (FD_ISSET (fdp->fd, &err_set)) 01164 msgp += sprintf (msgp, "E:%d\n\t", fdp->fd); 01165 } 01166 msgp += sprintf (msgp, "\n"); 01167 _dbus_verbose ("%s",msg); 01168 #endif 01169 01170 for (i = 0; i < n_fds; i++) 01171 { 01172 DBusPollFD *fdp = &fds[i]; 01173 01174 fdp->revents = 0; 01175 01176 if (FD_ISSET (fdp->fd, &read_set)) 01177 fdp->revents |= _DBUS_POLLIN; 01178 01179 if (FD_ISSET (fdp->fd, &write_set)) 01180 fdp->revents |= _DBUS_POLLOUT; 01181 01182 if (FD_ISSET (fdp->fd, &err_set)) 01183 fdp->revents |= _DBUS_POLLERR; 01184 } 01185 } 01186 return ready; 01187 #endif /* USE_CHRIS_IMPL */ 01188 } 01189 01190 01191 01192 01193 /****************************************************************************** 01194 01195 Original CVS version of dbus-sysdeps.c 01196 01197 ******************************************************************************/ 01198 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 01199 /* dbus-sysdeps.c Wrappers around system/libc features (internal to D-Bus implementation) 01200 * 01201 * Copyright (C) 2002, 2003 Red Hat, Inc. 01202 * Copyright (C) 2003 CodeFactory AB 01203 * Copyright (C) 2005 Novell, Inc. 01204 * 01205 * Licensed under the Academic Free License version 2.1 01206 * 01207 * This program is free software; you can redistribute it and/or modify 01208 * it under the terms of the GNU General Public License as published by 01209 * the Free Software Foundation; either version 2 of the License, or 01210 * (at your option) any later version. 01211 * 01212 * This program is distributed in the hope that it will be useful, 01213 * but WITHOUT ANY WARRANTY; without even the implied warranty of 01214 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 01215 * GNU General Public License for more details. 01216 * 01217 * You should have received a copy of the GNU General Public License 01218 * along with this program; if not, write to the Free Software 01219 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 01220 * 01221 */ 01222 01223 01229 void 01230 _dbus_exit (int code) 01231 { 01232 _exit (code); 01233 } 01234 01246 int 01247 _dbus_connect_tcp_socket (const char *host, 01248 const char *port, 01249 const char *family, 01250 DBusError *error) 01251 { 01252 return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error); 01253 } 01254 01255 int 01256 _dbus_connect_tcp_socket_with_nonce (const char *host, 01257 const char *port, 01258 const char *family, 01259 const char *noncefile, 01260 DBusError *error) 01261 { 01262 int fd = -1, res; 01263 struct addrinfo hints; 01264 struct addrinfo *ai, *tmp; 01265 01266 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01267 01268 _dbus_win_startup_winsock (); 01269 01270 _DBUS_ZERO (hints); 01271 01272 if (!family) 01273 hints.ai_family = AF_UNSPEC; 01274 else if (!strcmp(family, "ipv4")) 01275 hints.ai_family = AF_INET; 01276 else if (!strcmp(family, "ipv6")) 01277 hints.ai_family = AF_INET6; 01278 else 01279 { 01280 dbus_set_error (error, 01281 DBUS_ERROR_INVALID_ARGS, 01282 "Unknown address family %s", family); 01283 return -1; 01284 } 01285 hints.ai_protocol = IPPROTO_TCP; 01286 hints.ai_socktype = SOCK_STREAM; 01287 #ifdef AI_ADDRCONFIG 01288 hints.ai_flags = AI_ADDRCONFIG; 01289 #else 01290 hints.ai_flags = 0; 01291 #endif 01292 01293 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai) 01294 { 01295 dbus_set_error (error, 01296 _dbus_error_from_errno (res), 01297 "Failed to lookup host/port: \"%s:%s\": %s (%d)", 01298 host, port, _dbus_strerror(res), res); 01299 return -1; 01300 } 01301 01302 tmp = ai; 01303 while (tmp) 01304 { 01305 if ((fd = socket (tmp->ai_family, SOCK_STREAM, 0)) == INVALID_SOCKET) 01306 { 01307 DBUS_SOCKET_SET_ERRNO (); 01308 dbus_set_error (error, 01309 _dbus_error_from_errno (errno), 01310 "Failed to open socket: %s", 01311 _dbus_strerror_from_errno ()); 01312 freeaddrinfo(ai); 01313 return -1; 01314 } 01315 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01316 01317 if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) == SOCKET_ERROR) 01318 { 01319 DBUS_SOCKET_SET_ERRNO (); 01320 closesocket(fd); 01321 fd = -1; 01322 tmp = tmp->ai_next; 01323 continue; 01324 } 01325 01326 break; 01327 } 01328 freeaddrinfo(ai); 01329 01330 if (fd == -1) 01331 { 01332 dbus_set_error (error, 01333 _dbus_error_from_errno (errno), 01334 "Failed to connect to socket \"%s:%s\" %s", 01335 host, port, _dbus_strerror_from_errno ()); 01336 return -1; 01337 } 01338 01339 if (noncefile != NULL) 01340 { 01341 DBusString noncefileStr; 01342 dbus_bool_t ret; 01343 if (!_dbus_string_init (&noncefileStr) || 01344 !_dbus_string_append(&noncefileStr, noncefile)) 01345 { 01346 closesocket (fd); 01347 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01348 return -1; 01349 } 01350 01351 ret = _dbus_send_nonce (fd, &noncefileStr, error); 01352 01353 _dbus_string_free (&noncefileStr); 01354 01355 if (!ret) 01356 { 01357 closesocket (fd); 01358 return -1; 01359 } 01360 } 01361 01362 if (!_dbus_set_fd_nonblocking (fd, error)) 01363 { 01364 closesocket (fd); 01365 return -1; 01366 } 01367 01368 return fd; 01369 } 01370 01386 int 01387 _dbus_listen_tcp_socket (const char *host, 01388 const char *port, 01389 const char *family, 01390 DBusString *retport, 01391 int **fds_p, 01392 DBusError *error) 01393 { 01394 int nlisten_fd = 0, *listen_fd = NULL, res, i, port_num = -1; 01395 struct addrinfo hints; 01396 struct addrinfo *ai, *tmp; 01397 01398 // On Vista, sockaddr_gen must be a sockaddr_in6, and not a sockaddr_in6_old 01399 //That's required for family == IPv6(which is the default on Vista if family is not given) 01400 //So we use our own union instead of sockaddr_gen: 01401 01402 typedef union { 01403 struct sockaddr Address; 01404 struct sockaddr_in AddressIn; 01405 struct sockaddr_in6 AddressIn6; 01406 } mysockaddr_gen; 01407 01408 *fds_p = NULL; 01409 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01410 01411 _dbus_win_startup_winsock (); 01412 01413 _DBUS_ZERO (hints); 01414 01415 if (!family) 01416 hints.ai_family = AF_UNSPEC; 01417 else if (!strcmp(family, "ipv4")) 01418 hints.ai_family = AF_INET; 01419 else if (!strcmp(family, "ipv6")) 01420 hints.ai_family = AF_INET6; 01421 else 01422 { 01423 dbus_set_error (error, 01424 DBUS_ERROR_INVALID_ARGS, 01425 "Unknown address family %s", family); 01426 return -1; 01427 } 01428 01429 hints.ai_protocol = IPPROTO_TCP; 01430 hints.ai_socktype = SOCK_STREAM; 01431 #ifdef AI_ADDRCONFIG 01432 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE; 01433 #else 01434 hints.ai_flags = AI_PASSIVE; 01435 #endif 01436 01437 redo_lookup_with_port: 01438 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai) 01439 { 01440 dbus_set_error (error, 01441 _dbus_error_from_errno (res), 01442 "Failed to lookup host/port: \"%s:%s\": %s (%d)", 01443 host ? host : "*", port, _dbus_strerror(res), res); 01444 return -1; 01445 } 01446 01447 tmp = ai; 01448 while (tmp) 01449 { 01450 int fd = -1, *newlisten_fd; 01451 if ((fd = socket (tmp->ai_family, SOCK_STREAM, 0)) == INVALID_SOCKET) 01452 { 01453 DBUS_SOCKET_SET_ERRNO (); 01454 dbus_set_error (error, 01455 _dbus_error_from_errno (errno), 01456 "Failed to open socket: %s", 01457 _dbus_strerror_from_errno ()); 01458 goto failed; 01459 } 01460 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01461 01462 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) == SOCKET_ERROR) 01463 { 01464 DBUS_SOCKET_SET_ERRNO (); 01465 dbus_set_error (error, _dbus_error_from_errno (errno), 01466 "Failed to bind socket \"%s:%s\": %s", 01467 host ? host : "*", port, _dbus_strerror_from_errno ()); 01468 closesocket (fd); 01469 goto failed; 01470 } 01471 01472 if (listen (fd, 30 /* backlog */) == SOCKET_ERROR) 01473 { 01474 DBUS_SOCKET_SET_ERRNO (); 01475 dbus_set_error (error, _dbus_error_from_errno (errno), 01476 "Failed to listen on socket \"%s:%s\": %s", 01477 host ? host : "*", port, _dbus_strerror_from_errno ()); 01478 closesocket (fd); 01479 goto failed; 01480 } 01481 01482 newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1)); 01483 if (!newlisten_fd) 01484 { 01485 closesocket (fd); 01486 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, 01487 "Failed to allocate file handle array"); 01488 goto failed; 01489 } 01490 listen_fd = newlisten_fd; 01491 listen_fd[nlisten_fd] = fd; 01492 nlisten_fd++; 01493 01494 if (!_dbus_string_get_length(retport)) 01495 { 01496 /* If the user didn't specify a port, or used 0, then 01497 the kernel chooses a port. After the first address 01498 is bound to, we need to force all remaining addresses 01499 to use the same port */ 01500 if (!port || !strcmp(port, "0")) 01501 { 01502 mysockaddr_gen addr; 01503 socklen_t addrlen = sizeof(addr); 01504 char portbuf[10]; 01505 01506 if (getsockname(fd, &addr.Address, &addrlen) == SOCKET_ERROR) 01507 { 01508 DBUS_SOCKET_SET_ERRNO (); 01509 dbus_set_error (error, _dbus_error_from_errno (errno), 01510 "Failed to resolve port \"%s:%s\": %s", 01511 host ? host : "*", port, _dbus_strerror_from_errno()); 01512 goto failed; 01513 } 01514 snprintf( portbuf, sizeof( portbuf ) - 1, "%d", addr.AddressIn.sin_port ); 01515 if (!_dbus_string_append(retport, portbuf)) 01516 { 01517 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01518 goto failed; 01519 } 01520 01521 /* Release current address list & redo lookup */ 01522 port = _dbus_string_get_const_data(retport); 01523 freeaddrinfo(ai); 01524 goto redo_lookup_with_port; 01525 } 01526 else 01527 { 01528 if (!_dbus_string_append(retport, port)) 01529 { 01530 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01531 goto failed; 01532 } 01533 } 01534 } 01535 01536 tmp = tmp->ai_next; 01537 } 01538 freeaddrinfo(ai); 01539 ai = NULL; 01540 01541 if (!nlisten_fd) 01542 { 01543 _dbus_win_set_errno (WSAEADDRINUSE); 01544 dbus_set_error (error, _dbus_error_from_errno (errno), 01545 "Failed to bind socket \"%s:%s\": %s", 01546 host ? host : "*", port, _dbus_strerror_from_errno ()); 01547 return -1; 01548 } 01549 01550 sscanf(_dbus_string_get_const_data(retport), "%d", &port_num); 01551 01552 for (i = 0 ; i < nlisten_fd ; i++) 01553 { 01554 if (!_dbus_set_fd_nonblocking (listen_fd[i], error)) 01555 { 01556 goto failed; 01557 } 01558 } 01559 01560 *fds_p = listen_fd; 01561 01562 return nlisten_fd; 01563 01564 failed: 01565 if (ai) 01566 freeaddrinfo(ai); 01567 for (i = 0 ; i < nlisten_fd ; i++) 01568 closesocket (listen_fd[i]); 01569 dbus_free(listen_fd); 01570 return -1; 01571 } 01572 01573 01581 int 01582 _dbus_accept (int listen_fd) 01583 { 01584 int client_fd; 01585 01586 retry: 01587 client_fd = accept (listen_fd, NULL, NULL); 01588 01589 if (DBUS_SOCKET_IS_INVALID (client_fd)) 01590 { 01591 DBUS_SOCKET_SET_ERRNO (); 01592 if (errno == EINTR) 01593 goto retry; 01594 } 01595 01596 _dbus_verbose ("client fd %d accepted\n", client_fd); 01597 01598 return client_fd; 01599 } 01600 01601 01602 01603 01604 dbus_bool_t 01605 _dbus_send_credentials_socket (int handle, 01606 DBusError *error) 01607 { 01608 /* FIXME: for the session bus credentials shouldn't matter (?), but 01609 * for the system bus they are presumably essential. A rough outline 01610 * of a way to implement the credential transfer would be this: 01611 * 01612 * client waits to *read* a byte. 01613 * 01614 * server creates a named pipe with a random name, sends a byte 01615 * contining its length, and its name. 01616 * 01617 * client reads the name, connects to it (using Win32 API). 01618 * 01619 * server waits for connection to the named pipe, then calls 01620 * ImpersonateNamedPipeClient(), notes its now-current credentials, 01621 * calls RevertToSelf(), closes its handles to the named pipe, and 01622 * is done. (Maybe there is some other way to get the SID of a named 01623 * pipe client without having to use impersonation?) 01624 * 01625 * client closes its handles and is done. 01626 * 01627 * Ralf: Why not sending credentials over the given this connection ? 01628 * Using named pipes makes it impossible to be connected from a unix client. 01629 * 01630 */ 01631 int bytes_written; 01632 DBusString buf; 01633 01634 _dbus_string_init_const_len (&buf, "\0", 1); 01635 again: 01636 bytes_written = _dbus_write_socket (handle, &buf, 0, 1 ); 01637 01638 if (bytes_written < 0 && errno == EINTR) 01639 goto again; 01640 01641 if (bytes_written < 0) 01642 { 01643 dbus_set_error (error, _dbus_error_from_errno (errno), 01644 "Failed to write credentials byte: %s", 01645 _dbus_strerror_from_errno ()); 01646 return FALSE; 01647 } 01648 else if (bytes_written == 0) 01649 { 01650 dbus_set_error (error, DBUS_ERROR_IO_ERROR, 01651 "wrote zero bytes writing credentials byte"); 01652 return FALSE; 01653 } 01654 else 01655 { 01656 _dbus_assert (bytes_written == 1); 01657 _dbus_verbose ("wrote 1 zero byte, credential sending isn't implemented yet\n"); 01658 return TRUE; 01659 } 01660 return TRUE; 01661 } 01662 01681 dbus_bool_t 01682 _dbus_read_credentials_socket (int handle, 01683 DBusCredentials *credentials, 01684 DBusError *error) 01685 { 01686 int bytes_read = 0; 01687 DBusString buf; 01688 01689 // could fail due too OOM 01690 if (_dbus_string_init(&buf)) 01691 { 01692 bytes_read = _dbus_read_socket(handle, &buf, 1 ); 01693 01694 if (bytes_read > 0) 01695 _dbus_verbose("got one zero byte from server"); 01696 01697 _dbus_string_free(&buf); 01698 } 01699 01700 _dbus_credentials_add_from_current_process (credentials); 01701 _dbus_verbose("FIXME: get faked credentials from current process"); 01702 01703 return TRUE; 01704 } 01705 01714 dbus_bool_t 01715 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error) 01716 { 01717 /* TODO */ 01718 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01719 return TRUE; 01720 } 01721 01722 01733 dbus_bool_t 01734 _dbus_concat_dir_and_file (DBusString *dir, 01735 const DBusString *next_component) 01736 { 01737 dbus_bool_t dir_ends_in_slash; 01738 dbus_bool_t file_starts_with_slash; 01739 01740 if (_dbus_string_get_length (dir) == 0 || 01741 _dbus_string_get_length (next_component) == 0) 01742 return TRUE; 01743 01744 dir_ends_in_slash = 01745 ('/' == _dbus_string_get_byte (dir, _dbus_string_get_length (dir) - 1) || 01746 '\\' == _dbus_string_get_byte (dir, _dbus_string_get_length (dir) - 1)); 01747 01748 file_starts_with_slash = 01749 ('/' == _dbus_string_get_byte (next_component, 0) || 01750 '\\' == _dbus_string_get_byte (next_component, 0)); 01751 01752 if (dir_ends_in_slash && file_starts_with_slash) 01753 { 01754 _dbus_string_shorten (dir, 1); 01755 } 01756 else if (!(dir_ends_in_slash || file_starts_with_slash)) 01757 { 01758 if (!_dbus_string_append_byte (dir, '\\')) 01759 return FALSE; 01760 } 01761 01762 return _dbus_string_copy (next_component, 0, dir, 01763 _dbus_string_get_length (dir)); 01764 } 01765 01766 /*---------------- DBusCredentials ----------------------------------*/ 01767 01775 dbus_bool_t 01776 _dbus_credentials_add_from_user (DBusCredentials *credentials, 01777 const DBusString *username) 01778 { 01779 return _dbus_credentials_add_windows_sid (credentials, 01780 _dbus_string_get_const_data(username)); 01781 } 01782 01791 dbus_bool_t 01792 _dbus_credentials_add_from_current_process (DBusCredentials *credentials) 01793 { 01794 dbus_bool_t retval = FALSE; 01795 char *sid = NULL; 01796 01797 if (!_dbus_getsid(&sid)) 01798 goto failed; 01799 01800 if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid())) 01801 goto failed; 01802 01803 if (!_dbus_credentials_add_windows_sid (credentials,sid)) 01804 goto failed; 01805 01806 retval = TRUE; 01807 goto end; 01808 failed: 01809 retval = FALSE; 01810 end: 01811 if (sid) 01812 LocalFree(sid); 01813 01814 return retval; 01815 } 01816 01829 dbus_bool_t 01830 _dbus_append_user_from_current_process (DBusString *str) 01831 { 01832 dbus_bool_t retval = FALSE; 01833 char *sid = NULL; 01834 01835 if (!_dbus_getsid(&sid)) 01836 return FALSE; 01837 01838 retval = _dbus_string_append (str,sid); 01839 01840 LocalFree(sid); 01841 return retval; 01842 } 01843 01848 dbus_pid_t 01849 _dbus_getpid (void) 01850 { 01851 return GetCurrentProcessId (); 01852 } 01853 01855 #define NANOSECONDS_PER_SECOND 1000000000 01856 01857 #define MICROSECONDS_PER_SECOND 1000000 01858 01859 #define MILLISECONDS_PER_SECOND 1000 01860 01861 #define NANOSECONDS_PER_MILLISECOND 1000000 01862 01863 #define MICROSECONDS_PER_MILLISECOND 1000 01864 01869 void 01870 _dbus_sleep_milliseconds (int milliseconds) 01871 { 01872 Sleep (milliseconds); 01873 } 01874 01875 01882 void 01883 _dbus_get_current_time (long *tv_sec, 01884 long *tv_usec) 01885 { 01886 FILETIME ft; 01887 dbus_uint64_t time64; 01888 01889 GetSystemTimeAsFileTime (&ft); 01890 01891 memcpy (&time64, &ft, sizeof (time64)); 01892 01893 /* Convert from 100s of nanoseconds since 1601-01-01 01894 * to Unix epoch. Yes, this is Y2038 unsafe. 01895 */ 01896 time64 -= DBUS_INT64_CONSTANT (116444736000000000); 01897 time64 /= 10; 01898 01899 if (tv_sec) 01900 *tv_sec = time64 / 1000000; 01901 01902 if (tv_usec) 01903 *tv_usec = time64 % 1000000; 01904 } 01905 01906 01910 void 01911 _dbus_disable_sigpipe (void) 01912 { 01913 } 01914 01923 dbus_bool_t 01924 _dbus_create_directory (const DBusString *filename, 01925 DBusError *error) 01926 { 01927 const char *filename_c; 01928 01929 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01930 01931 filename_c = _dbus_string_get_const_data (filename); 01932 01933 if (!CreateDirectoryA (filename_c, NULL)) 01934 { 01935 if (GetLastError () == ERROR_ALREADY_EXISTS) 01936 return TRUE; 01937 01938 dbus_set_error (error, DBUS_ERROR_FAILED, 01939 "Failed to create directory %s: %s\n", 01940 filename_c, _dbus_strerror_from_errno ()); 01941 return FALSE; 01942 } 01943 else 01944 return TRUE; 01945 } 01946 01947 01956 dbus_bool_t 01957 _dbus_generate_random_bytes (DBusString *str, 01958 int n_bytes) 01959 { 01960 int old_len; 01961 char *p; 01962 HCRYPTPROV hprov; 01963 01964 old_len = _dbus_string_get_length (str); 01965 01966 if (!_dbus_string_lengthen (str, n_bytes)) 01967 return FALSE; 01968 01969 p = _dbus_string_get_data_len (str, old_len, n_bytes); 01970 01971 if (!CryptAcquireContext (&hprov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) 01972 return FALSE; 01973 01974 if (!CryptGenRandom (hprov, n_bytes, p)) 01975 { 01976 CryptReleaseContext (hprov, 0); 01977 return FALSE; 01978 } 01979 01980 CryptReleaseContext (hprov, 0); 01981 01982 return TRUE; 01983 } 01984 01991 const char* 01992 _dbus_get_tmpdir(void) 01993 { 01994 static const char* tmpdir = NULL; 01995 static char buf[1000]; 01996 01997 if (tmpdir == NULL) 01998 { 01999 char *last_slash; 02000 02001 if (!GetTempPathA (sizeof (buf), buf)) 02002 { 02003 _dbus_warn ("GetTempPath failed\n"); 02004 _dbus_abort (); 02005 } 02006 02007 /* Drop terminating backslash or slash */ 02008 last_slash = _mbsrchr (buf, '\\'); 02009 if (last_slash > buf && last_slash[1] == '\0') 02010 last_slash[0] = '\0'; 02011 last_slash = _mbsrchr (buf, '/'); 02012 if (last_slash > buf && last_slash[1] == '\0') 02013 last_slash[0] = '\0'; 02014 02015 tmpdir = buf; 02016 } 02017 02018 _dbus_assert(tmpdir != NULL); 02019 02020 return tmpdir; 02021 } 02022 02023 02032 dbus_bool_t 02033 _dbus_delete_file (const DBusString *filename, 02034 DBusError *error) 02035 { 02036 const char *filename_c; 02037 02038 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02039 02040 filename_c = _dbus_string_get_const_data (filename); 02041 02042 if (DeleteFileA (filename_c) == 0) 02043 { 02044 dbus_set_error (error, DBUS_ERROR_FAILED, 02045 "Failed to delete file %s: %s\n", 02046 filename_c, _dbus_strerror_from_errno ()); 02047 return FALSE; 02048 } 02049 else 02050 return TRUE; 02051 } 02052 02053 /* Forward declaration of prototype used in next function */ 02054 static dbus_bool_t 02055 _dbus_get_install_root(char *prefix, int len); 02056 02057 /* 02058 * replaces the term DBUS_PREFIX in configure_time_path by the 02059 * current dbus installation directory. On unix this function is a noop 02060 * 02061 * @param configure_time_path 02062 * @return real path 02063 */ 02064 const char * 02065 _dbus_replace_install_prefix (const char *configure_time_path) 02066 { 02067 #ifndef DBUS_PREFIX 02068 return configure_time_path; 02069 #else 02070 static char retval[1000]; 02071 static char runtime_prefix[1000]; 02072 int len = 1000; 02073 int i; 02074 02075 if (!configure_time_path) 02076 return NULL; 02077 02078 if ((!_dbus_get_install_root(runtime_prefix, len) || 02079 strncmp (configure_time_path, DBUS_PREFIX "/", 02080 strlen (DBUS_PREFIX) + 1))) { 02081 strcat (retval, configure_time_path); 02082 return retval; 02083 } 02084 02085 strcpy (retval, runtime_prefix); 02086 strcat (retval, configure_time_path + strlen (DBUS_PREFIX) + 1); 02087 02088 /* Somehow, in some situations, backslashes get collapsed in the string. 02089 * Since windows C library accepts both forward and backslashes as 02090 * path separators, convert all backslashes to forward slashes. 02091 */ 02092 02093 for(i = 0; retval[i] != '\0'; i++) { 02094 if(retval[i] == '\\') 02095 retval[i] = '/'; 02096 } 02097 return retval; 02098 #endif 02099 } 02100 02101 #if !defined (DBUS_DISABLE_ASSERTS) || defined(DBUS_BUILD_TESTS) 02102 02103 #if defined(_MSC_VER) || defined(DBUS_WINCE) 02104 # ifdef BACKTRACES 02105 # undef BACKTRACES 02106 # endif 02107 #else 02108 # define BACKTRACES 02109 #endif 02110 02111 #ifdef BACKTRACES 02112 /* 02113 * Backtrace Generator 02114 * 02115 * Copyright 2004 Eric Poech 02116 * Copyright 2004 Robert Shearman 02117 * 02118 * This library is free software; you can redistribute it and/or 02119 * modify it under the terms of the GNU Lesser General Public 02120 * License as published by the Free Software Foundation; either 02121 * version 2.1 of the License, or (at your option) any later version. 02122 * 02123 * This library is distributed in the hope that it will be useful, 02124 * but WITHOUT ANY WARRANTY; without even the implied warranty of 02125 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 02126 * Lesser General Public License for more details. 02127 * 02128 * You should have received a copy of the GNU Lesser General Public 02129 * License along with this library; if not, write to the Free Software 02130 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 02131 */ 02132 02133 #include <winver.h> 02134 #include <imagehlp.h> 02135 #include <stdio.h> 02136 02137 #define DPRINTF _dbus_warn 02138 02139 #ifdef _MSC_VER 02140 #define BOOL int 02141 02142 #define __i386__ 02143 #endif 02144 02145 //#define MAKE_FUNCPTR(f) static typeof(f) * p##f 02146 02147 //MAKE_FUNCPTR(StackWalk); 02148 //MAKE_FUNCPTR(SymGetModuleBase); 02149 //MAKE_FUNCPTR(SymFunctionTableAccess); 02150 //MAKE_FUNCPTR(SymInitialize); 02151 //MAKE_FUNCPTR(SymGetSymFromAddr); 02152 //MAKE_FUNCPTR(SymGetModuleInfo); 02153 static BOOL (WINAPI *pStackWalk)( 02154 DWORD MachineType, 02155 HANDLE hProcess, 02156 HANDLE hThread, 02157 LPSTACKFRAME StackFrame, 02158 PVOID ContextRecord, 02159 PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine, 02160 PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine, 02161 PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine, 02162 PTRANSLATE_ADDRESS_ROUTINE TranslateAddress 02163 ); 02164 #ifdef _WIN64 02165 static DWORD64 (WINAPI *pSymGetModuleBase)( 02166 HANDLE hProcess, 02167 DWORD64 dwAddr 02168 ); 02169 static PVOID (WINAPI *pSymFunctionTableAccess)( 02170 HANDLE hProcess, 02171 DWORD64 AddrBase 02172 ); 02173 #else 02174 static DWORD (WINAPI *pSymGetModuleBase)( 02175 HANDLE hProcess, 02176 DWORD dwAddr 02177 ); 02178 static PVOID (WINAPI *pSymFunctionTableAccess)( 02179 HANDLE hProcess, 02180 DWORD AddrBase 02181 ); 02182 #endif 02183 static BOOL (WINAPI *pSymInitialize)( 02184 HANDLE hProcess, 02185 PSTR UserSearchPath, 02186 BOOL fInvadeProcess 02187 ); 02188 static BOOL (WINAPI *pSymGetSymFromAddr)( 02189 HANDLE hProcess, 02190 DWORD Address, 02191 PDWORD Displacement, 02192 PIMAGEHLP_SYMBOL Symbol 02193 ); 02194 static BOOL (WINAPI *pSymGetModuleInfo)( 02195 HANDLE hProcess, 02196 DWORD dwAddr, 02197 PIMAGEHLP_MODULE ModuleInfo 02198 ); 02199 static DWORD (WINAPI *pSymSetOptions)( 02200 DWORD SymOptions 02201 ); 02202 02203 02204 static BOOL init_backtrace() 02205 { 02206 HMODULE hmodDbgHelp = LoadLibraryA("dbghelp"); 02207 /* 02208 #define GETFUNC(x) \ 02209 p##x = (typeof(x)*)GetProcAddress(hmodDbgHelp, #x); \ 02210 if (!p##x) \ 02211 { \ 02212 return FALSE; \ 02213 } 02214 */ 02215 02216 02217 // GETFUNC(StackWalk); 02218 // GETFUNC(SymGetModuleBase); 02219 // GETFUNC(SymFunctionTableAccess); 02220 // GETFUNC(SymInitialize); 02221 // GETFUNC(SymGetSymFromAddr); 02222 // GETFUNC(SymGetModuleInfo); 02223 02224 #define FUNC(x) #x 02225 02226 pStackWalk = (BOOL (WINAPI *)( 02227 DWORD MachineType, 02228 HANDLE hProcess, 02229 HANDLE hThread, 02230 LPSTACKFRAME StackFrame, 02231 PVOID ContextRecord, 02232 PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine, 02233 PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine, 02234 PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine, 02235 PTRANSLATE_ADDRESS_ROUTINE TranslateAddress 02236 ))GetProcAddress (hmodDbgHelp, FUNC(StackWalk)); 02237 #ifdef _WIN64 02238 pSymGetModuleBase=(DWORD64 (WINAPI *)( 02239 HANDLE hProcess, 02240 DWORD64 dwAddr 02241 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleBase)); 02242 pSymFunctionTableAccess=(PVOID (WINAPI *)( 02243 HANDLE hProcess, 02244 DWORD64 AddrBase 02245 ))GetProcAddress (hmodDbgHelp, FUNC(SymFunctionTableAccess)); 02246 #else 02247 pSymGetModuleBase=(DWORD (WINAPI *)( 02248 HANDLE hProcess, 02249 DWORD dwAddr 02250 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleBase)); 02251 pSymFunctionTableAccess=(PVOID (WINAPI *)( 02252 HANDLE hProcess, 02253 DWORD AddrBase 02254 ))GetProcAddress (hmodDbgHelp, FUNC(SymFunctionTableAccess)); 02255 #endif 02256 pSymInitialize = (BOOL (WINAPI *)( 02257 HANDLE hProcess, 02258 PSTR UserSearchPath, 02259 BOOL fInvadeProcess 02260 ))GetProcAddress (hmodDbgHelp, FUNC(SymInitialize)); 02261 pSymGetSymFromAddr = (BOOL (WINAPI *)( 02262 HANDLE hProcess, 02263 DWORD Address, 02264 PDWORD Displacement, 02265 PIMAGEHLP_SYMBOL Symbol 02266 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetSymFromAddr)); 02267 pSymGetModuleInfo = (BOOL (WINAPI *)( 02268 HANDLE hProcess, 02269 DWORD dwAddr, 02270 PIMAGEHLP_MODULE ModuleInfo 02271 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleInfo)); 02272 pSymSetOptions = (DWORD (WINAPI *)( 02273 DWORD SymOptions 02274 ))GetProcAddress (hmodDbgHelp, FUNC(SymSetOptions)); 02275 02276 02277 pSymSetOptions(SYMOPT_UNDNAME); 02278 02279 pSymInitialize(GetCurrentProcess(), NULL, TRUE); 02280 02281 return TRUE; 02282 } 02283 02284 static void dump_backtrace_for_thread(HANDLE hThread) 02285 { 02286 STACKFRAME sf; 02287 CONTEXT context; 02288 DWORD dwImageType; 02289 02290 if (!pStackWalk) 02291 if (!init_backtrace()) 02292 return; 02293 02294 /* can't use this function for current thread as GetThreadContext 02295 * doesn't support getting context from current thread */ 02296 if (hThread == GetCurrentThread()) 02297 return; 02298 02299 DPRINTF("Backtrace:\n"); 02300 02301 _DBUS_ZERO(context); 02302 context.ContextFlags = CONTEXT_FULL; 02303 02304 SuspendThread(hThread); 02305 02306 if (!GetThreadContext(hThread, &context)) 02307 { 02308 DPRINTF("Couldn't get thread context (error %ld)\n", GetLastError()); 02309 ResumeThread(hThread); 02310 return; 02311 } 02312 02313 _DBUS_ZERO(sf); 02314 02315 #ifdef __i386__ 02316 sf.AddrFrame.Offset = context.Ebp; 02317 sf.AddrFrame.Mode = AddrModeFlat; 02318 sf.AddrPC.Offset = context.Eip; 02319 sf.AddrPC.Mode = AddrModeFlat; 02320 dwImageType = IMAGE_FILE_MACHINE_I386; 02321 #elif _M_X64 02322 dwImageType = IMAGE_FILE_MACHINE_AMD64; 02323 sf.AddrPC.Offset = context.Rip; 02324 sf.AddrPC.Mode = AddrModeFlat; 02325 sf.AddrFrame.Offset = context.Rsp; 02326 sf.AddrFrame.Mode = AddrModeFlat; 02327 sf.AddrStack.Offset = context.Rsp; 02328 sf.AddrStack.Mode = AddrModeFlat; 02329 #elif _M_IA64 02330 dwImageType = IMAGE_FILE_MACHINE_IA64; 02331 sf.AddrPC.Offset = context.StIIP; 02332 sf.AddrPC.Mode = AddrModeFlat; 02333 sf.AddrFrame.Offset = context.IntSp; 02334 sf.AddrFrame.Mode = AddrModeFlat; 02335 sf.AddrBStore.Offset= context.RsBSP; 02336 sf.AddrBStore.Mode = AddrModeFlat; 02337 sf.AddrStack.Offset = context.IntSp; 02338 sf.AddrStack.Mode = AddrModeFlat; 02339 #else 02340 # error You need to fill in the STACKFRAME structure for your architecture 02341 #endif 02342 02343 while (pStackWalk(dwImageType, GetCurrentProcess(), 02344 hThread, &sf, &context, NULL, pSymFunctionTableAccess, 02345 pSymGetModuleBase, NULL)) 02346 { 02347 BYTE buffer[256]; 02348 IMAGEHLP_SYMBOL * pSymbol = (IMAGEHLP_SYMBOL *)buffer; 02349 DWORD dwDisplacement; 02350 02351 pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); 02352 pSymbol->MaxNameLength = sizeof(buffer) - sizeof(IMAGEHLP_SYMBOL) + 1; 02353 02354 if (!pSymGetSymFromAddr(GetCurrentProcess(), sf.AddrPC.Offset, 02355 &dwDisplacement, pSymbol)) 02356 { 02357 IMAGEHLP_MODULE ModuleInfo; 02358 ModuleInfo.SizeOfStruct = sizeof(ModuleInfo); 02359 02360 if (!pSymGetModuleInfo(GetCurrentProcess(), sf.AddrPC.Offset, 02361 &ModuleInfo)) 02362 DPRINTF("1\t%p\n", (void*)sf.AddrPC.Offset); 02363 else 02364 DPRINTF("2\t%s+0x%lx\n", ModuleInfo.ImageName, 02365 sf.AddrPC.Offset - ModuleInfo.BaseOfImage); 02366 } 02367 else if (dwDisplacement) 02368 DPRINTF("3\t%s+0x%lx\n", pSymbol->Name, dwDisplacement); 02369 else 02370 DPRINTF("4\t%s\n", pSymbol->Name); 02371 } 02372 02373 ResumeThread(hThread); 02374 } 02375 02376 static DWORD WINAPI dump_thread_proc(LPVOID lpParameter) 02377 { 02378 dump_backtrace_for_thread((HANDLE)lpParameter); 02379 return 0; 02380 } 02381 02382 /* cannot get valid context from current thread, so we have to execute 02383 * backtrace from another thread */ 02384 static void dump_backtrace() 02385 { 02386 HANDLE hCurrentThread; 02387 HANDLE hThread; 02388 DWORD dwThreadId; 02389 DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), 02390 GetCurrentProcess(), &hCurrentThread, 0, FALSE, DUPLICATE_SAME_ACCESS); 02391 hThread = CreateThread(NULL, 0, dump_thread_proc, (LPVOID)hCurrentThread, 02392 0, &dwThreadId); 02393 WaitForSingleObject(hThread, INFINITE); 02394 CloseHandle(hThread); 02395 CloseHandle(hCurrentThread); 02396 } 02397 #endif 02398 #endif /* asserts or tests enabled */ 02399 02400 #ifdef BACKTRACES 02401 void _dbus_print_backtrace(void) 02402 { 02403 init_backtrace(); 02404 dump_backtrace(); 02405 } 02406 #else 02407 void _dbus_print_backtrace(void) 02408 { 02409 _dbus_verbose (" D-Bus not compiled with backtrace support\n"); 02410 } 02411 #endif 02412 02413 static dbus_uint32_t fromAscii(char ascii) 02414 { 02415 if(ascii >= '0' && ascii <= '9') 02416 return ascii - '0'; 02417 if(ascii >= 'A' && ascii <= 'F') 02418 return ascii - 'A' + 10; 02419 if(ascii >= 'a' && ascii <= 'f') 02420 return ascii - 'a' + 10; 02421 return 0; 02422 } 02423 02424 dbus_bool_t _dbus_read_local_machine_uuid (DBusGUID *machine_id, 02425 dbus_bool_t create_if_not_found, 02426 DBusError *error) 02427 { 02428 #ifdef DBUS_WINCE 02429 return TRUE; 02430 // TODO 02431 #else 02432 HW_PROFILE_INFOA info; 02433 char *lpc = &info.szHwProfileGuid[0]; 02434 dbus_uint32_t u; 02435 02436 // the hw-profile guid lives long enough 02437 if(!GetCurrentHwProfileA(&info)) 02438 { 02439 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); // FIXME 02440 return FALSE; 02441 } 02442 02443 // Form: {12340001-4980-1920-6788-123456789012} 02444 lpc++; 02445 // 12340001 02446 u = ((fromAscii(lpc[0]) << 0) | 02447 (fromAscii(lpc[1]) << 4) | 02448 (fromAscii(lpc[2]) << 8) | 02449 (fromAscii(lpc[3]) << 12) | 02450 (fromAscii(lpc[4]) << 16) | 02451 (fromAscii(lpc[5]) << 20) | 02452 (fromAscii(lpc[6]) << 24) | 02453 (fromAscii(lpc[7]) << 28)); 02454 machine_id->as_uint32s[0] = u; 02455 02456 lpc += 9; 02457 // 4980-1920 02458 u = ((fromAscii(lpc[0]) << 0) | 02459 (fromAscii(lpc[1]) << 4) | 02460 (fromAscii(lpc[2]) << 8) | 02461 (fromAscii(lpc[3]) << 12) | 02462 (fromAscii(lpc[5]) << 16) | 02463 (fromAscii(lpc[6]) << 20) | 02464 (fromAscii(lpc[7]) << 24) | 02465 (fromAscii(lpc[8]) << 28)); 02466 machine_id->as_uint32s[1] = u; 02467 02468 lpc += 10; 02469 // 6788-1234 02470 u = ((fromAscii(lpc[0]) << 0) | 02471 (fromAscii(lpc[1]) << 4) | 02472 (fromAscii(lpc[2]) << 8) | 02473 (fromAscii(lpc[3]) << 12) | 02474 (fromAscii(lpc[5]) << 16) | 02475 (fromAscii(lpc[6]) << 20) | 02476 (fromAscii(lpc[7]) << 24) | 02477 (fromAscii(lpc[8]) << 28)); 02478 machine_id->as_uint32s[2] = u; 02479 02480 lpc += 9; 02481 // 56789012 02482 u = ((fromAscii(lpc[0]) << 0) | 02483 (fromAscii(lpc[1]) << 4) | 02484 (fromAscii(lpc[2]) << 8) | 02485 (fromAscii(lpc[3]) << 12) | 02486 (fromAscii(lpc[4]) << 16) | 02487 (fromAscii(lpc[5]) << 20) | 02488 (fromAscii(lpc[6]) << 24) | 02489 (fromAscii(lpc[7]) << 28)); 02490 machine_id->as_uint32s[3] = u; 02491 #endif 02492 return TRUE; 02493 } 02494 02495 static 02496 HANDLE _dbus_global_lock (const char *mutexname) 02497 { 02498 HANDLE mutex; 02499 DWORD gotMutex; 02500 02501 mutex = CreateMutexA( NULL, FALSE, mutexname ); 02502 if( !mutex ) 02503 { 02504 return FALSE; 02505 } 02506 02507 gotMutex = WaitForSingleObject( mutex, INFINITE ); 02508 switch( gotMutex ) 02509 { 02510 case WAIT_ABANDONED: 02511 ReleaseMutex (mutex); 02512 CloseHandle (mutex); 02513 return 0; 02514 case WAIT_FAILED: 02515 case WAIT_TIMEOUT: 02516 return 0; 02517 } 02518 02519 return mutex; 02520 } 02521 02522 static 02523 void _dbus_global_unlock (HANDLE mutex) 02524 { 02525 ReleaseMutex (mutex); 02526 CloseHandle (mutex); 02527 } 02528 02529 // for proper cleanup in dbus-daemon 02530 static HANDLE hDBusDaemonMutex = NULL; 02531 static HANDLE hDBusSharedMem = NULL; 02532 // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs 02533 static const char *cUniqueDBusInitMutex = "UniqueDBusInitMutex"; 02534 // sync _dbus_get_autolaunch_address 02535 static const char *cDBusAutolaunchMutex = "DBusAutolaunchMutex"; 02536 // mutex to determine if dbus-daemon is already started (per user) 02537 static const char *cDBusDaemonMutex = "DBusDaemonMutex"; 02538 // named shm for dbus adress info (per user) 02539 #ifdef _DEBUG 02540 static const char *cDBusDaemonAddressInfo = "DBusDaemonAddressInfoDebug"; 02541 #else 02542 static const char *cDBusDaemonAddressInfo = "DBusDaemonAddressInfo"; 02543 #endif 02544 02545 02546 void 02547 _dbus_daemon_publish_session_bus_address (const char* address) 02548 { 02549 HANDLE lock; 02550 char *shared_addr = NULL; 02551 DWORD ret; 02552 02553 _dbus_assert (address); 02554 // before _dbus_global_lock to keep correct lock/release order 02555 hDBusDaemonMutex = CreateMutexA( NULL, FALSE, cDBusDaemonMutex ); 02556 ret = WaitForSingleObject( hDBusDaemonMutex, 1000 ); 02557 if ( ret != WAIT_OBJECT_0 ) { 02558 _dbus_warn("Could not lock mutex %s (return code %ld). daemon already running? Bus address not published.\n", cDBusDaemonMutex, ret ); 02559 return; 02560 } 02561 02562 // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs 02563 lock = _dbus_global_lock( cUniqueDBusInitMutex ); 02564 02565 // create shm 02566 hDBusSharedMem = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 02567 0, strlen( address ) + 1, cDBusDaemonAddressInfo ); 02568 _dbus_assert( hDBusSharedMem ); 02569 02570 shared_addr = MapViewOfFile( hDBusSharedMem, FILE_MAP_WRITE, 0, 0, 0 ); 02571 02572 _dbus_assert (shared_addr); 02573 02574 strcpy( shared_addr, address); 02575 02576 // cleanup 02577 UnmapViewOfFile( shared_addr ); 02578 02579 _dbus_global_unlock( lock ); 02580 } 02581 02582 void 02583 _dbus_daemon_unpublish_session_bus_address (void) 02584 { 02585 HANDLE lock; 02586 02587 // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs 02588 lock = _dbus_global_lock( cUniqueDBusInitMutex ); 02589 02590 CloseHandle( hDBusSharedMem ); 02591 02592 hDBusSharedMem = NULL; 02593 02594 ReleaseMutex( hDBusDaemonMutex ); 02595 02596 CloseHandle( hDBusDaemonMutex ); 02597 02598 hDBusDaemonMutex = NULL; 02599 02600 _dbus_global_unlock( lock ); 02601 } 02602 02603 static dbus_bool_t 02604 _dbus_get_autolaunch_shm (DBusString *address) 02605 { 02606 HANDLE sharedMem; 02607 char *shared_addr; 02608 int i; 02609 02610 // read shm 02611 for(i=0;i<20;++i) { 02612 // we know that dbus-daemon is available, so we wait until shm is available 02613 sharedMem = OpenFileMappingA( FILE_MAP_READ, FALSE, cDBusDaemonAddressInfo ); 02614 if( sharedMem == 0 ) 02615 Sleep( 100 ); 02616 if ( sharedMem != 0) 02617 break; 02618 } 02619 02620 if( sharedMem == 0 ) 02621 return FALSE; 02622 02623 shared_addr = MapViewOfFile( sharedMem, FILE_MAP_READ, 0, 0, 0 ); 02624 02625 if( !shared_addr ) 02626 return FALSE; 02627 02628 _dbus_string_init( address ); 02629 02630 _dbus_string_append( address, shared_addr ); 02631 02632 // cleanup 02633 UnmapViewOfFile( shared_addr ); 02634 02635 CloseHandle( sharedMem ); 02636 02637 return TRUE; 02638 } 02639 02640 static dbus_bool_t 02641 _dbus_daemon_already_runs (DBusString *address) 02642 { 02643 HANDLE lock; 02644 HANDLE daemon; 02645 dbus_bool_t bRet = TRUE; 02646 02647 // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs 02648 lock = _dbus_global_lock( cUniqueDBusInitMutex ); 02649 02650 // do checks 02651 daemon = CreateMutexA( NULL, FALSE, cDBusDaemonMutex ); 02652 if(WaitForSingleObject( daemon, 10 ) != WAIT_TIMEOUT) 02653 { 02654 ReleaseMutex (daemon); 02655 CloseHandle (daemon); 02656 02657 _dbus_global_unlock( lock ); 02658 return FALSE; 02659 } 02660 02661 // read shm 02662 bRet = _dbus_get_autolaunch_shm( address ); 02663 02664 // cleanup 02665 CloseHandle ( daemon ); 02666 02667 _dbus_global_unlock( lock ); 02668 02669 return bRet; 02670 } 02671 02672 dbus_bool_t 02673 _dbus_get_autolaunch_address (DBusString *address, 02674 DBusError *error) 02675 { 02676 HANDLE mutex; 02677 STARTUPINFOA si; 02678 PROCESS_INFORMATION pi; 02679 dbus_bool_t retval = FALSE; 02680 LPSTR lpFile; 02681 char dbus_exe_path[MAX_PATH]; 02682 char dbus_args[MAX_PATH * 2]; 02683 const char * daemon_name = DBUS_DAEMON_NAME ".exe"; 02684 02685 mutex = _dbus_global_lock ( cDBusAutolaunchMutex ); 02686 02687 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02688 02689 if (_dbus_daemon_already_runs(address)) 02690 { 02691 _dbus_verbose("found already running dbus daemon\n"); 02692 retval = TRUE; 02693 goto out; 02694 } 02695 02696 if (!SearchPathA(NULL, daemon_name, NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile)) 02697 { 02698 printf ("please add the path to %s to your PATH environment variable\n", daemon_name); 02699 printf ("or start the daemon manually\n\n"); 02700 goto out; 02701 } 02702 02703 // Create process 02704 ZeroMemory( &si, sizeof(si) ); 02705 si.cb = sizeof(si); 02706 ZeroMemory( &pi, sizeof(pi) ); 02707 02708 _snprintf(dbus_args, sizeof(dbus_args) - 1, "\"%s\" %s", dbus_exe_path, " --session"); 02709 02710 // argv[i] = "--config-file=bus\\session.conf"; 02711 // printf("create process \"%s\" %s\n", dbus_exe_path, dbus_args); 02712 if(CreateProcessA(dbus_exe_path, dbus_args, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) 02713 { 02714 CloseHandle (pi.hThread); 02715 CloseHandle (pi.hProcess); 02716 retval = _dbus_get_autolaunch_shm( address ); 02717 } 02718 02719 if (retval == FALSE) 02720 dbus_set_error_const (error, DBUS_ERROR_FAILED, "Failed to launch dbus-daemon"); 02721 02722 out: 02723 if (retval) 02724 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02725 else 02726 _DBUS_ASSERT_ERROR_IS_SET (error); 02727 02728 _dbus_global_unlock (mutex); 02729 02730 return retval; 02731 } 02732 02733 02740 dbus_bool_t 02741 _dbus_make_file_world_readable(const DBusString *filename, 02742 DBusError *error) 02743 { 02744 // TODO 02745 return TRUE; 02746 } 02747 02754 static const char * 02755 _dbus_windows_get_datadir (void) 02756 { 02757 return _dbus_replace_install_prefix(DBUS_DATADIR); 02758 } 02759 02760 #undef DBUS_DATADIR 02761 #define DBUS_DATADIR _dbus_windows_get_datadir () 02762 02763 02764 #define DBUS_STANDARD_SESSION_SERVICEDIR "/dbus-1/services" 02765 #define DBUS_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services" 02766 02783 dbus_bool_t 02784 _dbus_get_standard_session_servicedirs (DBusList **dirs) 02785 { 02786 const char *common_progs; 02787 DBusString servicedir_path; 02788 02789 if (!_dbus_string_init (&servicedir_path)) 02790 return FALSE; 02791 02792 #ifdef DBUS_WINCE 02793 { 02794 /* On Windows CE, we adjust datadir dynamically to installation location. */ 02795 const char *data_dir = _dbus_getenv ("DBUS_DATADIR"); 02796 02797 if (data_dir != NULL) 02798 { 02799 if (!_dbus_string_append (&servicedir_path, data_dir)) 02800 goto oom; 02801 02802 if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR)) 02803 goto oom; 02804 } 02805 } 02806 #else 02807 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR)) 02808 goto oom; 02809 02810 if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR)) 02811 goto oom; 02812 #endif 02813 02814 common_progs = _dbus_getenv ("CommonProgramFiles"); 02815 02816 if (common_progs != NULL) 02817 { 02818 if (!_dbus_string_append (&servicedir_path, common_progs)) 02819 goto oom; 02820 02821 if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR)) 02822 goto oom; 02823 } 02824 02825 if (!_dbus_split_paths_and_append (&servicedir_path, 02826 DBUS_STANDARD_SESSION_SERVICEDIR, 02827 dirs)) 02828 goto oom; 02829 02830 _dbus_string_free (&servicedir_path); 02831 return TRUE; 02832 02833 oom: 02834 _dbus_string_free (&servicedir_path); 02835 return FALSE; 02836 } 02837 02856 dbus_bool_t 02857 _dbus_get_standard_system_servicedirs (DBusList **dirs) 02858 { 02859 *dirs = NULL; 02860 return TRUE; 02861 } 02862 02863 _DBUS_DEFINE_GLOBAL_LOCK (atomic); 02864 02872 dbus_int32_t 02873 _dbus_atomic_inc (DBusAtomic *atomic) 02874 { 02875 // +/- 1 is needed here! 02876 // no volatile argument with mingw 02877 return InterlockedIncrement (&atomic->value) - 1; 02878 } 02879 02887 dbus_int32_t 02888 _dbus_atomic_dec (DBusAtomic *atomic) 02889 { 02890 // +/- 1 is needed here! 02891 // no volatile argument with mingw 02892 return InterlockedDecrement (&atomic->value) + 1; 02893 } 02894 02902 void 02903 _dbus_flush_caches (void) 02904 { 02905 } 02906 02913 dbus_bool_t 02914 _dbus_get_is_errno_eagain_or_ewouldblock (void) 02915 { 02916 return errno == WSAEWOULDBLOCK; 02917 } 02918 02926 static dbus_bool_t 02927 _dbus_get_install_root(char *prefix, int len) 02928 { 02929 //To find the prefix, we cut the filename and also \bin\ if present 02930 char* p = 0; 02931 int i; 02932 DWORD pathLength; 02933 char *lastSlash; 02934 SetLastError( 0 ); 02935 pathLength = GetModuleFileNameA(_dbus_win_get_dll_hmodule(), prefix, len); 02936 if ( pathLength == 0 || GetLastError() != 0 ) { 02937 *prefix = '\0'; 02938 return FALSE; 02939 } 02940 lastSlash = _mbsrchr(prefix, '\\'); 02941 if (lastSlash == NULL) { 02942 *prefix = '\0'; 02943 return FALSE; 02944 } 02945 //cut off binary name 02946 lastSlash[1] = 0; 02947 02948 //cut possible "\\bin" 02949 02950 //this fails if we are in a double-byte system codepage and the 02951 //folder's name happens to end with the *bytes* 02952 //"\\bin"... (I.e. the second byte of some Han character and then 02953 //the Latin "bin", but that is not likely I think... 02954 if (lastSlash - prefix >= 4 && strnicmp(lastSlash - 4, "\\bin", 4) == 0) 02955 lastSlash[-3] = 0; 02956 else if (lastSlash - prefix >= 10 && strnicmp(lastSlash - 10, "\\bin\\debug", 10) == 0) 02957 lastSlash[-9] = 0; 02958 else if (lastSlash - prefix >= 12 && strnicmp(lastSlash - 12, "\\bin\\release", 12) == 0) 02959 lastSlash[-11] = 0; 02960 02961 return TRUE; 02962 } 02963 02977 dbus_bool_t 02978 _dbus_get_config_file_name(DBusString *config_file, char *s) 02979 { 02980 char path[MAX_PATH*2]; 02981 int path_size = sizeof(path); 02982 02983 if (!_dbus_get_install_root(path,path_size)) 02984 return FALSE; 02985 02986 if(strlen(s) + 4 + strlen(path) > sizeof(path)-2) 02987 return FALSE; 02988 strcat(path,"etc\\"); 02989 strcat(path,s); 02990 if (_dbus_file_exists(path)) 02991 { 02992 // find path from executable 02993 if (!_dbus_string_append (config_file, path)) 02994 return FALSE; 02995 } 02996 else 02997 { 02998 if (!_dbus_get_install_root(path,path_size)) 02999 return FALSE; 03000 if(strlen(s) + 11 + strlen(path) > sizeof(path)-2) 03001 return FALSE; 03002 strcat(path,"etc\\dbus-1\\"); 03003 strcat(path,s); 03004 03005 if (_dbus_file_exists(path)) 03006 { 03007 if (!_dbus_string_append (config_file, path)) 03008 return FALSE; 03009 } 03010 else 03011 { 03012 if (!_dbus_get_install_root(path,path_size)) 03013 return FALSE; 03014 if(strlen(s) + 4 + strlen(path) > sizeof(path)-2) 03015 return FALSE; 03016 strcat(path,"bus\\"); 03017 strcat(path,s); 03018 03019 if (_dbus_file_exists(path)) 03020 { 03021 if (!_dbus_string_append (config_file, path)) 03022 return FALSE; 03023 } 03024 } 03025 } 03026 return TRUE; 03027 } 03028 03037 dbus_bool_t 03038 _dbus_append_system_config_file (DBusString *str) 03039 { 03040 return _dbus_get_config_file_name(str, "system.conf"); 03041 } 03042 03049 dbus_bool_t 03050 _dbus_append_session_config_file (DBusString *str) 03051 { 03052 return _dbus_get_config_file_name(str, "session.conf"); 03053 } 03054 03055 /* See comment in dbus-sysdeps-unix.c */ 03056 dbus_bool_t 03057 _dbus_lookup_session_address (dbus_bool_t *supported, 03058 DBusString *address, 03059 DBusError *error) 03060 { 03061 /* Probably fill this in with something based on COM? */ 03062 *supported = FALSE; 03063 return TRUE; 03064 } 03065 03079 dbus_bool_t 03080 _dbus_append_keyring_directory_for_credentials (DBusString *directory, 03081 DBusCredentials *credentials) 03082 { 03083 DBusString homedir; 03084 DBusString dotdir; 03085 dbus_uid_t uid; 03086 const char *homepath; 03087 const char *homedrive; 03088 03089 _dbus_assert (credentials != NULL); 03090 _dbus_assert (!_dbus_credentials_are_anonymous (credentials)); 03091 03092 if (!_dbus_string_init (&homedir)) 03093 return FALSE; 03094 03095 homedrive = _dbus_getenv("HOMEDRIVE"); 03096 if (homedrive != NULL && *homedrive != '\0') 03097 { 03098 _dbus_string_append(&homedir,homedrive); 03099 } 03100 03101 homepath = _dbus_getenv("HOMEPATH"); 03102 if (homepath != NULL && *homepath != '\0') 03103 { 03104 _dbus_string_append(&homedir,homepath); 03105 } 03106 03107 #ifdef DBUS_BUILD_TESTS 03108 { 03109 const char *override; 03110 03111 override = _dbus_getenv ("DBUS_TEST_HOMEDIR"); 03112 if (override != NULL && *override != '\0') 03113 { 03114 _dbus_string_set_length (&homedir, 0); 03115 if (!_dbus_string_append (&homedir, override)) 03116 goto failed; 03117 03118 _dbus_verbose ("Using fake homedir for testing: %s\n", 03119 _dbus_string_get_const_data (&homedir)); 03120 } 03121 else 03122 { 03123 static dbus_bool_t already_warned = FALSE; 03124 if (!already_warned) 03125 { 03126 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n"); 03127 already_warned = TRUE; 03128 } 03129 } 03130 } 03131 #endif 03132 03133 #ifdef DBUS_WINCE 03134 /* It's not possible to create a .something directory in Windows CE 03135 using the file explorer. */ 03136 #define KEYRING_DIR "dbus-keyrings" 03137 #else 03138 #define KEYRING_DIR ".dbus-keyrings" 03139 #endif 03140 03141 _dbus_string_init_const (&dotdir, KEYRING_DIR); 03142 if (!_dbus_concat_dir_and_file (&homedir, 03143 &dotdir)) 03144 goto failed; 03145 03146 if (!_dbus_string_copy (&homedir, 0, 03147 directory, _dbus_string_get_length (directory))) { 03148 goto failed; 03149 } 03150 03151 _dbus_string_free (&homedir); 03152 return TRUE; 03153 03154 failed: 03155 _dbus_string_free (&homedir); 03156 return FALSE; 03157 } 03158 03164 dbus_bool_t 03165 _dbus_file_exists (const char *file) 03166 { 03167 DWORD attributes = GetFileAttributesA (file); 03168 03169 if (attributes != INVALID_FILE_ATTRIBUTES && GetLastError() != ERROR_PATH_NOT_FOUND) 03170 return TRUE; 03171 else 03172 return FALSE; 03173 } 03174 03182 const char* 03183 _dbus_strerror (int error_number) 03184 { 03185 #ifdef DBUS_WINCE 03186 // TODO 03187 return "unknown"; 03188 #else 03189 const char *msg; 03190 03191 switch (error_number) 03192 { 03193 case WSAEINTR: 03194 return "Interrupted function call"; 03195 case WSAEACCES: 03196 return "Permission denied"; 03197 case WSAEFAULT: 03198 return "Bad address"; 03199 case WSAEINVAL: 03200 return "Invalid argument"; 03201 case WSAEMFILE: 03202 return "Too many open files"; 03203 case WSAEWOULDBLOCK: 03204 return "Resource temporarily unavailable"; 03205 case WSAEINPROGRESS: 03206 return "Operation now in progress"; 03207 case WSAEALREADY: 03208 return "Operation already in progress"; 03209 case WSAENOTSOCK: 03210 return "Socket operation on nonsocket"; 03211 case WSAEDESTADDRREQ: 03212 return "Destination address required"; 03213 case WSAEMSGSIZE: 03214 return "Message too long"; 03215 case WSAEPROTOTYPE: 03216 return "Protocol wrong type for socket"; 03217 case WSAENOPROTOOPT: 03218 return "Bad protocol option"; 03219 case WSAEPROTONOSUPPORT: 03220 return "Protocol not supported"; 03221 case WSAESOCKTNOSUPPORT: 03222 return "Socket type not supported"; 03223 case WSAEOPNOTSUPP: 03224 return "Operation not supported"; 03225 case WSAEPFNOSUPPORT: 03226 return "Protocol family not supported"; 03227 case WSAEAFNOSUPPORT: 03228 return "Address family not supported by protocol family"; 03229 case WSAEADDRINUSE: 03230 return "Address already in use"; 03231 case WSAEADDRNOTAVAIL: 03232 return "Cannot assign requested address"; 03233 case WSAENETDOWN: 03234 return "Network is down"; 03235 case WSAENETUNREACH: 03236 return "Network is unreachable"; 03237 case WSAENETRESET: 03238 return "Network dropped connection on reset"; 03239 case WSAECONNABORTED: 03240 return "Software caused connection abort"; 03241 case WSAECONNRESET: 03242 return "Connection reset by peer"; 03243 case WSAENOBUFS: 03244 return "No buffer space available"; 03245 case WSAEISCONN: 03246 return "Socket is already connected"; 03247 case WSAENOTCONN: 03248 return "Socket is not connected"; 03249 case WSAESHUTDOWN: 03250 return "Cannot send after socket shutdown"; 03251 case WSAETIMEDOUT: 03252 return "Connection timed out"; 03253 case WSAECONNREFUSED: 03254 return "Connection refused"; 03255 case WSAEHOSTDOWN: 03256 return "Host is down"; 03257 case WSAEHOSTUNREACH: 03258 return "No route to host"; 03259 case WSAEPROCLIM: 03260 return "Too many processes"; 03261 case WSAEDISCON: 03262 return "Graceful shutdown in progress"; 03263 case WSATYPE_NOT_FOUND: 03264 return "Class type not found"; 03265 case WSAHOST_NOT_FOUND: 03266 return "Host not found"; 03267 case WSATRY_AGAIN: 03268 return "Nonauthoritative host not found"; 03269 case WSANO_RECOVERY: 03270 return "This is a nonrecoverable error"; 03271 case WSANO_DATA: 03272 return "Valid name, no data record of requested type"; 03273 case WSA_INVALID_HANDLE: 03274 return "Specified event object handle is invalid"; 03275 case WSA_INVALID_PARAMETER: 03276 return "One or more parameters are invalid"; 03277 case WSA_IO_INCOMPLETE: 03278 return "Overlapped I/O event object not in signaled state"; 03279 case WSA_IO_PENDING: 03280 return "Overlapped operations will complete later"; 03281 case WSA_NOT_ENOUGH_MEMORY: 03282 return "Insufficient memory available"; 03283 case WSA_OPERATION_ABORTED: 03284 return "Overlapped operation aborted"; 03285 #ifdef WSAINVALIDPROCTABLE 03286 03287 case WSAINVALIDPROCTABLE: 03288 return "Invalid procedure table from service provider"; 03289 #endif 03290 #ifdef WSAINVALIDPROVIDER 03291 03292 case WSAINVALIDPROVIDER: 03293 return "Invalid service provider version number"; 03294 #endif 03295 #ifdef WSAPROVIDERFAILEDINIT 03296 03297 case WSAPROVIDERFAILEDINIT: 03298 return "Unable to initialize a service provider"; 03299 #endif 03300 03301 case WSASYSCALLFAILURE: 03302 return "System call failure"; 03303 } 03304 msg = strerror (error_number); 03305 if (msg == NULL) 03306 msg = "unknown"; 03307 03308 return msg; 03309 #endif //DBUS_WINCE 03310 } 03311 03319 void 03320 _dbus_win_set_error_from_win_error (DBusError *error, 03321 int code) 03322 { 03323 char *msg; 03324 03325 /* As we want the English message, use the A API */ 03326 FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER | 03327 FORMAT_MESSAGE_IGNORE_INSERTS | 03328 FORMAT_MESSAGE_FROM_SYSTEM, 03329 NULL, code, MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US), 03330 (LPSTR) &msg, 0, NULL); 03331 if (msg) 03332 { 03333 char *msg_copy; 03334 03335 msg_copy = dbus_malloc (strlen (msg)); 03336 strcpy (msg_copy, msg); 03337 LocalFree (msg); 03338 03339 dbus_set_error (error, "win32.error", "%s", msg_copy); 03340 } 03341 else 03342 dbus_set_error (error, "win32.error", "Unknown error code %d or FormatMessage failed", code); 03343 } 03344 03345 void 03346 _dbus_win_warn_win_error (const char *message, 03347 int code) 03348 { 03349 DBusError error; 03350 03351 dbus_error_init (&error); 03352 _dbus_win_set_error_from_win_error (&error, code); 03353 _dbus_warn ("%s: %s\n", message, error.message); 03354 dbus_error_free (&error); 03355 } 03356 03364 dbus_bool_t 03365 _dbus_delete_directory (const DBusString *filename, 03366 DBusError *error) 03367 { 03368 const char *filename_c; 03369 03370 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03371 03372 filename_c = _dbus_string_get_const_data (filename); 03373 03374 if (RemoveDirectoryA (filename_c) == 0) 03375 { 03376 char *emsg = _dbus_win_error_string (GetLastError ()); 03377 dbus_set_error (error, _dbus_win_error_from_last_error (), 03378 "Failed to remove directory %s: %s", 03379 filename_c, emsg); 03380 _dbus_win_free_error_string (emsg); 03381 return FALSE; 03382 } 03383 03384 return TRUE; 03385 } 03386 03388 /* tests in dbus-sysdeps-util.c */ 03389