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