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