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