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