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