* cmake: added debug postfixes to debug exe's for easier debugging.
[platform/upstream/dbus.git] / dbus / dbus-sysdeps-win.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  *
27  */
28 #undef open
29
30 #define STRSAFE_NO_DEPRECATE
31
32 #ifndef DBUS_WINCE
33 #define _WIN32_WINNT 0x0500
34 #endif
35
36 #include "dbus-internals.h"
37 #include "dbus-sysdeps.h"
38 #include "dbus-threads.h"
39 #include "dbus-protocol.h"
40 #include "dbus-string.h"
41 #include "dbus-sysdeps-win.h"
42 #include "dbus-protocol.h"
43 #include "dbus-hash.h"
44 #include "dbus-sockets-win.h"
45 #include "dbus-userdb.h"
46 #include "dbus-list.h"
47
48 #include <windows.h>
49 #include <fcntl.h>
50
51 #include <process.h>
52 #include <sys/stat.h>
53 #include <sys/types.h>
54
55 #ifndef O_BINARY
56 #define O_BINARY 0
57 #endif
58
59 #ifndef HAVE_SOCKLEN_T
60 #define socklen_t int
61 #endif
62
63 _DBUS_DEFINE_GLOBAL_LOCK (win_fds);
64 _DBUS_DEFINE_GLOBAL_LOCK (sid_atom_cache);
65
66
67 static
68 void 
69 _dbus_lock_sockets()
70 {
71         _dbus_assert (win_fds!=0); 
72         _DBUS_LOCK   (win_fds);
73 }
74
75 static
76 void 
77 _dbus_unlock_sockets()
78 {
79         _dbus_assert (win_fds!=0); 
80         _DBUS_UNLOCK (win_fds);
81 }
82
83 #ifdef _DBUS_WIN_USE_RANDOMIZER
84 static int  win_encap_randomizer;
85 #endif
86 static DBusHashTable *sid_atom_cache = NULL;
87
88
89 static DBusString dbusdir;
90 static int working_dir_init = 0;
91
92 int _dbus_init_working_dir(char *s)
93 {
94   /* change working directory to one level above 
95      of dbus-daemon executable path.  
96      This allows the usage of relative path in 
97      config files or command line parameters */
98   DBusString daemon_path,bin_path;
99
100   if (!_dbus_string_init (&daemon_path))
101     return FALSE;
102   
103   if (!_dbus_string_init (&bin_path))
104     return FALSE;
105
106   if (!_dbus_string_init (&dbusdir))
107     return FALSE;
108   
109   _dbus_string_append(&daemon_path,s);
110   _dbus_string_get_dirname(&daemon_path,&bin_path);
111   _dbus_string_get_dirname(&bin_path,&dbusdir);
112   chdir(_dbus_string_get_const_data(&dbusdir));
113   _dbus_verbose ("Change working path to %s\n",_dbus_string_get_const_data (&dbusdir));
114   working_dir_init = 1;
115   return TRUE;
116 }
117
118 DBusString *_dbus_get_working_dir(void)
119 {
120   if (!working_dir_init) 
121     return NULL;
122         
123   _dbus_verbose ("retrieving working path %s\n",_dbus_string_get_const_data (&dbusdir));
124   return &dbusdir;
125 }
126
127 /**
128  * File interface
129  *
130  */
131 dbus_bool_t
132 _dbus_file_open (DBusFile   *file,
133                  const char *filename,
134                  int         oflag,
135                  int         pmode)
136 {
137   if (pmode!=-1)
138     file->FDATA = _open (filename, oflag, pmode);
139   else
140     file->FDATA = _open (filename, oflag);
141   if (file->FDATA >= 0)
142     return TRUE;
143   else
144     {
145       file->FDATA = -1;
146       return FALSE;
147     }
148 }
149
150 dbus_bool_t
151 _dbus_file_close (DBusFile  *file,
152                   DBusError *error)
153 {
154   const int fd = file->FDATA;
155
156   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
157
158   _dbus_assert (fd >= 0);
159
160   if (_close (fd) == -1)
161     {
162       dbus_set_error (error, _dbus_error_from_errno (errno),
163                       "Could not close fd %d: %s", fd,
164                       _dbus_strerror (errno));
165       return FALSE;
166     }
167
168   file->FDATA = -1;
169   _dbus_verbose ("closed C file descriptor %d:\n",fd);
170
171   return TRUE;
172 }
173
174 int
175 _dbus_file_read(DBusFile   *file,
176                 DBusString *buffer,
177                 int         count)
178 {
179   const int fd = file->FDATA;
180   int bytes_read;
181   int start;
182   char *data;
183   _dbus_assert (count >= 0);
184
185   start = _dbus_string_get_length (buffer);
186
187   if (!_dbus_string_lengthen (buffer, count))
188     {
189       errno = ENOMEM;
190       return -1;
191     }
192
193   data = _dbus_string_get_data_len (buffer, start, count);
194
195   _dbus_assert (fd >= 0);
196
197   _dbus_verbose ("read: count=%d fd=%d\n", count, fd);
198   bytes_read = read (fd, data, count);
199
200   if (bytes_read == -1)
201     _dbus_verbose ("read: failed: %s\n", _dbus_strerror (errno));
202   else
203     _dbus_verbose ("read: = %d\n", bytes_read);
204
205   if (bytes_read < 0)
206     {
207       /* put length back (note that this doesn't actually realloc anything) */
208       _dbus_string_set_length (buffer, start);
209       return -1;
210     }
211   else
212     {
213       /* put length back (doesn't actually realloc) */
214       _dbus_string_set_length (buffer, start + bytes_read);
215
216 #if 0
217
218       if (bytes_read > 0)
219         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
220 #endif
221
222       return bytes_read;
223     }
224 }
225
226 int
227 _dbus_file_write (DBusFile         *file,
228                   const DBusString *buffer,
229                   int               start,
230                   int               len)
231 {
232   const int fd = file->FDATA;
233   const char *data;
234   int bytes_written;
235
236   data = _dbus_string_get_const_data_len (buffer, start, len);
237
238   _dbus_assert (fd >= 0);
239
240   _dbus_verbose ("write: len=%d fd=%d\n", len, fd);
241   bytes_written = write (fd, data, len);
242
243   if (bytes_written == -1)
244     _dbus_verbose ("write: failed: %s\n", _dbus_strerror (errno));
245   else
246     _dbus_verbose ("write: = %d\n", bytes_written);
247
248 #if 0
249
250   if (bytes_written > 0)
251     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
252 #endif
253
254   return bytes_written;
255 }
256
257 dbus_bool_t
258 _dbus_is_valid_file (DBusFile* file)
259 {
260   return file->FDATA >= 0;
261 }
262
263 dbus_bool_t _dbus_fstat (DBusFile    *file,
264                          struct stat *sb)
265 {
266   return fstat(file->FDATA, sb) >= 0;
267 }
268
269 /**
270  * write data to a pipe.
271  *
272  * @param pipe the pipe instance
273  * @param buffer the buffer to write data from
274  * @param start the first byte in the buffer to write
275  * @param len the number of bytes to try to write
276  * @param error error return
277  * @returns the number of bytes written or -1 on error
278  */
279 int
280 _dbus_pipe_write (DBusPipe         *pipe,
281                   const DBusString *buffer,
282                   int               start,
283                   int               len,
284                   DBusError        *error)
285 {
286   int written;
287   DBusFile file;
288   file.FDATA = pipe->fd_or_handle;
289   written = _dbus_file_write (&file, buffer, start, len);
290   if (written < 0)
291     {
292       dbus_set_error (error, DBUS_ERROR_FAILED,
293                       "Writing to pipe: %s\n",
294                       _dbus_strerror (errno));
295     }
296   return written;
297 }
298
299 /**
300  * close a pipe.
301  *
302  * @param pipe the pipe instance
303  * @param error return location for an error
304  * @returns #FALSE if error is set
305  */
306 int
307 _dbus_pipe_close  (DBusPipe         *pipe,
308                    DBusError        *error)
309 {
310   DBusFile file;
311   file.FDATA = pipe->fd_or_handle;
312   if (_dbus_file_close (&file, error) < 0)
313     {
314       return -1;
315     }
316   else
317     {
318       _dbus_pipe_invalidate (pipe);
319       return 0;
320     }
321 }
322
323 #undef FDATA
324
325 /**
326  * Socket interface
327  *
328  */
329
330 static DBusSocket *win_fds = NULL;
331 static int win_n_fds = 0; // is this the size? rename to win_fds_size? #
332
333 #if 0
334 #define TO_HANDLE(n)   ((n)^win32_encap_randomizer)
335 #define FROM_HANDLE(n) ((n)^win32_encap_randomizer)
336 #else
337 #define TO_HANDLE(n)   ((n)+0x10000000)
338 #define FROM_HANDLE(n) ((n)-0x10000000)
339 #define IS_HANDLE(n)   ((n)&0x10000000)
340 #endif
341
342
343 static
344 void
345 _dbus_win_deallocate_fd (int fd)
346 {
347   _DBUS_LOCK (win_fds);
348   win_fds[FROM_HANDLE (fd)].is_used = 0;
349   _DBUS_UNLOCK (win_fds);
350 }
351
352 static
353 int
354 _dbus_win_allocate_fd (void)
355 {
356   int i;
357
358   _DBUS_LOCK (win_fds);
359
360   if (win_fds == NULL)
361     {
362 #ifdef _DBUS_WIN_USE_RANDOMIZER
363       DBusString random;
364 #endif
365
366       win_n_fds = 16;
367       /* Use malloc to avoid memory leak failure in dbus-test */
368       win_fds = malloc (win_n_fds * sizeof (*win_fds));
369
370       _dbus_assert (win_fds != NULL);
371
372       for (i = 0; i < win_n_fds; i++)
373         win_fds[i].is_used = 0;
374
375 #ifdef _DBUS_WIN_USE_RANDOMIZER
376
377       _dbus_string_init (&random);
378       _dbus_generate_random_bytes (&random, sizeof (int));
379       memmove (&win_encap_randomizer, _dbus_string_get_const_data (&random), sizeof (int));
380       win_encap_randomizer &= 0xFF;
381       _dbus_string_free (&random);
382 #endif
383
384     }
385
386   for (i = 0; i < win_n_fds && win_fds[i].is_used != 0; i++)
387     ;
388
389   if (i == win_n_fds)
390     {
391       int oldn = win_n_fds;
392       int j;
393
394       win_n_fds += 16;
395       win_fds = realloc (win_fds, win_n_fds * sizeof (*win_fds));
396
397       _dbus_assert (win_fds != NULL);
398
399       for (j = oldn; j < win_n_fds; j++)
400         win_fds[i].is_used = 0;
401     }
402
403   memset(&win_fds[i], 0, sizeof(win_fds[i]));
404
405   win_fds[i].is_used = 1;
406   win_fds[i].fd = -1;
407   win_fds[i].port_file_fd = -1;
408   win_fds[i].close_on_exec = FALSE;
409   win_fds[i].non_blocking = FALSE;
410
411   _DBUS_UNLOCK (win_fds);
412
413   return i;
414 }
415
416 static
417 int
418 _dbus_create_handle_from_socket (int s)
419 {
420   int i;
421   int handle = -1;
422
423   // check: parameter must be a valid value
424   _dbus_assert(s != -1);
425   _dbus_assert(!IS_HANDLE(s));
426
427   // get index of a new position in the map
428   i = _dbus_win_allocate_fd ();
429
430   // fill new posiiton in the map: value->index
431   win_fds[i].fd = s;
432   win_fds[i].is_used = 1;
433
434   // create handle from the index: index->handle
435   handle = TO_HANDLE (i);
436
437   _dbus_verbose ("_dbus_create_handle_from_value, value: %d, handle: %d\n", s, handle);
438
439   return handle;
440 }
441
442 int
443 _dbus_socket_to_handle (DBusSocket *s)
444 {
445   int i;
446   int handle = -1;
447
448   // check: parameter must be a valid socket
449   _dbus_assert(s != NULL);
450   _dbus_assert(s->fd != -1);
451   _dbus_assert(!IS_HANDLE(s->fd));
452
453   _DBUS_LOCK (win_fds);
454
455   // at the first call there is no win_fds
456   // will be constructed  _dbus_create_handle_from_socket
457   // because handle = -1
458   if (win_fds != NULL)
459     {
460       // search for the value in the map
461       // find the index of the value: value->index
462       for (i = 0; i < win_n_fds; i++)
463         if (win_fds[i].is_used == 1 && win_fds[i].fd == s->fd)
464           {
465             // create handle from the index: index->handle
466             handle = TO_HANDLE (i);
467             break;
468           }
469     }
470   _DBUS_UNLOCK (win_fds);
471
472
473   if (handle == -1)
474     {
475       handle = _dbus_create_handle_from_socket(s->fd);
476     }
477
478   _dbus_assert(handle != -1);
479
480   return handle;
481 }
482
483 static
484 void 
485 _dbus_handle_to_socket_unlocked (int          handle,
486                                  DBusSocket **ptr)
487 {
488   int i;
489
490   // check: parameter must be a valid handle
491   _dbus_assert(handle != -1);
492   _dbus_assert(IS_HANDLE(handle));
493   _dbus_assert(ptr != NULL);
494
495   // map from handle to index: handle->index
496   i = FROM_HANDLE (handle);
497
498   _dbus_assert (win_fds != NULL);
499   _dbus_assert (i >= 0 && i < win_n_fds);
500
501   // check for if fd is valid
502   _dbus_assert (win_fds[i].is_used == 1);
503
504   // get socket from index: index->socket
505   *ptr = &win_fds[i];
506
507   _dbus_verbose ("_dbus_socket_to_handle_unlocked: socket=%d, handle=%d, index=%d\n", (*ptr)->fd, handle, i);
508 }
509
510 void 
511 _dbus_handle_to_socket (int          handle,
512                         DBusSocket **ptr)
513 {
514   _dbus_lock_sockets();
515   _dbus_handle_to_socket_unlocked (handle, ptr);
516   _dbus_unlock_sockets();
517 }
518
519 #undef TO_HANDLE
520 #undef IS_HANDLE
521 #undef FROM_HANDLE
522 #define FROM_HANDLE(n) 1==DBUS_WIN_DONT_USE__FROM_HANDLE__DIRECTLY
523 #define win_fds 1==DBUS_WIN_DONT_USE_win_fds_DIRECTLY
524
525
526
527
528 /**
529  * Thin wrapper around the read() system call that appends
530  * the data it reads to the DBusString buffer. It appends
531  * up to the given count, and returns the same value
532  * and same errno as read(). The only exception is that
533  * _dbus_read() handles EINTR for you. _dbus_read() can
534  * return ENOMEM, even though regular UNIX read doesn't.
535  *
536  * @param fd the file descriptor to read from
537  * @param buffer the buffer to append data to
538  * @param count the amount of data to read
539  * @returns the number of bytes read or -1
540  */
541 int
542 _dbus_read_socket (int               handle,
543                    DBusString       *buffer,
544                    int               count)
545 {
546   DBusSocket *s;
547   int bytes_read;
548   int start;
549   char *data;
550
551   _dbus_assert (count >= 0);
552
553   start = _dbus_string_get_length (buffer);
554
555   if (!_dbus_string_lengthen (buffer, count))
556     {
557       errno = ENOMEM;
558       return -1;
559     }
560
561   data = _dbus_string_get_data_len (buffer, start, count);
562
563   _dbus_handle_to_socket(handle, &s);
564
565   if(s->is_used)
566     {
567       _dbus_verbose ("recv: count=%d socket=%d\n", count, s->fd);
568       bytes_read = recv (s->fd, data, count, 0);
569       if (bytes_read == SOCKET_ERROR)
570         {
571           DBUS_SOCKET_SET_ERRNO();
572           _dbus_verbose ("recv: failed: %s\n", _dbus_strerror (errno));
573           bytes_read = -1;
574         }
575       else
576         _dbus_verbose ("recv: = %d\n", bytes_read);
577     }
578   else
579     {
580       _dbus_assert_not_reached ("no valid socket");
581     }
582
583   if (bytes_read < 0)
584     {
585       /* put length back (note that this doesn't actually realloc anything) */
586       _dbus_string_set_length (buffer, start);
587       return -1;
588     }
589   else
590     {
591       /* put length back (doesn't actually realloc) */
592       _dbus_string_set_length (buffer, start + bytes_read);
593
594 #if 0
595
596       if (bytes_read > 0)
597         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
598 #endif
599
600       return bytes_read;
601     }
602 }
603
604 /**
605  * Thin wrapper around the write() system call that writes a part of a
606  * DBusString and handles EINTR for you.
607  * 
608  * @param fd the file descriptor to write
609  * @param buffer the buffer to write data from
610  * @param start the first byte in the buffer to write
611  * @param len the number of bytes to try to write
612  * @returns the number of bytes written or -1 on error
613  */
614 int
615 _dbus_write_socket (int               handle,
616                     const DBusString *buffer,
617                     int               start,
618                     int               len)
619 {
620   DBusSocket *s;
621   int is_used;
622   const char *data;
623   int bytes_written;
624
625   data = _dbus_string_get_const_data_len (buffer, start, len);
626
627   _dbus_handle_to_socket(handle, &s);
628
629   if (s->is_used)
630     {
631       _dbus_verbose ("send: len=%d socket=%d\n", len, s->fd);
632       bytes_written = send (s->fd, data, len, 0);
633       if (bytes_written == SOCKET_ERROR)
634         {
635           DBUS_SOCKET_SET_ERRNO();
636           _dbus_verbose ("send: failed: %s\n", _dbus_strerror (errno));
637           bytes_written = -1;
638         }
639       else
640         _dbus_verbose ("send: = %d\n", bytes_written);
641     }
642   else
643     {
644       _dbus_assert_not_reached ("unhandled fd type");
645     }
646
647 #if 0
648   if (bytes_written > 0)
649     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
650 #endif
651
652   return bytes_written;
653 }
654
655
656 /**
657  * Closes a file descriptor.
658  *
659  * @param fd the file descriptor
660  * @param error error object
661  * @returns #FALSE if error set
662  */
663 dbus_bool_t
664 _dbus_close_socket (int        handle,
665                     DBusError *error)
666 {
667   DBusSocket *s;
668
669   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
670
671   _dbus_lock_sockets();
672
673   _dbus_handle_to_socket_unlocked (handle, &s);
674
675
676   if (s->is_used)
677     {
678       if (s->port_file_fd >= 0)
679         {
680           _chsize (s->port_file_fd, 0);
681           close (s->port_file_fd);
682           s->port_file_fd = -1;
683           unlink (_dbus_string_get_const_data (&s->port_file));
684           free ((char *) _dbus_string_get_const_data (&s->port_file));
685         }
686
687       if (closesocket (s->fd) == SOCKET_ERROR)
688         {
689           DBUS_SOCKET_SET_ERRNO ();
690           dbus_set_error (error, _dbus_error_from_errno (errno),
691               "Could not close socket: socket=%d, handle=%d, %s",
692                           s->fd, handle, _dbus_strerror (errno));
693           _dbus_unlock_sockets();
694           return FALSE;
695         }
696       _dbus_verbose ("_dbus_close_socket: socket=%d, handle=%d\n",
697                      s->fd, handle);
698     }
699   else
700     {
701       _dbus_assert_not_reached ("unhandled fd type");
702     }
703
704   _dbus_unlock_sockets();
705
706   _dbus_win_deallocate_fd (handle);
707
708   return TRUE;
709
710 }
711
712 /**
713  * Sets the file descriptor to be close
714  * on exec. Should be called for all file
715  * descriptors in D-Bus code.
716  *
717  * @param fd the file descriptor
718  */
719 void
720 _dbus_fd_set_close_on_exec (int handle)
721 {
722   DBusSocket *s;
723   if (handle < 0)
724     return;
725
726   _dbus_lock_sockets();
727
728   _dbus_handle_to_socket_unlocked (handle, &s);
729   s->close_on_exec = TRUE;
730
731   _dbus_unlock_sockets();
732 }
733
734 /**
735  * Sets a file descriptor to be nonblocking.
736  *
737  * @param fd the file descriptor.
738  * @param error address of error location.
739  * @returns #TRUE on success.
740  */
741 dbus_bool_t
742 _dbus_set_fd_nonblocking (int             handle,
743                           DBusError      *error)
744 {
745   DBusSocket *s;
746   u_long one = 1;
747
748   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
749
750   _dbus_lock_sockets();
751
752   _dbus_handle_to_socket_unlocked(handle, &s);
753
754   if (s->is_used)
755     {
756       if (ioctlsocket (s->fd, FIONBIO, &one) == SOCKET_ERROR)
757         {
758           dbus_set_error (error, _dbus_error_from_errno (WSAGetLastError ()),
759                           "Failed to set socket %d:%d to nonblocking: %s", s->fd,
760                           _dbus_strerror (WSAGetLastError ()));
761           _dbus_unlock_sockets();
762           return FALSE;
763         }
764     }
765   else
766     {
767       _dbus_assert_not_reached ("unhandled fd type");
768     }
769
770   _dbus_unlock_sockets();
771
772   return TRUE;
773 }
774
775
776 /**
777  * Like _dbus_write() but will use writev() if possible
778  * to write both buffers in sequence. The return value
779  * is the number of bytes written in the first buffer,
780  * plus the number written in the second. If the first
781  * buffer is written successfully and an error occurs
782  * writing the second, the number of bytes in the first
783  * is returned (i.e. the error is ignored), on systems that
784  * don't have writev. Handles EINTR for you.
785  * The second buffer may be #NULL.
786  *
787  * @param fd the file descriptor
788  * @param buffer1 first buffer
789  * @param start1 first byte to write in first buffer
790  * @param len1 number of bytes to write from first buffer
791  * @param buffer2 second buffer, or #NULL
792  * @param start2 first byte to write in second buffer
793  * @param len2 number of bytes to write in second buffer
794  * @returns total bytes written from both buffers, or -1 on error
795  */
796 int
797 _dbus_write_socket_two (int               handle,
798                         const DBusString *buffer1,
799                         int               start1,
800                         int               len1,
801                         const DBusString *buffer2,
802                         int               start2,
803                         int               len2)
804 {
805   DBusSocket *s;
806   WSABUF vectors[2];
807   const char *data1;
808   const char *data2;
809   int rc;
810   DWORD bytes_written;
811   int ret1;
812
813   _dbus_assert (buffer1 != NULL);
814   _dbus_assert (start1 >= 0);
815   _dbus_assert (start2 >= 0);
816   _dbus_assert (len1 >= 0);
817   _dbus_assert (len2 >= 0);
818
819   _dbus_handle_to_socket(handle, &s);
820
821   data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
822
823   if (buffer2 != NULL)
824     data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
825   else
826     {
827       data2 = NULL;
828       start2 = 0;
829       len2 = 0;
830     }
831
832   if (s->is_used)
833     {
834       vectors[0].buf = (char*) data1;
835       vectors[0].len = len1;
836       vectors[1].buf = (char*) data2;
837       vectors[1].len = len2;
838
839       _dbus_verbose ("WSASend: len1+2=%d+%d socket=%d\n", len1, len2, s->fd);
840       rc = WSASend (s->fd, vectors, data2 ? 2 : 1, &bytes_written,
841                     0, NULL, NULL);
842       if (rc < 0)
843         {
844           DBUS_SOCKET_SET_ERRNO ();
845           _dbus_verbose ("WSASend: failed: %s\n", _dbus_strerror (errno));
846           bytes_written = -1;
847         }
848       else
849         _dbus_verbose ("WSASend: = %ld\n", bytes_written);
850       return bytes_written;
851     }
852   else
853     {
854       _dbus_assert_not_reached ("unhandled fd type");
855     }
856   return 0;
857 }
858
859 /**
860  * @def _DBUS_MAX_SUN_PATH_LENGTH
861  *
862  * Maximum length of the path to a UNIX domain socket,
863  * sockaddr_un::sun_path member. POSIX requires that all systems
864  * support at least 100 bytes here, including the nul termination.
865  * We use 99 for the max value to allow for the nul.
866  *
867  * We could probably also do sizeof (addr.sun_path)
868  * but this way we are the same on all platforms
869  * which is probably a good idea.
870  */
871
872 /**
873  * Creates a socket and connects it to the UNIX domain socket at the
874  * given path.  The connection fd is returned, and is set up as
875  * nonblocking.
876  * 
877  * On Windows there are no UNIX domain sockets. Instead, connects to a
878  * localhost-bound TCP socket, whose port number is stored in a file
879  * at the given path.
880  * 
881  * Uses abstract sockets instead of filesystem-linked sockets if
882  * requested (it's possible only on Linux; see "man 7 unix" on Linux).
883  * On non-Linux abstract socket usage always fails.
884  *
885  * @param path the path to UNIX domain socket
886  * @param abstract #TRUE to use abstract namespace
887  * @param error return location for error code
888  * @returns connection file descriptor or -1 on error
889  */
890 int
891 _dbus_connect_unix_socket (const char     *path,
892                            dbus_bool_t     abstract,
893                            DBusError      *error)
894 {
895 #ifdef DBUS_WINCE
896         return -1;
897 #else
898   int fd, n, port;
899   char buf[7];
900
901   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
902
903   _dbus_verbose ("connecting to pseudo-unix socket at %s\n",
904                  path);
905
906   if (abstract)
907     {
908       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
909                       "Implementation does not support abstract socket namespace\n");
910       return -1;
911     }
912
913   fd = _sopen (path, O_RDONLY, SH_DENYNO);
914
915   if (fd == -1)
916     {
917       dbus_set_error (error, _dbus_error_from_errno (errno),
918                       "Failed to open file %s: %s",
919                       path, _dbus_strerror (errno));
920       return -1;
921     }
922
923   n = read (fd, buf, sizeof (buf) - 1);
924   close (fd);
925
926   if (n == 0)
927     {
928       dbus_set_error (error, DBUS_ERROR_FAILED,
929                       "Failed to read port number from file %s",
930                       path);
931       return -1;
932     }
933
934   buf[n] = '\0';
935   port = atoi (buf);
936
937   if (port <= 0 || port > 0xFFFF)
938     {
939       dbus_set_error (error, DBUS_ERROR_FAILED,
940                       "Invalid port numer in file %s",
941                       path);
942       return -1;
943     }
944
945   return _dbus_connect_tcp_socket (NULL, port, error);
946 #endif //DBUS_WINCE
947
948 }
949
950 /**
951  * Creates a socket and binds it to the given path,
952  * then listens on the socket. The socket is
953  * set to be nonblocking.
954  *
955  * Uses abstract sockets instead of filesystem-linked
956  * sockets if requested (it's possible only on Linux;
957  * see "man 7 unix" on Linux).
958  * On non-Linux abstract socket usage always fails.
959  *
960  * @param path the socket name
961  * @param abstract #TRUE to use abstract namespace
962  * @param error return location for errors
963  * @returns the listening file descriptor or -1 on error
964  */
965 int
966 _dbus_listen_unix_socket (const char     *path,
967                           dbus_bool_t     abstract,
968                           DBusError      *error)
969 {
970 #ifdef DBUS_WINCE
971         return -1;
972 #else
973   DBusSocket *s;
974   int listen_handle;
975   struct sockaddr sa;
976   int addr_len;
977   int filefd;
978   int n, l;
979   DBusString portstr;
980
981   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
982
983   _dbus_verbose ("listening on pseudo-unix socket at %s\n",
984                  path);
985
986   if (abstract)
987     {
988       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
989                       "Implementation does not support abstract socket namespace\n");
990       return -1;
991     }
992
993   listen_handle = _dbus_listen_tcp_socket (NULL, 0, error);
994
995   if (listen_handle == -1)
996     return -1;
997
998   _dbus_handle_to_socket(listen_handle, &s);
999
1000   addr_len = sizeof (sa);
1001   if (getsockname (s->fd, &sa, &addr_len) == SOCKET_ERROR)
1002     {
1003       DBUS_SOCKET_SET_ERRNO ();
1004       dbus_set_error (error, _dbus_error_from_errno (errno),
1005                       "getsockname failed: %s",
1006                       _dbus_strerror (errno));
1007       _dbus_close_socket (listen_handle, NULL);
1008       return -1;
1009     }
1010
1011   _dbus_assert (((struct sockaddr_in*) &sa)->sin_family == AF_INET);
1012
1013   filefd = _sopen (path, O_CREAT|O_WRONLY|_O_SHORT_LIVED, SH_DENYWR, 0666);
1014
1015   if (filefd == -1)
1016     {
1017       dbus_set_error (error, _dbus_error_from_errno (errno),
1018                       "Failed to create pseudo-unix socket port number file %s: %s",
1019                       path, _dbus_strerror (errno));
1020       _dbus_close_socket (listen_handle, NULL);
1021       return -1;
1022     }
1023
1024   _dbus_lock_sockets();
1025   _dbus_handle_to_socket_unlocked(listen_handle, &s);
1026   s->port_file_fd = filefd;
1027   _dbus_unlock_sockets();
1028
1029   /* Use strdup() to avoid memory leak in dbus-test */
1030   path = strdup (path);
1031   if (!path)
1032     {
1033       _DBUS_SET_OOM (error);
1034       _dbus_close_socket (listen_handle, NULL);
1035       return -1;
1036     }
1037
1038   _dbus_string_init_const (&s->port_file, path);
1039
1040   if (!_dbus_string_init (&portstr))
1041     {
1042       _DBUS_SET_OOM (error);
1043       _dbus_close_socket (listen_handle, NULL);
1044       return -1;
1045     }
1046
1047   if (!_dbus_string_append_int (&portstr, ntohs (((struct sockaddr_in*) &sa)->sin_port)))
1048     {
1049       _DBUS_SET_OOM (error);
1050       _dbus_close_socket (listen_handle, NULL);
1051       return -1;
1052     }
1053
1054   l = _dbus_string_get_length (&portstr);
1055   n = write (filefd, _dbus_string_get_const_data (&portstr), l);
1056   _dbus_string_free (&portstr);
1057
1058   if (n == -1)
1059     {
1060       dbus_set_error (error, _dbus_error_from_errno (errno),
1061                       "Failed to write port number to file %s: %s",
1062                       path, _dbus_strerror (errno));
1063       _dbus_close_socket (listen_handle, NULL);
1064       return -1;
1065     }
1066   else if (n < l)
1067     {
1068       dbus_set_error (error, _dbus_error_from_errno (errno),
1069                       "Failed to write port number to file %s",
1070                       path);
1071       _dbus_close_socket (listen_handle, NULL);
1072       return -1;
1073     }
1074
1075   return listen_handle;
1076 #endif //DBUS_WINCE
1077 }
1078
1079 #if 0
1080
1081 /**
1082  * Opens the client side of a Windows named pipe. The connection D-BUS
1083  * file descriptor index is returned. It is set up as nonblocking.
1084  * 
1085  * @param path the path to named pipe socket
1086  * @param error return location for error code
1087  * @returns connection D-BUS file descriptor or -1 on error
1088  */
1089 int
1090 _dbus_connect_named_pipe (const char     *path,
1091                           DBusError      *error)
1092 {
1093   _dbus_assert_not_reached ("not implemented");
1094 }
1095
1096 #endif
1097
1098
1099 dbus_bool_t
1100 _dbus_account_to_win_sid (const wchar_t  *waccount,
1101                           void          **ppsid,
1102                           DBusError      *error)
1103 {
1104   dbus_bool_t retval = FALSE;
1105   DWORD sid_length, wdomain_length;
1106   SID_NAME_USE use;
1107   wchar_t *wdomain;
1108
1109   *ppsid = NULL;
1110
1111   sid_length = 0;
1112   wdomain_length = 0;
1113   if (!LookupAccountNameW (NULL, waccount, NULL, &sid_length,
1114                            NULL, &wdomain_length, &use)
1115       && GetLastError () != ERROR_INSUFFICIENT_BUFFER)
1116     {
1117       _dbus_win_set_error_from_win_error (error, GetLastError ());
1118       return FALSE;
1119     }
1120
1121   *ppsid = dbus_malloc (sid_length);
1122   if (!*ppsid)
1123     {
1124       _DBUS_SET_OOM (error);
1125       return FALSE;
1126     }
1127
1128   wdomain = dbus_new (wchar_t, wdomain_length);
1129   if (!wdomain)
1130     {
1131       _DBUS_SET_OOM (error);
1132       goto out1;
1133     }
1134
1135   if (!LookupAccountNameW (NULL, waccount, (PSID) *ppsid, &sid_length,
1136                            wdomain, &wdomain_length, &use))
1137     {
1138       _dbus_win_set_error_from_win_error (error, GetLastError ());
1139       goto out2;
1140     }
1141
1142   if (!IsValidSid ((PSID) *ppsid))
1143     {
1144       dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid SID");
1145       goto out2;
1146     }
1147
1148   retval = TRUE;
1149
1150 out2:
1151   dbus_free (wdomain);
1152 out1:
1153   if (!retval)
1154     {
1155       dbus_free (*ppsid);
1156       *ppsid = NULL;
1157     }
1158
1159   return retval;
1160 }
1161
1162
1163 dbus_bool_t
1164 fill_win_user_info_name_and_groups (wchar_t       *wname,
1165                                     wchar_t       *wdomain,
1166                                     DBusUserInfo *info,
1167                                     DBusError    *error)
1168 {
1169 #ifdef DBUS_WINCE
1170         return TRUE;
1171 #else
1172   dbus_bool_t retval = FALSE;
1173   char *name, *domain;
1174   LPLOCALGROUP_USERS_INFO_0 local_groups = NULL;
1175   LPGROUP_USERS_INFO_0 global_groups = NULL;
1176   DWORD nread, ntotal;
1177
1178   name = _dbus_win_utf16_to_utf8 (wname, error);
1179   if (!name)
1180     return FALSE;
1181
1182   domain = _dbus_win_utf16_to_utf8 (wdomain, error);
1183   if (!domain)
1184     goto out0;
1185
1186   info->username = dbus_malloc (strlen (domain) + 1 + strlen (name) + 1);
1187   if (!info->username)
1188     {
1189       _DBUS_SET_OOM (error);
1190       goto out1;
1191     }
1192
1193   strcpy (info->username, domain);
1194   strcat (info->username, "\\");
1195   strcat (info->username, name);
1196
1197   info->n_group_ids = 0;
1198   if (NetUserGetLocalGroups (NULL, wname, 0, LG_INCLUDE_INDIRECT,
1199                              (LPBYTE *) &local_groups, MAX_PREFERRED_LENGTH,
1200                              &nread, &ntotal) == NERR_Success)
1201     {
1202       DWORD i;
1203       int n;
1204
1205       info->group_ids = dbus_new (dbus_gid_t, nread);
1206       if (!info->group_ids)
1207         {
1208           _DBUS_SET_OOM (error);
1209           goto out3;
1210         }
1211
1212       for (i = n = 0; i < nread; i++)
1213         {
1214           PSID group_sid;
1215           if (_dbus_account_to_win_sid (local_groups[i].lgrui0_name,
1216                                         &group_sid, error))
1217             {
1218               info->group_ids[n++] = _dbus_win_sid_to_uid_t (group_sid);
1219               dbus_free (group_sid);
1220             }
1221         }
1222       info->n_group_ids = n;
1223     }
1224
1225   if (NetUserGetGroups (NULL, wname, 0,
1226                         (LPBYTE *) &global_groups, MAX_PREFERRED_LENGTH,
1227                         &nread, &ntotal) == NERR_Success)
1228     {
1229       DWORD i;
1230       int n = info->n_group_ids;
1231
1232       info->group_ids = dbus_realloc (info->group_ids, (n + nread) * sizeof (dbus_gid_t));
1233       if (!info->group_ids)
1234         {
1235           _DBUS_SET_OOM (error);
1236           goto out4;
1237         }
1238
1239       for (i = 0; i < nread; i++)
1240         {
1241           PSID group_sid;
1242           if (_dbus_account_to_win_sid (global_groups[i].grui0_name,
1243                                         &group_sid, error))
1244             {
1245               info->group_ids[n++] = _dbus_win_sid_to_uid_t (group_sid);
1246               dbus_free (group_sid);
1247             }
1248         }
1249       info->n_group_ids = n;
1250     }
1251
1252   if (info->n_group_ids > 0)
1253     {
1254       /* FIXME: find out actual primary group */
1255       info->primary_gid = info->group_ids[0];
1256     }
1257   else
1258     {
1259       info->group_ids = dbus_new (dbus_gid_t, 1);
1260       info->n_group_ids = 1;
1261       info->group_ids[0] = DBUS_GID_UNSET;
1262       info->primary_gid = DBUS_GID_UNSET;
1263     }
1264
1265   retval = TRUE;
1266
1267 out4:
1268   if (global_groups != NULL)
1269     NetApiBufferFree (global_groups);
1270 out3:
1271   if (local_groups != NULL)
1272     NetApiBufferFree (local_groups);
1273 out1:
1274   dbus_free (domain);
1275 out0:
1276   dbus_free (name);
1277
1278   return retval;
1279 #endif //DBUS_WINCE
1280 }
1281
1282 dbus_bool_t
1283 fill_win_user_info_homedir (wchar_t      *wname,
1284                             wchar_t      *wdomain,
1285                             DBusUserInfo *info,
1286                             DBusError    *error)
1287 {
1288 #ifdef DBUS_WINCE
1289         //TODO
1290         return TRUE;
1291 #else
1292   dbus_bool_t retval = FALSE;
1293   USER_INFO_1 *user_info = NULL;
1294   wchar_t wcomputername[MAX_COMPUTERNAME_LENGTH + 1];
1295   DWORD wcomputername_length = MAX_COMPUTERNAME_LENGTH + 1;
1296   dbus_bool_t local_computer;
1297   wchar_t *dc = NULL;
1298   NET_API_STATUS ret = 0;
1299
1300   /* If the domain is this computer's name, assume it's a local user.
1301    * Otherwise look up a DC for the domain, and ask it.
1302    */
1303
1304   GetComputerNameW (wcomputername, &wcomputername_length);
1305   local_computer = (wcsicmp (wcomputername, wdomain) == 0);
1306
1307   if (!local_computer)
1308     {
1309       ret = NetGetAnyDCName (NULL, wdomain, (LPBYTE *) &dc);
1310       if (ret != NERR_Success)
1311         {
1312           info->homedir = _dbus_strdup ("\\");
1313           _dbus_warn("NetGetAnyDCName() failed with errorcode %d '%s'\n",ret,_dbus_lm_strerror(ret));
1314           return TRUE;
1315         }
1316     }
1317
1318   /* No way to find out the profile of another user, let's try the
1319    * "home directory" from NetUserGetInfo's USER_INFO_1.
1320    */
1321   ret = NetUserGetInfo (dc, wname, 1, (LPBYTE *) &user_info);
1322   if (ret == NERR_Success )
1323     if(user_info->usri1_home_dir != NULL &&
1324         user_info->usri1_home_dir != (LPWSTR)0xfeeefeee &&  /* freed memory http://www.gamedev.net/community/forums/topic.asp?topic_id=158402 */
1325         user_info->usri1_home_dir[0] != '\0')
1326       {
1327         info->homedir = _dbus_win_utf16_to_utf8 (user_info->usri1_home_dir, error);
1328         if (!info->homedir)
1329           goto out1;
1330       }
1331     else
1332       {
1333         _dbus_verbose("NetUserGetInfo() returned no home dir entry\n");
1334         /* Not set, so use something random. */
1335         info->homedir = _dbus_strdup ("\\");
1336       }
1337   else
1338     {
1339       char *dc_string = _dbus_win_utf16_to_utf8(dc,error);
1340           char *user_name = _dbus_win_utf16_to_utf8(wname,error);
1341       _dbus_warn("NetUserGetInfo() for user '%s' failed with errorcode %d '%s', %s\n",user_name, ret,_dbus_lm_strerror(ret),dc_string);
1342       dbus_free(user_name);
1343       dbus_free(dc_string);
1344       /* Not set, so use something random. */
1345       info->homedir = _dbus_strdup ("\\");
1346     }
1347
1348   retval = TRUE;
1349
1350 out1:
1351   if (dc != NULL)
1352     NetApiBufferFree (dc);
1353   if (user_info != NULL)
1354     NetApiBufferFree (user_info);
1355
1356   return retval;
1357 #endif //DBUS_WINCE
1358 }
1359
1360 dbus_bool_t
1361 fill_win_user_info_from_name (wchar_t      *wname,
1362                               DBusUserInfo *info,
1363                               DBusError    *error)
1364 {
1365 #ifdef DBUS_WINCE
1366         return TRUE;
1367         //TODO
1368 #else
1369   dbus_bool_t retval = FALSE;
1370   PSID sid;
1371   wchar_t *wdomain;
1372   DWORD sid_length, wdomain_length;
1373   SID_NAME_USE use;
1374
1375   sid_length = 0;
1376   wdomain_length = 0;
1377   if (!LookupAccountNameW (NULL, wname, NULL, &sid_length,
1378                            NULL, &wdomain_length, &use) &&
1379       GetLastError () != ERROR_INSUFFICIENT_BUFFER)
1380     {
1381       _dbus_win_set_error_from_win_error (error, GetLastError ());
1382       return FALSE;
1383     }
1384
1385   sid = dbus_malloc (sid_length);
1386   if (!sid)
1387     {
1388       _DBUS_SET_OOM (error);
1389       return FALSE;
1390     }
1391
1392   wdomain = dbus_new (wchar_t, wdomain_length);
1393   if (!wdomain)
1394     {
1395       _DBUS_SET_OOM (error);
1396       goto out0;
1397     }
1398
1399   if (!LookupAccountNameW (NULL, wname, sid, &sid_length,
1400                            wdomain, &wdomain_length, &use))
1401     {
1402       _dbus_win_set_error_from_win_error (error, GetLastError ());
1403       goto out1;
1404     }
1405
1406   if (!IsValidSid (sid))
1407     {
1408       dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid SID");
1409       goto out1;
1410     }
1411
1412   info->uid = _dbus_win_sid_to_uid_t (sid);
1413
1414   if (!fill_win_user_info_name_and_groups (wname, wdomain, info, error))
1415     goto out1;
1416
1417   if (!fill_win_user_info_homedir (wname, wdomain, info, error))
1418     goto out1;
1419
1420   retval = TRUE;
1421
1422 out1:
1423   dbus_free (wdomain);
1424 out0:
1425   dbus_free (sid);
1426
1427   return retval;
1428 #endif //DBUS_WINCE
1429 }
1430
1431 dbus_bool_t
1432 _dbus_win_sid_to_name_and_domain (dbus_uid_t uid,
1433                                   wchar_t  **wname,
1434                                   wchar_t  **wdomain,
1435                                   DBusError *error)
1436 {
1437 #ifdef DBUS_WINCE
1438         return TRUE;
1439         //TODO
1440 #else
1441   PSID sid;
1442   DWORD wname_length, wdomain_length;
1443   SID_NAME_USE use;
1444
1445   if (!_dbus_uid_t_to_win_sid (uid, &sid))
1446     {
1447       _dbus_win_set_error_from_win_error (error, GetLastError ());
1448       return FALSE;
1449     }
1450
1451   wname_length = 0;
1452   wdomain_length = 0;
1453   if (!LookupAccountSidW (NULL, sid, NULL, &wname_length,
1454                           NULL, &wdomain_length, &use) &&
1455       GetLastError () != ERROR_INSUFFICIENT_BUFFER)
1456     {
1457       _dbus_win_set_error_from_win_error (error, GetLastError ());
1458       goto out0;
1459     }
1460
1461   *wname = dbus_new (wchar_t, wname_length);
1462   if (!*wname)
1463     {
1464       _DBUS_SET_OOM (error);
1465       goto out0;
1466     }
1467
1468   *wdomain = dbus_new (wchar_t, wdomain_length);
1469   if (!*wdomain)
1470     {
1471       _DBUS_SET_OOM (error);
1472       goto out1;
1473     }
1474
1475   if (!LookupAccountSidW (NULL, sid, *wname, &wname_length,
1476                           *wdomain, &wdomain_length, &use))
1477     {
1478       _dbus_win_set_error_from_win_error (error, GetLastError ());
1479       goto out2;
1480     }
1481
1482   return TRUE;
1483
1484 out2:
1485   dbus_free (*wdomain);
1486   *wdomain = NULL;
1487 out1:
1488   dbus_free (*wname);
1489   *wname = NULL;
1490 out0:
1491   LocalFree (sid);
1492
1493   return FALSE;
1494 #endif //DBUS_WINCE
1495 }
1496
1497 dbus_bool_t
1498 fill_win_user_info_from_uid (dbus_uid_t    uid,
1499                              DBusUserInfo *info,
1500                              DBusError    *error)
1501 {
1502 #ifdef DBUS_WINCE
1503         return TRUE;
1504         //TODO
1505 #else
1506   PSID sid;
1507   dbus_bool_t retval = FALSE;
1508   wchar_t *wname, *wdomain;
1509
1510   info->uid = uid;
1511
1512   if (!_dbus_win_sid_to_name_and_domain (uid, &wname, &wdomain, error))
1513     {
1514       _dbus_verbose("%s after _dbus_win_sid_to_name_and_domain\n",__FUNCTION__);
1515       return FALSE;
1516     }
1517
1518   if (!fill_win_user_info_name_and_groups (wname, wdomain, info, error))
1519     {
1520       _dbus_verbose("%s after fill_win_user_info_name_and_groups\n",__FUNCTION__);
1521       goto out0;
1522     }
1523
1524
1525   if (!fill_win_user_info_homedir (wname, wdomain, info, error))
1526     {
1527       _dbus_verbose("%s after fill_win_user_info_homedir\n",__FUNCTION__);
1528       goto out0;
1529     }
1530
1531   retval = TRUE;
1532
1533 out0:
1534   dbus_free (wdomain);
1535   dbus_free (wname);
1536
1537   return retval;
1538 #endif //DBUS_WINCE
1539 }
1540
1541
1542
1543
1544 void
1545 _dbus_win_startup_winsock (void)
1546 {
1547   /* Straight from MSDN, deuglified */
1548
1549   static dbus_bool_t beenhere = FALSE;
1550
1551   WORD wVersionRequested;
1552   WSADATA wsaData;
1553   int err;
1554
1555   if (beenhere)
1556     return;
1557
1558   wVersionRequested = MAKEWORD (2, 0);
1559
1560   err = WSAStartup (wVersionRequested, &wsaData);
1561   if (err != 0)
1562     {
1563       _dbus_assert_not_reached ("Could not initialize WinSock");
1564       _dbus_abort ();
1565     }
1566
1567   /* Confirm that the WinSock DLL supports 2.0.  Note that if the DLL
1568    * supports versions greater than 2.0 in addition to 2.0, it will
1569    * still return 2.0 in wVersion since that is the version we
1570    * requested.
1571    */
1572   if (LOBYTE (wsaData.wVersion) != 2 ||
1573       HIBYTE (wsaData.wVersion) != 0)
1574     {
1575       _dbus_assert_not_reached ("No usable WinSock found");
1576       _dbus_abort ();
1577     }
1578
1579   beenhere = TRUE;
1580 }
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590 /************************************************************************
1591  
1592  UTF / string code
1593  
1594  ************************************************************************/
1595
1596 /**
1597  * Measure the message length without terminating nul 
1598  */
1599 int _dbus_printf_string_upper_bound (const char *format,
1600                                      va_list args)
1601 {
1602   /* MSVCRT's vsnprintf semantics are a bit different */
1603   /* The C library source in the Platform SDK indicates that this
1604    * would work, but alas, it doesn't. At least not on Windows
1605    * 2000. Presumably those sources correspond to the C library on
1606    * some newer or even future Windows version.
1607    *
1608     len = _vsnprintf (NULL, _DBUS_INT_MAX, format, args);
1609    */
1610   char p[1024];
1611   int len;
1612   len = vsnprintf (p, sizeof(p)-1, format, args);
1613   if (len == -1) // try again
1614     {
1615       char *p;
1616       p = malloc (strlen(format)*3);
1617       len = vsnprintf (p, sizeof(p)-1, format, args);
1618       free(p);
1619     }
1620   return len;
1621 }
1622
1623
1624 /**
1625  * Returns the UTF-16 form of a UTF-8 string. The result should be
1626  * freed with dbus_free() when no longer needed.
1627  *
1628  * @param str the UTF-8 string
1629  * @param error return location for error code
1630  */
1631 wchar_t *
1632 _dbus_win_utf8_to_utf16 (const char *str,
1633                          DBusError  *error)
1634 {
1635   DBusString s;
1636   int n;
1637   wchar_t *retval;
1638
1639   _dbus_string_init_const (&s, str);
1640
1641   if (!_dbus_string_validate_utf8 (&s, 0, _dbus_string_get_length (&s)))
1642     {
1643       dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid UTF-8");
1644       return NULL;
1645     }
1646
1647   n = MultiByteToWideChar (CP_UTF8, 0, str, -1, NULL, 0);
1648
1649   if (n == 0)
1650     {
1651       _dbus_win_set_error_from_win_error (error, GetLastError ());
1652       return NULL;
1653     }
1654
1655   retval = dbus_new (wchar_t, n);
1656
1657   if (!retval)
1658     {
1659       _DBUS_SET_OOM (error);
1660       return NULL;
1661     }
1662
1663   if (MultiByteToWideChar (CP_UTF8, 0, str, -1, retval, n) != n)
1664     {
1665       dbus_free (retval);
1666       dbus_set_error_const (error, DBUS_ERROR_FAILED, "MultiByteToWideChar inconsistency");
1667       return NULL;
1668     }
1669
1670   return retval;
1671 }
1672
1673 /**
1674  * Returns the UTF-8 form of a UTF-16 string. The result should be
1675  * freed with dbus_free() when no longer needed.
1676  *
1677  * @param str the UTF-16 string
1678  * @param error return location for error code
1679  */
1680 char *
1681 _dbus_win_utf16_to_utf8 (const wchar_t *str,
1682                          DBusError     *error)
1683 {
1684   int n;
1685   char *retval;
1686
1687   n = WideCharToMultiByte (CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
1688
1689   if (n == 0)
1690     {
1691       _dbus_win_set_error_from_win_error (error, GetLastError ());
1692       return NULL;
1693     }
1694
1695   retval = dbus_malloc (n);
1696
1697   if (!retval)
1698     {
1699       _DBUS_SET_OOM (error);
1700       return NULL;
1701     }
1702
1703   if (WideCharToMultiByte (CP_UTF8, 0, str, -1, retval, n, NULL, NULL) != n)
1704     {
1705       dbus_free (retval);
1706       dbus_set_error_const (error, DBUS_ERROR_FAILED, "WideCharToMultiByte inconsistency");
1707       return NULL;
1708     }
1709
1710   return retval;
1711 }
1712
1713
1714
1715
1716
1717
1718 /************************************************************************
1719  
1720  uid ... <-> win sid functions
1721  
1722  ************************************************************************/
1723
1724 dbus_bool_t
1725 _dbus_win_account_to_sid (const wchar_t *waccount,
1726                           void           **ppsid,
1727                           DBusError       *error)
1728 {
1729   dbus_bool_t retval = FALSE;
1730   DWORD sid_length, wdomain_length;
1731   SID_NAME_USE use;
1732   wchar_t *wdomain;
1733
1734   *ppsid = NULL;
1735
1736   sid_length = 0;
1737   wdomain_length = 0;
1738   if (!LookupAccountNameW (NULL, waccount, NULL, &sid_length,
1739                            NULL, &wdomain_length, &use) &&
1740       GetLastError () != ERROR_INSUFFICIENT_BUFFER)
1741     {
1742       _dbus_win_set_error_from_win_error (error, GetLastError ());
1743       return FALSE;
1744     }
1745
1746   *ppsid = dbus_malloc (sid_length);
1747   if (!*ppsid)
1748     {
1749       _DBUS_SET_OOM (error);
1750       return FALSE;
1751     }
1752
1753   wdomain = dbus_new (wchar_t, wdomain_length);
1754   if (!wdomain)
1755     {
1756       _DBUS_SET_OOM (error);
1757       goto out1;
1758     }
1759
1760   if (!LookupAccountNameW (NULL, waccount, (PSID) *ppsid, &sid_length,
1761                            wdomain, &wdomain_length, &use))
1762     {
1763       _dbus_win_set_error_from_win_error (error, GetLastError ());
1764       goto out2;
1765     }
1766
1767   if (!IsValidSid ((PSID) *ppsid))
1768     {
1769       dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid SID");
1770       goto out2;
1771     }
1772
1773   retval = TRUE;
1774
1775 out2:
1776   dbus_free (wdomain);
1777 out1:
1778   if (!retval)
1779     {
1780       dbus_free (*ppsid);
1781       *ppsid = NULL;
1782     }
1783
1784   return retval;
1785 }
1786
1787 static void
1788 _sid_atom_cache_shutdown (void *unused)
1789 {
1790   DBusHashIter iter;
1791   _DBUS_LOCK (sid_atom_cache);
1792   _dbus_hash_iter_init (sid_atom_cache, &iter);
1793   while (_dbus_hash_iter_next (&iter))
1794     {
1795       ATOM atom;
1796       atom = (ATOM) _dbus_hash_iter_get_value (&iter);
1797       GlobalDeleteAtom(atom);
1798       _dbus_hash_iter_remove_entry(&iter);
1799     }
1800   _DBUS_UNLOCK (sid_atom_cache);
1801   _dbus_hash_table_unref (sid_atom_cache);
1802   sid_atom_cache = NULL;
1803 }
1804
1805 /**
1806  * Returns the 2-way associated dbus_uid_t form a SID.
1807  *
1808  * @param psid pointer to the SID
1809  */
1810 dbus_uid_t
1811 _dbus_win_sid_to_uid_t (PSID psid)
1812 {
1813   dbus_uid_t uid;
1814   dbus_uid_t olduid;
1815   char *string;
1816   ATOM atom;
1817
1818   if (!IsValidSid (psid))
1819     {
1820       _dbus_verbose("%s invalid sid\n",__FUNCTION__);
1821       return DBUS_UID_UNSET;
1822     }
1823   if (!ConvertSidToStringSidA (psid, &string))
1824     {
1825       _dbus_verbose("%s invalid sid\n",__FUNCTION__);
1826       return DBUS_UID_UNSET;
1827     }
1828
1829   atom = GlobalAddAtom(string);
1830
1831   if (atom == 0)
1832     {
1833       _dbus_verbose("%s GlobalAddAtom failed\n",__FUNCTION__);
1834       LocalFree (string);
1835       return DBUS_UID_UNSET;
1836     }
1837
1838   _DBUS_LOCK (sid_atom_cache);
1839
1840   if (sid_atom_cache == NULL)
1841     {
1842       sid_atom_cache = _dbus_hash_table_new (DBUS_HASH_ULONG, NULL, NULL);
1843       _dbus_register_shutdown_func (_sid_atom_cache_shutdown, NULL);
1844     }
1845
1846   uid = atom;
1847   olduid = (dbus_uid_t) _dbus_hash_table_lookup_ulong (sid_atom_cache, uid);
1848
1849   if (olduid)
1850     {
1851       _dbus_verbose("%s sid with id %i found in cache\n",__FUNCTION__, olduid);
1852       uid = olduid;
1853     }
1854   else
1855     {
1856       _dbus_hash_table_insert_ulong (sid_atom_cache, uid, (void*) uid);
1857       _dbus_verbose("%s sid %s added with uid %i to cache\n",__FUNCTION__, string, uid);
1858     }
1859
1860   _DBUS_UNLOCK (sid_atom_cache);
1861
1862   return uid;
1863 }
1864
1865 dbus_bool_t  _dbus_uid_t_to_win_sid (dbus_uid_t uid, PSID *ppsid)
1866 {
1867   void* atom;
1868   char string[255];
1869
1870   atom = _dbus_hash_table_lookup_ulong (sid_atom_cache, uid);
1871   if (atom == NULL)
1872     {
1873       _dbus_verbose("%s uid %i not found in cache\n",__FUNCTION__,uid);
1874       return FALSE;
1875     }
1876   memset( string, '.', sizeof(string) );
1877   if (!GlobalGetAtomNameA( (ATOM) atom, string, 255 ))
1878     {
1879       _dbus_verbose("%s uid %i not found in cache\n",__FUNCTION__, uid);
1880       return FALSE;
1881     }
1882   if (!ConvertStringSidToSidA(string, ppsid))
1883     {
1884       _dbus_verbose("%s could not convert %s into sid \n",__FUNCTION__, string);
1885       return FALSE;
1886     }
1887   _dbus_verbose("%s converted %s into sid \n",__FUNCTION__, string);
1888   return TRUE;
1889 }
1890
1891
1892 /** @} end of sysdeps-win */
1893
1894
1895 /** Gets our UID
1896  * @returns process UID
1897  */
1898 dbus_uid_t
1899 _dbus_getuid(void)
1900 {
1901   dbus_uid_t retval = DBUS_UID_UNSET;
1902   HANDLE process_token = NULL;
1903   TOKEN_USER *token_user = NULL;
1904   DWORD n;
1905
1906   if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &process_token))
1907     _dbus_win_warn_win_error ("OpenProcessToken failed", GetLastError ());
1908   else if ((!GetTokenInformation (process_token, TokenUser, NULL, 0, &n)
1909             && GetLastError () != ERROR_INSUFFICIENT_BUFFER)
1910            || (token_user = alloca (n)) == NULL
1911            || !GetTokenInformation (process_token, TokenUser, token_user, n, &n))
1912     _dbus_win_warn_win_error ("GetTokenInformation failed", GetLastError ());
1913   else
1914     retval = _dbus_win_sid_to_uid_t (token_user->User.Sid);
1915
1916   if (process_token != NULL)
1917     CloseHandle (process_token);
1918
1919   _dbus_verbose("_dbus_getuid() returns %d\n",retval);
1920   return retval;
1921 }
1922
1923 #ifdef DBUS_BUILD_TESTS
1924 /** Gets our GID
1925  * @returns process GID
1926  */
1927 dbus_gid_t
1928 _dbus_getgid (void)
1929 {
1930   dbus_gid_t retval = DBUS_GID_UNSET;
1931   HANDLE process_token = NULL;
1932   TOKEN_PRIMARY_GROUP *token_primary_group = NULL;
1933   DWORD n;
1934
1935   if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &process_token))
1936     _dbus_win_warn_win_error ("OpenProcessToken failed", GetLastError ());
1937   else if ((!GetTokenInformation (process_token, TokenPrimaryGroup,
1938                                   NULL, 0, &n) &&
1939             GetLastError () != ERROR_INSUFFICIENT_BUFFER) ||
1940            (token_primary_group = alloca (n)) == NULL ||
1941            !GetTokenInformation (process_token, TokenPrimaryGroup,
1942                                  token_primary_group, n, &n))
1943     _dbus_win_warn_win_error ("GetTokenInformation failed", GetLastError ());
1944   else
1945     retval = _dbus_win_sid_to_uid_t (token_primary_group->PrimaryGroup);
1946
1947   if (process_token != NULL)
1948     CloseHandle (process_token);
1949
1950   return retval;
1951 }
1952
1953 #if 0
1954 dbus_bool_t
1955 _dbus_domain_test (const char *test_data_dir)
1956 {
1957   if (!_dbus_test_oom_handling ("spawn_nonexistent",
1958                                 check_spawn_nonexistent,
1959                                 NULL))
1960     return FALSE;
1961 }
1962
1963 #endif
1964
1965 #endif //DBUS_BUILD_TESTS
1966
1967 /************************************************************************
1968  
1969  pipes
1970  
1971  ************************************************************************/
1972
1973 /**
1974  * Creates a full-duplex pipe (as in socketpair()).
1975  * Sets both ends of the pipe nonblocking.
1976  *
1977  * @todo libdbus only uses this for the debug-pipe server, so in
1978  * principle it could be in dbus-sysdeps-util.c, except that
1979  * dbus-sysdeps-util.c isn't in libdbus when tests are enabled and the
1980  * debug-pipe server is used.
1981  * 
1982  * @param fd1 return location for one end
1983  * @param fd2 return location for the other end
1984  * @param blocking #TRUE if pipe should be blocking
1985  * @param error error return
1986  * @returns #FALSE on failure (if error is set)
1987  */
1988 dbus_bool_t
1989 _dbus_full_duplex_pipe (int        *fd1,
1990                         int        *fd2,
1991                         dbus_bool_t blocking,
1992                         DBusError  *error)
1993 {
1994   SOCKET temp, socket1 = -1, socket2 = -1;
1995   struct sockaddr_in saddr;
1996   int len;
1997   u_long arg;
1998   fd_set read_set, write_set;
1999   struct timeval tv;
2000   DBusSocket sock;
2001
2002
2003   _dbus_win_startup_winsock ();
2004
2005   temp = socket (AF_INET, SOCK_STREAM, 0);
2006   if (temp == INVALID_SOCKET)
2007     {
2008       DBUS_SOCKET_SET_ERRNO ();
2009       goto out0;
2010     }
2011
2012   arg = 1;
2013   if (ioctlsocket (temp, FIONBIO, &arg) == SOCKET_ERROR)
2014     {
2015       DBUS_SOCKET_SET_ERRNO ();
2016       goto out0;
2017     }
2018
2019   _DBUS_ZERO (saddr);
2020   saddr.sin_family = AF_INET;
2021   saddr.sin_port = 0;
2022   saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
2023
2024   if (bind (temp, (struct sockaddr *)&saddr, sizeof (saddr)))
2025     {
2026       DBUS_SOCKET_SET_ERRNO ();
2027       goto out0;
2028     }
2029
2030   if (listen (temp, 1) == SOCKET_ERROR)
2031     {
2032       DBUS_SOCKET_SET_ERRNO ();
2033       goto out0;
2034     }
2035
2036   len = sizeof (saddr);
2037   if (getsockname (temp, (struct sockaddr *)&saddr, &len))
2038     {
2039       DBUS_SOCKET_SET_ERRNO ();
2040       goto out0;
2041     }
2042
2043   socket1 = socket (AF_INET, SOCK_STREAM, 0);
2044   if (socket1 == INVALID_SOCKET)
2045     {
2046       DBUS_SOCKET_SET_ERRNO ();
2047       goto out0;
2048     }
2049
2050   arg = 1;
2051   if (ioctlsocket (socket1, FIONBIO, &arg) == SOCKET_ERROR)
2052     {
2053       DBUS_SOCKET_SET_ERRNO ();
2054       goto out1;
2055     }
2056
2057   if (connect (socket1, (struct sockaddr  *)&saddr, len) != SOCKET_ERROR ||
2058       WSAGetLastError () != WSAEWOULDBLOCK)
2059     {
2060       dbus_set_error_const (error, DBUS_ERROR_FAILED,
2061                             "_dbus_full_duplex_pipe socketpair() emulation failed");
2062       goto out1;
2063     }
2064
2065   FD_ZERO (&read_set);
2066   FD_SET (temp, &read_set);
2067
2068   tv.tv_sec = 0;
2069   tv.tv_usec = 0;
2070
2071   if (select (0, &read_set, NULL, NULL, NULL) == SOCKET_ERROR)
2072     {
2073       DBUS_SOCKET_SET_ERRNO ();
2074       goto out1;
2075     }
2076
2077   _dbus_assert (FD_ISSET (temp, &read_set));
2078
2079   socket2 = accept (temp, (struct sockaddr *) &saddr, &len);
2080   if (socket2 == INVALID_SOCKET)
2081     {
2082       DBUS_SOCKET_SET_ERRNO ();
2083       goto out1;
2084     }
2085
2086   FD_ZERO (&write_set);
2087   FD_SET (socket1, &write_set);
2088
2089   tv.tv_sec = 0;
2090   tv.tv_usec = 0;
2091
2092   if (select (0, NULL, &write_set, NULL, NULL) == SOCKET_ERROR)
2093     {
2094       DBUS_SOCKET_SET_ERRNO ();
2095       goto out2;
2096     }
2097
2098   _dbus_assert (FD_ISSET (socket1, &write_set));
2099
2100   if (blocking)
2101     {
2102       arg = 0;
2103       if (ioctlsocket (socket1, FIONBIO, &arg) == SOCKET_ERROR)
2104         {
2105           DBUS_SOCKET_SET_ERRNO ();
2106           goto out2;
2107         }
2108
2109       arg = 0;
2110       if (ioctlsocket (socket2, FIONBIO, &arg) == SOCKET_ERROR)
2111         {
2112           DBUS_SOCKET_SET_ERRNO ();
2113           goto out2;
2114         }
2115     }
2116   else
2117     {
2118       arg = 1;
2119       if (ioctlsocket (socket2, FIONBIO, &arg) == SOCKET_ERROR)
2120         {
2121           DBUS_SOCKET_SET_ERRNO ();
2122           goto out2;
2123         }
2124     }
2125
2126   sock.fd = socket1;
2127   *fd1 = _dbus_socket_to_handle (&sock);
2128   sock.fd = socket2;
2129   *fd2 = _dbus_socket_to_handle (&sock);
2130
2131   _dbus_verbose ("full-duplex pipe %d:%d <-> %d:%d\n",
2132                  *fd1, socket1, *fd2, socket2);
2133
2134   closesocket (temp);
2135
2136   return TRUE;
2137
2138 out2:
2139   closesocket (socket2);
2140 out1:
2141   closesocket (socket1);
2142 out0:
2143   closesocket (temp);
2144
2145   dbus_set_error (error, _dbus_error_from_errno (errno),
2146                   "Could not setup socket pair: %s",
2147                   _dbus_strerror (errno));
2148
2149   return FALSE;
2150 }
2151
2152 /**
2153  * Wrapper for poll().
2154  *
2155  * @param fds the file descriptors to poll
2156  * @param n_fds number of descriptors in the array
2157  * @param timeout_milliseconds timeout or -1 for infinite
2158  * @returns numbers of fds with revents, or <0 on error
2159  */
2160 #define USE_CHRIS_IMPL 0
2161 #if USE_CHRIS_IMPL
2162 int
2163 _dbus_poll (DBusPollFD *fds,
2164             int         n_fds,
2165             int         timeout_milliseconds)
2166 {
2167 #define DBUS_POLL_CHAR_BUFFER_SIZE 2000
2168   char msg[DBUS_POLL_CHAR_BUFFER_SIZE];
2169   char *msgp;
2170
2171   int ret = 0;
2172   int i;
2173   struct timeval tv;
2174   int ready;
2175
2176 #define DBUS_STACK_WSAEVENTS 256
2177   WSAEVENT eventsOnStack[DBUS_STACK_WSAEVENTS];
2178   WSAEVENT *pEvents = NULL;
2179   if (n_fds > DBUS_STACK_WSAEVENTS)
2180     pEvents = calloc(sizeof(WSAEVENT), n_fds);
2181   else
2182     pEvents = eventsOnStack;
2183
2184   _dbus_lock_sockets();
2185
2186 #ifdef DBUS_ENABLE_VERBOSE_MODE
2187   msgp = msg;
2188   msgp += sprintf (msgp, "WSAEventSelect: to=%d\n\t", timeout_milliseconds);
2189   for (i = 0; i < n_fds; i++)
2190     {
2191       static dbus_bool_t warned = FALSE;
2192       DBusSocket *s;
2193       DBusPollFD *fdp = &fds[i];
2194
2195       _dbus_handle_to_socket_unlocked(fdp->fd, &s);  
2196
2197       if (s->is_used == 0)
2198         {
2199           _dbus_warn ("no valid socket");
2200           warned = TRUE;
2201         }
2202
2203       if (fdp->events & _DBUS_POLLIN)
2204         msgp += sprintf (msgp, "R:%d ", s->fd);
2205
2206       if (fdp->events & _DBUS_POLLOUT)
2207         msgp += sprintf (msgp, "W:%d ", s->fd);
2208
2209       msgp += sprintf (msgp, "E:%d\n\t", s->fd);
2210
2211       // FIXME: more robust code for long  msg
2212       //        create on heap when msg[] becomes too small
2213       if (msgp >= msg + DBUS_POLL_CHAR_BUFFER_SIZE)
2214         {
2215           _dbus_assert_not_reached ("buffer overflow in _dbus_poll");
2216         }
2217     }
2218
2219   msgp += sprintf (msgp, "\n");
2220   _dbus_verbose ("%s",msg);
2221 #endif
2222   for (i = 0; i < n_fds; i++)
2223     {
2224       DBusSocket *s;
2225       DBusPollFD *fdp = &fds[i];
2226       WSAEVENT ev;
2227       long lNetworkEvents = FD_OOB;
2228
2229       _dbus_handle_to_socket_unlocked(fdp->fd, &s); 
2230
2231       if (s->is_used == 0)
2232         continue;
2233
2234       ev = WSACreateEvent();
2235
2236       if (fdp->events & _DBUS_POLLIN)
2237         lNetworkEvents |= FD_READ | FD_ACCEPT | FD_CLOSE;
2238
2239       if (fdp->events & _DBUS_POLLOUT)
2240         lNetworkEvents |= FD_WRITE | FD_CONNECT;
2241
2242       WSAEventSelect(s->fd, ev, lNetworkEvents);
2243
2244       pEvents[i] = ev;
2245     }
2246
2247   _dbus_unlock_sockets();
2248
2249   ready = WSAWaitForMultipleEvents (n_fds, pEvents, FALSE, timeout_milliseconds, FALSE);
2250
2251   if (DBUS_SOCKET_API_RETURNS_ERROR (ready))
2252     {
2253       DBUS_SOCKET_SET_ERRNO ();
2254       if (errno != EWOULDBLOCK)
2255         _dbus_verbose ("WSAWaitForMultipleEvents: failed: %s\n", _dbus_strerror (errno));
2256       ret = -1;
2257     }
2258   else if (ready == WSA_WAIT_TIMEOUT)
2259     {
2260       _dbus_verbose ("WSAWaitForMultipleEvents: WSA_WAIT_TIMEOUT\n");
2261       ret = 0;
2262     }
2263   else if (ready >= WSA_WAIT_EVENT_0 && ready < (int)(WSA_WAIT_EVENT_0 + n_fds))
2264     {
2265       msgp = msg;
2266       msgp += sprintf (msgp, "WSAWaitForMultipleEvents: =%d\n\t", ready);
2267
2268       _dbus_lock_sockets();
2269       for (i = 0; i < n_fds; i++)
2270         {
2271           DBusSocket *s;
2272           DBusPollFD *fdp = &fds[i];
2273           WSANETWORKEVENTS ne;
2274
2275           _dbus_handle_to_socket_unlocked(fdp->fd, &s); 
2276
2277           fdp->revents = 0;
2278
2279           WSAEnumNetworkEvents(s->fd, pEvents[i], &ne);
2280
2281           if (ne.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
2282             fdp->revents |= _DBUS_POLLIN;
2283
2284           if (ne.lNetworkEvents & (FD_WRITE | FD_CONNECT))
2285             fdp->revents |= _DBUS_POLLOUT;
2286
2287           if (ne.lNetworkEvents & (FD_OOB))
2288             fdp->revents |= _DBUS_POLLERR;
2289
2290           if (ne.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
2291               msgp += sprintf (msgp, "R:%d ", s->fd);
2292
2293           if (ne.lNetworkEvents & (FD_WRITE | FD_CONNECT))
2294               msgp += sprintf (msgp, "W:%d ", s->fd);
2295
2296           if (ne.lNetworkEvents & (FD_OOB))
2297               msgp += sprintf (msgp, "E:%d ", s->fd);
2298
2299           msgp += sprintf (msgp, "lNetworkEvents:%d ", ne.lNetworkEvents);
2300
2301           if(ne.lNetworkEvents)
2302             ret++;
2303
2304           WSAEventSelect(s->fd, pEvents[i], 0);
2305         }
2306       _dbus_unlock_sockets();
2307
2308       msgp += sprintf (msgp, "\n");
2309       _dbus_verbose ("%s",msg);
2310     }
2311   else
2312     {
2313       _dbus_verbose ("WSAWaitForMultipleEvents: failed for unknown reason!");
2314       ret = -1;
2315     }
2316
2317   for(i = 0; i < n_fds; i++)
2318     {
2319       WSACloseEvent(pEvents[i]);
2320     }
2321
2322   if (n_fds > DBUS_STACK_WSAEVENTS)
2323     free(pEvents);
2324
2325   return ret;
2326 }
2327
2328 #else   // USE_CHRIS_IMPL
2329
2330 int
2331 _dbus_poll (DBusPollFD *fds,
2332             int         n_fds,
2333             int         timeout_milliseconds)
2334 {
2335 #define DBUS_POLL_CHAR_BUFFER_SIZE 2000
2336   char msg[DBUS_POLL_CHAR_BUFFER_SIZE];
2337   char *msgp;
2338
2339   fd_set read_set, write_set, err_set;
2340   int max_fd = 0;
2341   int i;
2342   struct timeval tv;
2343   int ready;
2344
2345   FD_ZERO (&read_set);
2346   FD_ZERO (&write_set);
2347   FD_ZERO (&err_set);
2348
2349   _dbus_lock_sockets();
2350
2351 #ifdef DBUS_ENABLE_VERBOSE_MODE
2352   msgp = msg;
2353   msgp += sprintf (msgp, "select: to=%d\n\t", timeout_milliseconds);
2354   for (i = 0; i < n_fds; i++)
2355     {
2356       static dbus_bool_t warned = FALSE;
2357       DBusSocket *s;
2358       DBusPollFD *fdp = &fds[i];
2359
2360       _dbus_handle_to_socket_unlocked(fdp->fd, &s);  
2361
2362       if (s->is_used == 0)
2363         {
2364           _dbus_warn ("no valid socket");
2365           warned = TRUE;
2366         }
2367
2368       if (fdp->events & _DBUS_POLLIN)
2369         msgp += sprintf (msgp, "R:%d ", s->fd);
2370
2371       if (fdp->events & _DBUS_POLLOUT)
2372         msgp += sprintf (msgp, "W:%d ", s->fd);
2373
2374       msgp += sprintf (msgp, "E:%d\n\t", s->fd);
2375
2376       // FIXME: more robust code for long  msg
2377       //        create on heap when msg[] becomes too small
2378       if (msgp >= msg + DBUS_POLL_CHAR_BUFFER_SIZE)
2379         {
2380           _dbus_assert_not_reached ("buffer overflow in _dbus_poll");
2381         }
2382     }
2383
2384   msgp += sprintf (msgp, "\n");
2385   _dbus_verbose ("%s",msg);
2386 #endif
2387   for (i = 0; i < n_fds; i++)
2388     {
2389       DBusSocket *s;
2390       DBusPollFD *fdp = &fds[i];
2391
2392       _dbus_handle_to_socket_unlocked(fdp->fd, &s); 
2393
2394       if (s->is_used != 1)
2395         continue;
2396
2397       if (fdp->events & _DBUS_POLLIN)
2398         FD_SET (s->fd, &read_set);
2399
2400       if (fdp->events & _DBUS_POLLOUT)
2401         FD_SET (s->fd, &write_set);
2402
2403       FD_SET (s->fd, &err_set);
2404
2405       max_fd = MAX (max_fd, s->fd);
2406     }
2407
2408   _dbus_unlock_sockets();
2409
2410   tv.tv_sec = timeout_milliseconds / 1000;
2411   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
2412
2413   ready = select (max_fd + 1, &read_set, &write_set, &err_set,
2414                   timeout_milliseconds < 0 ? NULL : &tv);
2415
2416   if (DBUS_SOCKET_API_RETURNS_ERROR (ready))
2417     {
2418       DBUS_SOCKET_SET_ERRNO ();
2419       if (errno != EWOULDBLOCK)
2420         _dbus_verbose ("select: failed: %s\n", _dbus_strerror (errno));
2421     }
2422   else if (ready == 0)
2423     _dbus_verbose ("select: = 0\n");
2424   else
2425     if (ready > 0)
2426       {
2427 #ifdef DBUS_ENABLE_VERBOSE_MODE
2428         msgp = msg;
2429         msgp += sprintf (msgp, "select: = %d:\n\t", ready);
2430         _dbus_lock_sockets();
2431         for (i = 0; i < n_fds; i++)
2432           {
2433             DBusSocket *s;
2434             DBusPollFD *fdp = &fds[i];
2435
2436             _dbus_handle_to_socket_unlocked(fdp->fd, &s); 
2437
2438             if (FD_ISSET (s->fd, &read_set))
2439               msgp += sprintf (msgp, "R:%d ", s->fd);
2440
2441             if (FD_ISSET (s->fd, &write_set))
2442               msgp += sprintf (msgp, "W:%d ", s->fd);
2443
2444             if (FD_ISSET (s->fd, &err_set))
2445               msgp += sprintf (msgp, "E:%d\n\t", s->fd);
2446           }
2447         msgp += sprintf (msgp, "\n");
2448         _dbus_verbose ("%s",msg);
2449 #endif
2450
2451         for (i = 0; i < n_fds; i++)
2452           {
2453             DBusSocket *s;
2454             DBusPollFD *fdp = &fds[i];
2455
2456             _dbus_handle_to_socket_unlocked(fdp->fd, &s); 
2457
2458             fdp->revents = 0;
2459
2460             if (FD_ISSET (s->fd, &read_set))
2461               fdp->revents |= _DBUS_POLLIN;
2462
2463             if (FD_ISSET (s->fd, &write_set))
2464               fdp->revents |= _DBUS_POLLOUT;
2465
2466             if (FD_ISSET (s->fd, &err_set))
2467               fdp->revents |= _DBUS_POLLERR;
2468           }
2469         _dbus_unlock_sockets();
2470       }
2471   return ready;
2472 }
2473 #endif  // USE_CHRIS_IMPL
2474
2475
2476 /************************************************************************
2477  
2478  error handling
2479  
2480  ************************************************************************/
2481
2482
2483 /**
2484  * Assigns an error name and message corresponding to a Win32 error
2485  * code to a DBusError. Does nothing if error is #NULL.
2486  *
2487  * @param error the error.
2488  * @param code the Win32 error code
2489  */
2490 void
2491 _dbus_win_set_error_from_win_error (DBusError *error,
2492                                     int        code)
2493 {
2494   char *msg;
2495
2496   /* As we want the English message, use the A API */
2497   FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
2498                   FORMAT_MESSAGE_IGNORE_INSERTS |
2499                   FORMAT_MESSAGE_FROM_SYSTEM,
2500                   NULL, code, MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US),
2501                   (LPTSTR) &msg, 0, NULL);
2502   if (msg)
2503     {
2504       char *msg_copy;
2505
2506       msg_copy = dbus_malloc (strlen (msg));
2507       strcpy (msg_copy, msg);
2508       LocalFree (msg);
2509
2510       dbus_set_error (error, "win32.error", "%s", msg_copy);
2511     }
2512   else
2513     dbus_set_error (error, "win32.error", "Unknown error code %d or FormatMessage failed", code);
2514 }
2515
2516 void
2517 _dbus_win_warn_win_error (const char *message,
2518                           int         code)
2519 {
2520   DBusError error;
2521
2522   dbus_error_init (&error);
2523   _dbus_win_set_error_from_win_error (&error, code);
2524   _dbus_warn ("%s: %s\n", message, error.message);
2525   dbus_error_free (&error);
2526 }
2527
2528 /**
2529  * A wrapper around strerror() because some platforms
2530  * may be lame and not have strerror().
2531  *
2532  * @param error_number errno.
2533  * @returns error description.
2534  */
2535 const char*
2536 _dbus_strerror (int error_number)
2537 {
2538 #ifdef DBUS_WINCE
2539   // TODO
2540   return "unknown";
2541 #else
2542   const char *msg;
2543
2544   switch (error_number)
2545     {
2546     case WSAEINTR:
2547       return "Interrupted function call";
2548     case WSAEACCES:
2549       return "Permission denied";
2550     case WSAEFAULT:
2551       return "Bad address";
2552     case WSAEINVAL:
2553       return "Invalid argument";
2554     case WSAEMFILE:
2555       return "Too many open files";
2556     case WSAEWOULDBLOCK:
2557       return "Resource temporarily unavailable";
2558     case WSAEINPROGRESS:
2559       return "Operation now in progress";
2560     case WSAEALREADY:
2561       return "Operation already in progress";
2562     case WSAENOTSOCK:
2563       return "Socket operation on nonsocket";
2564     case WSAEDESTADDRREQ:
2565       return "Destination address required";
2566     case WSAEMSGSIZE:
2567       return "Message too long";
2568     case WSAEPROTOTYPE:
2569       return "Protocol wrong type for socket";
2570     case WSAENOPROTOOPT:
2571       return "Bad protocol option";
2572     case WSAEPROTONOSUPPORT:
2573       return "Protocol not supported";
2574     case WSAESOCKTNOSUPPORT:
2575       return "Socket type not supported";
2576     case WSAEOPNOTSUPP:
2577       return "Operation not supported";
2578     case WSAEPFNOSUPPORT:
2579       return "Protocol family not supported";
2580     case WSAEAFNOSUPPORT:
2581       return "Address family not supported by protocol family";
2582     case WSAEADDRINUSE:
2583       return "Address already in use";
2584     case WSAEADDRNOTAVAIL:
2585       return "Cannot assign requested address";
2586     case WSAENETDOWN:
2587       return "Network is down";
2588     case WSAENETUNREACH:
2589       return "Network is unreachable";
2590     case WSAENETRESET:
2591       return "Network dropped connection on reset";
2592     case WSAECONNABORTED:
2593       return "Software caused connection abort";
2594     case WSAECONNRESET:
2595       return "Connection reset by peer";
2596     case WSAENOBUFS:
2597       return "No buffer space available";
2598     case WSAEISCONN:
2599       return "Socket is already connected";
2600     case WSAENOTCONN:
2601       return "Socket is not connected";
2602     case WSAESHUTDOWN:
2603       return "Cannot send after socket shutdown";
2604     case WSAETIMEDOUT:
2605       return "Connection timed out";
2606     case WSAECONNREFUSED:
2607       return "Connection refused";
2608     case WSAEHOSTDOWN:
2609       return "Host is down";
2610     case WSAEHOSTUNREACH:
2611       return "No route to host";
2612     case WSAEPROCLIM:
2613       return "Too many processes";
2614     case WSAEDISCON:
2615       return "Graceful shutdown in progress";
2616     case WSATYPE_NOT_FOUND:
2617       return "Class type not found";
2618     case WSAHOST_NOT_FOUND:
2619       return "Host not found";
2620     case WSATRY_AGAIN:
2621       return "Nonauthoritative host not found";
2622     case WSANO_RECOVERY:
2623       return "This is a nonrecoverable error";
2624     case WSANO_DATA:
2625       return "Valid name, no data record of requested type";
2626     case WSA_INVALID_HANDLE:
2627       return "Specified event object handle is invalid";
2628     case WSA_INVALID_PARAMETER:
2629       return "One or more parameters are invalid";
2630     case WSA_IO_INCOMPLETE:
2631       return "Overlapped I/O event object not in signaled state";
2632     case WSA_IO_PENDING:
2633       return "Overlapped operations will complete later";
2634     case WSA_NOT_ENOUGH_MEMORY:
2635       return "Insufficient memory available";
2636     case WSA_OPERATION_ABORTED:
2637       return "Overlapped operation aborted";
2638 #ifdef WSAINVALIDPROCTABLE
2639
2640     case WSAINVALIDPROCTABLE:
2641       return "Invalid procedure table from service provider";
2642 #endif
2643 #ifdef WSAINVALIDPROVIDER
2644
2645     case WSAINVALIDPROVIDER:
2646       return "Invalid service provider version number";
2647 #endif
2648 #ifdef WSAPROVIDERFAILEDINIT
2649
2650     case WSAPROVIDERFAILEDINIT:
2651       return "Unable to initialize a service provider";
2652 #endif
2653
2654     case WSASYSCALLFAILURE:
2655       return "System call failure";
2656     }
2657   msg = strerror (error_number);
2658   if (msg == NULL)
2659     msg = "unknown";
2660
2661   return msg;
2662 #endif //DBUS_WINCE
2663 }
2664
2665
2666
2667 /* lan manager error codes */
2668 const char*
2669 _dbus_lm_strerror(int error_number)
2670 {
2671 #ifdef DBUS_WINCE
2672   // TODO
2673   return "unknown";
2674 #else
2675   const char *msg;
2676   switch (error_number)
2677     {
2678     case NERR_NetNotStarted:
2679       return "The workstation driver is not installed.";
2680     case NERR_UnknownServer:
2681       return "The server could not be located.";
2682     case NERR_ShareMem:
2683       return "An internal error occurred. The network cannot access a shared memory segment.";
2684     case NERR_NoNetworkResource:
2685       return "A network resource shortage occurred.";
2686     case NERR_RemoteOnly:
2687       return "This operation is not supported on workstations.";
2688     case NERR_DevNotRedirected:
2689       return "The device is not connected.";
2690     case NERR_ServerNotStarted:
2691       return "The Server service is not started.";
2692     case NERR_ItemNotFound:
2693       return "The queue is empty.";
2694     case NERR_UnknownDevDir:
2695       return "The device or directory does not exist.";
2696     case NERR_RedirectedPath:
2697       return "The operation is invalid on a redirected resource.";
2698     case NERR_DuplicateShare:
2699       return "The name has already been shared.";
2700     case NERR_NoRoom:
2701       return "The server is currently out of the requested resource.";
2702     case NERR_TooManyItems:
2703       return "Requested addition of items exceeds the maximum allowed.";
2704     case NERR_InvalidMaxUsers:
2705       return "The Peer service supports only two simultaneous users.";
2706     case NERR_BufTooSmall:
2707       return "The API return buffer is too small.";
2708     case NERR_RemoteErr:
2709       return "A remote API error occurred.";
2710     case NERR_LanmanIniError:
2711       return "An error occurred when opening or reading the configuration file.";
2712     case NERR_NetworkError:
2713       return "A general network error occurred.";
2714     case NERR_WkstaInconsistentState:
2715       return "The Workstation service is in an inconsistent state. Restart the computer before restarting the Workstation service.";
2716     case NERR_WkstaNotStarted:
2717       return "The Workstation service has not been started.";
2718     case NERR_BrowserNotStarted:
2719       return "The requested information is not available.";
2720     case NERR_InternalError:
2721       return "An internal error occurred.";
2722     case NERR_BadTransactConfig:
2723       return "The server is not configured for transactions.";
2724     case NERR_InvalidAPI:
2725       return "The requested API is not supported on the remote server.";
2726     case NERR_BadEventName:
2727       return "The event name is invalid.";
2728     case NERR_DupNameReboot:
2729       return "The computer name already exists on the network. Change it and restart the computer.";
2730     case NERR_CfgCompNotFound:
2731       return "The specified component could not be found in the configuration information.";
2732     case NERR_CfgParamNotFound:
2733       return "The specified parameter could not be found in the configuration information.";
2734     case NERR_LineTooLong:
2735       return "A line in the configuration file is too long.";
2736     case NERR_QNotFound:
2737       return "The printer does not exist.";
2738     case NERR_JobNotFound:
2739       return "The print job does not exist.";
2740     case NERR_DestNotFound:
2741       return "The printer destination cannot be found.";
2742     case NERR_DestExists:
2743       return "The printer destination already exists.";
2744     case NERR_QExists:
2745       return "The printer queue already exists.";
2746     case NERR_QNoRoom:
2747       return "No more printers can be added.";
2748     case NERR_JobNoRoom:
2749       return "No more print jobs can be added.";
2750     case NERR_DestNoRoom:
2751       return "No more printer destinations can be added.";
2752     case NERR_DestIdle:
2753       return "This printer destination is idle and cannot accept control operations.";
2754     case NERR_DestInvalidOp:
2755       return "This printer destination request contains an invalid control function.";
2756     case NERR_ProcNoRespond:
2757       return "The print processor is not responding.";
2758     case NERR_SpoolerNotLoaded:
2759       return "The spooler is not running.";
2760     case NERR_DestInvalidState:
2761       return "This operation cannot be performed on the print destination in its current state.";
2762     case NERR_QInvalidState:
2763       return "This operation cannot be performed on the printer queue in its current state.";
2764     case NERR_JobInvalidState:
2765       return "This operation cannot be performed on the print job in its current state.";
2766     case NERR_SpoolNoMemory:
2767       return "A spooler memory allocation failure occurred.";
2768     case NERR_DriverNotFound:
2769       return "The device driver does not exist.";
2770     case NERR_DataTypeInvalid:
2771       return "The data type is not supported by the print processor.";
2772     case NERR_ProcNotFound:
2773       return "The print processor is not installed.";
2774     case NERR_ServiceTableLocked:
2775       return "The service database is locked.";
2776     case NERR_ServiceTableFull:
2777       return "The service table is full.";
2778     case NERR_ServiceInstalled:
2779       return "The requested service has already been started.";
2780     case NERR_ServiceEntryLocked:
2781       return "The service does not respond to control actions.";
2782     case NERR_ServiceNotInstalled:
2783       return "The service has not been started.";
2784     case NERR_BadServiceName:
2785       return "The service name is invalid.";
2786     case NERR_ServiceCtlTimeout:
2787       return "The service is not responding to the control function.";
2788     case NERR_ServiceCtlBusy:
2789       return "The service control is busy.";
2790     case NERR_BadServiceProgName:
2791       return "The configuration file contains an invalid service program name.";
2792     case NERR_ServiceNotCtrl:
2793       return "The service could not be controlled in its present state.";
2794     case NERR_ServiceKillProc:
2795       return "The service ended abnormally.";
2796     case NERR_ServiceCtlNotValid:
2797       return "The requested pause or stop is not valid for this service.";
2798     case NERR_NotInDispatchTbl:
2799       return "The service control dispatcher could not find the service name in the dispatch table.";
2800     case NERR_BadControlRecv:
2801       return "The service control dispatcher pipe read failed.";
2802     case NERR_ServiceNotStarting:
2803       return "A thread for the new service could not be created.";
2804     case NERR_AlreadyLoggedOn:
2805       return "This workstation is already logged on to the local-area network.";
2806     case NERR_NotLoggedOn:
2807       return "The workstation is not logged on to the local-area network.";
2808     case NERR_BadUsername:
2809       return "The user name or group name parameter is invalid.";
2810     case NERR_BadPassword:
2811       return "The password parameter is invalid.";
2812     case NERR_UnableToAddName_W:
2813       return "@W The logon processor did not add the message alias.";
2814     case NERR_UnableToAddName_F:
2815       return "The logon processor did not add the message alias.";
2816     case NERR_UnableToDelName_W:
2817       return "@W The logoff processor did not delete the message alias.";
2818     case NERR_UnableToDelName_F:
2819       return "The logoff processor did not delete the message alias.";
2820     case NERR_LogonsPaused:
2821       return "Network logons are paused.";
2822     case NERR_LogonServerConflict:
2823       return "A centralized logon-server conflict occurred.";
2824     case NERR_LogonNoUserPath:
2825       return "The server is configured without a valid user path.";
2826     case NERR_LogonScriptError:
2827       return "An error occurred while loading or running the logon script.";
2828     case NERR_StandaloneLogon:
2829       return "The logon server was not specified. Your computer will be logged on as STANDALONE.";
2830     case NERR_LogonServerNotFound:
2831       return "The logon server could not be found.";
2832     case NERR_LogonDomainExists:
2833       return "There is already a logon domain for this computer.";
2834     case NERR_NonValidatedLogon:
2835       return "The logon server could not validate the logon.";
2836     case NERR_ACFNotFound:
2837       return "The security database could not be found.";
2838     case NERR_GroupNotFound:
2839       return "The group name could not be found.";
2840     case NERR_UserNotFound:
2841       return "The user name could not be found.";
2842     case NERR_ResourceNotFound:
2843       return "The resource name could not be found.";
2844     case NERR_GroupExists:
2845       return "The group already exists.";
2846     case NERR_UserExists:
2847       return "The user account already exists.";
2848     case NERR_ResourceExists:
2849       return "The resource permission list already exists.";
2850     case NERR_NotPrimary:
2851       return "This operation is only allowed on the primary domain controller of the domain.";
2852     case NERR_ACFNotLoaded:
2853       return "The security database has not been started.";
2854     case NERR_ACFNoRoom:
2855       return "There are too many names in the user accounts database.";
2856     case NERR_ACFFileIOFail:
2857       return "A disk I/O failure occurred.";
2858     case NERR_ACFTooManyLists:
2859       return "The limit of 64 entries per resource was exceeded.";
2860     case NERR_UserLogon:
2861       return "Deleting a user with a session is not allowed.";
2862     case NERR_ACFNoParent:
2863       return "The parent directory could not be located.";
2864     case NERR_CanNotGrowSegment:
2865       return "Unable to add to the security database session cache segment.";
2866     case NERR_SpeGroupOp:
2867       return "This operation is not allowed on this special group.";
2868     case NERR_NotInCache:
2869       return "This user is not cached in user accounts database session cache.";
2870     case NERR_UserInGroup:
2871       return "The user already belongs to this group.";
2872     case NERR_UserNotInGroup:
2873       return "The user does not belong to this group.";
2874     case NERR_AccountUndefined:
2875       return "This user account is undefined.";
2876     case NERR_AccountExpired:
2877       return "This user account has expired.";
2878     case NERR_InvalidWorkstation:
2879       return "The user is not allowed to log on from this workstation.";
2880     case NERR_InvalidLogonHours:
2881       return "The user is not allowed to log on at this time.";
2882     case NERR_PasswordExpired:
2883       return "The password of this user has expired.";
2884     case NERR_PasswordCantChange:
2885       return "The password of this user cannot change.";
2886     case NERR_PasswordHistConflict:
2887       return "This password cannot be used now.";
2888     case NERR_PasswordTooShort:
2889       return "The password does not meet the password policy requirements. Check the minimum password length, password complexity and password history requirements.";
2890     case NERR_PasswordTooRecent:
2891       return "The password of this user is too recent to change.";
2892     case NERR_InvalidDatabase:
2893       return "The security database is corrupted.";
2894     case NERR_DatabaseUpToDate:
2895       return "No updates are necessary to this replicant network/local security database.";
2896     case NERR_SyncRequired:
2897       return "This replicant database is outdated; synchronization is required.";
2898     case NERR_UseNotFound:
2899       return "The network connection could not be found.";
2900     case NERR_BadAsgType:
2901       return "This asg_type is invalid.";
2902     case NERR_DeviceIsShared:
2903       return "This device is currently being shared.";
2904     case NERR_NoComputerName:
2905       return "The computer name could not be added as a message alias. The name may already exist on the network.";
2906     case NERR_MsgAlreadyStarted:
2907       return "The Messenger service is already started.";
2908     case NERR_MsgInitFailed:
2909       return "The Messenger service failed to start.";
2910     case NERR_NameNotFound:
2911       return "The message alias could not be found on the network.";
2912     case NERR_AlreadyForwarded:
2913       return "This message alias has already been forwarded.";
2914     case NERR_AddForwarded:
2915       return "This message alias has been added but is still forwarded.";
2916     case NERR_AlreadyExists:
2917       return "This message alias already exists locally.";
2918     case NERR_TooManyNames:
2919       return "The maximum number of added message aliases has been exceeded.";
2920     case NERR_DelComputerName:
2921       return "The computer name could not be deleted.";
2922     case NERR_LocalForward:
2923       return "Messages cannot be forwarded back to the same workstation.";
2924     case NERR_GrpMsgProcessor:
2925       return "An error occurred in the domain message processor.";
2926     case NERR_PausedRemote:
2927       return "The message was sent, but the recipient has paused the Messenger service.";
2928     case NERR_BadReceive:
2929       return "The message was sent but not received.";
2930     case NERR_NameInUse:
2931       return "The message alias is currently in use. Try again later.";
2932     case NERR_MsgNotStarted:
2933       return "The Messenger service has not been started.";
2934     case NERR_NotLocalName:
2935       return "The name is not on the local computer.";
2936     case NERR_NoForwardName:
2937       return "The forwarded message alias could not be found on the network.";
2938     case NERR_RemoteFull:
2939       return "The message alias table on the remote station is full.";
2940     case NERR_NameNotForwarded:
2941       return "Messages for this alias are not currently being forwarded.";
2942     case NERR_TruncatedBroadcast:
2943       return "The broadcast message was truncated.";
2944     case NERR_InvalidDevice:
2945       return "This is an invalid device name.";
2946     case NERR_WriteFault:
2947       return "A write fault occurred.";
2948     case NERR_DuplicateName:
2949       return "A duplicate message alias exists on the network.";
2950     case NERR_DeleteLater:
2951       return "@W This message alias will be deleted later.";
2952     case NERR_IncompleteDel:
2953       return "The message alias was not successfully deleted from all networks.";
2954     case NERR_MultipleNets:
2955       return "This operation is not supported on computers with multiple networks.";
2956     case NERR_NetNameNotFound:
2957       return "This shared resource does not exist.";
2958     case NERR_DeviceNotShared:
2959       return "This device is not shared.";
2960     case NERR_ClientNameNotFound:
2961       return "A session does not exist with that computer name.";
2962     case NERR_FileIdNotFound:
2963       return "There is not an open file with that identification number.";
2964     case NERR_ExecFailure:
2965       return "A failure occurred when executing a remote administration command.";
2966     case NERR_TmpFile:
2967       return "A failure occurred when opening a remote temporary file.";
2968     case NERR_TooMuchData:
2969       return "The data returned from a remote administration command has been truncated to 64K.";
2970     case NERR_DeviceShareConflict:
2971       return "This device cannot be shared as both a spooled and a non-spooled resource.";
2972     case NERR_BrowserTableIncomplete:
2973       return "The information in the list of servers may be incorrect.";
2974     case NERR_NotLocalDomain:
2975       return "The computer is not active in this domain.";
2976 #ifdef NERR_IsDfsShare
2977
2978     case NERR_IsDfsShare:
2979       return "The share must be removed from the Distributed File System before it can be deleted.";
2980 #endif
2981
2982     case NERR_DevInvalidOpCode:
2983       return "The operation is invalid for this device.";
2984     case NERR_DevNotFound:
2985       return "This device cannot be shared.";
2986     case NERR_DevNotOpen:
2987       return "This device was not open.";
2988     case NERR_BadQueueDevString:
2989       return "This device name list is invalid.";
2990     case NERR_BadQueuePriority:
2991       return "The queue priority is invalid.";
2992     case NERR_NoCommDevs:
2993       return "There are no shared communication devices.";
2994     case NERR_QueueNotFound:
2995       return "The queue you specified does not exist.";
2996     case NERR_BadDevString:
2997       return "This list of devices is invalid.";
2998     case NERR_BadDev:
2999       return "The requested device is invalid.";
3000     case NERR_InUseBySpooler:
3001       return "This device is already in use by the spooler.";
3002     case NERR_CommDevInUse:
3003       return "This device is already in use as a communication device.";
3004     case NERR_InvalidComputer:
3005       return "This computer name is invalid.";
3006     case NERR_MaxLenExceeded:
3007       return "The string and prefix specified are too long.";
3008     case NERR_BadComponent:
3009       return "This path component is invalid.";
3010     case NERR_CantType:
3011       return "Could not determine the type of input.";
3012     case NERR_TooManyEntries:
3013       return "The buffer for types is not big enough.";
3014     case NERR_ProfileFileTooBig:
3015       return "Profile files cannot exceed 64K.";
3016     case NERR_ProfileOffset:
3017       return "The start offset is out of range.";
3018     case NERR_ProfileCleanup:
3019       return "The system cannot delete current connections to network resources.";
3020     case NERR_ProfileUnknownCmd:
3021       return "The system was unable to parse the command line in this file.";
3022     case NERR_ProfileLoadErr:
3023       return "An error occurred while loading the profile file.";
3024     case NERR_ProfileSaveErr:
3025       return "@W Errors occurred while saving the profile file. The profile was partially saved.";
3026     case NERR_LogOverflow:
3027       return "Log file %1 is full.";
3028     case NERR_LogFileChanged:
3029       return "This log file has changed between reads.";
3030     case NERR_LogFileCorrupt:
3031       return "Log file %1 is corrupt.";
3032     case NERR_SourceIsDir:
3033       return "The source path cannot be a directory.";
3034     case NERR_BadSource:
3035       return "The source path is illegal.";
3036     case NERR_BadDest:
3037       return "The destination path is illegal.";
3038     case NERR_DifferentServers:
3039       return "The source and destination paths are on different servers.";
3040     case NERR_RunSrvPaused:
3041       return "The Run server you requested is paused.";
3042     case NERR_ErrCommRunSrv:
3043       return "An error occurred when communicating with a Run server.";
3044     case NERR_ErrorExecingGhost:
3045       return "An error occurred when starting a background process.";
3046     case NERR_ShareNotFound:
3047       return "The shared resource you are connected to could not be found.";
3048     case NERR_InvalidLana:
3049       return "The LAN adapter number is invalid.";
3050     case NERR_OpenFiles:
3051       return "There are open files on the connection.";
3052     case NERR_ActiveConns:
3053       return "Active connections still exist.";
3054     case NERR_BadPasswordCore:
3055       return "This share name or password is invalid.";
3056     case NERR_DevInUse:
3057       return "The device is being accessed by an active process.";
3058     case NERR_LocalDrive:
3059       return "The drive letter is in use locally.";
3060     case NERR_AlertExists:
3061       return "The specified client is already registered for the specified event.";
3062     case NERR_TooManyAlerts:
3063       return "The alert table is full.";
3064     case NERR_NoSuchAlert:
3065       return "An invalid or nonexistent alert name was raised.";
3066     case NERR_BadRecipient:
3067       return "The alert recipient is invalid.";
3068     case NERR_AcctLimitExceeded:
3069       return "A user's session with this server has been deleted.";
3070     case NERR_InvalidLogSeek:
3071       return "The log file does not contain the requested record number.";
3072     case NERR_BadUasConfig:
3073       return "The user accounts database is not configured correctly.";
3074     case NERR_InvalidUASOp:
3075       return "This operation is not permitted when the Netlogon service is running.";
3076     case NERR_LastAdmin:
3077       return "This operation is not allowed on the last administrative account.";
3078     case NERR_DCNotFound:
3079       return "Could not find domain controller for this domain.";
3080     case NERR_LogonTrackingError:
3081       return "Could not set logon information for this user.";
3082     case NERR_NetlogonNotStarted:
3083       return "The Netlogon service has not been started.";
3084     case NERR_CanNotGrowUASFile:
3085       return "Unable to add to the user accounts database.";
3086     case NERR_TimeDiffAtDC:
3087       return "This server's clock is not synchronized with the primary domain controller's clock.";
3088     case NERR_PasswordMismatch:
3089       return "A password mismatch has been detected.";
3090     case NERR_NoSuchServer:
3091       return "The server identification does not specify a valid server.";
3092     case NERR_NoSuchSession:
3093       return "The session identification does not specify a valid session.";
3094     case NERR_NoSuchConnection:
3095       return "The connection identification does not specify a valid connection.";
3096     case NERR_TooManyServers:
3097       return "There is no space for another entry in the table of available servers.";
3098     case NERR_TooManySessions:
3099       return "The server has reached the maximum number of sessions it supports.";
3100     case NERR_TooManyConnections:
3101       return "The server has reached the maximum number of connections it supports.";
3102     case NERR_TooManyFiles:
3103       return "The server cannot open more files because it has reached its maximum number.";
3104     case NERR_NoAlternateServers:
3105       return "There are no alternate servers registered on this server.";
3106     case NERR_TryDownLevel:
3107       return "Try down-level (remote admin protocol) version of API instead.";
3108     case NERR_UPSDriverNotStarted:
3109       return "The UPS driver could not be accessed by the UPS service.";
3110     case NERR_UPSInvalidConfig:
3111       return "The UPS service is not configured correctly.";
3112     case NERR_UPSInvalidCommPort:
3113       return "The UPS service could not access the specified Comm Port.";
3114     case NERR_UPSSignalAsserted:
3115       return "The UPS indicated a line fail or low battery situation. Service not started.";
3116     case NERR_UPSShutdownFailed:
3117       return "The UPS service failed to perform a system shut down.";
3118     case NERR_BadDosRetCode:
3119       return "The program below returned an MS-DOS error code:";
3120     case NERR_ProgNeedsExtraMem:
3121       return "The program below needs more memory:";
3122     case NERR_BadDosFunction:
3123       return "The program below called an unsupported MS-DOS function:";
3124     case NERR_RemoteBootFailed:
3125       return "The workstation failed to boot.";
3126     case NERR_BadFileCheckSum:
3127       return "The file below is corrupt.";
3128     case NERR_NoRplBootSystem:
3129       return "No loader is specified in the boot-block definition file.";
3130     case NERR_RplLoadrNetBiosErr:
3131       return "NetBIOS returned an error:      The NCB and SMB are dumped above.";
3132     case NERR_RplLoadrDiskErr:
3133       return "A disk I/O error occurred.";
3134     case NERR_ImageParamErr:
3135       return "Image parameter substitution failed.";
3136     case NERR_TooManyImageParams:
3137       return "Too many image parameters cross disk sector boundaries.";
3138     case NERR_NonDosFloppyUsed:
3139       return "The image was not generated from an MS-DOS diskette formatted with /S.";
3140     case NERR_RplBootRestart:
3141       return "Remote boot will be restarted later.";
3142     case NERR_RplSrvrCallFailed:
3143       return "The call to the Remoteboot server failed.";
3144     case NERR_CantConnectRplSrvr:
3145       return "Cannot connect to the Remoteboot server.";
3146     case NERR_CantOpenImageFile:
3147       return "Cannot open image file on the Remoteboot server.";
3148     case NERR_CallingRplSrvr:
3149       return "Connecting to the Remoteboot server...";
3150     case NERR_StartingRplBoot:
3151       return "Connecting to the Remoteboot server...";
3152     case NERR_RplBootServiceTerm:
3153       return "Remote boot service was stopped; check the error log for the cause of the problem.";
3154     case NERR_RplBootStartFailed:
3155       return "Remote boot startup failed; check the error log for the cause of the problem.";
3156     case NERR_RPL_CONNECTED:
3157       return "A second connection to a Remoteboot resource is not allowed.";
3158     case NERR_BrowserConfiguredToNotRun:
3159       return "The browser service was configured with MaintainServerList=No.";
3160     case NERR_RplNoAdaptersStarted:
3161       return "Service failed to start since none of the network adapters started with this service.";
3162     case NERR_RplBadRegistry:
3163       return "Service failed to start due to bad startup information in the registry.";
3164     case NERR_RplBadDatabase:
3165       return "Service failed to start because its database is absent or corrupt.";
3166     case NERR_RplRplfilesShare:
3167       return "Service failed to start because RPLFILES share is absent.";
3168     case NERR_RplNotRplServer:
3169       return "Service failed to start because RPLUSER group is absent.";
3170     case NERR_RplCannotEnum:
3171       return "Cannot enumerate service records.";
3172     case NERR_RplWkstaInfoCorrupted:
3173       return "Workstation record information has been corrupted.";
3174     case NERR_RplWkstaNotFound:
3175       return "Workstation record was not found.";
3176     case NERR_RplWkstaNameUnavailable:
3177       return "Workstation name is in use by some other workstation.";
3178     case NERR_RplProfileInfoCorrupted:
3179       return "Profile record information has been corrupted.";
3180     case NERR_RplProfileNotFound:
3181       return "Profile record was not found.";
3182     case NERR_RplProfileNameUnavailable:
3183       return "Profile name is in use by some other profile.";
3184     case NERR_RplProfileNotEmpty:
3185       return "There are workstations using this profile.";
3186     case NERR_RplConfigInfoCorrupted:
3187       return "Configuration record information has been corrupted.";
3188     case NERR_RplConfigNotFound:
3189       return "Configuration record was not found.";
3190     case NERR_RplAdapterInfoCorrupted:
3191       return "Adapter ID record information has been corrupted.";
3192     case NERR_RplInternal:
3193       return "An internal service error has occurred.";
3194     case NERR_RplVendorInfoCorrupted:
3195       return "Vendor ID record information has been corrupted.";
3196     case NERR_RplBootInfoCorrupted:
3197       return "Boot block record information has been corrupted.";
3198     case NERR_RplWkstaNeedsUserAcct:
3199       return "The user account for this workstation record is missing.";
3200     case NERR_RplNeedsRPLUSERAcct:
3201       return "The RPLUSER local group could not be found.";
3202     case NERR_RplBootNotFound:
3203       return "Boot block record was not found.";
3204     case NERR_RplIncompatibleProfile:
3205       return "Chosen profile is incompatible with this workstation.";
3206     case NERR_RplAdapterNameUnavailable:
3207       return "Chosen network adapter ID is in use by some other workstation.";
3208     case NERR_RplConfigNotEmpty:
3209       return "There are profiles using this configuration.";
3210     case NERR_RplBootInUse:
3211       return "There are workstations, profiles, or configurations using this boot block.";
3212     case NERR_RplBackupDatabase:
3213       return "Service failed to backup Remoteboot database.";
3214     case NERR_RplAdapterNotFound:
3215       return "Adapter record was not found.";
3216     case NERR_RplVendorNotFound:
3217       return "Vendor record was not found.";
3218     case NERR_RplVendorNameUnavailable:
3219       return "Vendor name is in use by some other vendor record.";
3220     case NERR_RplBootNameUnavailable:
3221       return "(boot name, vendor ID) is in use by some other boot block record.";
3222     case NERR_RplConfigNameUnavailable:
3223       return "Configuration name is in use by some other configuration.";
3224     case NERR_DfsInternalCorruption:
3225       return "The internal database maintained by the Dfs service is corrupt.";
3226     case NERR_DfsVolumeDataCorrupt:
3227       return "One of the records in the internal Dfs database is corrupt.";
3228     case NERR_DfsNoSuchVolume:
3229       return "There is no DFS name whose entry path matches the input Entry Path.";
3230     case NERR_DfsVolumeAlreadyExists:
3231       return "A root or link with the given name already exists.";
3232     case NERR_DfsAlreadyShared:
3233       return "The server share specified is already shared in the Dfs.";
3234     case NERR_DfsNoSuchShare:
3235       return "The indicated server share does not support the indicated DFS namespace.";
3236     case NERR_DfsNotALeafVolume:
3237       return "The operation is not valid on this portion of the namespace.";
3238     case NERR_DfsLeafVolume:
3239       return "The operation is not valid on this portion of the namespace.";
3240     case NERR_DfsVolumeHasMultipleServers:
3241       return "The operation is ambiguous because the link has multiple servers.";
3242     case NERR_DfsCantCreateJunctionPoint:
3243       return "Unable to create a link.";
3244     case NERR_DfsServerNotDfsAware:
3245       return "The server is not Dfs Aware.";
3246     case NERR_DfsBadRenamePath:
3247       return "The specified rename target path is invalid.";
3248     case NERR_DfsVolumeIsOffline:
3249       return "The specified DFS link is offline.";
3250     case NERR_DfsNoSuchServer:
3251       return "The specified server is not a server for this link.";
3252     case NERR_DfsCyclicalName:
3253       return "A cycle in the Dfs name was detected.";
3254     case NERR_DfsNotSupportedInServerDfs:
3255       return "The operation is not supported on a server-based Dfs.";
3256     case NERR_DfsDuplicateService:
3257       return "This link is already supported by the specified server-share.";
3258     case NERR_DfsCantRemoveLastServerShare:
3259       return "Can't remove the last server-share supporting this root or link.";
3260     case NERR_DfsVolumeIsInterDfs:
3261       return "The operation is not supported for an Inter-DFS link.";
3262     case NERR_DfsInconsistent:
3263       return "The internal state of the Dfs Service has become inconsistent.";
3264     case NERR_DfsServerUpgraded:
3265       return "The Dfs Service has been installed on the specified server.";
3266     case NERR_DfsDataIsIdentical:
3267       return "The Dfs data being reconciled is identical.";
3268     case NERR_DfsCantRemoveDfsRoot:
3269       return "The DFS root cannot be deleted. Uninstall DFS if required.";
3270     case NERR_DfsChildOrParentInDfs:
3271       return "A child or parent directory of the share is already in a Dfs.";
3272     case NERR_DfsInternalError:
3273       return "Dfs internal error.";
3274       /* the following are not defined in mingw */
3275 #if 0
3276
3277     case NERR_SetupAlreadyJoined:
3278       return "This machine is already joined to a domain.";
3279     case NERR_SetupNotJoined:
3280       return "This machine is not currently joined to a domain.";
3281     case NERR_SetupDomainController:
3282       return "This machine is a domain controller and cannot be unjoined from a domain.";
3283     case NERR_DefaultJoinRequired:
3284       return "The destination domain controller does not support creating machine accounts in OUs.";
3285     case NERR_InvalidWorkgroupName:
3286       return "The specified workgroup name is invalid.";
3287     case NERR_NameUsesIncompatibleCodePage:
3288       return "The specified computer name is incompatible with the default language used on the domain controller.";
3289     case NERR_ComputerAccountNotFound:
3290       return "The specified computer account could not be found.";
3291     case NERR_PersonalSku:
3292       return "This version of Windows cannot be joined to a domain.";
3293     case NERR_PasswordMustChange:
3294       return "The password must change at the next logon.";
3295     case NERR_AccountLockedOut:
3296       return "The account is locked out.";
3297     case NERR_PasswordTooLong:
3298       return "The password is too long.";
3299     case NERR_PasswordNotComplexEnough:
3300       return "The password does not meet the complexity policy.";
3301     case NERR_PasswordFilterError:
3302       return "The password does not meet the requirements of the password filter DLLs.";
3303 #endif
3304
3305     }
3306   msg = strerror (error_number);
3307   if (msg == NULL)
3308     msg = "unknown";
3309
3310   return msg;
3311 #endif //DBUS_WINCE
3312 }
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322 /******************************************************************************
3323  
3324 Original CVS version of dbus-sysdeps.c
3325  
3326 ******************************************************************************/
3327 /* -*- mode: C; c-file-style: "gnu" -*- */
3328 /* dbus-sysdeps.c Wrappers around system/libc features (internal to D-Bus implementation)
3329  * 
3330  * Copyright (C) 2002, 2003  Red Hat, Inc.
3331  * Copyright (C) 2003 CodeFactory AB
3332  * Copyright (C) 2005 Novell, Inc.
3333  *
3334  * Licensed under the Academic Free License version 2.1
3335  * 
3336  * This program is free software; you can redistribute it and/or modify
3337  * it under the terms of the GNU General Public License as published by
3338  * the Free Software Foundation; either version 2 of the License, or
3339  * (at your option) any later version.
3340  *
3341  * This program is distributed in the hope that it will be useful,
3342  * but WITHOUT ANY WARRANTY; without even the implied warranty of
3343  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3344  * GNU General Public License for more details.
3345  * 
3346  * You should have received a copy of the GNU General Public License
3347  * along with this program; if not, write to the Free Software
3348  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
3349  *
3350  */
3351
3352
3353 /**
3354  * @addtogroup DBusInternalsUtils
3355  * @{
3356  */
3357
3358 int _dbus_mkdir (const char *path,
3359                  mode_t mode)
3360 {
3361   return _mkdir(path);
3362 }
3363
3364 /**
3365  * Exit the process, returning the given value.
3366  *
3367  * @param code the exit code
3368  */
3369 void
3370 _dbus_exit (int code)
3371 {
3372   _exit (code);
3373 }
3374
3375 /**
3376  * Creates a socket and connects to a socket at the given host 
3377  * and port. The connection fd is returned, and is set up as
3378  * nonblocking.
3379  *
3380  * @param host the host name to connect to, NULL for loopback
3381  * @param port the prot to connect to
3382  * @param error return location for error code
3383  * @returns connection file descriptor or -1 on error
3384  */
3385 int
3386 _dbus_connect_tcp_socket (const char     *host,
3387                           dbus_uint32_t   port,
3388                           DBusError      *error)
3389 {
3390   DBusSocket s;
3391   int handle;
3392   struct sockaddr_in addr;
3393   struct hostent *he;
3394   struct in_addr *haddr;
3395   struct in_addr ina;
3396
3397   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3398
3399   _dbus_win_startup_winsock ();
3400
3401   s.fd = socket (AF_INET, SOCK_STREAM, 0);
3402
3403   if (DBUS_SOCKET_IS_INVALID (s.fd))
3404     {
3405       DBUS_SOCKET_SET_ERRNO ();
3406       dbus_set_error (error,
3407                       _dbus_error_from_errno (errno),
3408                       "Failed to create socket: %s",
3409                       _dbus_strerror (errno));
3410
3411       return -1;
3412     }
3413
3414   if (host == NULL)
3415     {
3416       host = "localhost";
3417       ina.s_addr = htonl (INADDR_LOOPBACK);
3418       haddr = &ina;
3419     }
3420
3421   he = gethostbyname (host);
3422   if (he == NULL)
3423     {
3424       DBUS_SOCKET_SET_ERRNO ();
3425       dbus_set_error (error,
3426                       _dbus_error_from_errno (errno),
3427                       "Failed to lookup hostname: %s",
3428                       host);
3429       DBUS_CLOSE_SOCKET (s.fd);
3430       return -1;
3431     }
3432
3433   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
3434
3435   _DBUS_ZERO (addr);
3436   memcpy (&addr.sin_addr, haddr, sizeof(struct in_addr));
3437   addr.sin_family = AF_INET;
3438   addr.sin_port = htons (port);
3439
3440   if (DBUS_SOCKET_API_RETURNS_ERROR
3441       (connect (s.fd, (struct sockaddr*) &addr, sizeof (addr)) < 0))
3442     {
3443       DBUS_SOCKET_SET_ERRNO ();
3444       dbus_set_error (error,
3445                       _dbus_error_from_errno (errno),
3446                       "Failed to connect to socket %s:%d %s",
3447                       host, port, _dbus_strerror (errno));
3448
3449       DBUS_CLOSE_SOCKET (s.fd);
3450       s.fd = -1;
3451
3452       return -1;
3453     }
3454
3455   handle = _dbus_socket_to_handle (&s);
3456
3457   if (!_dbus_set_fd_nonblocking (handle, error))
3458     {
3459       _dbus_close_socket (handle, NULL);
3460       handle = -1;
3461
3462       return -1;
3463     }
3464
3465   return handle;
3466 }
3467
3468 void
3469 _dbus_daemon_init(const char *host, dbus_uint32_t port);
3470 /**
3471  * Creates a socket and binds it to the given port,
3472  * then listens on the socket. The socket is
3473  * set to be nonblocking. 
3474  * In case of port=0 a random free port is used and 
3475  * returned in the port parameter. 
3476  *
3477  * @param host the interface to listen on, NULL for loopback, empty for any
3478  * @param port the port to listen on, if zero a free port will be used 
3479  * @param error return location for errors
3480  * @returns the listening file descriptor or -1 on error
3481  */
3482
3483 int
3484 _dbus_listen_tcp_socket (const char     *host,
3485                          dbus_uint32_t  *port,
3486                          DBusError      *error)
3487 {
3488   DBusSocket slisten;
3489   int handle;
3490   struct sockaddr_in addr;
3491   struct hostent *he;
3492   struct in_addr *haddr;
3493   socklen_t len = (socklen_t) sizeof (struct sockaddr);
3494   struct in_addr ina;
3495
3496
3497   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3498
3499   _dbus_win_startup_winsock ();
3500
3501   slisten.fd = socket (AF_INET, SOCK_STREAM, 0);
3502
3503   if (DBUS_SOCKET_IS_INVALID (slisten.fd))
3504     {
3505       DBUS_SOCKET_SET_ERRNO ();
3506       dbus_set_error (error, _dbus_error_from_errno (errno),
3507                       "Failed to create socket \"%s:%d\": %s",
3508                       host, port, _dbus_strerror (errno));
3509       return -1;
3510     }
3511   if (host == NULL)
3512     {
3513       host = "localhost";
3514       ina.s_addr = htonl (INADDR_LOOPBACK);
3515       haddr = &ina;
3516     }
3517   else if (!host[0])
3518     {
3519       ina.s_addr = htonl (INADDR_ANY);
3520       haddr = &ina;
3521     }
3522   else
3523     {
3524       he = gethostbyname (host);
3525       if (he == NULL)
3526         {
3527           DBUS_SOCKET_SET_ERRNO ();
3528           dbus_set_error (error,
3529                           _dbus_error_from_errno (errno),
3530                           "Failed to lookup hostname: %s",
3531                           host);
3532           DBUS_CLOSE_SOCKET (slisten.fd);
3533           return -1;
3534         }
3535
3536       haddr = ((struct in_addr *) (he->h_addr_list)[0]);
3537     }
3538
3539   _DBUS_ZERO (addr);
3540   memcpy (&addr.sin_addr, haddr, sizeof (struct in_addr));
3541   addr.sin_family = AF_INET;
3542   addr.sin_port = htons (*port);
3543
3544   if (bind (slisten.fd, (struct sockaddr*) &addr, sizeof (struct sockaddr)))
3545     {
3546       DBUS_SOCKET_SET_ERRNO ();
3547       dbus_set_error (error, _dbus_error_from_errno (errno),
3548                       "Failed to bind socket \"%s:%d\": %s",
3549                       host, *port, _dbus_strerror (errno));
3550       DBUS_CLOSE_SOCKET (slisten.fd);
3551       return -1;
3552     }
3553
3554   if (DBUS_SOCKET_API_RETURNS_ERROR (listen (slisten.fd, 30 /* backlog */)))
3555     {
3556       DBUS_SOCKET_SET_ERRNO ();
3557       dbus_set_error (error, _dbus_error_from_errno (errno),
3558                       "Failed to listen on socket \"%s:%d\": %s",
3559                       host, *port, _dbus_strerror (errno));
3560       DBUS_CLOSE_SOCKET (slisten.fd);
3561       return -1;
3562     }
3563
3564   getsockname(slisten.fd, (struct sockaddr*) &addr, &len);
3565   *port = (dbus_uint32_t) ntohs(addr.sin_port);
3566   
3567   _dbus_daemon_init(host, ntohs(addr.sin_port));
3568
3569   handle = _dbus_socket_to_handle (&slisten);
3570
3571   if (!_dbus_set_fd_nonblocking (handle, error))
3572     {
3573       _dbus_close_socket (handle, NULL);
3574       return -1;
3575     }
3576
3577   return handle;
3578 }
3579
3580 /**
3581  * Accepts a connection on a listening socket.
3582  * Handles EINTR for you.
3583  *
3584  * @param listen_fd the listen file descriptor
3585  * @returns the connection fd of the client, or -1 on error
3586  */
3587 int
3588 _dbus_accept  (int listen_handle)
3589 {
3590   DBusSocket *slisten;
3591   DBusSocket sclient;
3592   struct sockaddr addr;
3593   socklen_t addrlen;
3594
3595   _dbus_handle_to_socket(listen_handle, &slisten);
3596
3597   addrlen = sizeof (addr);
3598
3599   //FIXME:  why do we not try it again on Windows?
3600 #if !defined(DBUS_WIN) && !defined(DBUS_WINCE)
3601 retry:
3602 #endif
3603
3604   sclient.fd = accept (slisten->fd, &addr, &addrlen);
3605
3606   if (DBUS_SOCKET_IS_INVALID (sclient.fd))
3607     {
3608       DBUS_SOCKET_SET_ERRNO ();
3609 #if !defined(DBUS_WIN) && !defined(DBUS_WINCE)
3610       if (errno == EINTR)
3611         goto retry;
3612 #else
3613       return -1;
3614 #endif
3615     }
3616
3617   return _dbus_socket_to_handle (&sclient);
3618 }
3619
3620
3621
3622 dbus_bool_t
3623 write_credentials_byte (int            handle,
3624                         DBusError      *error)
3625 {
3626 /* FIXME: for the session bus credentials shouldn't matter (?), but
3627  * for the system bus they are presumably essential. A rough outline
3628  * of a way to implement the credential transfer would be this:
3629  *
3630  * client waits to *read* a byte.
3631  *
3632  * server creates a named pipe with a random name, sends a byte
3633  * contining its length, and its name.
3634  *
3635  * client reads the name, connects to it (using Win32 API).
3636  *
3637  * server waits for connection to the named pipe, then calls
3638  * ImpersonateNamedPipeClient(), notes its now-current credentials,
3639  * calls RevertToSelf(), closes its handles to the named pipe, and
3640  * is done. (Maybe there is some other way to get the SID of a named
3641  * pipe client without having to use impersonation?)
3642  *
3643  * client closes its handles and is done.
3644  * 
3645  * Ralf: Why not sending credentials over the given this connection ?
3646  * Using named pipes makes it impossible to be connected from a unix client.  
3647  *
3648  */
3649   int bytes_written;
3650   DBusString buf; 
3651
3652   _dbus_string_init_const_len (&buf, "\0", 1);
3653 again:
3654   bytes_written = _dbus_write_socket (handle, &buf, 0, 1 );
3655
3656   if (bytes_written < 0 && errno == EINTR)
3657     goto again;
3658
3659   if (bytes_written < 0)
3660     {
3661       dbus_set_error (error, _dbus_error_from_errno (errno),
3662                       "Failed to write credentials byte: %s",
3663                      _dbus_strerror (errno));
3664       return FALSE;
3665     }
3666   else if (bytes_written == 0)
3667     {
3668       dbus_set_error (error, DBUS_ERROR_IO_ERROR,
3669                       "wrote zero bytes writing credentials byte");
3670       return FALSE;
3671     }
3672   else
3673     {
3674       _dbus_assert (bytes_written == 1);
3675       _dbus_verbose ("wrote 1 zero byte, credential sending isn't implemented yet\n");
3676       return TRUE;
3677     }
3678   return TRUE;
3679 }
3680
3681 /**
3682  * Reads a single byte which must be nul (an error occurs otherwise),
3683  * and reads unix credentials if available. Fills in pid/uid/gid with
3684  * -1 if no credentials are available. Return value indicates whether
3685  * a byte was read, not whether we got valid credentials. On some
3686  * systems, such as Linux, reading/writing the byte isn't actually
3687  * required, but we do it anyway just to avoid multiple codepaths.
3688  * 
3689  * Fails if no byte is available, so you must select() first.
3690  *
3691  * The point of the byte is that on some systems we have to
3692  * use sendmsg()/recvmsg() to transmit credentials.
3693  *
3694  * @param client_fd the client file descriptor
3695  * @param credentials struct to fill with credentials of client
3696  * @param error location to store error code
3697  * @returns #TRUE on success
3698  */
3699 dbus_bool_t
3700 _dbus_read_credentials_unix_socket  (int              handle,
3701                                      DBusCredentials *credentials,
3702                                      DBusError       *error)
3703 {
3704   int bytes_read;
3705   DBusString buf;
3706   _dbus_string_init(&buf);
3707
3708   bytes_read = _dbus_read_socket(handle, &buf, 1 );
3709   if (bytes_read > 0) 
3710     {
3711                 _dbus_verbose("got one zero byte from server");
3712     }
3713
3714   _dbus_string_free(&buf);
3715   _dbus_credentials_from_current_process (credentials);
3716   _dbus_verbose("FIXME: get faked credentials from current process");
3717
3718   return TRUE;
3719 }
3720
3721 /**
3722 * Checks to make sure the given directory is 
3723 * private to the user 
3724 *
3725 * @param dir the name of the directory
3726 * @param error error return
3727 * @returns #FALSE on failure
3728 **/
3729 dbus_bool_t
3730 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
3731 {
3732   const char *directory;
3733   struct stat sb;
3734
3735   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3736
3737   return TRUE;
3738 }
3739
3740
3741 /**
3742  * Gets user info for the given user ID.
3743  *
3744  * @param info user info object to initialize
3745  * @param uid the user ID
3746  * @param error error return
3747  * @returns #TRUE on success
3748  */
3749 dbus_bool_t
3750 _dbus_user_info_fill_uid (DBusUserInfo *info,
3751                           dbus_uid_t    uid,
3752                           DBusError    *error)
3753 {
3754   return fill_user_info (info, uid,
3755                          NULL, error);
3756 }
3757
3758 /**
3759  * Gets user info for the given username.
3760  *
3761  * @param info user info object to initialize
3762  * @param username the username
3763  * @param error error return
3764  * @returns #TRUE on success
3765  */
3766 dbus_bool_t
3767 _dbus_user_info_fill (DBusUserInfo     *info,
3768                       const DBusString *username,
3769                       DBusError        *error)
3770 {
3771   return fill_user_info (info, DBUS_UID_UNSET,
3772                          username, error);
3773 }
3774
3775
3776 dbus_bool_t
3777 fill_user_info (DBusUserInfo       *info,
3778                 dbus_uid_t          uid,
3779                 const DBusString   *username,
3780                 DBusError          *error)
3781 {
3782   const char *username_c;
3783
3784   /* exactly one of username/uid provided */
3785   _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
3786   _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
3787
3788   info->uid = DBUS_UID_UNSET;
3789   info->primary_gid = DBUS_GID_UNSET;
3790   info->group_ids = NULL;
3791   info->n_group_ids = 0;
3792   info->username = NULL;
3793   info->homedir = NULL;
3794
3795   if (username != NULL)
3796     username_c = _dbus_string_get_const_data (username);
3797   else
3798     username_c = NULL;
3799
3800   if (uid != DBUS_UID_UNSET)
3801     {
3802       if (!fill_win_user_info_from_uid (uid, info, error))
3803         {
3804           _dbus_verbose("%s after fill_win_user_info_from_uid\n",__FUNCTION__);
3805           return FALSE;
3806         }
3807     }
3808   else
3809     {
3810       wchar_t *wname = _dbus_win_utf8_to_utf16 (username_c, error);
3811
3812       if (!wname)
3813         return FALSE;
3814
3815       if (!fill_win_user_info_from_name (wname, info, error))
3816         {
3817           dbus_free (wname);
3818           return FALSE;
3819         }
3820       dbus_free (wname);
3821     }
3822
3823   return TRUE;
3824 }
3825
3826
3827 /**
3828  * Appends the given filename to the given directory.
3829  *
3830  * @todo it might be cute to collapse multiple '/' such as "foo//"
3831  * concat "//bar"
3832  *
3833  * @param dir the directory name
3834  * @param next_component the filename
3835  * @returns #TRUE on success
3836  */
3837 dbus_bool_t
3838 _dbus_concat_dir_and_file (DBusString       *dir,
3839                            const DBusString *next_component)
3840 {
3841   dbus_bool_t dir_ends_in_slash;
3842   dbus_bool_t file_starts_with_slash;
3843
3844   if (_dbus_string_get_length (dir) == 0 ||
3845       _dbus_string_get_length (next_component) == 0)
3846     return TRUE;
3847
3848   dir_ends_in_slash =
3849     ('/' == _dbus_string_get_byte (dir, _dbus_string_get_length (dir) - 1) ||
3850      '\\' == _dbus_string_get_byte (dir, _dbus_string_get_length (dir) - 1));
3851
3852   file_starts_with_slash =
3853     ('/' == _dbus_string_get_byte (next_component, 0) ||
3854      '\\' == _dbus_string_get_byte (next_component, 0));
3855
3856   if (dir_ends_in_slash && file_starts_with_slash)
3857     {
3858       _dbus_string_shorten (dir, 1);
3859     }
3860   else if (!(dir_ends_in_slash || file_starts_with_slash))
3861     {
3862       if (!_dbus_string_append_byte (dir, '\\'))
3863         return FALSE;
3864     }
3865
3866   return _dbus_string_copy (next_component, 0, dir,
3867                             _dbus_string_get_length (dir));
3868 }
3869
3870
3871
3872
3873 /**
3874  * Gets our process ID
3875  * @returns process ID
3876  */
3877 unsigned long
3878 _dbus_getpid (void)
3879 {
3880   return GetCurrentProcessId ();
3881 }
3882
3883 /** nanoseconds in a second */
3884 #define NANOSECONDS_PER_SECOND       1000000000
3885 /** microseconds in a second */
3886 #define MICROSECONDS_PER_SECOND      1000000
3887 /** milliseconds in a second */
3888 #define MILLISECONDS_PER_SECOND      1000
3889 /** nanoseconds in a millisecond */
3890 #define NANOSECONDS_PER_MILLISECOND  1000000
3891 /** microseconds in a millisecond */
3892 #define MICROSECONDS_PER_MILLISECOND 1000
3893
3894 /**
3895  * Sleeps the given number of milliseconds.
3896  * @param milliseconds number of milliseconds
3897  */
3898 void
3899 _dbus_sleep_milliseconds (int milliseconds)
3900 {
3901   Sleep (milliseconds);
3902 }
3903
3904
3905 /**
3906  * Get current time, as in gettimeofday().
3907  *
3908  * @param tv_sec return location for number of seconds
3909  * @param tv_usec return location for number of microseconds
3910  */
3911 void
3912 _dbus_get_current_time (long *tv_sec,
3913                         long *tv_usec)
3914 {
3915   FILETIME ft;
3916   dbus_uint64_t *time64 = (dbus_uint64_t *) &ft;
3917
3918   GetSystemTimeAsFileTime (&ft);
3919
3920   /* Convert from 100s of nanoseconds since 1601-01-01
3921   * to Unix epoch. Yes, this is Y2038 unsafe.
3922   */
3923   *time64 -= DBUS_INT64_CONSTANT (116444736000000000);
3924   *time64 /= 10;
3925
3926   if (tv_sec)
3927     *tv_sec = *time64 / 1000000;
3928
3929   if (tv_usec)
3930     *tv_usec = *time64 % 1000000;
3931 }
3932
3933
3934 /**
3935  * signal (SIGPIPE, SIG_IGN);
3936  */
3937 void
3938 _dbus_disable_sigpipe (void)
3939 {
3940     _dbus_verbose("FIXME: implement _dbus_disable_sigpipe (void)\n");
3941 }
3942
3943 /**
3944  * Gets the credentials of the current process.
3945  *
3946  * @param credentials credentials to fill in.
3947  */
3948 void
3949 _dbus_credentials_from_current_process (DBusCredentials *credentials)
3950 {
3951   credentials->pid = _dbus_getpid ();
3952   credentials->uid = _dbus_getuid ();
3953   credentials->gid = _dbus_getgid ();
3954 }
3955
3956 /**
3957  * Appends the contents of the given file to the string,
3958  * returning error code. At the moment, won't open a file
3959  * more than a megabyte in size.
3960  *
3961  * @param str the string to append to
3962  * @param filename filename to load
3963  * @param error place to set an error
3964  * @returns #FALSE if error was set
3965  */
3966 dbus_bool_t
3967 _dbus_file_get_contents (DBusString       *str,
3968                          const DBusString *filename,
3969                          DBusError        *error)
3970 {
3971   DBusFile file;
3972   struct stat sb;
3973   int orig_len;
3974   int total;
3975   const char *filename_c;
3976
3977   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3978
3979   filename_c = _dbus_string_get_const_data (filename);
3980
3981   /* O_BINARY useful on Cygwin and Win32 */
3982   if (!_dbus_file_open (&file, filename_c, O_RDONLY | O_BINARY, -1))
3983     {
3984       dbus_set_error (error, _dbus_error_from_errno (errno),
3985                       "Failed to open \"%s\": %s",
3986                       filename_c,
3987                       _dbus_strerror (errno));
3988       return FALSE;
3989     }
3990
3991   if (!_dbus_fstat (&file, &sb))
3992     {
3993       dbus_set_error (error, _dbus_error_from_errno (errno),
3994                       "Failed to stat \"%s\": %s",
3995                       filename_c,
3996                       _dbus_strerror (errno));
3997
3998       _dbus_verbose ("fstat() failed: %s",
3999                      _dbus_strerror (errno));
4000
4001       _dbus_file_close (&file, NULL);
4002
4003       return FALSE;
4004     }
4005
4006   if (sb.st_size > _DBUS_ONE_MEGABYTE)
4007     {
4008       dbus_set_error (error, DBUS_ERROR_FAILED,
4009                       "File size %lu of \"%s\" is too large.",
4010                       (unsigned long) sb.st_size, filename_c);
4011       _dbus_file_close (&file, NULL);
4012       return FALSE;
4013     }
4014
4015   total = 0;
4016   orig_len = _dbus_string_get_length (str);
4017   if (sb.st_size > 0 && S_ISREG (sb.st_mode))
4018     {
4019       int bytes_read;
4020
4021       while (total < (int) sb.st_size)
4022         {
4023           bytes_read = _dbus_file_read (&file, str,
4024                                         sb.st_size - total);
4025           if (bytes_read <= 0)
4026             {
4027               dbus_set_error (error, _dbus_error_from_errno (errno),
4028                               "Error reading \"%s\": %s",
4029                               filename_c,
4030                               _dbus_strerror (errno));
4031
4032               _dbus_verbose ("read() failed: %s",
4033                              _dbus_strerror (errno));
4034
4035               _dbus_file_close (&file, NULL);
4036               _dbus_string_set_length (str, orig_len);
4037               return FALSE;
4038             }
4039           else
4040             total += bytes_read;
4041         }
4042
4043       _dbus_file_close (&file, NULL);
4044       return TRUE;
4045     }
4046   else if (sb.st_size != 0)
4047     {
4048       _dbus_verbose ("Can only open regular files at the moment.\n");
4049       dbus_set_error (error, DBUS_ERROR_FAILED,
4050                       "\"%s\" is not a regular file",
4051                       filename_c);
4052       _dbus_file_close (&file, NULL);
4053       return FALSE;
4054     }
4055   else
4056     {
4057       _dbus_file_close (&file, NULL);
4058       return TRUE;
4059     }
4060 }
4061
4062 /**
4063  * Writes a string out to a file. If the file exists,
4064  * it will be atomically overwritten by the new data.
4065  *
4066  * @param str the string to write out
4067  * @param filename the file to save string to
4068  * @param error error to be filled in on failure
4069  * @returns #FALSE on failure
4070  */
4071 dbus_bool_t
4072 _dbus_string_save_to_file (const DBusString *str,
4073                            const DBusString *filename,
4074                            DBusError        *error)
4075 {
4076   DBusFile file;
4077   int bytes_to_write;
4078   const char *filename_c;
4079   DBusString tmp_filename;
4080   const char *tmp_filename_c;
4081   int total;
4082   dbus_bool_t need_unlink;
4083   dbus_bool_t retval;
4084
4085   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4086
4087   retval = FALSE;
4088   need_unlink = FALSE;
4089
4090   if (!_dbus_string_init (&tmp_filename))
4091     {
4092       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
4093       return FALSE;
4094     }
4095
4096   if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
4097     {
4098       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
4099       _dbus_string_free (&tmp_filename);
4100       return FALSE;
4101     }
4102
4103   if (!_dbus_string_append (&tmp_filename, "."))
4104     {
4105       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
4106       _dbus_string_free (&tmp_filename);
4107       return FALSE;
4108     }
4109
4110 #define N_TMP_FILENAME_RANDOM_BYTES 8
4111   if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
4112     {
4113       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
4114       _dbus_string_free (&tmp_filename);
4115       return FALSE;
4116     }
4117
4118   filename_c = _dbus_string_get_const_data (filename);
4119   tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
4120
4121   if (!_dbus_file_open (&file, tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
4122                         0600))
4123     {
4124       dbus_set_error (error, _dbus_error_from_errno (errno),
4125                       "Could not create %s: %s", tmp_filename_c,
4126                       _dbus_strerror (errno));
4127       goto out;
4128     }
4129
4130   need_unlink = TRUE;
4131
4132   total = 0;
4133   bytes_to_write = _dbus_string_get_length (str);
4134
4135   while (total < bytes_to_write)
4136     {
4137       int bytes_written;
4138
4139       bytes_written = _dbus_file_write (&file, str, total,
4140                                         bytes_to_write - total);
4141
4142       if (bytes_written <= 0)
4143         {
4144           dbus_set_error (error, _dbus_error_from_errno (errno),
4145                           "Could not write to %s: %s", tmp_filename_c,
4146                           _dbus_strerror (errno));
4147
4148           goto out;
4149         }
4150
4151       total += bytes_written;
4152     }
4153
4154   if (!_dbus_file_close (&file, NULL))
4155     {
4156       dbus_set_error (error, _dbus_error_from_errno (errno),
4157                       "Could not close file %s: %s",
4158                       tmp_filename_c, _dbus_strerror (errno));
4159
4160       goto out;
4161     }
4162
4163
4164   if ((unlink (filename_c) == -1 && errno != ENOENT) ||
4165        rename (tmp_filename_c, filename_c) < 0)
4166     {
4167       dbus_set_error (error, _dbus_error_from_errno (errno),
4168                       "Could not rename %s to %s: %s",
4169                       tmp_filename_c, filename_c,
4170                       _dbus_strerror (errno));
4171
4172       goto out;
4173     }
4174
4175   need_unlink = FALSE;
4176
4177   retval = TRUE;
4178
4179 out:
4180   /* close first, then unlink, to prevent ".nfs34234235" garbage
4181    * files
4182    */
4183
4184   if (_dbus_is_valid_file(&file))
4185     _dbus_file_close (&file, NULL);
4186
4187   if (need_unlink && unlink (tmp_filename_c) < 0)
4188     _dbus_verbose ("Failed to unlink temp file %s: %s\n",
4189                    tmp_filename_c, _dbus_strerror (errno));
4190
4191   _dbus_string_free (&tmp_filename);
4192
4193   if (!retval)
4194     _DBUS_ASSERT_ERROR_IS_SET (error);
4195
4196   return retval;
4197 }
4198
4199
4200 /** Creates the given file, failing if the file already exists.
4201  *
4202  * @param filename the filename
4203  * @param error error location
4204  * @returns #TRUE if we created the file and it didn't exist
4205  */
4206 dbus_bool_t
4207 _dbus_create_file_exclusively (const DBusString *filename,
4208                                DBusError        *error)
4209 {
4210   DBusFile file;
4211   const char *filename_c;
4212
4213   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4214
4215   filename_c = _dbus_string_get_const_data (filename);
4216
4217   if (!_dbus_file_open (&file, filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
4218                         0600))
4219     {
4220       dbus_set_error (error,
4221                       DBUS_ERROR_FAILED,
4222                       "Could not create file %s: %s\n",
4223                       filename_c,
4224                       _dbus_strerror (errno));
4225       return FALSE;
4226     }
4227
4228   if (!_dbus_file_close (&file, NULL))
4229     {
4230       dbus_set_error (error,
4231                       DBUS_ERROR_FAILED,
4232                       "Could not close file %s: %s\n",
4233                       filename_c,
4234                       _dbus_strerror (errno));
4235       return FALSE;
4236     }
4237
4238   return TRUE;
4239 }
4240
4241
4242 /**
4243  * Creates a directory; succeeds if the directory
4244  * is created or already existed.
4245  *
4246  * @param filename directory filename
4247  * @param error initialized error object
4248  * @returns #TRUE on success
4249  */
4250 dbus_bool_t
4251 _dbus_create_directory (const DBusString *filename,
4252                         DBusError        *error)
4253 {
4254   const char *filename_c;
4255
4256   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4257
4258   filename_c = _dbus_string_get_const_data (filename);
4259
4260   if (_dbus_mkdir (filename_c, 0700) < 0)
4261     {
4262       if (errno == EEXIST)
4263         return TRUE;
4264
4265       dbus_set_error (error, DBUS_ERROR_FAILED,
4266                       "Failed to create directory %s: %s\n",
4267                       filename_c, _dbus_strerror (errno));
4268       return FALSE;
4269     }
4270   else
4271     return TRUE;
4272 }
4273
4274
4275 static void
4276 pseudorandom_generate_random_bytes_buffer (char *buffer,
4277     int   n_bytes)
4278 {
4279   long tv_usec;
4280   int i;
4281
4282   /* fall back to pseudorandom */
4283   _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
4284                  n_bytes);
4285
4286   _dbus_get_current_time (NULL, &tv_usec);
4287   srand (tv_usec);
4288
4289   i = 0;
4290   while (i < n_bytes)
4291     {
4292       double r;
4293       unsigned int b;
4294
4295       r = rand ();
4296       b = (r / (double) RAND_MAX) * 255.0;
4297
4298       buffer[i] = b;
4299
4300       ++i;
4301     }
4302 }
4303
4304 static dbus_bool_t
4305 pseudorandom_generate_random_bytes (DBusString *str,
4306                                     int         n_bytes)
4307 {
4308   int old_len;
4309   char *p;
4310
4311   old_len = _dbus_string_get_length (str);
4312
4313   if (!_dbus_string_lengthen (str, n_bytes))
4314     return FALSE;
4315
4316   p = _dbus_string_get_data_len (str, old_len, n_bytes);
4317
4318   pseudorandom_generate_random_bytes_buffer (p, n_bytes);
4319
4320   return TRUE;
4321 }
4322
4323 /**
4324  * Gets the temporary files directory by inspecting the environment variables 
4325  * TMPDIR, TMP, and TEMP in that order. If none of those are set "/tmp" is returned
4326  *
4327  * @returns location of temp directory
4328  */
4329 const char*
4330 _dbus_get_tmpdir(void)
4331 {
4332   static const char* tmpdir = NULL;
4333
4334   if (tmpdir == NULL)
4335     {
4336       if (tmpdir == NULL)
4337         tmpdir = getenv("TMP");
4338       if (tmpdir == NULL)
4339         tmpdir = getenv("TEMP");
4340       if (tmpdir == NULL)
4341         tmpdir = getenv("TMPDIR");
4342       if (tmpdir == NULL)
4343           tmpdir = "C:\\Temp";
4344     }
4345
4346   _dbus_assert(tmpdir != NULL);
4347
4348   return tmpdir;
4349 }
4350
4351
4352 /**
4353  * Deletes the given file.
4354  *
4355  * @param filename the filename
4356  * @param error error location
4357  * 
4358  * @returns #TRUE if unlink() succeeded
4359  */
4360 dbus_bool_t
4361 _dbus_delete_file (const DBusString *filename,
4362                    DBusError        *error)
4363 {
4364   const char *filename_c;
4365
4366   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4367
4368   filename_c = _dbus_string_get_const_data (filename);
4369
4370   if (unlink (filename_c) < 0)
4371     {
4372       dbus_set_error (error, DBUS_ERROR_FAILED,
4373                       "Failed to delete file %s: %s\n",
4374                       filename_c, _dbus_strerror (errno));
4375       return FALSE;
4376     }
4377   else
4378     return TRUE;
4379 }
4380
4381 /**
4382  * Generates the given number of random bytes,
4383  * using the best mechanism we can come up with.
4384  *
4385  * @param str the string
4386  * @param n_bytes the number of random bytes to append to string
4387  * @returns #TRUE on success, #FALSE if no memory
4388  */
4389 dbus_bool_t
4390 _dbus_generate_random_bytes (DBusString *str,
4391                              int         n_bytes)
4392 {
4393   return pseudorandom_generate_random_bytes (str, n_bytes);
4394 }
4395
4396 #if !defined (DBUS_DISABLE_ASSERT) || defined(DBUS_BUILD_TESTS)
4397
4398 #ifdef _MSC_VER
4399 # ifdef BACKTRACES
4400 #  undef BACKTRACES
4401 # endif
4402 #else
4403 # define BACKTRACES
4404 #endif
4405
4406 #ifdef BACKTRACES
4407 /*
4408  * Backtrace Generator
4409  *
4410  * Copyright 2004 Eric Poech
4411  * Copyright 2004 Robert Shearman
4412  *
4413  * This library is free software; you can redistribute it and/or
4414  * modify it under the terms of the GNU Lesser General Public
4415  * License as published by the Free Software Foundation; either
4416  * version 2.1 of the License, or (at your option) any later version.
4417  *
4418  * This library is distributed in the hope that it will be useful,
4419  * but WITHOUT ANY WARRANTY; without even the implied warranty of
4420  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
4421  * Lesser General Public License for more details.
4422  *
4423  * You should have received a copy of the GNU Lesser General Public
4424  * License along with this library; if not, write to the Free Software
4425  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
4426  */
4427
4428 #include <winver.h>
4429 #include <imagehlp.h>
4430 #include <stdio.h>
4431
4432 #define DPRINTF _dbus_warn
4433
4434 #ifdef _MSC_VER
4435 #define BOOL int
4436
4437 #define __i386__
4438 #endif
4439
4440 //#define MAKE_FUNCPTR(f) static typeof(f) * p##f
4441
4442 //MAKE_FUNCPTR(StackWalk);
4443 //MAKE_FUNCPTR(SymGetModuleBase);
4444 //MAKE_FUNCPTR(SymFunctionTableAccess);
4445 //MAKE_FUNCPTR(SymInitialize);
4446 //MAKE_FUNCPTR(SymGetSymFromAddr);
4447 //MAKE_FUNCPTR(SymGetModuleInfo);
4448 static BOOL (WINAPI *pStackWalk)(
4449   DWORD MachineType,
4450   HANDLE hProcess,
4451   HANDLE hThread,
4452   LPSTACKFRAME StackFrame,
4453   PVOID ContextRecord,
4454   PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
4455   PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
4456   PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
4457   PTRANSLATE_ADDRESS_ROUTINE TranslateAddress
4458 );
4459 static DWORD (WINAPI *pSymGetModuleBase)(
4460   HANDLE hProcess,
4461   DWORD dwAddr
4462 );
4463 static PVOID  (WINAPI *pSymFunctionTableAccess)(
4464   HANDLE hProcess,
4465   DWORD AddrBase
4466 );
4467 static BOOL  (WINAPI *pSymInitialize)(
4468   HANDLE hProcess,
4469   PSTR UserSearchPath,
4470   BOOL fInvadeProcess
4471 );
4472 static BOOL  (WINAPI *pSymGetSymFromAddr)(
4473   HANDLE hProcess,
4474   DWORD Address,
4475   PDWORD Displacement,
4476   PIMAGEHLP_SYMBOL Symbol
4477 );
4478 static BOOL  (WINAPI *pSymGetModuleInfo)(
4479   HANDLE hProcess,
4480   DWORD dwAddr,
4481   PIMAGEHLP_MODULE ModuleInfo
4482 );
4483 static DWORD  (WINAPI *pSymSetOptions)(
4484   DWORD SymOptions
4485 );
4486
4487
4488 static BOOL init_backtrace()
4489 {
4490     HMODULE hmodDbgHelp = LoadLibraryA("dbghelp");
4491 /*
4492     #define GETFUNC(x) \
4493     p##x = (typeof(x)*)GetProcAddress(hmodDbgHelp, #x); \
4494     if (!p##x) \
4495     { \
4496         return FALSE; \
4497     }
4498     */
4499
4500
4501 //    GETFUNC(StackWalk);
4502 //    GETFUNC(SymGetModuleBase);
4503 //    GETFUNC(SymFunctionTableAccess);
4504 //    GETFUNC(SymInitialize);
4505 //    GETFUNC(SymGetSymFromAddr);
4506 //    GETFUNC(SymGetModuleInfo);
4507
4508 #define FUNC(x) #x
4509
4510       pStackWalk = (BOOL  (WINAPI *)(
4511 DWORD MachineType,
4512 HANDLE hProcess,
4513 HANDLE hThread,
4514 LPSTACKFRAME StackFrame,
4515 PVOID ContextRecord,
4516 PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
4517 PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
4518 PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
4519 PTRANSLATE_ADDRESS_ROUTINE TranslateAddress
4520 ))GetProcAddress (hmodDbgHelp, FUNC(StackWalk));
4521     pSymGetModuleBase=(DWORD  (WINAPI *)(
4522   HANDLE hProcess,
4523   DWORD dwAddr
4524 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleBase));
4525     pSymFunctionTableAccess=(PVOID  (WINAPI *)(
4526   HANDLE hProcess,
4527   DWORD AddrBase
4528 ))GetProcAddress (hmodDbgHelp, FUNC(SymFunctionTableAccess));
4529     pSymInitialize = (BOOL  (WINAPI *)(
4530   HANDLE hProcess,
4531   PSTR UserSearchPath,
4532   BOOL fInvadeProcess
4533 ))GetProcAddress (hmodDbgHelp, FUNC(SymInitialize));
4534     pSymGetSymFromAddr = (BOOL  (WINAPI *)(
4535   HANDLE hProcess,
4536   DWORD Address,
4537   PDWORD Displacement,
4538   PIMAGEHLP_SYMBOL Symbol
4539 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetSymFromAddr));
4540     pSymGetModuleInfo = (BOOL  (WINAPI *)(
4541   HANDLE hProcess,
4542   DWORD dwAddr,
4543   PIMAGEHLP_MODULE ModuleInfo
4544 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleInfo));
4545 pSymSetOptions = (DWORD  (WINAPI *)(
4546 DWORD SymOptions
4547 ))GetProcAddress (hmodDbgHelp, FUNC(SymSetOptions));
4548
4549
4550     pSymSetOptions(SYMOPT_UNDNAME);
4551
4552     pSymInitialize(GetCurrentProcess(), NULL, TRUE);
4553
4554     return TRUE;
4555 }
4556
4557 static void dump_backtrace_for_thread(HANDLE hThread)
4558 {
4559     STACKFRAME sf;
4560     CONTEXT context;
4561     DWORD dwImageType;
4562
4563     if (!pStackWalk)
4564         if (!init_backtrace())
4565             return;
4566
4567     /* can't use this function for current thread as GetThreadContext
4568      * doesn't support getting context from current thread */
4569     if (hThread == GetCurrentThread())
4570         return;
4571
4572     DPRINTF("Backtrace:\n");
4573
4574     memset(&context, 0, sizeof(context));
4575     context.ContextFlags = CONTEXT_FULL;
4576
4577     SuspendThread(hThread);
4578
4579     if (!GetThreadContext(hThread, &context))
4580     {
4581         DPRINTF("Couldn't get thread context (error %ld)\n", GetLastError());
4582         ResumeThread(hThread);
4583         return;
4584     }
4585
4586     memset(&sf, 0, sizeof(sf));
4587
4588 #ifdef __i386__
4589     sf.AddrFrame.Offset = context.Ebp;
4590     sf.AddrFrame.Mode = AddrModeFlat;
4591     sf.AddrPC.Offset = context.Eip;
4592     sf.AddrPC.Mode = AddrModeFlat;
4593     dwImageType = IMAGE_FILE_MACHINE_I386;
4594 #else
4595 # error You need to fill in the STACKFRAME structure for your architecture
4596 #endif
4597
4598     while (pStackWalk(dwImageType, GetCurrentProcess(),
4599                      hThread, &sf, &context, NULL, pSymFunctionTableAccess,
4600                      pSymGetModuleBase, NULL))
4601     {
4602         BYTE buffer[256];
4603         IMAGEHLP_SYMBOL * pSymbol = (IMAGEHLP_SYMBOL *)buffer;
4604         DWORD dwDisplacement;
4605
4606         pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
4607         pSymbol->MaxNameLength = sizeof(buffer) - sizeof(IMAGEHLP_SYMBOL) + 1;
4608
4609         if (!pSymGetSymFromAddr(GetCurrentProcess(), sf.AddrPC.Offset,
4610                                 &dwDisplacement, pSymbol))
4611         {
4612             IMAGEHLP_MODULE ModuleInfo;
4613             ModuleInfo.SizeOfStruct = sizeof(ModuleInfo);
4614
4615             if (!pSymGetModuleInfo(GetCurrentProcess(), sf.AddrPC.Offset,
4616                                    &ModuleInfo))
4617                 DPRINTF("1\t%p\n", (void*)sf.AddrPC.Offset);
4618             else
4619                 DPRINTF("2\t%s+0x%lx\n", ModuleInfo.ImageName,
4620                     sf.AddrPC.Offset - ModuleInfo.BaseOfImage);
4621         }
4622         else if (dwDisplacement)
4623             DPRINTF("3\t%s+0x%lx\n", pSymbol->Name, dwDisplacement);
4624         else
4625             DPRINTF("4\t%s\n", pSymbol->Name);
4626     }
4627
4628     ResumeThread(hThread);
4629 }
4630
4631 static DWORD WINAPI dump_thread_proc(LPVOID lpParameter)
4632 {
4633     dump_backtrace_for_thread((HANDLE)lpParameter);
4634     return 0;
4635 }
4636
4637 /* cannot get valid context from current thread, so we have to execute
4638  * backtrace from another thread */
4639 static void dump_backtrace()
4640 {
4641     HANDLE hCurrentThread;
4642     HANDLE hThread;
4643     DWORD dwThreadId;
4644     DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
4645         GetCurrentProcess(), &hCurrentThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
4646     hThread = CreateThread(NULL, 0, dump_thread_proc, (LPVOID)hCurrentThread,
4647         0, &dwThreadId);
4648     WaitForSingleObject(hThread, INFINITE);
4649     CloseHandle(hThread);
4650     CloseHandle(hCurrentThread);
4651 }
4652
4653 void _dbus_print_backtrace(void)
4654 {
4655   init_backtrace();
4656   dump_backtrace();
4657 }
4658 #else
4659 void _dbus_print_backtrace(void)
4660 {
4661   _dbus_verbose ("  D-Bus not compiled with backtrace support\n");
4662 }
4663 #endif
4664
4665 /**
4666  * Sends a single nul byte with our UNIX credentials as ancillary
4667  * data.  Returns #TRUE if the data was successfully written.  On
4668  * systems that don't support sending credentials, just writes a byte,
4669  * doesn't send any credentials.  On some systems, such as Linux,
4670  * reading/writing the byte isn't actually required, but we do it
4671  * anyway just to avoid multiple codepaths.
4672  *
4673  * Fails if no byte can be written, so you must select() first.
4674  *
4675  * The point of the byte is that on some systems we have to
4676  * use sendmsg()/recvmsg() to transmit credentials.
4677  *
4678  * @param server_fd file descriptor for connection to server
4679  * @param error return location for error code
4680  * @returns #TRUE if the byte was sent
4681  */
4682 dbus_bool_t
4683 _dbus_send_credentials_unix_socket  (int              server_fd,
4684                                      DBusError       *error)
4685 {
4686   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4687
4688   if (write_credentials_byte (server_fd, error))
4689     return TRUE;
4690   else
4691     return FALSE;
4692 }
4693
4694 static dbus_uint32_t fromAscii(char ascii)
4695 {
4696     if(ascii >= '0' && ascii <= '9')
4697         return ascii - '0';
4698     if(ascii >= 'A' && ascii <= 'F')
4699         return ascii - 'A' + 10;
4700     if(ascii >= 'a' && ascii <= 'f')
4701         return ascii - 'a' + 10;
4702     return 0;    
4703 }
4704
4705 dbus_bool_t _dbus_read_local_machine_uuid   (DBusGUID         *machine_id,
4706                                              dbus_bool_t       create_if_not_found,
4707                                              DBusError        *error)
4708 {
4709 #ifdef DBUS_WINCE
4710         return TRUE;
4711   // TODO
4712 #else
4713     HW_PROFILE_INFOA info;
4714     char *lpc = &info.szHwProfileGuid[0];
4715     dbus_uint32_t u;
4716
4717     //  the hw-profile guid lives long enough
4718     if(!GetCurrentHwProfileA(&info))
4719       {
4720         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); // FIXME
4721         return FALSE;  
4722       }
4723
4724     // Form: {12340001-4980-1920-6788-123456789012}
4725     lpc++;
4726     // 12340001
4727     u = ((fromAscii(lpc[0]) <<  0) |
4728          (fromAscii(lpc[1]) <<  4) |
4729          (fromAscii(lpc[2]) <<  8) |
4730          (fromAscii(lpc[3]) << 12) |
4731          (fromAscii(lpc[4]) << 16) |
4732          (fromAscii(lpc[5]) << 20) |
4733          (fromAscii(lpc[6]) << 24) |
4734          (fromAscii(lpc[7]) << 28));
4735     machine_id->as_uint32s[0] = u;
4736
4737     lpc += 9;
4738     // 4980-1920
4739     u = ((fromAscii(lpc[0]) <<  0) |
4740          (fromAscii(lpc[1]) <<  4) |
4741          (fromAscii(lpc[2]) <<  8) |
4742          (fromAscii(lpc[3]) << 12) |
4743          (fromAscii(lpc[5]) << 16) |
4744          (fromAscii(lpc[6]) << 20) |
4745          (fromAscii(lpc[7]) << 24) |
4746          (fromAscii(lpc[8]) << 28));
4747     machine_id->as_uint32s[1] = u;
4748     
4749     lpc += 10;
4750     // 6788-1234
4751     u = ((fromAscii(lpc[0]) <<  0) |
4752          (fromAscii(lpc[1]) <<  4) |
4753          (fromAscii(lpc[2]) <<  8) |
4754          (fromAscii(lpc[3]) << 12) |
4755          (fromAscii(lpc[5]) << 16) |
4756          (fromAscii(lpc[6]) << 20) |
4757          (fromAscii(lpc[7]) << 24) |
4758          (fromAscii(lpc[8]) << 28));
4759     machine_id->as_uint32s[2] = u;
4760     
4761     lpc += 9;
4762     // 56789012
4763     u = ((fromAscii(lpc[0]) <<  0) |
4764          (fromAscii(lpc[1]) <<  4) |
4765          (fromAscii(lpc[2]) <<  8) |
4766          (fromAscii(lpc[3]) << 12) |
4767          (fromAscii(lpc[4]) << 16) |
4768          (fromAscii(lpc[5]) << 20) |
4769          (fromAscii(lpc[6]) << 24) |
4770          (fromAscii(lpc[7]) << 28));
4771     machine_id->as_uint32s[3] = u;
4772 #endif
4773     return TRUE;
4774 }
4775
4776 static
4777 HANDLE _dbus_global_lock (const char *mutexname)
4778 {
4779   HANDLE mutex;
4780   DWORD gotMutex;
4781
4782   mutex = CreateMutex( NULL, FALSE, mutexname );
4783   if( !mutex )
4784     {
4785       return FALSE;
4786     }
4787
4788    gotMutex = WaitForSingleObject( mutex, INFINITE );
4789    switch( gotMutex )
4790      {
4791        case WAIT_ABANDONED:
4792                ReleaseMutex (mutex);
4793                CloseHandle (mutex);
4794                return 0;
4795        case WAIT_FAILED:
4796        case WAIT_TIMEOUT:
4797                return 0;
4798      }
4799
4800    return mutex;
4801 }
4802
4803 static
4804 void _dbus_global_unlock (HANDLE mutex)
4805 {
4806   ReleaseMutex (mutex);
4807   CloseHandle (mutex); 
4808 }
4809
4810 // for proper cleanup in dbus-daemon
4811 static HANDLE hDBusDaemonMutex = NULL;
4812 static HANDLE hDBusSharedMem = NULL;
4813 // sync _dbus_daemon_init, _dbus_daemon_uninit and _dbus_daemon_already_runs
4814 static const char *cUniqueDBusInitMutex = "UniqueDBusInitMutex";
4815 // sync _dbus_get_autolaunch_address
4816 static const char *cDBusAutolaunchMutex = "DBusAutolaunchMutex";
4817 // mutex to determine if dbus-daemon is already started (per user)
4818 static const char *cDBusDaemonMutex = "DBusDaemonMutex";
4819 // named shm for dbus adress info (per user)
4820 static const char *cDBusDaemonAddressInfo = "DBusDaemonAddressInfo";
4821
4822 void
4823 _dbus_daemon_init(const char *host, dbus_uint32_t port)
4824 {
4825   HANDLE lock;
4826   const char *adr = NULL;
4827   char szUserName[64];
4828   DWORD dwUserNameSize = sizeof(szUserName);
4829   char szDBusDaemonMutex[128];
4830   char szDBusDaemonAddressInfo[128];
4831   char szAddress[128];
4832
4833   _dbus_assert(host);
4834   _dbus_assert(port);
4835
4836   _snprintf(szAddress, sizeof(szAddress) - 1, "tcp:host=%s,port=%d", host, port);
4837
4838   _dbus_assert( GetUserName(szUserName, &dwUserNameSize) != 0);
4839   _snprintf(szDBusDaemonMutex, sizeof(szDBusDaemonMutex) - 1, "%s:%s",
4840             cDBusDaemonMutex, szUserName);
4841   _snprintf(szDBusDaemonAddressInfo, sizeof(szDBusDaemonAddressInfo) - 1, "%s:%s",
4842             cDBusDaemonAddressInfo, szUserName);
4843
4844   // before _dbus_global_lock to keep correct lock/release order
4845   hDBusDaemonMutex = CreateMutex( NULL, FALSE, szDBusDaemonMutex );
4846
4847   _dbus_assert(WaitForSingleObject( hDBusDaemonMutex, 1000 ) == WAIT_OBJECT_0);
4848
4849   // sync _dbus_daemon_init, _dbus_daemon_uninit and _dbus_daemon_already_runs
4850   lock = _dbus_global_lock( cUniqueDBusInitMutex );
4851
4852   // create shm
4853   hDBusSharedMem = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
4854                                       0, strlen( szAddress ) + 1, szDBusDaemonAddressInfo );
4855   _dbus_assert( hDBusSharedMem );
4856
4857   adr = MapViewOfFile( hDBusSharedMem, FILE_MAP_WRITE, 0, 0, 0 );
4858
4859   _dbus_assert( adr );
4860
4861   strcpy(adr, szAddress);
4862
4863   // cleanup
4864   UnmapViewOfFile( adr );
4865
4866   _dbus_global_unlock( lock );
4867 }
4868
4869 void
4870 _dbus_daemon_release()
4871 {
4872   HANDLE lock;
4873
4874   // sync _dbus_daemon_init, _dbus_daemon_uninit and _dbus_daemon_already_runs
4875   lock = _dbus_global_lock( cUniqueDBusInitMutex );
4876
4877   CloseHandle( hDBusSharedMem );
4878
4879   hDBusSharedMem = NULL;
4880
4881   ReleaseMutex( hDBusDaemonMutex );
4882
4883   CloseHandle( hDBusDaemonMutex );
4884
4885   hDBusDaemonMutex = NULL;
4886
4887   _dbus_global_unlock( lock );
4888 }
4889
4890 static dbus_bool_t
4891 _dbus_get_autolaunch_shm(DBusString *adress)
4892 {
4893   HANDLE sharedMem;
4894   const char *adr;
4895   char szUserName[64];
4896   DWORD dwUserNameSize = sizeof(szUserName);
4897   char szDBusDaemonAddressInfo[128];
4898
4899   if( !GetUserName(szUserName, &dwUserNameSize) )
4900       return FALSE;
4901   _snprintf(szDBusDaemonAddressInfo, sizeof(szDBusDaemonAddressInfo) - 1, "%s:%s",
4902             cDBusDaemonAddressInfo, szUserName);
4903
4904   // read shm
4905   do {
4906       // we know that dbus-daemon is available, so we wait until shm is available
4907       sharedMem = OpenFileMapping( FILE_MAP_READ, FALSE, szDBusDaemonAddressInfo );
4908       if( sharedMem == 0 )
4909           Sleep( 100 );
4910   } while( sharedMem == 0 );
4911
4912   if( sharedMem == 0 )
4913       return FALSE;
4914
4915   adr = MapViewOfFile( sharedMem, FILE_MAP_READ, 0, 0, 0 );
4916
4917   if( adr == 0 )
4918       return FALSE;
4919
4920   _dbus_string_init( adress );
4921
4922   _dbus_string_append( adress, adr ); 
4923
4924   // cleanup
4925   UnmapViewOfFile( adr );
4926
4927   CloseHandle( sharedMem );
4928
4929   return TRUE;
4930 }
4931
4932 static dbus_bool_t
4933 _dbus_daemon_already_runs (DBusString *adress)
4934 {
4935   HANDLE lock;
4936   HANDLE daemon;
4937   dbus_bool_t bRet = TRUE;
4938   char szUserName[64];
4939   DWORD dwUserNameSize = sizeof(szUserName);
4940   char szDBusDaemonMutex[128];
4941
4942   // sync _dbus_daemon_init, _dbus_daemon_uninit and _dbus_daemon_already_runs
4943   lock = _dbus_global_lock( cUniqueDBusInitMutex );
4944
4945   if( !GetUserName(szUserName, &dwUserNameSize) )
4946       return FALSE;
4947   _snprintf(szDBusDaemonMutex, sizeof(szDBusDaemonMutex) - 1, "%s:%s",
4948             cDBusDaemonMutex, szUserName);
4949
4950   // do checks
4951   daemon = CreateMutex( NULL, FALSE, szDBusDaemonMutex );
4952   if(WaitForSingleObject( daemon, 10 ) != WAIT_TIMEOUT)
4953     {
4954       ReleaseMutex (daemon);
4955       CloseHandle (daemon);
4956
4957       _dbus_global_unlock( lock );
4958       return FALSE;
4959     }
4960
4961   // read shm
4962   bRet = _dbus_get_autolaunch_shm( adress );
4963
4964   // cleanup
4965   CloseHandle ( daemon );
4966
4967   _dbus_global_unlock( lock );
4968
4969   return bRet;
4970 }
4971
4972 dbus_bool_t
4973 _dbus_get_autolaunch_address (DBusString *address, 
4974                               DBusError *error)
4975 {
4976   HANDLE mutex;
4977   STARTUPINFOA si;
4978   PROCESS_INFORMATION pi;
4979   dbus_bool_t retval = FALSE;
4980   LPSTR lpFile;
4981   char dbus_exe_path[MAX_PATH];
4982   char dbus_args[MAX_PATH * 2];
4983
4984   mutex = _dbus_global_lock ( cDBusAutolaunchMutex );
4985
4986   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4987
4988   if (_dbus_daemon_already_runs(address))
4989     {
4990         printf("dbus daemon already exists\n");
4991         retval = TRUE;
4992         goto out;
4993     }
4994
4995   if (!SearchPathA(NULL, "dbus-daemon.exe", NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile))
4996     {
4997       printf ("could not find dbus-daemon executable\n");
4998       goto out;
4999     }
5000
5001   // Create process
5002   ZeroMemory( &si, sizeof(si) );
5003   si.cb = sizeof(si);
5004   ZeroMemory( &pi, sizeof(pi) );
5005
5006   _snprintf(dbus_args, sizeof(dbus_args) - 1, "\"%s\" %s", dbus_exe_path,  " --session");
5007
5008 //  argv[i] = "--config-file=bus\\session.conf";
5009   printf("create process \"%s\" %s\n", dbus_exe_path, dbus_args);
5010   if(CreateProcessA(dbus_exe_path, dbus_args, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
5011     {
5012       retval = TRUE;
5013
5014       // Wait until started (see _dbus_get_autolaunch_shm())
5015       WaitForInputIdle(pi.hProcess, INFINITE);
5016
5017       retval = _dbus_get_autolaunch_shm( address );
5018     } else {
5019       retval = FALSE;
5020     }
5021   
5022 out:
5023   if (retval)
5024     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
5025   else
5026     _DBUS_ASSERT_ERROR_IS_SET (error);
5027   
5028   _dbus_global_unlock (mutex);
5029
5030   return retval;
5031  }
5032
5033
5034 /** Makes the file readable by every user in the system.
5035  *
5036  * @param filename the filename
5037  * @param error error location
5038  * @returns #TRUE if the file's permissions could be changed.
5039  */
5040 dbus_bool_t
5041 _dbus_make_file_world_readable(const DBusString *filename,
5042                                DBusError *error)
5043 {
5044   // TODO
5045   return TRUE;
5046 }
5047
5048
5049 #define DBUS_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
5050
5051
5052 /**
5053  * Returns the standard directories for a session bus to look for service 
5054  * activation files 
5055  *
5056  * On Windows this should be data directories:
5057  *
5058  * %CommonProgramFiles%/dbus
5059  *
5060  * and
5061  *
5062  * DBUS_DATADIR
5063  *
5064  * @param dirs the directory list we are returning
5065  * @returns #FALSE on OOM 
5066  */
5067
5068 dbus_bool_t 
5069 _dbus_get_standard_session_servicedirs (DBusList **dirs)
5070 {
5071   const char *common_progs;
5072   DBusString servicedir_path;
5073
5074   if (!_dbus_string_init (&servicedir_path))
5075     return FALSE;
5076
5077   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR _DBUS_PATH_SEPARATOR))
5078         goto oom;
5079
5080   common_progs = _dbus_getenv ("CommonProgramFiles");
5081
5082   if (common_progs != NULL)
5083     {
5084       if (!_dbus_string_append (&servicedir_path, common_progs))
5085         goto oom;
5086
5087       if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR))
5088         goto oom;
5089     }
5090
5091   if (!_dbus_split_paths_and_append (&servicedir_path, 
5092                                DBUS_STANDARD_SESSION_SERVICEDIR, 
5093                                dirs))
5094     goto oom;
5095
5096   _dbus_string_free (&servicedir_path);  
5097   return TRUE;
5098
5099  oom:
5100   _dbus_string_free (&servicedir_path);
5101   return FALSE;
5102 }
5103
5104 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
5105
5106 /**
5107  * Atomically increments an integer
5108  *
5109  * @param atomic pointer to the integer to increment
5110  * @returns the value before incrementing
5111  *
5112  */
5113 dbus_int32_t
5114 _dbus_atomic_inc (DBusAtomic *atomic)
5115 {
5116   // +/- 1 is needed here!
5117   return InterlockedIncrement (&atomic->value) - 1;
5118 }
5119
5120 /**
5121  * Atomically decrement an integer
5122  *
5123  * @param atomic pointer to the integer to decrement
5124  * @returns the value before decrementing
5125  *
5126  */
5127 dbus_int32_t
5128 _dbus_atomic_dec (DBusAtomic *atomic)
5129 {
5130   // +/- 1 is needed here!
5131   return InterlockedDecrement (&atomic->value) + 1;
5132 }
5133
5134 #endif /* asserts or tests enabled */
5135
5136 /** @} end of sysdeps-win */
5137
5138 /* tests in dbus-sysdeps-util.c */