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