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