Home | History | Annotate | Download | only in dbus
      1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
      2 /* dbus-sysdeps.c Wrappers around system/libc features (internal to D-BUS implementation)
      3  *
      4  * Copyright (C) 2002, 2003  Red Hat, Inc.
      5  * Copyright (C) 2003 CodeFactory AB
      6  * Copyright (C) 2005 Novell, Inc.
      7  * Copyright (C) 2006 Ralf Habacker <ralf.habacker (at) freenet.de>
      8  * Copyright (C) 2006 Peter Kmmel  <syntheticpp (at) gmx.net>
      9  * Copyright (C) 2006 Christian Ehrlicher <ch.ehrlicher (at) gmx.de>
     10  *
     11  * Licensed under the Academic Free License version 2.1
     12  *
     13  * This program is free software; you can redistribute it and/or modify
     14  * it under the terms of the GNU General Public License as published by
     15  * the Free Software Foundation; either version 2 of the License, or
     16  * (at your option) any later version.
     17  *
     18  * This program is distributed in the hope that it will be useful,
     19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     21  * GNU General Public License for more details.
     22  *
     23  * You should have received a copy of the GNU General Public License
     24  * along with this program; if not, write to the Free Software
     25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     26  *
     27  */
     28 
     29 #include <config.h>
     30 
     31 #define STRSAFE_NO_DEPRECATE
     32 
     33 #ifndef DBUS_WINCE
     34 #ifndef _WIN32_WINNT
     35 #define _WIN32_WINNT 0x0501
     36 #endif
     37 #endif
     38 
     39 #include "dbus-internals.h"
     40 #include "dbus-sysdeps.h"
     41 #include "dbus-threads.h"
     42 #include "dbus-protocol.h"
     43 #include "dbus-string.h"
     44 #include "dbus-sysdeps-win.h"
     45 #include "dbus-protocol.h"
     46 #include "dbus-hash.h"
     47 #include "dbus-sockets-win.h"
     48 #include "dbus-list.h"
     49 #include "dbus-nonce.h"
     50 #include "dbus-credentials.h"
     51 
     52 #include <windows.h>
     53 #include <ws2tcpip.h>
     54 #include <wincrypt.h>
     55 
     56 /* Declarations missing in mingw's headers */
     57 extern BOOL WINAPI ConvertStringSidToSidA (LPCSTR  StringSid, PSID *Sid);
     58 extern BOOL WINAPI ConvertSidToStringSidA (PSID Sid, LPSTR *StringSid);
     59 
     60 #include <stdio.h>
     61 
     62 #include <string.h>
     63 #if HAVE_ERRNO_H
     64 #include <errno.h>
     65 #endif
     66 #ifndef DBUS_WINCE
     67 #include <mbstring.h>
     68 #include <sys/stat.h>
     69 #include <sys/types.h>
     70 #endif
     71 
     72 #ifdef HAVE_WS2TCPIP_H
     73 /* getaddrinfo for Windows CE (and Windows).  */
     74 #include <ws2tcpip.h>
     75 #endif
     76 
     77 #ifdef HAVE_WSPIAPI_H
     78 // needed for w2k compatibility (getaddrinfo/freeaddrinfo/getnameinfo)
     79 #ifdef __GNUC__
     80 #define _inline
     81 #include "wspiapi.h"
     82 #else
     83 #include <wspiapi.h>
     84 #endif
     85 #endif // HAVE_WSPIAPI_H
     86 
     87 #ifndef O_BINARY
     88 #define O_BINARY 0
     89 #endif
     90 
     91 typedef int socklen_t;
     92 
     93 
     94 void
     95 _dbus_win_set_errno (int err)
     96 {
     97 #ifdef DBUS_WINCE
     98   SetLastError (err);
     99 #else
    100   errno = err;
    101 #endif
    102 }
    103 
    104 
    105 /* Convert GetLastError() to a dbus error.  */
    106 const char*
    107 _dbus_win_error_from_last_error (void)
    108 {
    109   switch (GetLastError())
    110     {
    111     case 0:
    112       return DBUS_ERROR_FAILED;
    113 
    114     case ERROR_NO_MORE_FILES:
    115     case ERROR_TOO_MANY_OPEN_FILES:
    116       return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
    117 
    118     case ERROR_ACCESS_DENIED:
    119     case ERROR_CANNOT_MAKE:
    120       return DBUS_ERROR_ACCESS_DENIED;
    121 
    122     case ERROR_NOT_ENOUGH_MEMORY:
    123       return DBUS_ERROR_NO_MEMORY;
    124 
    125     case ERROR_FILE_EXISTS:
    126       return DBUS_ERROR_FILE_EXISTS;
    127 
    128     case ERROR_FILE_NOT_FOUND:
    129     case ERROR_PATH_NOT_FOUND:
    130       return DBUS_ERROR_FILE_NOT_FOUND;
    131     }
    132 
    133   return DBUS_ERROR_FAILED;
    134 }
    135 
    136 
    137 char*
    138 _dbus_win_error_string (int error_number)
    139 {
    140   char *msg;
    141 
    142   FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
    143                   FORMAT_MESSAGE_IGNORE_INSERTS |
    144                   FORMAT_MESSAGE_FROM_SYSTEM,
    145                   NULL, error_number, 0,
    146                   (LPSTR) &msg, 0, NULL);
    147 
    148   if (msg[strlen (msg) - 1] == '\n')
    149     msg[strlen (msg) - 1] = '\0';
    150   if (msg[strlen (msg) - 1] == '\r')
    151     msg[strlen (msg) - 1] = '\0';
    152 
    153   return msg;
    154 }
    155 
    156 void
    157 _dbus_win_free_error_string (char *string)
    158 {
    159   LocalFree (string);
    160 }
    161 
    162 /**
    163  * Socket interface
    164  *
    165  */
    166 
    167 /**
    168  * Thin wrapper around the read() system call that appends
    169  * the data it reads to the DBusString buffer. It appends
    170  * up to the given count, and returns the same value
    171  * and same errno as read(). The only exception is that
    172  * _dbus_read_socket() handles EINTR for you.
    173  * _dbus_read_socket() can return ENOMEM, even though
    174  * regular UNIX read doesn't.
    175  *
    176  * @param fd the file descriptor to read from
    177  * @param buffer the buffer to append data to
    178  * @param count the amount of data to read
    179  * @returns the number of bytes read or -1
    180  */
    181 
    182 int
    183 _dbus_read_socket (int               fd,
    184                    DBusString       *buffer,
    185                    int               count)
    186 {
    187   int bytes_read;
    188   int start;
    189   char *data;
    190 
    191   _dbus_assert (count >= 0);
    192 
    193   start = _dbus_string_get_length (buffer);
    194 
    195   if (!_dbus_string_lengthen (buffer, count))
    196     {
    197       _dbus_win_set_errno (ENOMEM);
    198       return -1;
    199     }
    200 
    201   data = _dbus_string_get_data_len (buffer, start, count);
    202 
    203  again:
    204 
    205   _dbus_verbose ("recv: count=%d fd=%d\n", count, fd);
    206   bytes_read = recv (fd, data, count, 0);
    207 
    208   if (bytes_read == SOCKET_ERROR)
    209 	{
    210 	  DBUS_SOCKET_SET_ERRNO();
    211 	  _dbus_verbose ("recv: failed: %s (%d)\n", _dbus_strerror (errno), errno);
    212 	  bytes_read = -1;
    213 	}
    214 	else
    215 	  _dbus_verbose ("recv: = %d\n", bytes_read);
    216 
    217   if (bytes_read < 0)
    218     {
    219       if (errno == EINTR)
    220         goto again;
    221       else
    222         {
    223           /* put length back (note that this doesn't actually realloc anything) */
    224           _dbus_string_set_length (buffer, start);
    225           return -1;
    226         }
    227     }
    228   else
    229     {
    230       /* put length back (doesn't actually realloc) */
    231       _dbus_string_set_length (buffer, start + bytes_read);
    232 
    233 #if 0
    234       if (bytes_read > 0)
    235         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
    236 #endif
    237 
    238       return bytes_read;
    239     }
    240 }
    241 
    242 /**
    243  * Thin wrapper around the write() system call that writes a part of a
    244  * DBusString and handles EINTR for you.
    245  *
    246  * @param fd the file descriptor to write
    247  * @param buffer the buffer to write data from
    248  * @param start the first byte in the buffer to write
    249  * @param len the number of bytes to try to write
    250  * @returns the number of bytes written or -1 on error
    251  */
    252 int
    253 _dbus_write_socket (int               fd,
    254                     const DBusString *buffer,
    255                     int               start,
    256                     int               len)
    257 {
    258   const char *data;
    259   int bytes_written;
    260 
    261   data = _dbus_string_get_const_data_len (buffer, start, len);
    262 
    263  again:
    264 
    265   _dbus_verbose ("send: len=%d fd=%d\n", len, fd);
    266   bytes_written = send (fd, data, len, 0);
    267 
    268   if (bytes_written == SOCKET_ERROR)
    269     {
    270       DBUS_SOCKET_SET_ERRNO();
    271       _dbus_verbose ("send: failed: %s\n", _dbus_strerror_from_errno ());
    272       bytes_written = -1;
    273     }
    274     else
    275       _dbus_verbose ("send: = %d\n", bytes_written);
    276 
    277   if (bytes_written < 0 && errno == EINTR)
    278     goto again;
    279 
    280 #if 0
    281   if (bytes_written > 0)
    282     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
    283 #endif
    284 
    285   return bytes_written;
    286 }
    287 
    288 
    289 /**
    290  * Closes a file descriptor.
    291  *
    292  * @param fd the file descriptor
    293  * @param error error object
    294  * @returns #FALSE if error set
    295  */
    296 dbus_bool_t
    297 _dbus_close_socket (int        fd,
    298                     DBusError *error)
    299 {
    300   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
    301 
    302  again:
    303   if (closesocket (fd) == SOCKET_ERROR)
    304     {
    305       DBUS_SOCKET_SET_ERRNO ();
    306 
    307       if (errno == EINTR)
    308         goto again;
    309 
    310       dbus_set_error (error, _dbus_error_from_errno (errno),
    311                       "Could not close socket: socket=%d, , %s",
    312                       fd, _dbus_strerror_from_errno ());
    313       return FALSE;
    314     }
    315   _dbus_verbose ("_dbus_close_socket: socket=%d, \n", fd);
    316 
    317   return TRUE;
    318 }
    319 
    320 /**
    321  * Sets the file descriptor to be close
    322  * on exec. Should be called for all file
    323  * descriptors in D-Bus code.
    324  *
    325  * @param fd the file descriptor
    326  */
    327 void
    328 _dbus_fd_set_close_on_exec (intptr_t handle)
    329 {
    330   if ( !SetHandleInformation( (HANDLE) handle,
    331                         HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE,
    332                         0 /*disable both flags*/ ) )
    333     {
    334       _dbus_win_warn_win_error ("Disabling socket handle inheritance failed:", GetLastError());
    335     }
    336 }
    337 
    338 /**
    339  * Sets a file descriptor to be nonblocking.
    340  *
    341  * @param fd the file descriptor.
    342  * @param error address of error location.
    343  * @returns #TRUE on success.
    344  */
    345 dbus_bool_t
    346 _dbus_set_fd_nonblocking (int             handle,
    347                           DBusError      *error)
    348 {
    349   u_long one = 1;
    350 
    351   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
    352 
    353   if (ioctlsocket (handle, FIONBIO, &one) == SOCKET_ERROR)
    354     {
    355       DBUS_SOCKET_SET_ERRNO ();
    356       dbus_set_error (error, _dbus_error_from_errno (errno),
    357                       "Failed to set socket %d:%d to nonblocking: %s", handle,
    358                       _dbus_strerror_from_errno ());
    359       return FALSE;
    360     }
    361 
    362   return TRUE;
    363 }
    364 
    365 
    366 /**
    367  * Like _dbus_write() but will use writev() if possible
    368  * to write both buffers in sequence. The return value
    369  * is the number of bytes written in the first buffer,
    370  * plus the number written in the second. If the first
    371  * buffer is written successfully and an error occurs
    372  * writing the second, the number of bytes in the first
    373  * is returned (i.e. the error is ignored), on systems that
    374  * don't have writev. Handles EINTR for you.
    375  * The second buffer may be #NULL.
    376  *
    377  * @param fd the file descriptor
    378  * @param buffer1 first buffer
    379  * @param start1 first byte to write in first buffer
    380  * @param len1 number of bytes to write from first buffer
    381  * @param buffer2 second buffer, or #NULL
    382  * @param start2 first byte to write in second buffer
    383  * @param len2 number of bytes to write in second buffer
    384  * @returns total bytes written from both buffers, or -1 on error
    385  */
    386 int
    387 _dbus_write_socket_two (int               fd,
    388                         const DBusString *buffer1,
    389                         int               start1,
    390                         int               len1,
    391                         const DBusString *buffer2,
    392                         int               start2,
    393                         int               len2)
    394 {
    395   WSABUF vectors[2];
    396   const char *data1;
    397   const char *data2;
    398   int rc;
    399   DWORD bytes_written;
    400 
    401   _dbus_assert (buffer1 != NULL);
    402   _dbus_assert (start1 >= 0);
    403   _dbus_assert (start2 >= 0);
    404   _dbus_assert (len1 >= 0);
    405   _dbus_assert (len2 >= 0);
    406 
    407 
    408   data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
    409 
    410   if (buffer2 != NULL)
    411     data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
    412   else
    413     {
    414       data2 = NULL;
    415       start2 = 0;
    416       len2 = 0;
    417     }
    418 
    419   vectors[0].buf = (char*) data1;
    420   vectors[0].len = len1;
    421   vectors[1].buf = (char*) data2;
    422   vectors[1].len = len2;
    423 
    424  again:
    425 
    426   _dbus_verbose ("WSASend: len1+2=%d+%d fd=%d\n", len1, len2, fd);
    427   rc = WSASend (fd,
    428                 vectors,
    429                 data2 ? 2 : 1,
    430                 &bytes_written,
    431                 0,
    432                 NULL,
    433                 NULL);
    434 
    435   if (rc == SOCKET_ERROR)
    436     {
    437       DBUS_SOCKET_SET_ERRNO ();
    438       _dbus_verbose ("WSASend: failed: %s\n", _dbus_strerror_from_errno ());
    439       bytes_written = -1;
    440     }
    441   else
    442     _dbus_verbose ("WSASend: = %ld\n", bytes_written);
    443 
    444   if (bytes_written < 0 && errno == EINTR)
    445     goto again;
    446 
    447   return bytes_written;
    448 }
    449 
    450 dbus_bool_t
    451 _dbus_socket_is_invalid (int fd)
    452 {
    453     return fd == INVALID_SOCKET ? TRUE : FALSE;
    454 }
    455 
    456 #if 0
    457 
    458 /**
    459  * Opens the client side of a Windows named pipe. The connection D-BUS
    460  * file descriptor index is returned. It is set up as nonblocking.
    461  *
    462  * @param path the path to named pipe socket
    463  * @param error return location for error code
    464  * @returns connection D-BUS file descriptor or -1 on error
    465  */
    466 int
    467 _dbus_connect_named_pipe (const char     *path,
    468                           DBusError      *error)
    469 {
    470   _dbus_assert_not_reached ("not implemented");
    471 }
    472 
    473 #endif
    474 
    475 
    476 
    477 void
    478 _dbus_win_startup_winsock (void)
    479 {
    480   /* Straight from MSDN, deuglified */
    481 
    482   static dbus_bool_t beenhere = FALSE;
    483 
    484   WORD wVersionRequested;
    485   WSADATA wsaData;
    486   int err;
    487 
    488   if (beenhere)
    489     return;
    490 
    491   wVersionRequested = MAKEWORD (2, 0);
    492 
    493   err = WSAStartup (wVersionRequested, &wsaData);
    494   if (err != 0)
    495     {
    496       _dbus_assert_not_reached ("Could not initialize WinSock");
    497       _dbus_abort ();
    498     }
    499 
    500   /* Confirm that the WinSock DLL supports 2.0.  Note that if the DLL
    501    * supports versions greater than 2.0 in addition to 2.0, it will
    502    * still return 2.0 in wVersion since that is the version we
    503    * requested.
    504    */
    505   if (LOBYTE (wsaData.wVersion) != 2 ||
    506       HIBYTE (wsaData.wVersion) != 0)
    507     {
    508       _dbus_assert_not_reached ("No usable WinSock found");
    509       _dbus_abort ();
    510     }
    511 
    512   beenhere = TRUE;
    513 }
    514 
    515 
    516 
    517 
    518 
    519 
    520 
    521 
    522 
    523 /************************************************************************
    524 
    525  UTF / string code
    526 
    527  ************************************************************************/
    528 
    529 /**
    530  * Measure the message length without terminating nul
    531  */
    532 int _dbus_printf_string_upper_bound (const char *format,
    533                                      va_list args)
    534 {
    535   /* MSVCRT's vsnprintf semantics are a bit different */
    536   char buf[1024];
    537   int bufsize;
    538   int len;
    539 
    540   bufsize = sizeof (buf);
    541   len = _vsnprintf (buf, bufsize - 1, format, args);
    542 
    543   while (len == -1) /* try again */
    544     {
    545       char *p;
    546 
    547       bufsize *= 2;
    548 
    549       p = malloc (bufsize);
    550       len = _vsnprintf (p, bufsize - 1, format, args);
    551       free (p);
    552     }
    553 
    554   return len;
    555 }
    556 
    557 
    558 /**
    559  * Returns the UTF-16 form of a UTF-8 string. The result should be
    560  * freed with dbus_free() when no longer needed.
    561  *
    562  * @param str the UTF-8 string
    563  * @param error return location for error code
    564  */
    565 wchar_t *
    566 _dbus_win_utf8_to_utf16 (const char *str,
    567                          DBusError  *error)
    568 {
    569   DBusString s;
    570   int n;
    571   wchar_t *retval;
    572 
    573   _dbus_string_init_const (&s, str);
    574 
    575   if (!_dbus_string_validate_utf8 (&s, 0, _dbus_string_get_length (&s)))
    576     {
    577       dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid UTF-8");
    578       return NULL;
    579     }
    580 
    581   n = MultiByteToWideChar (CP_UTF8, 0, str, -1, NULL, 0);
    582 
    583   if (n == 0)
    584     {
    585       _dbus_win_set_error_from_win_error (error, GetLastError ());
    586       return NULL;
    587     }
    588 
    589   retval = dbus_new (wchar_t, n);
    590 
    591   if (!retval)
    592     {
    593       _DBUS_SET_OOM (error);
    594       return NULL;
    595     }
    596 
    597   if (MultiByteToWideChar (CP_UTF8, 0, str, -1, retval, n) != n)
    598     {
    599       dbus_free (retval);
    600       dbus_set_error_const (error, DBUS_ERROR_FAILED, "MultiByteToWideChar inconsistency");
    601       return NULL;
    602     }
    603 
    604   return retval;
    605 }
    606 
    607 /**
    608  * Returns the UTF-8 form of a UTF-16 string. The result should be
    609  * freed with dbus_free() when no longer needed.
    610  *
    611  * @param str the UTF-16 string
    612  * @param error return location for error code
    613  */
    614 char *
    615 _dbus_win_utf16_to_utf8 (const wchar_t *str,
    616                          DBusError     *error)
    617 {
    618   int n;
    619   char *retval;
    620 
    621   n = WideCharToMultiByte (CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
    622 
    623   if (n == 0)
    624     {
    625       _dbus_win_set_error_from_win_error (error, GetLastError ());
    626       return NULL;
    627     }
    628 
    629   retval = dbus_malloc (n);
    630 
    631   if (!retval)
    632     {
    633       _DBUS_SET_OOM (error);
    634       return NULL;
    635     }
    636 
    637   if (WideCharToMultiByte (CP_UTF8, 0, str, -1, retval, n, NULL, NULL) != n)
    638     {
    639       dbus_free (retval);
    640       dbus_set_error_const (error, DBUS_ERROR_FAILED, "WideCharToMultiByte inconsistency");
    641       return NULL;
    642     }
    643 
    644   return retval;
    645 }
    646 
    647 
    648 
    649 
    650 
    651 
    652 /************************************************************************
    653 
    654 
    655  ************************************************************************/
    656 
    657 dbus_bool_t
    658 _dbus_win_account_to_sid (const wchar_t *waccount,
    659                           void      	 **ppsid,
    660                           DBusError 	  *error)
    661 {
    662   dbus_bool_t retval = FALSE;
    663   DWORD sid_length, wdomain_length;
    664   SID_NAME_USE use;
    665   wchar_t *wdomain;
    666 
    667   *ppsid = NULL;
    668 
    669   sid_length = 0;
    670   wdomain_length = 0;
    671   if (!LookupAccountNameW (NULL, waccount, NULL, &sid_length,
    672                            NULL, &wdomain_length, &use) &&
    673       GetLastError () != ERROR_INSUFFICIENT_BUFFER)
    674     {
    675       _dbus_win_set_error_from_win_error (error, GetLastError ());
    676       return FALSE;
    677     }
    678 
    679   *ppsid = dbus_malloc (sid_length);
    680   if (!*ppsid)
    681     {
    682       _DBUS_SET_OOM (error);
    683       return FALSE;
    684     }
    685 
    686   wdomain = dbus_new (wchar_t, wdomain_length);
    687   if (!wdomain)
    688     {
    689       _DBUS_SET_OOM (error);
    690       goto out1;
    691     }
    692 
    693   if (!LookupAccountNameW (NULL, waccount, (PSID) *ppsid, &sid_length,
    694                            wdomain, &wdomain_length, &use))
    695     {
    696       _dbus_win_set_error_from_win_error (error, GetLastError ());
    697       goto out2;
    698     }
    699 
    700   if (!IsValidSid ((PSID) *ppsid))
    701     {
    702       dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid SID");
    703       goto out2;
    704     }
    705 
    706   retval = TRUE;
    707 
    708 out2:
    709   dbus_free (wdomain);
    710 out1:
    711   if (!retval)
    712     {
    713       dbus_free (*ppsid);
    714       *ppsid = NULL;
    715     }
    716 
    717   return retval;
    718 }
    719 
    720 /** @} end of sysdeps-win */
    721 
    722 
    723 /**
    724  * The only reason this is separate from _dbus_getpid() is to allow it
    725  * on Windows for logging but not for other purposes.
    726  *
    727  * @returns process ID to put in log messages
    728  */
    729 unsigned long
    730 _dbus_pid_for_log (void)
    731 {
    732   return _dbus_getpid ();
    733 }
    734 
    735 
    736 #ifndef DBUS_WINCE
    737 /** Gets our SID
    738  * @param points to sid buffer, need to be freed with LocalFree()
    739  * @returns process sid
    740  */
    741 static dbus_bool_t
    742 _dbus_getsid(char **sid)
    743 {
    744   HANDLE process_token = INVALID_HANDLE_VALUE;
    745   TOKEN_USER *token_user = NULL;
    746   DWORD n;
    747   PSID psid;
    748   int retval = FALSE;
    749 
    750   if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &process_token))
    751     {
    752       _dbus_win_warn_win_error ("OpenProcessToken failed", GetLastError ());
    753       goto failed;
    754     }
    755   if ((!GetTokenInformation (process_token, TokenUser, NULL, 0, &n)
    756             && GetLastError () != ERROR_INSUFFICIENT_BUFFER)
    757            || (token_user = alloca (n)) == NULL
    758            || !GetTokenInformation (process_token, TokenUser, token_user, n, &n))
    759     {
    760       _dbus_win_warn_win_error ("GetTokenInformation failed", GetLastError ());
    761       goto failed;
    762     }
    763   psid = token_user->User.Sid;
    764   if (!IsValidSid (psid))
    765     {
    766       _dbus_verbose("%s invalid sid\n",__FUNCTION__);
    767       goto failed;
    768     }
    769   if (!ConvertSidToStringSidA (psid, sid))
    770     {
    771       _dbus_verbose("%s invalid sid\n",__FUNCTION__);
    772       goto failed;
    773     }
    774 //okay:
    775   retval = TRUE;
    776 
    777 failed:
    778   if (process_token != INVALID_HANDLE_VALUE)
    779     CloseHandle (process_token);
    780 
    781   _dbus_verbose("_dbus_getsid() returns %d\n",retval);
    782   return retval;
    783 }
    784 #endif
    785 
    786 /************************************************************************
    787 
    788  pipes
    789 
    790  ************************************************************************/
    791 
    792 /**
    793  * Creates a full-duplex pipe (as in socketpair()).
    794  * Sets both ends of the pipe nonblocking.
    795  *
    796  * @todo libdbus only uses this for the debug-pipe server, so in
    797  * principle it could be in dbus-sysdeps-util.c, except that
    798  * dbus-sysdeps-util.c isn't in libdbus when tests are enabled and the
    799  * debug-pipe server is used.
    800  *
    801  * @param fd1 return location for one end
    802  * @param fd2 return location for the other end
    803  * @param blocking #TRUE if pipe should be blocking
    804  * @param error error return
    805  * @returns #FALSE on failure (if error is set)
    806  */
    807 dbus_bool_t
    808 _dbus_full_duplex_pipe (int        *fd1,
    809                         int        *fd2,
    810                         dbus_bool_t blocking,
    811                         DBusError  *error)
    812 {
    813   SOCKET temp, socket1 = -1, socket2 = -1;
    814   struct sockaddr_in saddr;
    815   int len;
    816   u_long arg;
    817   fd_set read_set, write_set;
    818   struct timeval tv;
    819   int res;
    820 
    821   _dbus_win_startup_winsock ();
    822 
    823   temp = socket (AF_INET, SOCK_STREAM, 0);
    824   if (temp == INVALID_SOCKET)
    825     {
    826       DBUS_SOCKET_SET_ERRNO ();
    827       goto out0;
    828     }
    829 
    830   _DBUS_ZERO (saddr);
    831   saddr.sin_family = AF_INET;
    832   saddr.sin_port = 0;
    833   saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
    834 
    835   if (bind (temp, (struct sockaddr *)&saddr, sizeof (saddr)) == SOCKET_ERROR)
    836     {
    837       DBUS_SOCKET_SET_ERRNO ();
    838       goto out0;
    839     }
    840 
    841   if (listen (temp, 1) == SOCKET_ERROR)
    842     {
    843       DBUS_SOCKET_SET_ERRNO ();
    844       goto out0;
    845     }
    846 
    847   len = sizeof (saddr);
    848   if (getsockname (temp, (struct sockaddr *)&saddr, &len) == SOCKET_ERROR)
    849     {
    850       DBUS_SOCKET_SET_ERRNO ();
    851       goto out0;
    852     }
    853 
    854   socket1 = socket (AF_INET, SOCK_STREAM, 0);
    855   if (socket1 == INVALID_SOCKET)
    856     {
    857       DBUS_SOCKET_SET_ERRNO ();
    858       goto out0;
    859     }
    860 
    861   if (connect (socket1, (struct sockaddr  *)&saddr, len) == SOCKET_ERROR)
    862     {
    863       DBUS_SOCKET_SET_ERRNO ();
    864       goto out1;
    865     }
    866 
    867   socket2 = accept (temp, (struct sockaddr *) &saddr, &len);
    868   if (socket2 == INVALID_SOCKET)
    869     {
    870       DBUS_SOCKET_SET_ERRNO ();
    871       goto out1;
    872     }
    873 
    874   if (!blocking)
    875     {
    876       arg = 1;
    877       if (ioctlsocket (socket1, FIONBIO, &arg) == SOCKET_ERROR)
    878         {
    879           DBUS_SOCKET_SET_ERRNO ();
    880           goto out2;
    881         }
    882 
    883       arg = 1;
    884       if (ioctlsocket (socket2, FIONBIO, &arg) == SOCKET_ERROR)
    885         {
    886           DBUS_SOCKET_SET_ERRNO ();
    887           goto out2;
    888         }
    889     }
    890 
    891   *fd1 = socket1;
    892   *fd2 = socket2;
    893 
    894   _dbus_verbose ("full-duplex pipe %d:%d <-> %d:%d\n",
    895                  *fd1, socket1, *fd2, socket2);
    896 
    897   closesocket (temp);
    898 
    899   return TRUE;
    900 
    901 out2:
    902   closesocket (socket2);
    903 out1:
    904   closesocket (socket1);
    905 out0:
    906   closesocket (temp);
    907 
    908   dbus_set_error (error, _dbus_error_from_errno (errno),
    909                   "Could not setup socket pair: %s",
    910                   _dbus_strerror_from_errno ());
    911 
    912   return FALSE;
    913 }
    914 
    915 /**
    916  * Wrapper for poll().
    917  *
    918  * @param fds the file descriptors to poll
    919  * @param n_fds number of descriptors in the array
    920  * @param timeout_milliseconds timeout or -1 for infinite
    921  * @returns numbers of fds with revents, or <0 on error
    922  */
    923 int
    924 _dbus_poll (DBusPollFD *fds,
    925             int         n_fds,
    926             int         timeout_milliseconds)
    927 {
    928 #define USE_CHRIS_IMPL 0
    929 
    930 #if USE_CHRIS_IMPL
    931 
    932 #define DBUS_POLL_CHAR_BUFFER_SIZE 2000
    933   char msg[DBUS_POLL_CHAR_BUFFER_SIZE];
    934   char *msgp;
    935 
    936   int ret = 0;
    937   int i;
    938   struct timeval tv;
    939   int ready;
    940 
    941 #define DBUS_STACK_WSAEVENTS 256
    942   WSAEVENT eventsOnStack[DBUS_STACK_WSAEVENTS];
    943   WSAEVENT *pEvents = NULL;
    944   if (n_fds > DBUS_STACK_WSAEVENTS)
    945     pEvents = calloc(sizeof(WSAEVENT), n_fds);
    946   else
    947     pEvents = eventsOnStack;
    948 
    949 
    950 #ifdef DBUS_ENABLE_VERBOSE_MODE
    951   msgp = msg;
    952   msgp += sprintf (msgp, "WSAEventSelect: to=%d\n\t", timeout_milliseconds);
    953   for (i = 0; i < n_fds; i++)
    954     {
    955       static dbus_bool_t warned = FALSE;
    956       DBusPollFD *fdp = &fds[i];
    957 
    958 
    959       if (fdp->events & _DBUS_POLLIN)
    960         msgp += sprintf (msgp, "R:%d ", fdp->fd);
    961 
    962       if (fdp->events & _DBUS_POLLOUT)
    963         msgp += sprintf (msgp, "W:%d ", fdp->fd);
    964 
    965       msgp += sprintf (msgp, "E:%d\n\t", fdp->fd);
    966 
    967       // FIXME: more robust code for long  msg
    968       //        create on heap when msg[] becomes too small
    969       if (msgp >= msg + DBUS_POLL_CHAR_BUFFER_SIZE)
    970         {
    971           _dbus_assert_not_reached ("buffer overflow in _dbus_poll");
    972         }
    973     }
    974 
    975   msgp += sprintf (msgp, "\n");
    976   _dbus_verbose ("%s",msg);
    977 #endif
    978   for (i = 0; i < n_fds; i++)
    979     {
    980       DBusPollFD *fdp = &fds[i];
    981       WSAEVENT ev;
    982       long lNetworkEvents = FD_OOB;
    983 
    984       ev = WSACreateEvent();
    985 
    986       if (fdp->events & _DBUS_POLLIN)
    987         lNetworkEvents |= FD_READ | FD_ACCEPT | FD_CLOSE;
    988 
    989       if (fdp->events & _DBUS_POLLOUT)
    990         lNetworkEvents |= FD_WRITE | FD_CONNECT;
    991 
    992       WSAEventSelect(fdp->fd, ev, lNetworkEvents);
    993 
    994       pEvents[i] = ev;
    995     }
    996 
    997 
    998   ready = WSAWaitForMultipleEvents (n_fds, pEvents, FALSE, timeout_milliseconds, FALSE);
    999 
   1000   if (DBUS_SOCKET_API_RETURNS_ERROR (ready))
   1001     {
   1002       DBUS_SOCKET_SET_ERRNO ();
   1003       if (errno != WSAEWOULDBLOCK)
   1004         _dbus_verbose ("WSAWaitForMultipleEvents: failed: %s\n", _dbus_strerror_from_errno ());
   1005       ret = -1;
   1006     }
   1007   else if (ready == WSA_WAIT_TIMEOUT)
   1008     {
   1009       _dbus_verbose ("WSAWaitForMultipleEvents: WSA_WAIT_TIMEOUT\n");
   1010       ret = 0;
   1011     }
   1012   else if (ready >= WSA_WAIT_EVENT_0 && ready < (int)(WSA_WAIT_EVENT_0 + n_fds))
   1013     {
   1014       msgp = msg;
   1015       msgp += sprintf (msgp, "WSAWaitForMultipleEvents: =%d\n\t", ready);
   1016 
   1017       for (i = 0; i < n_fds; i++)
   1018         {
   1019           DBusPollFD *fdp = &fds[i];
   1020           WSANETWORKEVENTS ne;
   1021 
   1022           fdp->revents = 0;
   1023 
   1024           WSAEnumNetworkEvents(fdp->fd, pEvents[i], &ne);
   1025 
   1026           if (ne.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
   1027             fdp->revents |= _DBUS_POLLIN;
   1028 
   1029           if (ne.lNetworkEvents & (FD_WRITE | FD_CONNECT))
   1030             fdp->revents |= _DBUS_POLLOUT;
   1031 
   1032           if (ne.lNetworkEvents & (FD_OOB))
   1033             fdp->revents |= _DBUS_POLLERR;
   1034 
   1035           if (ne.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
   1036               msgp += sprintf (msgp, "R:%d ", fdp->fd);
   1037 
   1038           if (ne.lNetworkEvents & (FD_WRITE | FD_CONNECT))
   1039               msgp += sprintf (msgp, "W:%d ", fdp->fd);
   1040 
   1041           if (ne.lNetworkEvents & (FD_OOB))
   1042               msgp += sprintf (msgp, "E:%d ", fdp->fd);
   1043 
   1044           msgp += sprintf (msgp, "lNetworkEvents:%d ", ne.lNetworkEvents);
   1045 
   1046           if(ne.lNetworkEvents)
   1047             ret++;
   1048 
   1049           WSAEventSelect(fdp->fd, pEvents[i], 0);
   1050         }
   1051 
   1052       msgp += sprintf (msgp, "\n");
   1053       _dbus_verbose ("%s",msg);
   1054     }
   1055   else
   1056     {
   1057       _dbus_verbose ("WSAWaitForMultipleEvents: failed for unknown reason!");
   1058       ret = -1;
   1059     }
   1060 
   1061   for(i = 0; i < n_fds; i++)
   1062     {
   1063       WSACloseEvent(pEvents[i]);
   1064     }
   1065 
   1066   if (n_fds > DBUS_STACK_WSAEVENTS)
   1067     free(pEvents);
   1068 
   1069   return ret;
   1070 
   1071 #else   /* USE_CHRIS_IMPL */
   1072 
   1073 #define DBUS_POLL_CHAR_BUFFER_SIZE 2000
   1074   char msg[DBUS_POLL_CHAR_BUFFER_SIZE];
   1075   char *msgp;
   1076 
   1077   fd_set read_set, write_set, err_set;
   1078   int max_fd = 0;
   1079   int i;
   1080   struct timeval tv;
   1081   int ready;
   1082 
   1083   FD_ZERO (&read_set);
   1084   FD_ZERO (&write_set);
   1085   FD_ZERO (&err_set);
   1086 
   1087 
   1088 #ifdef DBUS_ENABLE_VERBOSE_MODE
   1089   msgp = msg;
   1090   msgp += sprintf (msgp, "select: to=%d\n\t", timeout_milliseconds);
   1091   for (i = 0; i < n_fds; i++)
   1092     {
   1093       static dbus_bool_t warned = FALSE;
   1094       DBusPollFD *fdp = &fds[i];
   1095 
   1096 
   1097       if (fdp->events & _DBUS_POLLIN)
   1098         msgp += sprintf (msgp, "R:%d ", fdp->fd);
   1099 
   1100       if (fdp->events & _DBUS_POLLOUT)
   1101         msgp += sprintf (msgp, "W:%d ", fdp->fd);
   1102 
   1103       msgp += sprintf (msgp, "E:%d\n\t", fdp->fd);
   1104 
   1105       // FIXME: more robust code for long  msg
   1106       //        create on heap when msg[] becomes too small
   1107       if (msgp >= msg + DBUS_POLL_CHAR_BUFFER_SIZE)
   1108         {
   1109           _dbus_assert_not_reached ("buffer overflow in _dbus_poll");
   1110         }
   1111     }
   1112 
   1113   msgp += sprintf (msgp, "\n");
   1114   _dbus_verbose ("%s",msg);
   1115 #endif
   1116   for (i = 0; i < n_fds; i++)
   1117     {
   1118       DBusPollFD *fdp = &fds[i];
   1119 
   1120       if (fdp->events & _DBUS_POLLIN)
   1121         FD_SET (fdp->fd, &read_set);
   1122 
   1123       if (fdp->events & _DBUS_POLLOUT)
   1124         FD_SET (fdp->fd, &write_set);
   1125 
   1126       FD_SET (fdp->fd, &err_set);
   1127 
   1128       max_fd = MAX (max_fd, fdp->fd);
   1129     }
   1130 
   1131 
   1132   tv.tv_sec = timeout_milliseconds / 1000;
   1133   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
   1134 
   1135   ready = select (max_fd + 1, &read_set, &write_set, &err_set,
   1136                   timeout_milliseconds < 0 ? NULL : &tv);
   1137 
   1138   if (DBUS_SOCKET_API_RETURNS_ERROR (ready))
   1139     {
   1140       DBUS_SOCKET_SET_ERRNO ();
   1141       if (errno != WSAEWOULDBLOCK)
   1142         _dbus_verbose ("select: failed: %s\n", _dbus_strerror_from_errno ());
   1143     }
   1144   else if (ready == 0)
   1145     _dbus_verbose ("select: = 0\n");
   1146   else
   1147     if (ready > 0)
   1148       {
   1149 #ifdef DBUS_ENABLE_VERBOSE_MODE
   1150         msgp = msg;
   1151         msgp += sprintf (msgp, "select: = %d:\n\t", ready);
   1152 
   1153         for (i = 0; i < n_fds; i++)
   1154           {
   1155             DBusPollFD *fdp = &fds[i];
   1156 
   1157             if (FD_ISSET (fdp->fd, &read_set))
   1158               msgp += sprintf (msgp, "R:%d ", fdp->fd);
   1159 
   1160             if (FD_ISSET (fdp->fd, &write_set))
   1161               msgp += sprintf (msgp, "W:%d ", fdp->fd);
   1162 
   1163             if (FD_ISSET (fdp->fd, &err_set))
   1164               msgp += sprintf (msgp, "E:%d\n\t", fdp->fd);
   1165           }
   1166         msgp += sprintf (msgp, "\n");
   1167         _dbus_verbose ("%s",msg);
   1168 #endif
   1169 
   1170         for (i = 0; i < n_fds; i++)
   1171           {
   1172             DBusPollFD *fdp = &fds[i];
   1173 
   1174             fdp->revents = 0;
   1175 
   1176             if (FD_ISSET (fdp->fd, &read_set))
   1177               fdp->revents |= _DBUS_POLLIN;
   1178 
   1179             if (FD_ISSET (fdp->fd, &write_set))
   1180               fdp->revents |= _DBUS_POLLOUT;
   1181 
   1182             if (FD_ISSET (fdp->fd, &err_set))
   1183               fdp->revents |= _DBUS_POLLERR;
   1184           }
   1185       }
   1186   return ready;
   1187 #endif  /* USE_CHRIS_IMPL */
   1188 }
   1189 
   1190 
   1191 
   1192 
   1193 /******************************************************************************
   1194 
   1195 Original CVS version of dbus-sysdeps.c
   1196 
   1197 ******************************************************************************/
   1198 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
   1199 /* dbus-sysdeps.c Wrappers around system/libc features (internal to D-Bus implementation)
   1200  *
   1201  * Copyright (C) 2002, 2003  Red Hat, Inc.
   1202  * Copyright (C) 2003 CodeFactory AB
   1203  * Copyright (C) 2005 Novell, Inc.
   1204  *
   1205  * Licensed under the Academic Free License version 2.1
   1206  *
   1207  * This program is free software; you can redistribute it and/or modify
   1208  * it under the terms of the GNU General Public License as published by
   1209  * the Free Software Foundation; either version 2 of the License, or
   1210  * (at your option) any later version.
   1211  *
   1212  * This program is distributed in the hope that it will be useful,
   1213  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   1214  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   1215  * GNU General Public License for more details.
   1216  *
   1217  * You should have received a copy of the GNU General Public License
   1218  * along with this program; if not, write to the Free Software
   1219  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
   1220  *
   1221  */
   1222 
   1223 
   1224 /**
   1225  * Exit the process, returning the given value.
   1226  *
   1227  * @param code the exit code
   1228  */
   1229 void
   1230 _dbus_exit (int code)
   1231 {
   1232   _exit (code);
   1233 }
   1234 
   1235 /**
   1236  * Creates a socket and connects to a socket at the given host
   1237  * and port. The connection fd is returned, and is set up as
   1238  * nonblocking.
   1239  *
   1240  * @param host the host name to connect to
   1241  * @param port the port to connect to
   1242  * @param family the address family to listen on, NULL for all
   1243  * @param error return location for error code
   1244  * @returns connection file descriptor or -1 on error
   1245  */
   1246 int
   1247 _dbus_connect_tcp_socket (const char     *host,
   1248                           const char     *port,
   1249                           const char     *family,
   1250                           DBusError      *error)
   1251 {
   1252   return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
   1253 }
   1254 
   1255 int
   1256 _dbus_connect_tcp_socket_with_nonce (const char     *host,
   1257                                      const char     *port,
   1258                                      const char     *family,
   1259                                      const char     *noncefile,
   1260                                      DBusError      *error)
   1261 {
   1262   int fd = -1, res;
   1263   struct addrinfo hints;
   1264   struct addrinfo *ai, *tmp;
   1265 
   1266   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   1267 
   1268   _dbus_win_startup_winsock ();
   1269 
   1270   _DBUS_ZERO (hints);
   1271 
   1272   if (!family)
   1273     hints.ai_family = AF_UNSPEC;
   1274   else if (!strcmp(family, "ipv4"))
   1275     hints.ai_family = AF_INET;
   1276   else if (!strcmp(family, "ipv6"))
   1277     hints.ai_family = AF_INET6;
   1278   else
   1279     {
   1280       dbus_set_error (error,
   1281                       DBUS_ERROR_INVALID_ARGS,
   1282                       "Unknown address family %s", family);
   1283       return -1;
   1284     }
   1285   hints.ai_protocol = IPPROTO_TCP;
   1286   hints.ai_socktype = SOCK_STREAM;
   1287 #ifdef AI_ADDRCONFIG
   1288   hints.ai_flags = AI_ADDRCONFIG;
   1289 #else
   1290   hints.ai_flags = 0;
   1291 #endif
   1292 
   1293   if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
   1294     {
   1295       dbus_set_error (error,
   1296                       _dbus_error_from_errno (res),
   1297                       "Failed to lookup host/port: \"%s:%s\": %s (%d)",
   1298                       host, port, _dbus_strerror(res), res);
   1299       return -1;
   1300     }
   1301 
   1302   tmp = ai;
   1303   while (tmp)
   1304     {
   1305       if ((fd = socket (tmp->ai_family, SOCK_STREAM, 0)) == INVALID_SOCKET)
   1306         {
   1307           DBUS_SOCKET_SET_ERRNO ();
   1308           dbus_set_error (error,
   1309                           _dbus_error_from_errno (errno),
   1310                           "Failed to open socket: %s",
   1311                           _dbus_strerror_from_errno ());
   1312           freeaddrinfo(ai);
   1313           return -1;
   1314         }
   1315       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
   1316 
   1317       if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) == SOCKET_ERROR)
   1318         {
   1319           DBUS_SOCKET_SET_ERRNO ();
   1320           closesocket(fd);
   1321           fd = -1;
   1322           tmp = tmp->ai_next;
   1323           continue;
   1324         }
   1325 
   1326       break;
   1327     }
   1328   freeaddrinfo(ai);
   1329 
   1330   if (fd == -1)
   1331     {
   1332       dbus_set_error (error,
   1333                       _dbus_error_from_errno (errno),
   1334                       "Failed to connect to socket \"%s:%s\" %s",
   1335                       host, port, _dbus_strerror_from_errno ());
   1336       return -1;
   1337     }
   1338 
   1339   if (noncefile != NULL)
   1340     {
   1341       DBusString noncefileStr;
   1342       dbus_bool_t ret;
   1343       if (!_dbus_string_init (&noncefileStr) ||
   1344           !_dbus_string_append(&noncefileStr, noncefile))
   1345         {
   1346           closesocket (fd);
   1347           dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
   1348           return -1;
   1349         }
   1350 
   1351       ret = _dbus_send_nonce (fd, &noncefileStr, error);
   1352 
   1353       _dbus_string_free (&noncefileStr);
   1354 
   1355       if (!ret)
   1356         {
   1357           closesocket (fd);
   1358           return -1;
   1359         }
   1360     }
   1361 
   1362   if (!_dbus_set_fd_nonblocking (fd, error))
   1363     {
   1364       closesocket (fd);
   1365       return -1;
   1366     }
   1367 
   1368   return fd;
   1369 }
   1370 
   1371 /**
   1372  * Creates a socket and binds it to the given path, then listens on
   1373  * the socket. The socket is set to be nonblocking.  In case of port=0
   1374  * a random free port is used and returned in the port parameter.
   1375  * If inaddr_any is specified, the hostname is ignored.
   1376  *
   1377  * @param host the host name to listen on
   1378  * @param port the port to listen on, if zero a free port will be used
   1379  * @param family the address family to listen on, NULL for all
   1380  * @param retport string to return the actual port listened on
   1381  * @param fds_p location to store returned file descriptors
   1382  * @param error return location for errors
   1383  * @returns the number of listening file descriptors or -1 on error
   1384  */
   1385 
   1386 int
   1387 _dbus_listen_tcp_socket (const char     *host,
   1388                          const char     *port,
   1389                          const char     *family,
   1390                          DBusString     *retport,
   1391                          int           **fds_p,
   1392                          DBusError      *error)
   1393 {
   1394   int nlisten_fd = 0, *listen_fd = NULL, res, i, port_num = -1;
   1395   struct addrinfo hints;
   1396   struct addrinfo *ai, *tmp;
   1397 
   1398   // On Vista, sockaddr_gen must be a sockaddr_in6, and not a sockaddr_in6_old
   1399   //That's required for family == IPv6(which is the default on Vista if family is not given)
   1400   //So we use our own union instead of sockaddr_gen:
   1401 
   1402   typedef union {
   1403 	struct sockaddr Address;
   1404 	struct sockaddr_in AddressIn;
   1405 	struct sockaddr_in6 AddressIn6;
   1406   } mysockaddr_gen;
   1407 
   1408   *fds_p = NULL;
   1409   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   1410 
   1411   _dbus_win_startup_winsock ();
   1412 
   1413   _DBUS_ZERO (hints);
   1414 
   1415   if (!family)
   1416     hints.ai_family = AF_UNSPEC;
   1417   else if (!strcmp(family, "ipv4"))
   1418     hints.ai_family = AF_INET;
   1419   else if (!strcmp(family, "ipv6"))
   1420     hints.ai_family = AF_INET6;
   1421   else
   1422     {
   1423       dbus_set_error (error,
   1424                       DBUS_ERROR_INVALID_ARGS,
   1425                       "Unknown address family %s", family);
   1426       return -1;
   1427     }
   1428 
   1429   hints.ai_protocol = IPPROTO_TCP;
   1430   hints.ai_socktype = SOCK_STREAM;
   1431 #ifdef AI_ADDRCONFIG
   1432   hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
   1433 #else
   1434   hints.ai_flags = AI_PASSIVE;
   1435 #endif
   1436 
   1437  redo_lookup_with_port:
   1438   if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
   1439     {
   1440       dbus_set_error (error,
   1441                       _dbus_error_from_errno (res),
   1442                       "Failed to lookup host/port: \"%s:%s\": %s (%d)",
   1443                       host ? host : "*", port, _dbus_strerror(res), res);
   1444       return -1;
   1445     }
   1446 
   1447   tmp = ai;
   1448   while (tmp)
   1449     {
   1450       int fd = -1, *newlisten_fd;
   1451       if ((fd = socket (tmp->ai_family, SOCK_STREAM, 0)) == INVALID_SOCKET)
   1452         {
   1453           DBUS_SOCKET_SET_ERRNO ();
   1454           dbus_set_error (error,
   1455                           _dbus_error_from_errno (errno),
   1456                          "Failed to open socket: %s",
   1457                          _dbus_strerror_from_errno ());
   1458           goto failed;
   1459         }
   1460       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
   1461 
   1462       if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) == SOCKET_ERROR)
   1463         {
   1464           DBUS_SOCKET_SET_ERRNO ();
   1465           dbus_set_error (error, _dbus_error_from_errno (errno),
   1466                           "Failed to bind socket \"%s:%s\": %s",
   1467                           host ? host : "*", port, _dbus_strerror_from_errno ());
   1468           closesocket (fd);
   1469           goto failed;
   1470     }
   1471 
   1472       if (listen (fd, 30 /* backlog */) == SOCKET_ERROR)
   1473         {
   1474           DBUS_SOCKET_SET_ERRNO ();
   1475           dbus_set_error (error, _dbus_error_from_errno (errno),
   1476                           "Failed to listen on socket \"%s:%s\": %s",
   1477                           host ? host : "*", port, _dbus_strerror_from_errno ());
   1478           closesocket (fd);
   1479           goto failed;
   1480         }
   1481 
   1482       newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1));
   1483       if (!newlisten_fd)
   1484         {
   1485           closesocket (fd);
   1486           dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
   1487                           "Failed to allocate file handle array");
   1488           goto failed;
   1489         }
   1490       listen_fd = newlisten_fd;
   1491       listen_fd[nlisten_fd] = fd;
   1492       nlisten_fd++;
   1493 
   1494       if (!_dbus_string_get_length(retport))
   1495         {
   1496           /* If the user didn't specify a port, or used 0, then
   1497              the kernel chooses a port. After the first address
   1498              is bound to, we need to force all remaining addresses
   1499              to use the same port */
   1500           if (!port || !strcmp(port, "0"))
   1501             {
   1502               mysockaddr_gen addr;
   1503               socklen_t addrlen = sizeof(addr);
   1504               char portbuf[10];
   1505 
   1506               if (getsockname(fd, &addr.Address, &addrlen) == SOCKET_ERROR)
   1507                 {
   1508                   DBUS_SOCKET_SET_ERRNO ();
   1509                   dbus_set_error (error, _dbus_error_from_errno (errno),
   1510                                   "Failed to resolve port \"%s:%s\": %s",
   1511                                   host ? host : "*", port, _dbus_strerror_from_errno());
   1512                   goto failed;
   1513                 }
   1514               snprintf( portbuf, sizeof( portbuf ) - 1, "%d", addr.AddressIn.sin_port );
   1515               if (!_dbus_string_append(retport, portbuf))
   1516                 {
   1517                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
   1518                   goto failed;
   1519                 }
   1520 
   1521               /* Release current address list & redo lookup */
   1522               port = _dbus_string_get_const_data(retport);
   1523               freeaddrinfo(ai);
   1524               goto redo_lookup_with_port;
   1525             }
   1526           else
   1527             {
   1528               if (!_dbus_string_append(retport, port))
   1529                 {
   1530                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
   1531                     goto failed;
   1532                 }
   1533             }
   1534         }
   1535 
   1536       tmp = tmp->ai_next;
   1537     }
   1538   freeaddrinfo(ai);
   1539   ai = NULL;
   1540 
   1541   if (!nlisten_fd)
   1542     {
   1543       _dbus_win_set_errno (WSAEADDRINUSE);
   1544       dbus_set_error (error, _dbus_error_from_errno (errno),
   1545                       "Failed to bind socket \"%s:%s\": %s",
   1546                       host ? host : "*", port, _dbus_strerror_from_errno ());
   1547       return -1;
   1548     }
   1549 
   1550   sscanf(_dbus_string_get_const_data(retport), "%d", &port_num);
   1551 
   1552   for (i = 0 ; i < nlisten_fd ; i++)
   1553     {
   1554       if (!_dbus_set_fd_nonblocking (listen_fd[i], error))
   1555         {
   1556           goto failed;
   1557         }
   1558     }
   1559 
   1560   *fds_p = listen_fd;
   1561 
   1562   return nlisten_fd;
   1563 
   1564  failed:
   1565   if (ai)
   1566     freeaddrinfo(ai);
   1567   for (i = 0 ; i < nlisten_fd ; i++)
   1568     closesocket (listen_fd[i]);
   1569   dbus_free(listen_fd);
   1570   return -1;
   1571 }
   1572 
   1573 
   1574 /**
   1575  * Accepts a connection on a listening socket.
   1576  * Handles EINTR for you.
   1577  *
   1578  * @param listen_fd the listen file descriptor
   1579  * @returns the connection fd of the client, or -1 on error
   1580  */
   1581 int
   1582 _dbus_accept  (int listen_fd)
   1583 {
   1584   int client_fd;
   1585 
   1586  retry:
   1587   client_fd = accept (listen_fd, NULL, NULL);
   1588 
   1589   if (DBUS_SOCKET_IS_INVALID (client_fd))
   1590     {
   1591       DBUS_SOCKET_SET_ERRNO ();
   1592       if (errno == EINTR)
   1593         goto retry;
   1594     }
   1595 
   1596   _dbus_verbose ("client fd %d accepted\n", client_fd);
   1597 
   1598   return client_fd;
   1599 }
   1600 
   1601 
   1602 
   1603 
   1604 dbus_bool_t
   1605 _dbus_send_credentials_socket (int            handle,
   1606                         DBusError      *error)
   1607 {
   1608 /* FIXME: for the session bus credentials shouldn't matter (?), but
   1609  * for the system bus they are presumably essential. A rough outline
   1610  * of a way to implement the credential transfer would be this:
   1611  *
   1612  * client waits to *read* a byte.
   1613  *
   1614  * server creates a named pipe with a random name, sends a byte
   1615  * contining its length, and its name.
   1616  *
   1617  * client reads the name, connects to it (using Win32 API).
   1618  *
   1619  * server waits for connection to the named pipe, then calls
   1620  * ImpersonateNamedPipeClient(), notes its now-current credentials,
   1621  * calls RevertToSelf(), closes its handles to the named pipe, and
   1622  * is done. (Maybe there is some other way to get the SID of a named
   1623  * pipe client without having to use impersonation?)
   1624  *
   1625  * client closes its handles and is done.
   1626  *
   1627  * Ralf: Why not sending credentials over the given this connection ?
   1628  * Using named pipes makes it impossible to be connected from a unix client.
   1629  *
   1630  */
   1631   int bytes_written;
   1632   DBusString buf;
   1633 
   1634   _dbus_string_init_const_len (&buf, "\0", 1);
   1635 again:
   1636   bytes_written = _dbus_write_socket (handle, &buf, 0, 1 );
   1637 
   1638   if (bytes_written < 0 && errno == EINTR)
   1639     goto again;
   1640 
   1641   if (bytes_written < 0)
   1642     {
   1643       dbus_set_error (error, _dbus_error_from_errno (errno),
   1644                       "Failed to write credentials byte: %s",
   1645                      _dbus_strerror_from_errno ());
   1646       return FALSE;
   1647     }
   1648   else if (bytes_written == 0)
   1649     {
   1650       dbus_set_error (error, DBUS_ERROR_IO_ERROR,
   1651                       "wrote zero bytes writing credentials byte");
   1652       return FALSE;
   1653     }
   1654   else
   1655     {
   1656       _dbus_assert (bytes_written == 1);
   1657       _dbus_verbose ("wrote 1 zero byte, credential sending isn't implemented yet\n");
   1658       return TRUE;
   1659     }
   1660   return TRUE;
   1661 }
   1662 
   1663 /**
   1664  * Reads a single byte which must be nul (an error occurs otherwise),
   1665  * and reads unix credentials if available. Fills in pid/uid/gid with
   1666  * -1 if no credentials are available. Return value indicates whether
   1667  * a byte was read, not whether we got valid credentials. On some
   1668  * systems, such as Linux, reading/writing the byte isn't actually
   1669  * required, but we do it anyway just to avoid multiple codepaths.
   1670  *
   1671  * Fails if no byte is available, so you must select() first.
   1672  *
   1673  * The point of the byte is that on some systems we have to
   1674  * use sendmsg()/recvmsg() to transmit credentials.
   1675  *
   1676  * @param client_fd the client file descriptor
   1677  * @param credentials struct to fill with credentials of client
   1678  * @param error location to store error code
   1679  * @returns #TRUE on success
   1680  */
   1681 dbus_bool_t
   1682 _dbus_read_credentials_socket  (int              handle,
   1683                                 DBusCredentials *credentials,
   1684                                 DBusError       *error)
   1685 {
   1686   int bytes_read = 0;
   1687   DBusString buf;
   1688 
   1689   // could fail due too OOM
   1690   if (_dbus_string_init(&buf))
   1691     {
   1692       bytes_read = _dbus_read_socket(handle, &buf, 1 );
   1693 
   1694       if (bytes_read > 0)
   1695         _dbus_verbose("got one zero byte from server");
   1696 
   1697       _dbus_string_free(&buf);
   1698     }
   1699 
   1700   _dbus_credentials_add_from_current_process (credentials);
   1701   _dbus_verbose("FIXME: get faked credentials from current process");
   1702 
   1703   return TRUE;
   1704 }
   1705 
   1706 /**
   1707 * Checks to make sure the given directory is
   1708 * private to the user
   1709 *
   1710 * @param dir the name of the directory
   1711 * @param error error return
   1712 * @returns #FALSE on failure
   1713 **/
   1714 dbus_bool_t
   1715 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
   1716 {
   1717   /* TODO */
   1718   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   1719   return TRUE;
   1720 }
   1721 
   1722 
   1723 /**
   1724  * Appends the given filename to the given directory.
   1725  *
   1726  * @todo it might be cute to collapse multiple '/' such as "foo//"
   1727  * concat "//bar"
   1728  *
   1729  * @param dir the directory name
   1730  * @param next_component the filename
   1731  * @returns #TRUE on success
   1732  */
   1733 dbus_bool_t
   1734 _dbus_concat_dir_and_file (DBusString       *dir,
   1735                            const DBusString *next_component)
   1736 {
   1737   dbus_bool_t dir_ends_in_slash;
   1738   dbus_bool_t file_starts_with_slash;
   1739 
   1740   if (_dbus_string_get_length (dir) == 0 ||
   1741       _dbus_string_get_length (next_component) == 0)
   1742     return TRUE;
   1743 
   1744   dir_ends_in_slash =
   1745     ('/' == _dbus_string_get_byte (dir, _dbus_string_get_length (dir) - 1) ||
   1746      '\\' == _dbus_string_get_byte (dir, _dbus_string_get_length (dir) - 1));
   1747 
   1748   file_starts_with_slash =
   1749     ('/' == _dbus_string_get_byte (next_component, 0) ||
   1750      '\\' == _dbus_string_get_byte (next_component, 0));
   1751 
   1752   if (dir_ends_in_slash && file_starts_with_slash)
   1753     {
   1754       _dbus_string_shorten (dir, 1);
   1755     }
   1756   else if (!(dir_ends_in_slash || file_starts_with_slash))
   1757     {
   1758       if (!_dbus_string_append_byte (dir, '\\'))
   1759         return FALSE;
   1760     }
   1761 
   1762   return _dbus_string_copy (next_component, 0, dir,
   1763                             _dbus_string_get_length (dir));
   1764 }
   1765 
   1766 /*---------------- DBusCredentials ----------------------------------*/
   1767 
   1768 /**
   1769  * Adds the credentials corresponding to the given username.
   1770  *
   1771  * @param credentials credentials to fill in
   1772  * @param username the username
   1773  * @returns #TRUE if the username existed and we got some credentials
   1774  */
   1775 dbus_bool_t
   1776 _dbus_credentials_add_from_user (DBusCredentials  *credentials,
   1777                                      const DBusString *username)
   1778 {
   1779   return _dbus_credentials_add_windows_sid (credentials,
   1780                     _dbus_string_get_const_data(username));
   1781 }
   1782 
   1783 /**
   1784  * Adds the credentials of the current process to the
   1785  * passed-in credentials object.
   1786  *
   1787  * @param credentials credentials to add to
   1788  * @returns #FALSE if no memory; does not properly roll back on failure, so only some credentials may have been added
   1789  */
   1790 
   1791 dbus_bool_t
   1792 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
   1793 {
   1794   dbus_bool_t retval = FALSE;
   1795   char *sid = NULL;
   1796 
   1797   if (!_dbus_getsid(&sid))
   1798     goto failed;
   1799 
   1800   if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid()))
   1801     goto failed;
   1802 
   1803   if (!_dbus_credentials_add_windows_sid (credentials,sid))
   1804     goto failed;
   1805 
   1806   retval = TRUE;
   1807   goto end;
   1808 failed:
   1809   retval = FALSE;
   1810 end:
   1811   if (sid)
   1812     LocalFree(sid);
   1813 
   1814   return retval;
   1815 }
   1816 
   1817 /**
   1818  * Append to the string the identity we would like to have when we
   1819  * authenticate, on UNIX this is the current process UID and on
   1820  * Windows something else, probably a Windows SID string.  No escaping
   1821  * is required, that is done in dbus-auth.c. The username here
   1822  * need not be anything human-readable, it can be the machine-readable
   1823  * form i.e. a user id.
   1824  *
   1825  * @param str the string to append to
   1826  * @returns #FALSE on no memory
   1827  * @todo to which class belongs this
   1828  */
   1829 dbus_bool_t
   1830 _dbus_append_user_from_current_process (DBusString *str)
   1831 {
   1832   dbus_bool_t retval = FALSE;
   1833   char *sid = NULL;
   1834 
   1835   if (!_dbus_getsid(&sid))
   1836     return FALSE;
   1837 
   1838   retval = _dbus_string_append (str,sid);
   1839 
   1840   LocalFree(sid);
   1841   return retval;
   1842 }
   1843 
   1844 /**
   1845  * Gets our process ID
   1846  * @returns process ID
   1847  */
   1848 dbus_pid_t
   1849 _dbus_getpid (void)
   1850 {
   1851   return GetCurrentProcessId ();
   1852 }
   1853 
   1854 /** nanoseconds in a second */
   1855 #define NANOSECONDS_PER_SECOND       1000000000
   1856 /** microseconds in a second */
   1857 #define MICROSECONDS_PER_SECOND      1000000
   1858 /** milliseconds in a second */
   1859 #define MILLISECONDS_PER_SECOND      1000
   1860 /** nanoseconds in a millisecond */
   1861 #define NANOSECONDS_PER_MILLISECOND  1000000
   1862 /** microseconds in a millisecond */
   1863 #define MICROSECONDS_PER_MILLISECOND 1000
   1864 
   1865 /**
   1866  * Sleeps the given number of milliseconds.
   1867  * @param milliseconds number of milliseconds
   1868  */
   1869 void
   1870 _dbus_sleep_milliseconds (int milliseconds)
   1871 {
   1872   Sleep (milliseconds);
   1873 }
   1874 
   1875 
   1876 /**
   1877  * Get current time, as in gettimeofday().
   1878  *
   1879  * @param tv_sec return location for number of seconds
   1880  * @param tv_usec return location for number of microseconds
   1881  */
   1882 void
   1883 _dbus_get_current_time (long *tv_sec,
   1884                         long *tv_usec)
   1885 {
   1886   FILETIME ft;
   1887   dbus_uint64_t time64;
   1888 
   1889   GetSystemTimeAsFileTime (&ft);
   1890 
   1891   memcpy (&time64, &ft, sizeof (time64));
   1892 
   1893   /* Convert from 100s of nanoseconds since 1601-01-01
   1894   * to Unix epoch. Yes, this is Y2038 unsafe.
   1895   */
   1896   time64 -= DBUS_INT64_CONSTANT (116444736000000000);
   1897   time64 /= 10;
   1898 
   1899   if (tv_sec)
   1900     *tv_sec = time64 / 1000000;
   1901 
   1902   if (tv_usec)
   1903     *tv_usec = time64 % 1000000;
   1904 }
   1905 
   1906 
   1907 /**
   1908  * signal (SIGPIPE, SIG_IGN);
   1909  */
   1910 void
   1911 _dbus_disable_sigpipe (void)
   1912 {
   1913 }
   1914 
   1915 /**
   1916  * Creates a directory; succeeds if the directory
   1917  * is created or already existed.
   1918  *
   1919  * @param filename directory filename
   1920  * @param error initialized error object
   1921  * @returns #TRUE on success
   1922  */
   1923 dbus_bool_t
   1924 _dbus_create_directory (const DBusString *filename,
   1925                         DBusError        *error)
   1926 {
   1927   const char *filename_c;
   1928 
   1929   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   1930 
   1931   filename_c = _dbus_string_get_const_data (filename);
   1932 
   1933   if (!CreateDirectoryA (filename_c, NULL))
   1934     {
   1935       if (GetLastError () == ERROR_ALREADY_EXISTS)
   1936         return TRUE;
   1937 
   1938       dbus_set_error (error, DBUS_ERROR_FAILED,
   1939                       "Failed to create directory %s: %s\n",
   1940                       filename_c, _dbus_strerror_from_errno ());
   1941       return FALSE;
   1942     }
   1943   else
   1944     return TRUE;
   1945 }
   1946 
   1947 
   1948 /**
   1949  * Generates the given number of random bytes,
   1950  * using the best mechanism we can come up with.
   1951  *
   1952  * @param str the string
   1953  * @param n_bytes the number of random bytes to append to string
   1954  * @returns #TRUE on success, #FALSE if no memory
   1955  */
   1956 dbus_bool_t
   1957 _dbus_generate_random_bytes (DBusString *str,
   1958                              int         n_bytes)
   1959 {
   1960   int old_len;
   1961   char *p;
   1962   HCRYPTPROV hprov;
   1963 
   1964   old_len = _dbus_string_get_length (str);
   1965 
   1966   if (!_dbus_string_lengthen (str, n_bytes))
   1967     return FALSE;
   1968 
   1969   p = _dbus_string_get_data_len (str, old_len, n_bytes);
   1970 
   1971   if (!CryptAcquireContext (&hprov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
   1972     return FALSE;
   1973 
   1974   if (!CryptGenRandom (hprov, n_bytes, p))
   1975     {
   1976       CryptReleaseContext (hprov, 0);
   1977       return FALSE;
   1978     }
   1979 
   1980   CryptReleaseContext (hprov, 0);
   1981 
   1982   return TRUE;
   1983 }
   1984 
   1985 /**
   1986  * Gets the temporary files directory by inspecting the environment variables
   1987  * TMPDIR, TMP, and TEMP in that order. If none of those are set "/tmp" is returned
   1988  *
   1989  * @returns location of temp directory
   1990  */
   1991 const char*
   1992 _dbus_get_tmpdir(void)
   1993 {
   1994   static const char* tmpdir = NULL;
   1995   static char buf[1000];
   1996 
   1997   if (tmpdir == NULL)
   1998     {
   1999       char *last_slash;
   2000 
   2001       if (!GetTempPathA (sizeof (buf), buf))
   2002         {
   2003           _dbus_warn ("GetTempPath failed\n");
   2004           _dbus_abort ();
   2005         }
   2006 
   2007       /* Drop terminating backslash or slash */
   2008       last_slash = _mbsrchr (buf, '\\');
   2009       if (last_slash > buf && last_slash[1] == '\0')
   2010         last_slash[0] = '\0';
   2011       last_slash = _mbsrchr (buf, '/');
   2012       if (last_slash > buf && last_slash[1] == '\0')
   2013         last_slash[0] = '\0';
   2014 
   2015       tmpdir = buf;
   2016     }
   2017 
   2018   _dbus_assert(tmpdir != NULL);
   2019 
   2020   return tmpdir;
   2021 }
   2022 
   2023 
   2024 /**
   2025  * Deletes the given file.
   2026  *
   2027  * @param filename the filename
   2028  * @param error error location
   2029  *
   2030  * @returns #TRUE if unlink() succeeded
   2031  */
   2032 dbus_bool_t
   2033 _dbus_delete_file (const DBusString *filename,
   2034                    DBusError        *error)
   2035 {
   2036   const char *filename_c;
   2037 
   2038   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   2039 
   2040   filename_c = _dbus_string_get_const_data (filename);
   2041 
   2042   if (DeleteFileA (filename_c) == 0)
   2043     {
   2044       dbus_set_error (error, DBUS_ERROR_FAILED,
   2045                       "Failed to delete file %s: %s\n",
   2046                       filename_c, _dbus_strerror_from_errno ());
   2047       return FALSE;
   2048     }
   2049   else
   2050     return TRUE;
   2051 }
   2052 
   2053 /* Forward declaration of prototype used in next function */
   2054 static dbus_bool_t
   2055 _dbus_get_install_root(char *prefix, int len);
   2056 
   2057 /*
   2058  * replaces the term DBUS_PREFIX in configure_time_path by the
   2059  * current dbus installation directory. On unix this function is a noop
   2060  *
   2061  * @param configure_time_path
   2062  * @return real path
   2063  */
   2064 const char *
   2065 _dbus_replace_install_prefix (const char *configure_time_path)
   2066 {
   2067 #ifndef DBUS_PREFIX
   2068   return configure_time_path;
   2069 #else
   2070   static char retval[1000];
   2071   static char runtime_prefix[1000];
   2072   int len = 1000;
   2073   int i;
   2074 
   2075   if (!configure_time_path)
   2076     return NULL;
   2077 
   2078   if ((!_dbus_get_install_root(runtime_prefix, len) ||
   2079        strncmp (configure_time_path, DBUS_PREFIX "/",
   2080                 strlen (DBUS_PREFIX) + 1))) {
   2081      strcat (retval, configure_time_path);
   2082      return retval;
   2083   }
   2084 
   2085   strcpy (retval, runtime_prefix);
   2086   strcat (retval, configure_time_path + strlen (DBUS_PREFIX) + 1);
   2087 
   2088   /* Somehow, in some situations, backslashes get collapsed in the string.
   2089    * Since windows C library accepts both forward and backslashes as
   2090    * path separators, convert all backslashes to forward slashes.
   2091    */
   2092 
   2093   for(i = 0; retval[i] != '\0'; i++) {
   2094     if(retval[i] == '\\')
   2095       retval[i] = '/';
   2096   }
   2097   return retval;
   2098 #endif
   2099 }
   2100 
   2101 #if !defined (DBUS_DISABLE_ASSERTS) || defined(DBUS_BUILD_TESTS)
   2102 
   2103 #if defined(_MSC_VER) || defined(DBUS_WINCE)
   2104 # ifdef BACKTRACES
   2105 #  undef BACKTRACES
   2106 # endif
   2107 #else
   2108 # define BACKTRACES
   2109 #endif
   2110 
   2111 #ifdef BACKTRACES
   2112 /*
   2113  * Backtrace Generator
   2114  *
   2115  * Copyright 2004 Eric Poech
   2116  * Copyright 2004 Robert Shearman
   2117  *
   2118  * This library is free software; you can redistribute it and/or
   2119  * modify it under the terms of the GNU Lesser General Public
   2120  * License as published by the Free Software Foundation; either
   2121  * version 2.1 of the License, or (at your option) any later version.
   2122  *
   2123  * This library is distributed in the hope that it will be useful,
   2124  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   2125  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   2126  * Lesser General Public License for more details.
   2127  *
   2128  * You should have received a copy of the GNU Lesser General Public
   2129  * License along with this library; if not, write to the Free Software
   2130  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
   2131  */
   2132 
   2133 #include <winver.h>
   2134 #include <imagehlp.h>
   2135 #include <stdio.h>
   2136 
   2137 #define DPRINTF _dbus_warn
   2138 
   2139 #ifdef _MSC_VER
   2140 #define BOOL int
   2141 
   2142 #define __i386__
   2143 #endif
   2144 
   2145 //#define MAKE_FUNCPTR(f) static typeof(f) * p##f
   2146 
   2147 //MAKE_FUNCPTR(StackWalk);
   2148 //MAKE_FUNCPTR(SymGetModuleBase);
   2149 //MAKE_FUNCPTR(SymFunctionTableAccess);
   2150 //MAKE_FUNCPTR(SymInitialize);
   2151 //MAKE_FUNCPTR(SymGetSymFromAddr);
   2152 //MAKE_FUNCPTR(SymGetModuleInfo);
   2153 static BOOL (WINAPI *pStackWalk)(
   2154   DWORD MachineType,
   2155   HANDLE hProcess,
   2156   HANDLE hThread,
   2157   LPSTACKFRAME StackFrame,
   2158   PVOID ContextRecord,
   2159   PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
   2160   PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
   2161   PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
   2162   PTRANSLATE_ADDRESS_ROUTINE TranslateAddress
   2163 );
   2164 #ifdef _WIN64
   2165 static DWORD64 (WINAPI *pSymGetModuleBase)(
   2166   HANDLE hProcess,
   2167   DWORD64 dwAddr
   2168 );
   2169 static PVOID  (WINAPI *pSymFunctionTableAccess)(
   2170   HANDLE hProcess,
   2171   DWORD64 AddrBase
   2172 );
   2173 #else
   2174 static DWORD (WINAPI *pSymGetModuleBase)(
   2175   HANDLE hProcess,
   2176   DWORD dwAddr
   2177 );
   2178 static PVOID  (WINAPI *pSymFunctionTableAccess)(
   2179   HANDLE hProcess,
   2180   DWORD AddrBase
   2181 );
   2182 #endif
   2183 static BOOL  (WINAPI *pSymInitialize)(
   2184   HANDLE hProcess,
   2185   PSTR UserSearchPath,
   2186   BOOL fInvadeProcess
   2187 );
   2188 static BOOL  (WINAPI *pSymGetSymFromAddr)(
   2189   HANDLE hProcess,
   2190   DWORD Address,
   2191   PDWORD Displacement,
   2192   PIMAGEHLP_SYMBOL Symbol
   2193 );
   2194 static BOOL  (WINAPI *pSymGetModuleInfo)(
   2195   HANDLE hProcess,
   2196   DWORD dwAddr,
   2197   PIMAGEHLP_MODULE ModuleInfo
   2198 );
   2199 static DWORD  (WINAPI *pSymSetOptions)(
   2200   DWORD SymOptions
   2201 );
   2202 
   2203 
   2204 static BOOL init_backtrace()
   2205 {
   2206     HMODULE hmodDbgHelp = LoadLibraryA("dbghelp");
   2207 /*
   2208     #define GETFUNC(x) \
   2209     p##x = (typeof(x)*)GetProcAddress(hmodDbgHelp, #x); \
   2210     if (!p##x) \
   2211     { \
   2212         return FALSE; \
   2213     }
   2214     */
   2215 
   2216 
   2217 //    GETFUNC(StackWalk);
   2218 //    GETFUNC(SymGetModuleBase);
   2219 //    GETFUNC(SymFunctionTableAccess);
   2220 //    GETFUNC(SymInitialize);
   2221 //    GETFUNC(SymGetSymFromAddr);
   2222 //    GETFUNC(SymGetModuleInfo);
   2223 
   2224 #define FUNC(x) #x
   2225 
   2226       pStackWalk = (BOOL  (WINAPI *)(
   2227 DWORD MachineType,
   2228 HANDLE hProcess,
   2229 HANDLE hThread,
   2230 LPSTACKFRAME StackFrame,
   2231 PVOID ContextRecord,
   2232 PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
   2233 PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
   2234 PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
   2235 PTRANSLATE_ADDRESS_ROUTINE TranslateAddress
   2236 ))GetProcAddress (hmodDbgHelp, FUNC(StackWalk));
   2237 #ifdef _WIN64
   2238     pSymGetModuleBase=(DWORD64  (WINAPI *)(
   2239   HANDLE hProcess,
   2240   DWORD64 dwAddr
   2241 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleBase));
   2242     pSymFunctionTableAccess=(PVOID  (WINAPI *)(
   2243   HANDLE hProcess,
   2244   DWORD64 AddrBase
   2245 ))GetProcAddress (hmodDbgHelp, FUNC(SymFunctionTableAccess));
   2246 #else
   2247     pSymGetModuleBase=(DWORD  (WINAPI *)(
   2248   HANDLE hProcess,
   2249   DWORD dwAddr
   2250 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleBase));
   2251     pSymFunctionTableAccess=(PVOID  (WINAPI *)(
   2252   HANDLE hProcess,
   2253   DWORD AddrBase
   2254 ))GetProcAddress (hmodDbgHelp, FUNC(SymFunctionTableAccess));
   2255 #endif
   2256     pSymInitialize = (BOOL  (WINAPI *)(
   2257   HANDLE hProcess,
   2258   PSTR UserSearchPath,
   2259   BOOL fInvadeProcess
   2260 ))GetProcAddress (hmodDbgHelp, FUNC(SymInitialize));
   2261     pSymGetSymFromAddr = (BOOL  (WINAPI *)(
   2262   HANDLE hProcess,
   2263   DWORD Address,
   2264   PDWORD Displacement,
   2265   PIMAGEHLP_SYMBOL Symbol
   2266 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetSymFromAddr));
   2267     pSymGetModuleInfo = (BOOL  (WINAPI *)(
   2268   HANDLE hProcess,
   2269   DWORD dwAddr,
   2270   PIMAGEHLP_MODULE ModuleInfo
   2271 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleInfo));
   2272 pSymSetOptions = (DWORD  (WINAPI *)(
   2273 DWORD SymOptions
   2274 ))GetProcAddress (hmodDbgHelp, FUNC(SymSetOptions));
   2275 
   2276 
   2277     pSymSetOptions(SYMOPT_UNDNAME);
   2278 
   2279     pSymInitialize(GetCurrentProcess(), NULL, TRUE);
   2280 
   2281     return TRUE;
   2282 }
   2283 
   2284 static void dump_backtrace_for_thread(HANDLE hThread)
   2285 {
   2286     STACKFRAME sf;
   2287     CONTEXT context;
   2288     DWORD dwImageType;
   2289 
   2290     if (!pStackWalk)
   2291         if (!init_backtrace())
   2292             return;
   2293 
   2294     /* can't use this function for current thread as GetThreadContext
   2295      * doesn't support getting context from current thread */
   2296     if (hThread == GetCurrentThread())
   2297         return;
   2298 
   2299     DPRINTF("Backtrace:\n");
   2300 
   2301     _DBUS_ZERO(context);
   2302     context.ContextFlags = CONTEXT_FULL;
   2303 
   2304     SuspendThread(hThread);
   2305 
   2306     if (!GetThreadContext(hThread, &context))
   2307     {
   2308         DPRINTF("Couldn't get thread context (error %ld)\n", GetLastError());
   2309         ResumeThread(hThread);
   2310         return;
   2311     }
   2312 
   2313     _DBUS_ZERO(sf);
   2314 
   2315 #ifdef __i386__
   2316     sf.AddrFrame.Offset = context.Ebp;
   2317     sf.AddrFrame.Mode = AddrModeFlat;
   2318     sf.AddrPC.Offset = context.Eip;
   2319     sf.AddrPC.Mode = AddrModeFlat;
   2320     dwImageType = IMAGE_FILE_MACHINE_I386;
   2321 #elif _M_X64
   2322   dwImageType                = IMAGE_FILE_MACHINE_AMD64;
   2323   sf.AddrPC.Offset    = context.Rip;
   2324   sf.AddrPC.Mode      = AddrModeFlat;
   2325   sf.AddrFrame.Offset = context.Rsp;
   2326   sf.AddrFrame.Mode   = AddrModeFlat;
   2327   sf.AddrStack.Offset = context.Rsp;
   2328   sf.AddrStack.Mode   = AddrModeFlat;
   2329 #elif _M_IA64
   2330   dwImageType                 = IMAGE_FILE_MACHINE_IA64;
   2331   sf.AddrPC.Offset    = context.StIIP;
   2332   sf.AddrPC.Mode      = AddrModeFlat;
   2333   sf.AddrFrame.Offset = context.IntSp;
   2334   sf.AddrFrame.Mode   = AddrModeFlat;
   2335   sf.AddrBStore.Offset= context.RsBSP;
   2336   sf.AddrBStore.Mode  = AddrModeFlat;
   2337   sf.AddrStack.Offset = context.IntSp;
   2338   sf.AddrStack.Mode   = AddrModeFlat;
   2339 #else
   2340 # error You need to fill in the STACKFRAME structure for your architecture
   2341 #endif
   2342 
   2343     while (pStackWalk(dwImageType, GetCurrentProcess(),
   2344                      hThread, &sf, &context, NULL, pSymFunctionTableAccess,
   2345                      pSymGetModuleBase, NULL))
   2346     {
   2347         BYTE buffer[256];
   2348         IMAGEHLP_SYMBOL * pSymbol = (IMAGEHLP_SYMBOL *)buffer;
   2349         DWORD dwDisplacement;
   2350 
   2351         pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
   2352         pSymbol->MaxNameLength = sizeof(buffer) - sizeof(IMAGEHLP_SYMBOL) + 1;
   2353 
   2354         if (!pSymGetSymFromAddr(GetCurrentProcess(), sf.AddrPC.Offset,
   2355                                 &dwDisplacement, pSymbol))
   2356         {
   2357             IMAGEHLP_MODULE ModuleInfo;
   2358             ModuleInfo.SizeOfStruct = sizeof(ModuleInfo);
   2359 
   2360             if (!pSymGetModuleInfo(GetCurrentProcess(), sf.AddrPC.Offset,
   2361                                    &ModuleInfo))
   2362                 DPRINTF("1\t%p\n", (void*)sf.AddrPC.Offset);
   2363             else
   2364                 DPRINTF("2\t%s+0x%lx\n", ModuleInfo.ImageName,
   2365                     sf.AddrPC.Offset - ModuleInfo.BaseOfImage);
   2366         }
   2367         else if (dwDisplacement)
   2368             DPRINTF("3\t%s+0x%lx\n", pSymbol->Name, dwDisplacement);
   2369         else
   2370             DPRINTF("4\t%s\n", pSymbol->Name);
   2371     }
   2372 
   2373     ResumeThread(hThread);
   2374 }
   2375 
   2376 static DWORD WINAPI dump_thread_proc(LPVOID lpParameter)
   2377 {
   2378     dump_backtrace_for_thread((HANDLE)lpParameter);
   2379     return 0;
   2380 }
   2381 
   2382 /* cannot get valid context from current thread, so we have to execute
   2383  * backtrace from another thread */
   2384 static void dump_backtrace()
   2385 {
   2386     HANDLE hCurrentThread;
   2387     HANDLE hThread;
   2388     DWORD dwThreadId;
   2389     DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
   2390         GetCurrentProcess(), &hCurrentThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
   2391     hThread = CreateThread(NULL, 0, dump_thread_proc, (LPVOID)hCurrentThread,
   2392         0, &dwThreadId);
   2393     WaitForSingleObject(hThread, INFINITE);
   2394     CloseHandle(hThread);
   2395     CloseHandle(hCurrentThread);
   2396 }
   2397 #endif
   2398 #endif /* asserts or tests enabled */
   2399 
   2400 #ifdef BACKTRACES
   2401 void _dbus_print_backtrace(void)
   2402 {
   2403   init_backtrace();
   2404   dump_backtrace();
   2405 }
   2406 #else
   2407 void _dbus_print_backtrace(void)
   2408 {
   2409   _dbus_verbose ("  D-Bus not compiled with backtrace support\n");
   2410 }
   2411 #endif
   2412 
   2413 static dbus_uint32_t fromAscii(char ascii)
   2414 {
   2415     if(ascii >= '0' && ascii <= '9')
   2416         return ascii - '0';
   2417     if(ascii >= 'A' && ascii <= 'F')
   2418         return ascii - 'A' + 10;
   2419     if(ascii >= 'a' && ascii <= 'f')
   2420         return ascii - 'a' + 10;
   2421     return 0;
   2422 }
   2423 
   2424 dbus_bool_t _dbus_read_local_machine_uuid   (DBusGUID         *machine_id,
   2425                                              dbus_bool_t       create_if_not_found,
   2426                                              DBusError        *error)
   2427 {
   2428 #ifdef DBUS_WINCE
   2429 	return TRUE;
   2430   // TODO
   2431 #else
   2432     HW_PROFILE_INFOA info;
   2433     char *lpc = &info.szHwProfileGuid[0];
   2434     dbus_uint32_t u;
   2435 
   2436     //  the hw-profile guid lives long enough
   2437     if(!GetCurrentHwProfileA(&info))
   2438       {
   2439         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); // FIXME
   2440         return FALSE;
   2441       }
   2442 
   2443     // Form: {12340001-4980-1920-6788-123456789012}
   2444     lpc++;
   2445     // 12340001
   2446     u = ((fromAscii(lpc[0]) <<  0) |
   2447          (fromAscii(lpc[1]) <<  4) |
   2448          (fromAscii(lpc[2]) <<  8) |
   2449          (fromAscii(lpc[3]) << 12) |
   2450          (fromAscii(lpc[4]) << 16) |
   2451          (fromAscii(lpc[5]) << 20) |
   2452          (fromAscii(lpc[6]) << 24) |
   2453          (fromAscii(lpc[7]) << 28));
   2454     machine_id->as_uint32s[0] = u;
   2455 
   2456     lpc += 9;
   2457     // 4980-1920
   2458     u = ((fromAscii(lpc[0]) <<  0) |
   2459          (fromAscii(lpc[1]) <<  4) |
   2460          (fromAscii(lpc[2]) <<  8) |
   2461          (fromAscii(lpc[3]) << 12) |
   2462          (fromAscii(lpc[5]) << 16) |
   2463          (fromAscii(lpc[6]) << 20) |
   2464          (fromAscii(lpc[7]) << 24) |
   2465          (fromAscii(lpc[8]) << 28));
   2466     machine_id->as_uint32s[1] = u;
   2467 
   2468     lpc += 10;
   2469     // 6788-1234
   2470     u = ((fromAscii(lpc[0]) <<  0) |
   2471          (fromAscii(lpc[1]) <<  4) |
   2472          (fromAscii(lpc[2]) <<  8) |
   2473          (fromAscii(lpc[3]) << 12) |
   2474          (fromAscii(lpc[5]) << 16) |
   2475          (fromAscii(lpc[6]) << 20) |
   2476          (fromAscii(lpc[7]) << 24) |
   2477          (fromAscii(lpc[8]) << 28));
   2478     machine_id->as_uint32s[2] = u;
   2479 
   2480     lpc += 9;
   2481     // 56789012
   2482     u = ((fromAscii(lpc[0]) <<  0) |
   2483          (fromAscii(lpc[1]) <<  4) |
   2484          (fromAscii(lpc[2]) <<  8) |
   2485          (fromAscii(lpc[3]) << 12) |
   2486          (fromAscii(lpc[4]) << 16) |
   2487          (fromAscii(lpc[5]) << 20) |
   2488          (fromAscii(lpc[6]) << 24) |
   2489          (fromAscii(lpc[7]) << 28));
   2490     machine_id->as_uint32s[3] = u;
   2491 #endif
   2492     return TRUE;
   2493 }
   2494 
   2495 static
   2496 HANDLE _dbus_global_lock (const char *mutexname)
   2497 {
   2498   HANDLE mutex;
   2499   DWORD gotMutex;
   2500 
   2501   mutex = CreateMutexA( NULL, FALSE, mutexname );
   2502   if( !mutex )
   2503     {
   2504       return FALSE;
   2505     }
   2506 
   2507    gotMutex = WaitForSingleObject( mutex, INFINITE );
   2508    switch( gotMutex )
   2509      {
   2510        case WAIT_ABANDONED:
   2511                ReleaseMutex (mutex);
   2512                CloseHandle (mutex);
   2513                return 0;
   2514        case WAIT_FAILED:
   2515        case WAIT_TIMEOUT:
   2516                return 0;
   2517      }
   2518 
   2519    return mutex;
   2520 }
   2521 
   2522 static
   2523 void _dbus_global_unlock (HANDLE mutex)
   2524 {
   2525   ReleaseMutex (mutex);
   2526   CloseHandle (mutex);
   2527 }
   2528 
   2529 // for proper cleanup in dbus-daemon
   2530 static HANDLE hDBusDaemonMutex = NULL;
   2531 static HANDLE hDBusSharedMem = NULL;
   2532 // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
   2533 static const char *cUniqueDBusInitMutex = "UniqueDBusInitMutex";
   2534 // sync _dbus_get_autolaunch_address
   2535 static const char *cDBusAutolaunchMutex = "DBusAutolaunchMutex";
   2536 // mutex to determine if dbus-daemon is already started (per user)
   2537 static const char *cDBusDaemonMutex = "DBusDaemonMutex";
   2538 // named shm for dbus adress info (per user)
   2539 #ifdef _DEBUG
   2540 static const char *cDBusDaemonAddressInfo = "DBusDaemonAddressInfoDebug";
   2541 #else
   2542 static const char *cDBusDaemonAddressInfo = "DBusDaemonAddressInfo";
   2543 #endif
   2544 
   2545 
   2546 void
   2547 _dbus_daemon_publish_session_bus_address (const char* address)
   2548 {
   2549   HANDLE lock;
   2550   char *shared_addr = NULL;
   2551   DWORD ret;
   2552 
   2553   _dbus_assert (address);
   2554   // before _dbus_global_lock to keep correct lock/release order
   2555   hDBusDaemonMutex = CreateMutexA( NULL, FALSE, cDBusDaemonMutex );
   2556   ret = WaitForSingleObject( hDBusDaemonMutex, 1000 );
   2557   if ( ret != WAIT_OBJECT_0 ) {
   2558     _dbus_warn("Could not lock mutex %s (return code %ld). daemon already running? Bus address not published.\n", cDBusDaemonMutex, ret );
   2559     return;
   2560   }
   2561 
   2562   // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
   2563   lock = _dbus_global_lock( cUniqueDBusInitMutex );
   2564 
   2565   // create shm
   2566   hDBusSharedMem = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
   2567                                       0, strlen( address ) + 1, cDBusDaemonAddressInfo );
   2568   _dbus_assert( hDBusSharedMem );
   2569 
   2570   shared_addr = MapViewOfFile( hDBusSharedMem, FILE_MAP_WRITE, 0, 0, 0 );
   2571 
   2572   _dbus_assert (shared_addr);
   2573 
   2574   strcpy( shared_addr, address);
   2575 
   2576   // cleanup
   2577   UnmapViewOfFile( shared_addr );
   2578 
   2579   _dbus_global_unlock( lock );
   2580 }
   2581 
   2582 void
   2583 _dbus_daemon_unpublish_session_bus_address (void)
   2584 {
   2585   HANDLE lock;
   2586 
   2587   // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
   2588   lock = _dbus_global_lock( cUniqueDBusInitMutex );
   2589 
   2590   CloseHandle( hDBusSharedMem );
   2591 
   2592   hDBusSharedMem = NULL;
   2593 
   2594   ReleaseMutex( hDBusDaemonMutex );
   2595 
   2596   CloseHandle( hDBusDaemonMutex );
   2597 
   2598   hDBusDaemonMutex = NULL;
   2599 
   2600   _dbus_global_unlock( lock );
   2601 }
   2602 
   2603 static dbus_bool_t
   2604 _dbus_get_autolaunch_shm (DBusString *address)
   2605 {
   2606   HANDLE sharedMem;
   2607   char *shared_addr;
   2608   int i;
   2609 
   2610   // read shm
   2611   for(i=0;i<20;++i) {
   2612       // we know that dbus-daemon is available, so we wait until shm is available
   2613       sharedMem = OpenFileMappingA( FILE_MAP_READ, FALSE, cDBusDaemonAddressInfo );
   2614       if( sharedMem == 0 )
   2615           Sleep( 100 );
   2616       if ( sharedMem != 0)
   2617           break;
   2618   }
   2619 
   2620   if( sharedMem == 0 )
   2621       return FALSE;
   2622 
   2623   shared_addr = MapViewOfFile( sharedMem, FILE_MAP_READ, 0, 0, 0 );
   2624 
   2625   if( !shared_addr )
   2626       return FALSE;
   2627 
   2628   _dbus_string_init( address );
   2629 
   2630   _dbus_string_append( address, shared_addr );
   2631 
   2632   // cleanup
   2633   UnmapViewOfFile( shared_addr );
   2634 
   2635   CloseHandle( sharedMem );
   2636 
   2637   return TRUE;
   2638 }
   2639 
   2640 static dbus_bool_t
   2641 _dbus_daemon_already_runs (DBusString *address)
   2642 {
   2643   HANDLE lock;
   2644   HANDLE daemon;
   2645   dbus_bool_t bRet = TRUE;
   2646 
   2647   // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
   2648   lock = _dbus_global_lock( cUniqueDBusInitMutex );
   2649 
   2650   // do checks
   2651   daemon = CreateMutexA( NULL, FALSE, cDBusDaemonMutex );
   2652   if(WaitForSingleObject( daemon, 10 ) != WAIT_TIMEOUT)
   2653     {
   2654       ReleaseMutex (daemon);
   2655       CloseHandle (daemon);
   2656 
   2657       _dbus_global_unlock( lock );
   2658       return FALSE;
   2659     }
   2660 
   2661   // read shm
   2662   bRet = _dbus_get_autolaunch_shm( address );
   2663 
   2664   // cleanup
   2665   CloseHandle ( daemon );
   2666 
   2667   _dbus_global_unlock( lock );
   2668 
   2669   return bRet;
   2670 }
   2671 
   2672 dbus_bool_t
   2673 _dbus_get_autolaunch_address (DBusString *address,
   2674                               DBusError *error)
   2675 {
   2676   HANDLE mutex;
   2677   STARTUPINFOA si;
   2678   PROCESS_INFORMATION pi;
   2679   dbus_bool_t retval = FALSE;
   2680   LPSTR lpFile;
   2681   char dbus_exe_path[MAX_PATH];
   2682   char dbus_args[MAX_PATH * 2];
   2683   const char * daemon_name = DBUS_DAEMON_NAME ".exe";
   2684 
   2685   mutex = _dbus_global_lock ( cDBusAutolaunchMutex );
   2686 
   2687   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   2688 
   2689   if (_dbus_daemon_already_runs(address))
   2690     {
   2691         _dbus_verbose("found already running dbus daemon\n");
   2692         retval = TRUE;
   2693         goto out;
   2694     }
   2695 
   2696   if (!SearchPathA(NULL, daemon_name, NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile))
   2697     {
   2698       printf ("please add the path to %s to your PATH environment variable\n", daemon_name);
   2699       printf ("or start the daemon manually\n\n");
   2700       goto out;
   2701     }
   2702 
   2703   // Create process
   2704   ZeroMemory( &si, sizeof(si) );
   2705   si.cb = sizeof(si);
   2706   ZeroMemory( &pi, sizeof(pi) );
   2707 
   2708   _snprintf(dbus_args, sizeof(dbus_args) - 1, "\"%s\" %s", dbus_exe_path,  " --session");
   2709 
   2710 //  argv[i] = "--config-file=bus\\session.conf";
   2711 //  printf("create process \"%s\" %s\n", dbus_exe_path, dbus_args);
   2712   if(CreateProcessA(dbus_exe_path, dbus_args, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
   2713     {
   2714       CloseHandle (pi.hThread);
   2715       CloseHandle (pi.hProcess);
   2716       retval = _dbus_get_autolaunch_shm( address );
   2717     }
   2718 
   2719   if (retval == FALSE)
   2720     dbus_set_error_const (error, DBUS_ERROR_FAILED, "Failed to launch dbus-daemon");
   2721 
   2722 out:
   2723   if (retval)
   2724     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   2725   else
   2726     _DBUS_ASSERT_ERROR_IS_SET (error);
   2727 
   2728   _dbus_global_unlock (mutex);
   2729 
   2730   return retval;
   2731  }
   2732 
   2733 
   2734 /** Makes the file readable by every user in the system.
   2735  *
   2736  * @param filename the filename
   2737  * @param error error location
   2738  * @returns #TRUE if the file's permissions could be changed.
   2739  */
   2740 dbus_bool_t
   2741 _dbus_make_file_world_readable(const DBusString *filename,
   2742                                DBusError *error)
   2743 {
   2744   // TODO
   2745   return TRUE;
   2746 }
   2747 
   2748 /**
   2749  * return the relocated DATADIR
   2750  *
   2751  * @returns relocated DATADIR static string
   2752  */
   2753 
   2754 static const char *
   2755 _dbus_windows_get_datadir (void)
   2756 {
   2757 	return _dbus_replace_install_prefix(DBUS_DATADIR);
   2758 }
   2759 
   2760 #undef DBUS_DATADIR
   2761 #define DBUS_DATADIR _dbus_windows_get_datadir ()
   2762 
   2763 
   2764 #define DBUS_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
   2765 #define DBUS_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
   2766 
   2767 /**
   2768  * Returns the standard directories for a session bus to look for service
   2769  * activation files
   2770  *
   2771  * On Windows this should be data directories:
   2772  *
   2773  * %CommonProgramFiles%/dbus
   2774  *
   2775  * and
   2776  *
   2777  * relocated DBUS_DATADIR
   2778  *
   2779  * @param dirs the directory list we are returning
   2780  * @returns #FALSE on OOM
   2781  */
   2782 
   2783 dbus_bool_t
   2784 _dbus_get_standard_session_servicedirs (DBusList **dirs)
   2785 {
   2786   const char *common_progs;
   2787   DBusString servicedir_path;
   2788 
   2789   if (!_dbus_string_init (&servicedir_path))
   2790     return FALSE;
   2791 
   2792 #ifdef DBUS_WINCE
   2793   {
   2794     /* On Windows CE, we adjust datadir dynamically to installation location.  */
   2795     const char *data_dir = _dbus_getenv ("DBUS_DATADIR");
   2796 
   2797     if (data_dir != NULL)
   2798       {
   2799         if (!_dbus_string_append (&servicedir_path, data_dir))
   2800           goto oom;
   2801 
   2802         if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR))
   2803           goto oom;
   2804       }
   2805   }
   2806 #else
   2807   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR))
   2808     goto oom;
   2809 
   2810   if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR))
   2811     goto oom;
   2812 #endif
   2813 
   2814   common_progs = _dbus_getenv ("CommonProgramFiles");
   2815 
   2816   if (common_progs != NULL)
   2817     {
   2818       if (!_dbus_string_append (&servicedir_path, common_progs))
   2819         goto oom;
   2820 
   2821       if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR))
   2822         goto oom;
   2823     }
   2824 
   2825   if (!_dbus_split_paths_and_append (&servicedir_path,
   2826                                DBUS_STANDARD_SESSION_SERVICEDIR,
   2827                                dirs))
   2828     goto oom;
   2829 
   2830   _dbus_string_free (&servicedir_path);
   2831   return TRUE;
   2832 
   2833  oom:
   2834   _dbus_string_free (&servicedir_path);
   2835   return FALSE;
   2836 }
   2837 
   2838 /**
   2839  * Returns the standard directories for a system bus to look for service
   2840  * activation files
   2841  *
   2842  * On UNIX this should be the standard xdg freedesktop.org data directories:
   2843  *
   2844  * XDG_DATA_DIRS=${XDG_DATA_DIRS-/usr/local/share:/usr/share}
   2845  *
   2846  * and
   2847  *
   2848  * DBUS_DATADIR
   2849  *
   2850  * On Windows there is no system bus and this function can return nothing.
   2851  *
   2852  * @param dirs the directory list we are returning
   2853  * @returns #FALSE on OOM
   2854  */
   2855 
   2856 dbus_bool_t
   2857 _dbus_get_standard_system_servicedirs (DBusList **dirs)
   2858 {
   2859   *dirs = NULL;
   2860   return TRUE;
   2861 }
   2862 
   2863 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
   2864 
   2865 /**
   2866  * Atomically increments an integer
   2867  *
   2868  * @param atomic pointer to the integer to increment
   2869  * @returns the value before incrementing
   2870  *
   2871  */
   2872 dbus_int32_t
   2873 _dbus_atomic_inc (DBusAtomic *atomic)
   2874 {
   2875   // +/- 1 is needed here!
   2876   // no volatile argument with mingw
   2877   return InterlockedIncrement (&atomic->value) - 1;
   2878 }
   2879 
   2880 /**
   2881  * Atomically decrement an integer
   2882  *
   2883  * @param atomic pointer to the integer to decrement
   2884  * @returns the value before decrementing
   2885  *
   2886  */
   2887 dbus_int32_t
   2888 _dbus_atomic_dec (DBusAtomic *atomic)
   2889 {
   2890   // +/- 1 is needed here!
   2891   // no volatile argument with mingw
   2892   return InterlockedDecrement (&atomic->value) + 1;
   2893 }
   2894 
   2895 /**
   2896  * Called when the bus daemon is signaled to reload its configuration; any
   2897  * caches should be nuked. Of course any caches that need explicit reload
   2898  * are probably broken, but c'est la vie.
   2899  *
   2900  *
   2901  */
   2902 void
   2903 _dbus_flush_caches (void)
   2904 {
   2905 }
   2906 
   2907 /**
   2908  * See if errno is EAGAIN or EWOULDBLOCK (this has to be done differently
   2909  * for Winsock so is abstracted)
   2910  *
   2911  * @returns #TRUE if errno == EAGAIN or errno == EWOULDBLOCK
   2912  */
   2913 dbus_bool_t
   2914 _dbus_get_is_errno_eagain_or_ewouldblock (void)
   2915 {
   2916   return errno == WSAEWOULDBLOCK;
   2917 }
   2918 
   2919 /**
   2920  * return the absolute path of the dbus installation
   2921  *
   2922  * @param s buffer for installation path
   2923  * @param len length of buffer
   2924  * @returns #FALSE on failure
   2925  */
   2926 static dbus_bool_t
   2927 _dbus_get_install_root(char *prefix, int len)
   2928 {
   2929     //To find the prefix, we cut the filename and also \bin\ if present
   2930     char* p = 0;
   2931     int i;
   2932     DWORD pathLength;
   2933     char *lastSlash;
   2934     SetLastError( 0 );
   2935     pathLength = GetModuleFileNameA(_dbus_win_get_dll_hmodule(), prefix, len);
   2936     if ( pathLength == 0 || GetLastError() != 0 ) {
   2937         *prefix = '\0';
   2938         return FALSE;
   2939     }
   2940     lastSlash = _mbsrchr(prefix, '\\');
   2941     if (lastSlash == NULL) {
   2942         *prefix = '\0';
   2943         return FALSE;
   2944     }
   2945     //cut off binary name
   2946     lastSlash[1] = 0;
   2947 
   2948     //cut possible "\\bin"
   2949 
   2950     //this fails if we are in a double-byte system codepage and the
   2951     //folder's name happens to end with the *bytes*
   2952     //"\\bin"... (I.e. the second byte of some Han character and then
   2953     //the Latin "bin", but that is not likely I think...
   2954     if (lastSlash - prefix >= 4 && strnicmp(lastSlash - 4, "\\bin", 4) == 0)
   2955         lastSlash[-3] = 0;
   2956     else if (lastSlash - prefix >= 10 && strnicmp(lastSlash - 10, "\\bin\\debug", 10) == 0)
   2957         lastSlash[-9] = 0;
   2958     else if (lastSlash - prefix >= 12 && strnicmp(lastSlash - 12, "\\bin\\release", 12) == 0)
   2959         lastSlash[-11] = 0;
   2960 
   2961     return TRUE;
   2962 }
   2963 
   2964 /**
   2965   find config file either from installation or build root according to
   2966   the following path layout
   2967     install-root/
   2968       bin/dbus-daemon[d].exe
   2969       etc/<config-file>.conf *or* etc/dbus-1/<config-file>.conf
   2970       (the former above is what dbus4win uses, the latter above is
   2971       what a "normal" Unix-style "make install" uses)
   2972 
   2973     build-root/
   2974       bin/dbus-daemon[d].exe
   2975       bus/<config-file>.conf
   2976 */
   2977 dbus_bool_t
   2978 _dbus_get_config_file_name(DBusString *config_file, char *s)
   2979 {
   2980   char path[MAX_PATH*2];
   2981   int path_size = sizeof(path);
   2982 
   2983   if (!_dbus_get_install_root(path,path_size))
   2984     return FALSE;
   2985 
   2986   if(strlen(s) + 4 + strlen(path) > sizeof(path)-2)
   2987     return FALSE;
   2988   strcat(path,"etc\\");
   2989   strcat(path,s);
   2990   if (_dbus_file_exists(path))
   2991     {
   2992       // find path from executable
   2993       if (!_dbus_string_append (config_file, path))
   2994         return FALSE;
   2995     }
   2996   else
   2997     {
   2998       if (!_dbus_get_install_root(path,path_size))
   2999         return FALSE;
   3000       if(strlen(s) + 11 + strlen(path) > sizeof(path)-2)
   3001         return FALSE;
   3002       strcat(path,"etc\\dbus-1\\");
   3003       strcat(path,s);
   3004 
   3005       if (_dbus_file_exists(path))
   3006         {
   3007           if (!_dbus_string_append (config_file, path))
   3008             return FALSE;
   3009         }
   3010       else
   3011         {
   3012           if (!_dbus_get_install_root(path,path_size))
   3013             return FALSE;
   3014           if(strlen(s) + 4 + strlen(path) > sizeof(path)-2)
   3015             return FALSE;
   3016           strcat(path,"bus\\");
   3017           strcat(path,s);
   3018 
   3019           if (_dbus_file_exists(path))
   3020             {
   3021               if (!_dbus_string_append (config_file, path))
   3022                 return FALSE;
   3023             }
   3024         }
   3025     }
   3026   return TRUE;
   3027 }
   3028 
   3029 /**
   3030  * Append the absolute path of the system.conf file
   3031  * (there is no system bus on Windows so this can just
   3032  * return FALSE and print a warning or something)
   3033  *
   3034  * @param str the string to append to
   3035  * @returns #FALSE if no memory
   3036  */
   3037 dbus_bool_t
   3038 _dbus_append_system_config_file (DBusString *str)
   3039 {
   3040   return _dbus_get_config_file_name(str, "system.conf");
   3041 }
   3042 
   3043 /**
   3044  * Append the absolute path of the session.conf file.
   3045  *
   3046  * @param str the string to append to
   3047  * @returns #FALSE if no memory
   3048  */
   3049 dbus_bool_t
   3050 _dbus_append_session_config_file (DBusString *str)
   3051 {
   3052   return _dbus_get_config_file_name(str, "session.conf");
   3053 }
   3054 
   3055 /* See comment in dbus-sysdeps-unix.c */
   3056 dbus_bool_t
   3057 _dbus_lookup_session_address (dbus_bool_t *supported,
   3058                               DBusString  *address,
   3059                               DBusError   *error)
   3060 {
   3061   /* Probably fill this in with something based on COM? */
   3062   *supported = FALSE;
   3063   return TRUE;
   3064 }
   3065 
   3066 /**
   3067  * Appends the directory in which a keyring for the given credentials
   3068  * should be stored.  The credentials should have either a Windows or
   3069  * UNIX user in them.  The directory should be an absolute path.
   3070  *
   3071  * On UNIX the directory is ~/.dbus-keyrings while on Windows it should probably
   3072  * be something else, since the dotfile convention is not normal on Windows.
   3073  *
   3074  * @param directory string to append directory to
   3075  * @param credentials credentials the directory should be for
   3076  *
   3077  * @returns #FALSE on no memory
   3078  */
   3079 dbus_bool_t
   3080 _dbus_append_keyring_directory_for_credentials (DBusString      *directory,
   3081                                                 DBusCredentials *credentials)
   3082 {
   3083   DBusString homedir;
   3084   DBusString dotdir;
   3085   dbus_uid_t uid;
   3086   const char *homepath;
   3087   const char *homedrive;
   3088 
   3089   _dbus_assert (credentials != NULL);
   3090   _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
   3091 
   3092   if (!_dbus_string_init (&homedir))
   3093     return FALSE;
   3094 
   3095   homedrive = _dbus_getenv("HOMEDRIVE");
   3096   if (homedrive != NULL && *homedrive != '\0')
   3097     {
   3098       _dbus_string_append(&homedir,homedrive);
   3099     }
   3100 
   3101   homepath = _dbus_getenv("HOMEPATH");
   3102   if (homepath != NULL && *homepath != '\0')
   3103     {
   3104       _dbus_string_append(&homedir,homepath);
   3105     }
   3106 
   3107 #ifdef DBUS_BUILD_TESTS
   3108   {
   3109     const char *override;
   3110 
   3111     override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
   3112     if (override != NULL && *override != '\0')
   3113       {
   3114         _dbus_string_set_length (&homedir, 0);
   3115         if (!_dbus_string_append (&homedir, override))
   3116           goto failed;
   3117 
   3118         _dbus_verbose ("Using fake homedir for testing: %s\n",
   3119                        _dbus_string_get_const_data (&homedir));
   3120       }
   3121     else
   3122       {
   3123         static dbus_bool_t already_warned = FALSE;
   3124         if (!already_warned)
   3125           {
   3126             _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
   3127             already_warned = TRUE;
   3128           }
   3129       }
   3130   }
   3131 #endif
   3132 
   3133 #ifdef DBUS_WINCE
   3134   /* It's not possible to create a .something directory in Windows CE
   3135      using the file explorer.  */
   3136 #define KEYRING_DIR "dbus-keyrings"
   3137 #else
   3138 #define KEYRING_DIR ".dbus-keyrings"
   3139 #endif
   3140 
   3141   _dbus_string_init_const (&dotdir, KEYRING_DIR);
   3142   if (!_dbus_concat_dir_and_file (&homedir,
   3143                                   &dotdir))
   3144     goto failed;
   3145 
   3146   if (!_dbus_string_copy (&homedir, 0,
   3147                           directory, _dbus_string_get_length (directory))) {
   3148     goto failed;
   3149   }
   3150 
   3151   _dbus_string_free (&homedir);
   3152   return TRUE;
   3153 
   3154  failed:
   3155   _dbus_string_free (&homedir);
   3156   return FALSE;
   3157 }
   3158 
   3159 /** Checks if a file exists
   3160 *
   3161 * @param file full path to the file
   3162 * @returns #TRUE if file exists
   3163 */
   3164 dbus_bool_t
   3165 _dbus_file_exists (const char *file)
   3166 {
   3167   DWORD attributes = GetFileAttributesA (file);
   3168 
   3169   if (attributes != INVALID_FILE_ATTRIBUTES && GetLastError() != ERROR_PATH_NOT_FOUND)
   3170     return TRUE;
   3171   else
   3172     return FALSE;
   3173 }
   3174 
   3175 /**
   3176  * A wrapper around strerror() because some platforms
   3177  * may be lame and not have strerror().
   3178  *
   3179  * @param error_number errno.
   3180  * @returns error description.
   3181  */
   3182 const char*
   3183 _dbus_strerror (int error_number)
   3184 {
   3185 #ifdef DBUS_WINCE
   3186   // TODO
   3187   return "unknown";
   3188 #else
   3189   const char *msg;
   3190 
   3191   switch (error_number)
   3192     {
   3193     case WSAEINTR:
   3194       return "Interrupted function call";
   3195     case WSAEACCES:
   3196       return "Permission denied";
   3197     case WSAEFAULT:
   3198       return "Bad address";
   3199     case WSAEINVAL:
   3200       return "Invalid argument";
   3201     case WSAEMFILE:
   3202       return "Too many open files";
   3203     case WSAEWOULDBLOCK:
   3204       return "Resource temporarily unavailable";
   3205     case WSAEINPROGRESS:
   3206       return "Operation now in progress";
   3207     case WSAEALREADY:
   3208       return "Operation already in progress";
   3209     case WSAENOTSOCK:
   3210       return "Socket operation on nonsocket";
   3211     case WSAEDESTADDRREQ:
   3212       return "Destination address required";
   3213     case WSAEMSGSIZE:
   3214       return "Message too long";
   3215     case WSAEPROTOTYPE:
   3216       return "Protocol wrong type for socket";
   3217     case WSAENOPROTOOPT:
   3218       return "Bad protocol option";
   3219     case WSAEPROTONOSUPPORT:
   3220       return "Protocol not supported";
   3221     case WSAESOCKTNOSUPPORT:
   3222       return "Socket type not supported";
   3223     case WSAEOPNOTSUPP:
   3224       return "Operation not supported";
   3225     case WSAEPFNOSUPPORT:
   3226       return "Protocol family not supported";
   3227     case WSAEAFNOSUPPORT:
   3228       return "Address family not supported by protocol family";
   3229     case WSAEADDRINUSE:
   3230       return "Address already in use";
   3231     case WSAEADDRNOTAVAIL:
   3232       return "Cannot assign requested address";
   3233     case WSAENETDOWN:
   3234       return "Network is down";
   3235     case WSAENETUNREACH:
   3236       return "Network is unreachable";
   3237     case WSAENETRESET:
   3238       return "Network dropped connection on reset";
   3239     case WSAECONNABORTED:
   3240       return "Software caused connection abort";
   3241     case WSAECONNRESET:
   3242       return "Connection reset by peer";
   3243     case WSAENOBUFS:
   3244       return "No buffer space available";
   3245     case WSAEISCONN:
   3246       return "Socket is already connected";
   3247     case WSAENOTCONN:
   3248       return "Socket is not connected";
   3249     case WSAESHUTDOWN:
   3250       return "Cannot send after socket shutdown";
   3251     case WSAETIMEDOUT:
   3252       return "Connection timed out";
   3253     case WSAECONNREFUSED:
   3254       return "Connection refused";
   3255     case WSAEHOSTDOWN:
   3256       return "Host is down";
   3257     case WSAEHOSTUNREACH:
   3258       return "No route to host";
   3259     case WSAEPROCLIM:
   3260       return "Too many processes";
   3261     case WSAEDISCON:
   3262       return "Graceful shutdown in progress";
   3263     case WSATYPE_NOT_FOUND:
   3264       return "Class type not found";
   3265     case WSAHOST_NOT_FOUND:
   3266       return "Host not found";
   3267     case WSATRY_AGAIN:
   3268       return "Nonauthoritative host not found";
   3269     case WSANO_RECOVERY:
   3270       return "This is a nonrecoverable error";
   3271     case WSANO_DATA:
   3272       return "Valid name, no data record of requested type";
   3273     case WSA_INVALID_HANDLE:
   3274       return "Specified event object handle is invalid";
   3275     case WSA_INVALID_PARAMETER:
   3276       return "One or more parameters are invalid";
   3277     case WSA_IO_INCOMPLETE:
   3278       return "Overlapped I/O event object not in signaled state";
   3279     case WSA_IO_PENDING:
   3280       return "Overlapped operations will complete later";
   3281     case WSA_NOT_ENOUGH_MEMORY:
   3282       return "Insufficient memory available";
   3283     case WSA_OPERATION_ABORTED:
   3284       return "Overlapped operation aborted";
   3285 #ifdef WSAINVALIDPROCTABLE
   3286 
   3287     case WSAINVALIDPROCTABLE:
   3288       return "Invalid procedure table from service provider";
   3289 #endif
   3290 #ifdef WSAINVALIDPROVIDER
   3291 
   3292     case WSAINVALIDPROVIDER:
   3293       return "Invalid service provider version number";
   3294 #endif
   3295 #ifdef WSAPROVIDERFAILEDINIT
   3296 
   3297     case WSAPROVIDERFAILEDINIT:
   3298       return "Unable to initialize a service provider";
   3299 #endif
   3300 
   3301     case WSASYSCALLFAILURE:
   3302       return "System call failure";
   3303     }
   3304   msg = strerror (error_number);
   3305   if (msg == NULL)
   3306     msg = "unknown";
   3307 
   3308   return msg;
   3309 #endif //DBUS_WINCE
   3310 }
   3311 
   3312 /**
   3313  * Assigns an error name and message corresponding to a Win32 error
   3314  * code to a DBusError. Does nothing if error is #NULL.
   3315  *
   3316  * @param error the error.
   3317  * @param code the Win32 error code
   3318  */
   3319 void
   3320 _dbus_win_set_error_from_win_error (DBusError *error,
   3321                                     int        code)
   3322 {
   3323   char *msg;
   3324 
   3325   /* As we want the English message, use the A API */
   3326   FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
   3327                   FORMAT_MESSAGE_IGNORE_INSERTS |
   3328                   FORMAT_MESSAGE_FROM_SYSTEM,
   3329                   NULL, code, MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US),
   3330                   (LPSTR) &msg, 0, NULL);
   3331   if (msg)
   3332     {
   3333       char *msg_copy;
   3334 
   3335       msg_copy = dbus_malloc (strlen (msg));
   3336       strcpy (msg_copy, msg);
   3337       LocalFree (msg);
   3338 
   3339       dbus_set_error (error, "win32.error", "%s", msg_copy);
   3340     }
   3341   else
   3342     dbus_set_error (error, "win32.error", "Unknown error code %d or FormatMessage failed", code);
   3343 }
   3344 
   3345 void
   3346 _dbus_win_warn_win_error (const char *message,
   3347                           int         code)
   3348 {
   3349   DBusError error;
   3350 
   3351   dbus_error_init (&error);
   3352   _dbus_win_set_error_from_win_error (&error, code);
   3353   _dbus_warn ("%s: %s\n", message, error.message);
   3354   dbus_error_free (&error);
   3355 }
   3356 
   3357 /**
   3358  * Removes a directory; Directory must be empty
   3359  *
   3360  * @param filename directory filename
   3361  * @param error initialized error object
   3362  * @returns #TRUE on success
   3363  */
   3364 dbus_bool_t
   3365 _dbus_delete_directory (const DBusString *filename,
   3366                         DBusError        *error)
   3367 {
   3368   const char *filename_c;
   3369 
   3370   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   3371 
   3372   filename_c = _dbus_string_get_const_data (filename);
   3373 
   3374   if (RemoveDirectoryA (filename_c) == 0)
   3375     {
   3376       char *emsg = _dbus_win_error_string (GetLastError ());
   3377       dbus_set_error (error, _dbus_win_error_from_last_error (),
   3378                       "Failed to remove directory %s: %s",
   3379                       filename_c, emsg);
   3380       _dbus_win_free_error_string (emsg);
   3381       return FALSE;
   3382     }
   3383 
   3384   return TRUE;
   3385 }
   3386 
   3387 /** @} end of sysdeps-win */
   3388 /* tests in dbus-sysdeps-util.c */
   3389 
   3390