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