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