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