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