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