* dbus/dbus-sysdeps.h (_dbus_listen_tcp_socket): changed type or port to pointer...
[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           char *user_name = _dbus_win_utf16_to_utf8(wname,error);
1308       _dbus_warn("NetUserGetInfo() for user '%s' failed with errorcode %d '%s', %s\n",user_name, ret,_dbus_lm_strerror(ret),dc_string);
1309       dbus_free(user_name);
1310       dbus_free(dc_string);
1311       /* Not set, so use something random. */
1312       info->homedir = _dbus_strdup ("\\");
1313     }
1314
1315   retval = TRUE;
1316
1317 out1:
1318   if (dc != NULL)
1319     NetApiBufferFree (dc);
1320   if (user_info != NULL)
1321     NetApiBufferFree (user_info);
1322
1323   return retval;
1324 #endif //DBUS_WINCE
1325 }
1326
1327 dbus_bool_t
1328 fill_win_user_info_from_name (wchar_t      *wname,
1329                               DBusUserInfo *info,
1330                               DBusError    *error)
1331 {
1332 #ifdef DBUS_WINCE
1333         return TRUE;
1334         //TODO
1335 #else
1336   dbus_bool_t retval = FALSE;
1337   PSID sid;
1338   wchar_t *wdomain;
1339   DWORD sid_length, wdomain_length;
1340   SID_NAME_USE use;
1341
1342   sid_length = 0;
1343   wdomain_length = 0;
1344   if (!LookupAccountNameW (NULL, wname, NULL, &sid_length,
1345                            NULL, &wdomain_length, &use) &&
1346       GetLastError () != ERROR_INSUFFICIENT_BUFFER)
1347     {
1348       _dbus_win_set_error_from_win_error (error, GetLastError ());
1349       return FALSE;
1350     }
1351
1352   sid = dbus_malloc (sid_length);
1353   if (!sid)
1354     {
1355       _DBUS_SET_OOM (error);
1356       return FALSE;
1357     }
1358
1359   wdomain = dbus_new (wchar_t, wdomain_length);
1360   if (!wdomain)
1361     {
1362       _DBUS_SET_OOM (error);
1363       goto out0;
1364     }
1365
1366   if (!LookupAccountNameW (NULL, wname, sid, &sid_length,
1367                            wdomain, &wdomain_length, &use))
1368     {
1369       _dbus_win_set_error_from_win_error (error, GetLastError ());
1370       goto out1;
1371     }
1372
1373   if (!IsValidSid (sid))
1374     {
1375       dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid SID");
1376       goto out1;
1377     }
1378
1379   info->uid = _dbus_win_sid_to_uid_t (sid);
1380
1381   if (!fill_win_user_info_name_and_groups (wname, wdomain, info, error))
1382     goto out1;
1383
1384   if (!fill_win_user_info_homedir (wname, wdomain, info, error))
1385     goto out1;
1386
1387   retval = TRUE;
1388
1389 out1:
1390   dbus_free (wdomain);
1391 out0:
1392   dbus_free (sid);
1393
1394   return retval;
1395 #endif //DBUS_WINCE
1396 }
1397
1398 dbus_bool_t
1399 _dbus_win_sid_to_name_and_domain (dbus_uid_t uid,
1400                                   wchar_t  **wname,
1401                                   wchar_t  **wdomain,
1402                                   DBusError *error)
1403 {
1404 #ifdef DBUS_WINCE
1405         return TRUE;
1406         //TODO
1407 #else
1408   PSID sid;
1409   DWORD wname_length, wdomain_length;
1410   SID_NAME_USE use;
1411
1412   if (!_dbus_uid_t_to_win_sid (uid, &sid))
1413     {
1414       _dbus_win_set_error_from_win_error (error, GetLastError ());
1415       return FALSE;
1416     }
1417
1418   wname_length = 0;
1419   wdomain_length = 0;
1420   if (!LookupAccountSidW (NULL, sid, NULL, &wname_length,
1421                           NULL, &wdomain_length, &use) &&
1422       GetLastError () != ERROR_INSUFFICIENT_BUFFER)
1423     {
1424       _dbus_win_set_error_from_win_error (error, GetLastError ());
1425       goto out0;
1426     }
1427
1428   *wname = dbus_new (wchar_t, wname_length);
1429   if (!*wname)
1430     {
1431       _DBUS_SET_OOM (error);
1432       goto out0;
1433     }
1434
1435   *wdomain = dbus_new (wchar_t, wdomain_length);
1436   if (!*wdomain)
1437     {
1438       _DBUS_SET_OOM (error);
1439       goto out1;
1440     }
1441
1442   if (!LookupAccountSidW (NULL, sid, *wname, &wname_length,
1443                           *wdomain, &wdomain_length, &use))
1444     {
1445       _dbus_win_set_error_from_win_error (error, GetLastError ());
1446       goto out2;
1447     }
1448
1449   return TRUE;
1450
1451 out2:
1452   dbus_free (*wdomain);
1453   *wdomain = NULL;
1454 out1:
1455   dbus_free (*wname);
1456   *wname = NULL;
1457 out0:
1458   LocalFree (sid);
1459
1460   return FALSE;
1461 #endif //DBUS_WINCE
1462 }
1463
1464 dbus_bool_t
1465 fill_win_user_info_from_uid (dbus_uid_t    uid,
1466                              DBusUserInfo *info,
1467                              DBusError    *error)
1468 {
1469 #ifdef DBUS_WINCE
1470         return TRUE;
1471         //TODO
1472 #else
1473   PSID sid;
1474   dbus_bool_t retval = FALSE;
1475   wchar_t *wname, *wdomain;
1476
1477   info->uid = uid;
1478
1479   if (!_dbus_win_sid_to_name_and_domain (uid, &wname, &wdomain, error))
1480     {
1481       _dbus_verbose("%s after _dbus_win_sid_to_name_and_domain\n",__FUNCTION__);
1482       return FALSE;
1483     }
1484
1485   if (!fill_win_user_info_name_and_groups (wname, wdomain, info, error))
1486     {
1487       _dbus_verbose("%s after fill_win_user_info_name_and_groups\n",__FUNCTION__);
1488       goto out0;
1489     }
1490
1491
1492   if (!fill_win_user_info_homedir (wname, wdomain, info, error))
1493     {
1494       _dbus_verbose("%s after fill_win_user_info_homedir\n",__FUNCTION__);
1495       goto out0;
1496     }
1497
1498   retval = TRUE;
1499
1500 out0:
1501   dbus_free (wdomain);
1502   dbus_free (wname);
1503
1504   return retval;
1505 #endif //DBUS_WINCE
1506 }
1507
1508
1509
1510
1511 void
1512 _dbus_win_startup_winsock (void)
1513 {
1514   /* Straight from MSDN, deuglified */
1515
1516   static dbus_bool_t beenhere = FALSE;
1517
1518   WORD wVersionRequested;
1519   WSADATA wsaData;
1520   int err;
1521
1522   if (beenhere)
1523     return;
1524
1525   wVersionRequested = MAKEWORD (2, 0);
1526
1527   err = WSAStartup (wVersionRequested, &wsaData);
1528   if (err != 0)
1529     {
1530       _dbus_assert_not_reached ("Could not initialize WinSock");
1531       _dbus_abort ();
1532     }
1533
1534   /* Confirm that the WinSock DLL supports 2.0.  Note that if the DLL
1535    * supports versions greater than 2.0 in addition to 2.0, it will
1536    * still return 2.0 in wVersion since that is the version we
1537    * requested.
1538    */
1539   if (LOBYTE (wsaData.wVersion) != 2 ||
1540       HIBYTE (wsaData.wVersion) != 0)
1541     {
1542       _dbus_assert_not_reached ("No usable WinSock found");
1543       _dbus_abort ();
1544     }
1545
1546   beenhere = TRUE;
1547 }
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557 /************************************************************************
1558  
1559  UTF / string code
1560  
1561  ************************************************************************/
1562
1563 /**
1564  * Measure the message length without terminating nul 
1565  */
1566 int _dbus_printf_string_upper_bound (const char *format,
1567                                      va_list args)
1568 {
1569   /* MSVCRT's vsnprintf semantics are a bit different */
1570   /* The C library source in the Platform SDK indicates that this
1571    * would work, but alas, it doesn't. At least not on Windows
1572    * 2000. Presumably those sources correspond to the C library on
1573    * some newer or even future Windows version.
1574    *
1575     len = _vsnprintf (NULL, _DBUS_INT_MAX, format, args);
1576    */
1577   char p[1024];
1578   int len;
1579   len = vsnprintf (p, sizeof(p)-1, format, args);
1580   if (len == -1) // try again
1581     {
1582       char *p;
1583       p = malloc (strlen(format)*3);
1584       len = vsnprintf (p, sizeof(p)-1, format, args);
1585       free(p);
1586     }
1587   return len;
1588 }
1589
1590
1591 /**
1592  * Returns the UTF-16 form of a UTF-8 string. The result should be
1593  * freed with dbus_free() when no longer needed.
1594  *
1595  * @param str the UTF-8 string
1596  * @param error return location for error code
1597  */
1598 wchar_t *
1599 _dbus_win_utf8_to_utf16 (const char *str,
1600                          DBusError  *error)
1601 {
1602   DBusString s;
1603   int n;
1604   wchar_t *retval;
1605
1606   _dbus_string_init_const (&s, str);
1607
1608   if (!_dbus_string_validate_utf8 (&s, 0, _dbus_string_get_length (&s)))
1609     {
1610       dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid UTF-8");
1611       return NULL;
1612     }
1613
1614   n = MultiByteToWideChar (CP_UTF8, 0, str, -1, NULL, 0);
1615
1616   if (n == 0)
1617     {
1618       _dbus_win_set_error_from_win_error (error, GetLastError ());
1619       return NULL;
1620     }
1621
1622   retval = dbus_new (wchar_t, n);
1623
1624   if (!retval)
1625     {
1626       _DBUS_SET_OOM (error);
1627       return NULL;
1628     }
1629
1630   if (MultiByteToWideChar (CP_UTF8, 0, str, -1, retval, n) != n)
1631     {
1632       dbus_free (retval);
1633       dbus_set_error_const (error, DBUS_ERROR_FAILED, "MultiByteToWideChar inconsistency");
1634       return NULL;
1635     }
1636
1637   return retval;
1638 }
1639
1640 /**
1641  * Returns the UTF-8 form of a UTF-16 string. The result should be
1642  * freed with dbus_free() when no longer needed.
1643  *
1644  * @param str the UTF-16 string
1645  * @param error return location for error code
1646  */
1647 char *
1648 _dbus_win_utf16_to_utf8 (const wchar_t *str,
1649                          DBusError     *error)
1650 {
1651   int n;
1652   char *retval;
1653
1654   n = WideCharToMultiByte (CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
1655
1656   if (n == 0)
1657     {
1658       _dbus_win_set_error_from_win_error (error, GetLastError ());
1659       return NULL;
1660     }
1661
1662   retval = dbus_malloc (n);
1663
1664   if (!retval)
1665     {
1666       _DBUS_SET_OOM (error);
1667       return NULL;
1668     }
1669
1670   if (WideCharToMultiByte (CP_UTF8, 0, str, -1, retval, n, NULL, NULL) != n)
1671     {
1672       dbus_free (retval);
1673       dbus_set_error_const (error, DBUS_ERROR_FAILED, "WideCharToMultiByte inconsistency");
1674       return NULL;
1675     }
1676
1677   return retval;
1678 }
1679
1680
1681
1682
1683
1684
1685 /************************************************************************
1686  
1687  uid ... <-> win sid functions
1688  
1689  ************************************************************************/
1690
1691 dbus_bool_t
1692 _dbus_win_account_to_sid (const wchar_t *waccount,
1693                           void           **ppsid,
1694                           DBusError       *error)
1695 {
1696   dbus_bool_t retval = FALSE;
1697   DWORD sid_length, wdomain_length;
1698   SID_NAME_USE use;
1699   wchar_t *wdomain;
1700
1701   *ppsid = NULL;
1702
1703   sid_length = 0;
1704   wdomain_length = 0;
1705   if (!LookupAccountNameW (NULL, waccount, NULL, &sid_length,
1706                            NULL, &wdomain_length, &use) &&
1707       GetLastError () != ERROR_INSUFFICIENT_BUFFER)
1708     {
1709       _dbus_win_set_error_from_win_error (error, GetLastError ());
1710       return FALSE;
1711     }
1712
1713   *ppsid = dbus_malloc (sid_length);
1714   if (!*ppsid)
1715     {
1716       _DBUS_SET_OOM (error);
1717       return FALSE;
1718     }
1719
1720   wdomain = dbus_new (wchar_t, wdomain_length);
1721   if (!wdomain)
1722     {
1723       _DBUS_SET_OOM (error);
1724       goto out1;
1725     }
1726
1727   if (!LookupAccountNameW (NULL, waccount, (PSID) *ppsid, &sid_length,
1728                            wdomain, &wdomain_length, &use))
1729     {
1730       _dbus_win_set_error_from_win_error (error, GetLastError ());
1731       goto out2;
1732     }
1733
1734   if (!IsValidSid ((PSID) *ppsid))
1735     {
1736       dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid SID");
1737       goto out2;
1738     }
1739
1740   retval = TRUE;
1741
1742 out2:
1743   dbus_free (wdomain);
1744 out1:
1745   if (!retval)
1746     {
1747       dbus_free (*ppsid);
1748       *ppsid = NULL;
1749     }
1750
1751   return retval;
1752 }
1753
1754 static void
1755 _sid_atom_cache_shutdown (void *unused)
1756 {
1757   DBusHashIter iter;
1758   _DBUS_LOCK (sid_atom_cache);
1759   _dbus_hash_iter_init (sid_atom_cache, &iter);
1760   while (_dbus_hash_iter_next (&iter))
1761     {
1762       ATOM atom;
1763       atom = (ATOM) _dbus_hash_iter_get_value (&iter);
1764       GlobalDeleteAtom(atom);
1765       _dbus_hash_iter_remove_entry(&iter);
1766     }
1767   _DBUS_UNLOCK (sid_atom_cache);
1768   _dbus_hash_table_unref (sid_atom_cache);
1769   sid_atom_cache = NULL;
1770 }
1771
1772 /**
1773  * Returns the 2-way associated dbus_uid_t form a SID.
1774  *
1775  * @param psid pointer to the SID
1776  */
1777 dbus_uid_t
1778 _dbus_win_sid_to_uid_t (PSID psid)
1779 {
1780   dbus_uid_t uid;
1781   dbus_uid_t olduid;
1782   char *string;
1783   ATOM atom;
1784
1785   if (!IsValidSid (psid))
1786     {
1787       _dbus_verbose("%s invalid sid\n",__FUNCTION__);
1788       return DBUS_UID_UNSET;
1789     }
1790   if (!ConvertSidToStringSidA (psid, &string))
1791     {
1792       _dbus_verbose("%s invalid sid\n",__FUNCTION__);
1793       return DBUS_UID_UNSET;
1794     }
1795
1796   atom = GlobalAddAtom(string);
1797
1798   if (atom == 0)
1799     {
1800       _dbus_verbose("%s GlobalAddAtom failed\n",__FUNCTION__);
1801       LocalFree (string);
1802       return DBUS_UID_UNSET;
1803     }
1804
1805   _DBUS_LOCK (sid_atom_cache);
1806
1807   if (sid_atom_cache == NULL)
1808     {
1809       sid_atom_cache = _dbus_hash_table_new (DBUS_HASH_ULONG, NULL, NULL);
1810       _dbus_register_shutdown_func (_sid_atom_cache_shutdown, NULL);
1811     }
1812
1813   uid = atom;
1814   olduid = (dbus_uid_t) _dbus_hash_table_lookup_ulong (sid_atom_cache, uid);
1815
1816   if (olduid)
1817     {
1818       _dbus_verbose("%s sid with id %i found in cache\n",__FUNCTION__, olduid);
1819       uid = olduid;
1820     }
1821   else
1822     {
1823       _dbus_hash_table_insert_ulong (sid_atom_cache, uid, (void*) uid);
1824       _dbus_verbose("%s sid %s added with uid %i to cache\n",__FUNCTION__, string, uid);
1825     }
1826
1827   _DBUS_UNLOCK (sid_atom_cache);
1828
1829   return uid;
1830 }
1831
1832 dbus_bool_t  _dbus_uid_t_to_win_sid (dbus_uid_t uid, PSID *ppsid)
1833 {
1834   void* atom;
1835   char string[255];
1836
1837   atom = _dbus_hash_table_lookup_ulong (sid_atom_cache, uid);
1838   if (atom == NULL)
1839     {
1840       _dbus_verbose("%s uid %i not found in cache\n",__FUNCTION__,uid);
1841       return FALSE;
1842     }
1843   memset( string, '.', sizeof(string) );
1844   if (!GlobalGetAtomNameA( (ATOM) atom, string, 255 ))
1845     {
1846       _dbus_verbose("%s uid %i not found in cache\n",__FUNCTION__, uid);
1847       return FALSE;
1848     }
1849   if (!ConvertStringSidToSidA(string, ppsid))
1850     {
1851       _dbus_verbose("%s could not convert %s into sid \n",__FUNCTION__, string);
1852       return FALSE;
1853     }
1854   _dbus_verbose("%s converted %s into sid \n",__FUNCTION__, string);
1855   return TRUE;
1856 }
1857
1858
1859 /** @} end of sysdeps-win */
1860
1861
1862 /** Gets our UID
1863  * @returns process UID
1864  */
1865 dbus_uid_t
1866 _dbus_getuid(void)
1867 {
1868   dbus_uid_t retval = DBUS_UID_UNSET;
1869   HANDLE process_token = NULL;
1870   TOKEN_USER *token_user = NULL;
1871   DWORD n;
1872
1873   if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &process_token))
1874     _dbus_win_warn_win_error ("OpenProcessToken failed", GetLastError ());
1875   else if ((!GetTokenInformation (process_token, TokenUser, NULL, 0, &n)
1876             && GetLastError () != ERROR_INSUFFICIENT_BUFFER)
1877            || (token_user = alloca (n)) == NULL
1878            || !GetTokenInformation (process_token, TokenUser, token_user, n, &n))
1879     _dbus_win_warn_win_error ("GetTokenInformation failed", GetLastError ());
1880   else
1881     retval = _dbus_win_sid_to_uid_t (token_user->User.Sid);
1882
1883   if (process_token != NULL)
1884     CloseHandle (process_token);
1885
1886   _dbus_verbose("_dbus_getuid() returns %d\n",retval);
1887   return retval;
1888 }
1889
1890 #ifdef DBUS_BUILD_TESTS
1891 /** Gets our GID
1892  * @returns process GID
1893  */
1894 dbus_gid_t
1895 _dbus_getgid (void)
1896 {
1897   dbus_gid_t retval = DBUS_GID_UNSET;
1898   HANDLE process_token = NULL;
1899   TOKEN_PRIMARY_GROUP *token_primary_group = NULL;
1900   DWORD n;
1901
1902   if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &process_token))
1903     _dbus_win_warn_win_error ("OpenProcessToken failed", GetLastError ());
1904   else if ((!GetTokenInformation (process_token, TokenPrimaryGroup,
1905                                   NULL, 0, &n) &&
1906             GetLastError () != ERROR_INSUFFICIENT_BUFFER) ||
1907            (token_primary_group = alloca (n)) == NULL ||
1908            !GetTokenInformation (process_token, TokenPrimaryGroup,
1909                                  token_primary_group, n, &n))
1910     _dbus_win_warn_win_error ("GetTokenInformation failed", GetLastError ());
1911   else
1912     retval = _dbus_win_sid_to_uid_t (token_primary_group->PrimaryGroup);
1913
1914   if (process_token != NULL)
1915     CloseHandle (process_token);
1916
1917   return retval;
1918 }
1919
1920 #if 0
1921 dbus_bool_t
1922 _dbus_domain_test (const char *test_data_dir)
1923 {
1924   if (!_dbus_test_oom_handling ("spawn_nonexistent",
1925                                 check_spawn_nonexistent,
1926                                 NULL))
1927     return FALSE;
1928 }
1929
1930 #endif
1931
1932 #endif //DBUS_BUILD_TESTS
1933
1934 /************************************************************************
1935  
1936  pipes
1937  
1938  ************************************************************************/
1939
1940 /**
1941  * Creates a full-duplex pipe (as in socketpair()).
1942  * Sets both ends of the pipe nonblocking.
1943  *
1944  * @todo libdbus only uses this for the debug-pipe server, so in
1945  * principle it could be in dbus-sysdeps-util.c, except that
1946  * dbus-sysdeps-util.c isn't in libdbus when tests are enabled and the
1947  * debug-pipe server is used.
1948  * 
1949  * @param fd1 return location for one end
1950  * @param fd2 return location for the other end
1951  * @param blocking #TRUE if pipe should be blocking
1952  * @param error error return
1953  * @returns #FALSE on failure (if error is set)
1954  */
1955 dbus_bool_t
1956 _dbus_full_duplex_pipe (int        *fd1,
1957                         int        *fd2,
1958                         dbus_bool_t blocking,
1959                         DBusError  *error)
1960 {
1961   SOCKET temp, socket1 = -1, socket2 = -1;
1962   struct sockaddr_in saddr;
1963   int len;
1964   u_long arg;
1965   fd_set read_set, write_set;
1966   struct timeval tv;
1967   DBusSocket sock;
1968
1969
1970   _dbus_win_startup_winsock ();
1971
1972   temp = socket (AF_INET, SOCK_STREAM, 0);
1973   if (temp == INVALID_SOCKET)
1974     {
1975       DBUS_SOCKET_SET_ERRNO ();
1976       goto out0;
1977     }
1978
1979   arg = 1;
1980   if (ioctlsocket (temp, FIONBIO, &arg) == SOCKET_ERROR)
1981     {
1982       DBUS_SOCKET_SET_ERRNO ();
1983       goto out0;
1984     }
1985
1986   _DBUS_ZERO (saddr);
1987   saddr.sin_family = AF_INET;
1988   saddr.sin_port = 0;
1989   saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
1990
1991   if (bind (temp, (struct sockaddr *)&saddr, sizeof (saddr)))
1992     {
1993       DBUS_SOCKET_SET_ERRNO ();
1994       goto out0;
1995     }
1996
1997   if (listen (temp, 1) == SOCKET_ERROR)
1998     {
1999       DBUS_SOCKET_SET_ERRNO ();
2000       goto out0;
2001     }
2002
2003   len = sizeof (saddr);
2004   if (getsockname (temp, (struct sockaddr *)&saddr, &len))
2005     {
2006       DBUS_SOCKET_SET_ERRNO ();
2007       goto out0;
2008     }
2009
2010   socket1 = socket (AF_INET, SOCK_STREAM, 0);
2011   if (socket1 == INVALID_SOCKET)
2012     {
2013       DBUS_SOCKET_SET_ERRNO ();
2014       goto out0;
2015     }
2016
2017   arg = 1;
2018   if (ioctlsocket (socket1, FIONBIO, &arg) == SOCKET_ERROR)
2019     {
2020       DBUS_SOCKET_SET_ERRNO ();
2021       goto out1;
2022     }
2023
2024   if (connect (socket1, (struct sockaddr  *)&saddr, len) != SOCKET_ERROR ||
2025       WSAGetLastError () != WSAEWOULDBLOCK)
2026     {
2027       dbus_set_error_const (error, DBUS_ERROR_FAILED,
2028                             "_dbus_full_duplex_pipe socketpair() emulation failed");
2029       goto out1;
2030     }
2031
2032   FD_ZERO (&read_set);
2033   FD_SET (temp, &read_set);
2034
2035   tv.tv_sec = 0;
2036   tv.tv_usec = 0;
2037
2038   if (select (0, &read_set, NULL, NULL, NULL) == SOCKET_ERROR)
2039     {
2040       DBUS_SOCKET_SET_ERRNO ();
2041       goto out1;
2042     }
2043
2044   _dbus_assert (FD_ISSET (temp, &read_set));
2045
2046   socket2 = accept (temp, (struct sockaddr *) &saddr, &len);
2047   if (socket2 == INVALID_SOCKET)
2048     {
2049       DBUS_SOCKET_SET_ERRNO ();
2050       goto out1;
2051     }
2052
2053   FD_ZERO (&write_set);
2054   FD_SET (socket1, &write_set);
2055
2056   tv.tv_sec = 0;
2057   tv.tv_usec = 0;
2058
2059   if (select (0, NULL, &write_set, NULL, NULL) == SOCKET_ERROR)
2060     {
2061       DBUS_SOCKET_SET_ERRNO ();
2062       goto out2;
2063     }
2064
2065   _dbus_assert (FD_ISSET (socket1, &write_set));
2066
2067   if (blocking)
2068     {
2069       arg = 0;
2070       if (ioctlsocket (socket1, FIONBIO, &arg) == SOCKET_ERROR)
2071         {
2072           DBUS_SOCKET_SET_ERRNO ();
2073           goto out2;
2074         }
2075
2076       arg = 0;
2077       if (ioctlsocket (socket2, FIONBIO, &arg) == SOCKET_ERROR)
2078         {
2079           DBUS_SOCKET_SET_ERRNO ();
2080           goto out2;
2081         }
2082     }
2083   else
2084     {
2085       arg = 1;
2086       if (ioctlsocket (socket2, FIONBIO, &arg) == SOCKET_ERROR)
2087         {
2088           DBUS_SOCKET_SET_ERRNO ();
2089           goto out2;
2090         }
2091     }
2092
2093   sock.fd = socket1;
2094   *fd1 = _dbus_socket_to_handle (&sock);
2095   sock.fd = socket2;
2096   *fd2 = _dbus_socket_to_handle (&sock);
2097
2098   _dbus_verbose ("full-duplex pipe %d:%d <-> %d:%d\n",
2099                  *fd1, socket1, *fd2, socket2);
2100
2101   closesocket (temp);
2102
2103   return TRUE;
2104
2105 out2:
2106   closesocket (socket2);
2107 out1:
2108   closesocket (socket1);
2109 out0:
2110   closesocket (temp);
2111
2112   dbus_set_error (error, _dbus_error_from_errno (errno),
2113                   "Could not setup socket pair: %s",
2114                   _dbus_strerror (errno));
2115
2116   return FALSE;
2117 }
2118
2119 /**
2120  * Wrapper for poll().
2121  *
2122  * @param fds the file descriptors to poll
2123  * @param n_fds number of descriptors in the array
2124  * @param timeout_milliseconds timeout or -1 for infinite
2125  * @returns numbers of fds with revents, or <0 on error
2126  */
2127 #define USE_CHRIS_IMPL 0
2128 #if USE_CHRIS_IMPL
2129 int
2130 _dbus_poll (DBusPollFD *fds,
2131             int         n_fds,
2132             int         timeout_milliseconds)
2133 {
2134 #define DBUS_POLL_CHAR_BUFFER_SIZE 2000
2135   char msg[DBUS_POLL_CHAR_BUFFER_SIZE];
2136   char *msgp;
2137
2138   int ret = 0;
2139   int i;
2140   struct timeval tv;
2141   int ready;
2142
2143 #define DBUS_STACK_WSAEVENTS 256
2144   WSAEVENT eventsOnStack[DBUS_STACK_WSAEVENTS];
2145   WSAEVENT *pEvents = NULL;
2146   if (n_fds > DBUS_STACK_WSAEVENTS)
2147     pEvents = calloc(sizeof(WSAEVENT), n_fds);
2148   else
2149     pEvents = eventsOnStack;
2150
2151   _dbus_lock_sockets();
2152
2153 #ifdef DBUS_ENABLE_VERBOSE_MODE
2154   msgp = msg;
2155   msgp += sprintf (msgp, "WSAEventSelect: to=%d\n\t", timeout_milliseconds);
2156   for (i = 0; i < n_fds; i++)
2157     {
2158       static dbus_bool_t warned = FALSE;
2159       DBusSocket *s;
2160       DBusPollFD *fdp = &fds[i];
2161
2162       _dbus_handle_to_socket_unlocked(fdp->fd, &s);  
2163
2164       if (s->is_used == 0)
2165         {
2166           _dbus_warn ("no valid socket");
2167           warned = TRUE;
2168         }
2169
2170       if (fdp->events & _DBUS_POLLIN)
2171         msgp += sprintf (msgp, "R:%d ", s->fd);
2172
2173       if (fdp->events & _DBUS_POLLOUT)
2174         msgp += sprintf (msgp, "W:%d ", s->fd);
2175
2176       msgp += sprintf (msgp, "E:%d\n\t", s->fd);
2177
2178       // FIXME: more robust code for long  msg
2179       //        create on heap when msg[] becomes too small
2180       if (msgp >= msg + DBUS_POLL_CHAR_BUFFER_SIZE)
2181         {
2182           _dbus_assert_not_reached ("buffer overflow in _dbus_poll");
2183         }
2184     }
2185
2186   msgp += sprintf (msgp, "\n");
2187   _dbus_verbose ("%s",msg);
2188 #endif
2189   for (i = 0; i < n_fds; i++)
2190     {
2191       DBusSocket *s;
2192       DBusPollFD *fdp = &fds[i];
2193       WSAEVENT ev;
2194       long lNetworkEvents = FD_OOB;
2195
2196       _dbus_handle_to_socket_unlocked(fdp->fd, &s); 
2197
2198       if (s->is_used == 0)
2199         continue;
2200
2201       ev = WSACreateEvent();
2202
2203       if (fdp->events & _DBUS_POLLIN)
2204         lNetworkEvents |= FD_READ | FD_ACCEPT | FD_CLOSE;
2205
2206       if (fdp->events & _DBUS_POLLOUT)
2207         lNetworkEvents |= FD_WRITE | FD_CONNECT;
2208
2209       WSAEventSelect(s->fd, ev, lNetworkEvents);
2210
2211       pEvents[i] = ev;
2212     }
2213
2214   _dbus_unlock_sockets();
2215
2216   ready = WSAWaitForMultipleEvents (n_fds, pEvents, FALSE, timeout_milliseconds, FALSE);
2217
2218   if (DBUS_SOCKET_API_RETURNS_ERROR (ready))
2219     {
2220       DBUS_SOCKET_SET_ERRNO ();
2221       if (errno != EWOULDBLOCK)
2222         _dbus_verbose ("WSAWaitForMultipleEvents: failed: %s\n", _dbus_strerror (errno));
2223       ret = -1;
2224     }
2225   else if (ready == WSA_WAIT_TIMEOUT)
2226     {
2227       _dbus_verbose ("WSAWaitForMultipleEvents: WSA_WAIT_TIMEOUT\n");
2228       ret = 0;
2229     }
2230   else if (ready >= WSA_WAIT_EVENT_0 && ready < (int)(WSA_WAIT_EVENT_0 + n_fds))
2231     {
2232       msgp = msg;
2233       msgp += sprintf (msgp, "WSAWaitForMultipleEvents: =%d\n\t", ready);
2234
2235       _dbus_lock_sockets();
2236       for (i = 0; i < n_fds; i++)
2237         {
2238           DBusSocket *s;
2239           DBusPollFD *fdp = &fds[i];
2240           WSANETWORKEVENTS ne;
2241
2242           _dbus_handle_to_socket_unlocked(fdp->fd, &s); 
2243
2244           fdp->revents = 0;
2245
2246           WSAEnumNetworkEvents(s->fd, pEvents[i], &ne);
2247
2248           if (ne.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
2249             fdp->revents |= _DBUS_POLLIN;
2250
2251           if (ne.lNetworkEvents & (FD_WRITE | FD_CONNECT))
2252             fdp->revents |= _DBUS_POLLOUT;
2253
2254           if (ne.lNetworkEvents & (FD_OOB))
2255             fdp->revents |= _DBUS_POLLERR;
2256
2257           if (ne.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
2258               msgp += sprintf (msgp, "R:%d ", s->fd);
2259
2260           if (ne.lNetworkEvents & (FD_WRITE | FD_CONNECT))
2261               msgp += sprintf (msgp, "W:%d ", s->fd);
2262
2263           if (ne.lNetworkEvents & (FD_OOB))
2264               msgp += sprintf (msgp, "E:%d ", s->fd);
2265
2266           msgp += sprintf (msgp, "lNetworkEvents:%d ", ne.lNetworkEvents);
2267
2268           if(ne.lNetworkEvents)
2269             ret++;
2270
2271           WSAEventSelect(s->fd, pEvents[i], 0);
2272         }
2273       _dbus_unlock_sockets();
2274
2275       msgp += sprintf (msgp, "\n");
2276       _dbus_verbose ("%s",msg);
2277     }
2278   else
2279     {
2280       _dbus_verbose ("WSAWaitForMultipleEvents: failed for unknown reason!");
2281       ret = -1;
2282     }
2283
2284   for(i = 0; i < n_fds; i++)
2285     {
2286       WSACloseEvent(pEvents[i]);
2287     }
2288
2289   if (n_fds > DBUS_STACK_WSAEVENTS)
2290     free(pEvents);
2291
2292   return ret;
2293 }
2294
2295 #else   // USE_CHRIS_IMPL
2296
2297 int
2298 _dbus_poll (DBusPollFD *fds,
2299             int         n_fds,
2300             int         timeout_milliseconds)
2301 {
2302 #define DBUS_POLL_CHAR_BUFFER_SIZE 2000
2303   char msg[DBUS_POLL_CHAR_BUFFER_SIZE];
2304   char *msgp;
2305
2306   fd_set read_set, write_set, err_set;
2307   int max_fd = 0;
2308   int i;
2309   struct timeval tv;
2310   int ready;
2311
2312   FD_ZERO (&read_set);
2313   FD_ZERO (&write_set);
2314   FD_ZERO (&err_set);
2315
2316   _dbus_lock_sockets();
2317
2318 #ifdef DBUS_ENABLE_VERBOSE_MODE
2319   msgp = msg;
2320   msgp += sprintf (msgp, "select: to=%d\n\t", timeout_milliseconds);
2321   for (i = 0; i < n_fds; i++)
2322     {
2323       static dbus_bool_t warned = FALSE;
2324       DBusSocket *s;
2325       DBusPollFD *fdp = &fds[i];
2326
2327       _dbus_handle_to_socket_unlocked(fdp->fd, &s);  
2328
2329       if (s->is_used == 0)
2330         {
2331           _dbus_warn ("no valid socket");
2332           warned = TRUE;
2333         }
2334
2335       if (fdp->events & _DBUS_POLLIN)
2336         msgp += sprintf (msgp, "R:%d ", s->fd);
2337
2338       if (fdp->events & _DBUS_POLLOUT)
2339         msgp += sprintf (msgp, "W:%d ", s->fd);
2340
2341       msgp += sprintf (msgp, "E:%d\n\t", s->fd);
2342
2343       // FIXME: more robust code for long  msg
2344       //        create on heap when msg[] becomes too small
2345       if (msgp >= msg + DBUS_POLL_CHAR_BUFFER_SIZE)
2346         {
2347           _dbus_assert_not_reached ("buffer overflow in _dbus_poll");
2348         }
2349     }
2350
2351   msgp += sprintf (msgp, "\n");
2352   _dbus_verbose ("%s",msg);
2353 #endif
2354   for (i = 0; i < n_fds; i++)
2355     {
2356       DBusSocket *s;
2357       DBusPollFD *fdp = &fds[i];
2358
2359       _dbus_handle_to_socket_unlocked(fdp->fd, &s); 
2360
2361       if (s->is_used != 1)
2362         continue;
2363
2364       if (fdp->events & _DBUS_POLLIN)
2365         FD_SET (s->fd, &read_set);
2366
2367       if (fdp->events & _DBUS_POLLOUT)
2368         FD_SET (s->fd, &write_set);
2369
2370       FD_SET (s->fd, &err_set);
2371
2372       max_fd = MAX (max_fd, s->fd);
2373     }
2374
2375   _dbus_unlock_sockets();
2376
2377   tv.tv_sec = timeout_milliseconds / 1000;
2378   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
2379
2380   ready = select (max_fd + 1, &read_set, &write_set, &err_set,
2381                   timeout_milliseconds < 0 ? NULL : &tv);
2382
2383   if (DBUS_SOCKET_API_RETURNS_ERROR (ready))
2384     {
2385       DBUS_SOCKET_SET_ERRNO ();
2386       if (errno != EWOULDBLOCK)
2387         _dbus_verbose ("select: failed: %s\n", _dbus_strerror (errno));
2388     }
2389   else if (ready == 0)
2390     _dbus_verbose ("select: = 0\n");
2391   else
2392     if (ready > 0)
2393       {
2394 #ifdef DBUS_ENABLE_VERBOSE_MODE
2395         msgp = msg;
2396         msgp += sprintf (msgp, "select: = %d:\n\t", ready);
2397         _dbus_lock_sockets();
2398         for (i = 0; i < n_fds; i++)
2399           {
2400             DBusSocket *s;
2401             DBusPollFD *fdp = &fds[i];
2402
2403             _dbus_handle_to_socket_unlocked(fdp->fd, &s); 
2404
2405             if (FD_ISSET (s->fd, &read_set))
2406               msgp += sprintf (msgp, "R:%d ", s->fd);
2407
2408             if (FD_ISSET (s->fd, &write_set))
2409               msgp += sprintf (msgp, "W:%d ", s->fd);
2410
2411             if (FD_ISSET (s->fd, &err_set))
2412               msgp += sprintf (msgp, "E:%d\n\t", s->fd);
2413           }
2414         msgp += sprintf (msgp, "\n");
2415         _dbus_verbose ("%s",msg);
2416 #endif
2417
2418         for (i = 0; i < n_fds; i++)
2419           {
2420             DBusSocket *s;
2421             DBusPollFD *fdp = &fds[i];
2422
2423             _dbus_handle_to_socket_unlocked(fdp->fd, &s); 
2424
2425             fdp->revents = 0;
2426
2427             if (FD_ISSET (s->fd, &read_set))
2428               fdp->revents |= _DBUS_POLLIN;
2429
2430             if (FD_ISSET (s->fd, &write_set))
2431               fdp->revents |= _DBUS_POLLOUT;
2432
2433             if (FD_ISSET (s->fd, &err_set))
2434               fdp->revents |= _DBUS_POLLERR;
2435           }
2436         _dbus_unlock_sockets();
2437       }
2438   return ready;
2439 }
2440 #endif  // USE_CHRIS_IMPL
2441
2442
2443 /************************************************************************
2444  
2445  error handling
2446  
2447  ************************************************************************/
2448
2449
2450 /**
2451  * Assigns an error name and message corresponding to a Win32 error
2452  * code to a DBusError. Does nothing if error is #NULL.
2453  *
2454  * @param error the error.
2455  * @param code the Win32 error code
2456  */
2457 void
2458 _dbus_win_set_error_from_win_error (DBusError *error,
2459                                     int        code)
2460 {
2461   char *msg;
2462
2463   /* As we want the English message, use the A API */
2464   FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
2465                   FORMAT_MESSAGE_IGNORE_INSERTS |
2466                   FORMAT_MESSAGE_FROM_SYSTEM,
2467                   NULL, code, MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US),
2468                   (LPTSTR) &msg, 0, NULL);
2469   if (msg)
2470     {
2471       char *msg_copy;
2472
2473       msg_copy = dbus_malloc (strlen (msg));
2474       strcpy (msg_copy, msg);
2475       LocalFree (msg);
2476
2477       dbus_set_error (error, "win32.error", "%s", msg_copy);
2478     }
2479   else
2480     dbus_set_error_const (error, "win32.error", "Unknown error code or FormatMessage failed");
2481 }
2482
2483 void
2484 _dbus_win_warn_win_error (const char *message,
2485                           int         code)
2486 {
2487   DBusError error;
2488
2489   dbus_error_init (&error);
2490   _dbus_win_set_error_from_win_error (&error, code);
2491   _dbus_warn ("%s: %s\n", message, error.message);
2492   dbus_error_free (&error);
2493 }
2494
2495 /**
2496  * A wrapper around strerror() because some platforms
2497  * may be lame and not have strerror().
2498  *
2499  * @param error_number errno.
2500  * @returns error description.
2501  */
2502 const char*
2503 _dbus_strerror (int error_number)
2504 {
2505 #ifdef DBUS_WINCE
2506   // TODO
2507   return "unknown";
2508 #else
2509   const char *msg;
2510
2511   switch (error_number)
2512     {
2513     case WSAEINTR:
2514       return "Interrupted function call";
2515     case WSAEACCES:
2516       return "Permission denied";
2517     case WSAEFAULT:
2518       return "Bad address";
2519     case WSAEINVAL:
2520       return "Invalid argument";
2521     case WSAEMFILE:
2522       return "Too many open files";
2523     case WSAEWOULDBLOCK:
2524       return "Resource temporarily unavailable";
2525     case WSAEINPROGRESS:
2526       return "Operation now in progress";
2527     case WSAEALREADY:
2528       return "Operation already in progress";
2529     case WSAENOTSOCK:
2530       return "Socket operation on nonsocket";
2531     case WSAEDESTADDRREQ:
2532       return "Destination address required";
2533     case WSAEMSGSIZE:
2534       return "Message too long";
2535     case WSAEPROTOTYPE:
2536       return "Protocol wrong type for socket";
2537     case WSAENOPROTOOPT:
2538       return "Bad protocol option";
2539     case WSAEPROTONOSUPPORT:
2540       return "Protocol not supported";
2541     case WSAESOCKTNOSUPPORT:
2542       return "Socket type not supported";
2543     case WSAEOPNOTSUPP:
2544       return "Operation not supported";
2545     case WSAEPFNOSUPPORT:
2546       return "Protocol family not supported";
2547     case WSAEAFNOSUPPORT:
2548       return "Address family not supported by protocol family";
2549     case WSAEADDRINUSE:
2550       return "Address already in use";
2551     case WSAEADDRNOTAVAIL:
2552       return "Cannot assign requested address";
2553     case WSAENETDOWN:
2554       return "Network is down";
2555     case WSAENETUNREACH:
2556       return "Network is unreachable";
2557     case WSAENETRESET:
2558       return "Network dropped connection on reset";
2559     case WSAECONNABORTED:
2560       return "Software caused connection abort";
2561     case WSAECONNRESET:
2562       return "Connection reset by peer";
2563     case WSAENOBUFS:
2564       return "No buffer space available";
2565     case WSAEISCONN:
2566       return "Socket is already connected";
2567     case WSAENOTCONN:
2568       return "Socket is not connected";
2569     case WSAESHUTDOWN:
2570       return "Cannot send after socket shutdown";
2571     case WSAETIMEDOUT:
2572       return "Connection timed out";
2573     case WSAECONNREFUSED:
2574       return "Connection refused";
2575     case WSAEHOSTDOWN:
2576       return "Host is down";
2577     case WSAEHOSTUNREACH:
2578       return "No route to host";
2579     case WSAEPROCLIM:
2580       return "Too many processes";
2581     case WSAEDISCON:
2582       return "Graceful shutdown in progress";
2583     case WSATYPE_NOT_FOUND:
2584       return "Class type not found";
2585     case WSAHOST_NOT_FOUND:
2586       return "Host not found";
2587     case WSATRY_AGAIN:
2588       return "Nonauthoritative host not found";
2589     case WSANO_RECOVERY:
2590       return "This is a nonrecoverable error";
2591     case WSANO_DATA:
2592       return "Valid name, no data record of requested type";
2593     case WSA_INVALID_HANDLE:
2594       return "Specified event object handle is invalid";
2595     case WSA_INVALID_PARAMETER:
2596       return "One or more parameters are invalid";
2597     case WSA_IO_INCOMPLETE:
2598       return "Overlapped I/O event object not in signaled state";
2599     case WSA_IO_PENDING:
2600       return "Overlapped operations will complete later";
2601     case WSA_NOT_ENOUGH_MEMORY:
2602       return "Insufficient memory available";
2603     case WSA_OPERATION_ABORTED:
2604       return "Overlapped operation aborted";
2605 #ifdef WSAINVALIDPROCTABLE
2606
2607     case WSAINVALIDPROCTABLE:
2608       return "Invalid procedure table from service provider";
2609 #endif
2610 #ifdef WSAINVALIDPROVIDER
2611
2612     case WSAINVALIDPROVIDER:
2613       return "Invalid service provider version number";
2614 #endif
2615 #ifdef WSAPROVIDERFAILEDINIT
2616
2617     case WSAPROVIDERFAILEDINIT:
2618       return "Unable to initialize a service provider";
2619 #endif
2620
2621     case WSASYSCALLFAILURE:
2622       return "System call failure";
2623     }
2624   msg = strerror (error_number);
2625   if (msg == NULL)
2626     msg = "unknown";
2627
2628   return msg;
2629 #endif //DBUS_WINCE
2630 }
2631
2632
2633
2634 /* lan manager error codes */
2635 const char*
2636 _dbus_lm_strerror(int error_number)
2637 {
2638 #ifdef DBUS_WINCE
2639   // TODO
2640   return "unknown";
2641 #else
2642   const char *msg;
2643   switch (error_number)
2644     {
2645     case NERR_NetNotStarted:
2646       return "The workstation driver is not installed.";
2647     case NERR_UnknownServer:
2648       return "The server could not be located.";
2649     case NERR_ShareMem:
2650       return "An internal error occurred. The network cannot access a shared memory segment.";
2651     case NERR_NoNetworkResource:
2652       return "A network resource shortage occurred.";
2653     case NERR_RemoteOnly:
2654       return "This operation is not supported on workstations.";
2655     case NERR_DevNotRedirected:
2656       return "The device is not connected.";
2657     case NERR_ServerNotStarted:
2658       return "The Server service is not started.";
2659     case NERR_ItemNotFound:
2660       return "The queue is empty.";
2661     case NERR_UnknownDevDir:
2662       return "The device or directory does not exist.";
2663     case NERR_RedirectedPath:
2664       return "The operation is invalid on a redirected resource.";
2665     case NERR_DuplicateShare:
2666       return "The name has already been shared.";
2667     case NERR_NoRoom:
2668       return "The server is currently out of the requested resource.";
2669     case NERR_TooManyItems:
2670       return "Requested addition of items exceeds the maximum allowed.";
2671     case NERR_InvalidMaxUsers:
2672       return "The Peer service supports only two simultaneous users.";
2673     case NERR_BufTooSmall:
2674       return "The API return buffer is too small.";
2675     case NERR_RemoteErr:
2676       return "A remote API error occurred.";
2677     case NERR_LanmanIniError:
2678       return "An error occurred when opening or reading the configuration file.";
2679     case NERR_NetworkError:
2680       return "A general network error occurred.";
2681     case NERR_WkstaInconsistentState:
2682       return "The Workstation service is in an inconsistent state. Restart the computer before restarting the Workstation service.";
2683     case NERR_WkstaNotStarted:
2684       return "The Workstation service has not been started.";
2685     case NERR_BrowserNotStarted:
2686       return "The requested information is not available.";
2687     case NERR_InternalError:
2688       return "An internal error occurred.";
2689     case NERR_BadTransactConfig:
2690       return "The server is not configured for transactions.";
2691     case NERR_InvalidAPI:
2692       return "The requested API is not supported on the remote server.";
2693     case NERR_BadEventName:
2694       return "The event name is invalid.";
2695     case NERR_DupNameReboot:
2696       return "The computer name already exists on the network. Change it and restart the computer.";
2697     case NERR_CfgCompNotFound:
2698       return "The specified component could not be found in the configuration information.";
2699     case NERR_CfgParamNotFound:
2700       return "The specified parameter could not be found in the configuration information.";
2701     case NERR_LineTooLong:
2702       return "A line in the configuration file is too long.";
2703     case NERR_QNotFound:
2704       return "The printer does not exist.";
2705     case NERR_JobNotFound:
2706       return "The print job does not exist.";
2707     case NERR_DestNotFound:
2708       return "The printer destination cannot be found.";
2709     case NERR_DestExists:
2710       return "The printer destination already exists.";
2711     case NERR_QExists:
2712       return "The printer queue already exists.";
2713     case NERR_QNoRoom:
2714       return "No more printers can be added.";
2715     case NERR_JobNoRoom:
2716       return "No more print jobs can be added.";
2717     case NERR_DestNoRoom:
2718       return "No more printer destinations can be added.";
2719     case NERR_DestIdle:
2720       return "This printer destination is idle and cannot accept control operations.";
2721     case NERR_DestInvalidOp:
2722       return "This printer destination request contains an invalid control function.";
2723     case NERR_ProcNoRespond:
2724       return "The print processor is not responding.";
2725     case NERR_SpoolerNotLoaded:
2726       return "The spooler is not running.";
2727     case NERR_DestInvalidState:
2728       return "This operation cannot be performed on the print destination in its current state.";
2729     case NERR_QInvalidState:
2730       return "This operation cannot be performed on the printer queue in its current state.";
2731     case NERR_JobInvalidState:
2732       return "This operation cannot be performed on the print job in its current state.";
2733     case NERR_SpoolNoMemory:
2734       return "A spooler memory allocation failure occurred.";
2735     case NERR_DriverNotFound:
2736       return "The device driver does not exist.";
2737     case NERR_DataTypeInvalid:
2738       return "The data type is not supported by the print processor.";
2739     case NERR_ProcNotFound:
2740       return "The print processor is not installed.";
2741     case NERR_ServiceTableLocked:
2742       return "The service database is locked.";
2743     case NERR_ServiceTableFull:
2744       return "The service table is full.";
2745     case NERR_ServiceInstalled:
2746       return "The requested service has already been started.";
2747     case NERR_ServiceEntryLocked:
2748       return "The service does not respond to control actions.";
2749     case NERR_ServiceNotInstalled:
2750       return "The service has not been started.";
2751     case NERR_BadServiceName:
2752       return "The service name is invalid.";
2753     case NERR_ServiceCtlTimeout:
2754       return "The service is not responding to the control function.";
2755     case NERR_ServiceCtlBusy:
2756       return "The service control is busy.";
2757     case NERR_BadServiceProgName:
2758       return "The configuration file contains an invalid service program name.";
2759     case NERR_ServiceNotCtrl:
2760       return "The service could not be controlled in its present state.";
2761     case NERR_ServiceKillProc:
2762       return "The service ended abnormally.";
2763     case NERR_ServiceCtlNotValid:
2764       return "The requested pause or stop is not valid for this service.";
2765     case NERR_NotInDispatchTbl:
2766       return "The service control dispatcher could not find the service name in the dispatch table.";
2767     case NERR_BadControlRecv:
2768       return "The service control dispatcher pipe read failed.";
2769     case NERR_ServiceNotStarting:
2770       return "A thread for the new service could not be created.";
2771     case NERR_AlreadyLoggedOn:
2772       return "This workstation is already logged on to the local-area network.";
2773     case NERR_NotLoggedOn:
2774       return "The workstation is not logged on to the local-area network.";
2775     case NERR_BadUsername:
2776       return "The user name or group name parameter is invalid.";
2777     case NERR_BadPassword:
2778       return "The password parameter is invalid.";
2779     case NERR_UnableToAddName_W:
2780       return "@W The logon processor did not add the message alias.";
2781     case NERR_UnableToAddName_F:
2782       return "The logon processor did not add the message alias.";
2783     case NERR_UnableToDelName_W:
2784       return "@W The logoff processor did not delete the message alias.";
2785     case NERR_UnableToDelName_F:
2786       return "The logoff processor did not delete the message alias.";
2787     case NERR_LogonsPaused:
2788       return "Network logons are paused.";
2789     case NERR_LogonServerConflict:
2790       return "A centralized logon-server conflict occurred.";
2791     case NERR_LogonNoUserPath:
2792       return "The server is configured without a valid user path.";
2793     case NERR_LogonScriptError:
2794       return "An error occurred while loading or running the logon script.";
2795     case NERR_StandaloneLogon:
2796       return "The logon server was not specified. Your computer will be logged on as STANDALONE.";
2797     case NERR_LogonServerNotFound:
2798       return "The logon server could not be found.";
2799     case NERR_LogonDomainExists:
2800       return "There is already a logon domain for this computer.";
2801     case NERR_NonValidatedLogon:
2802       return "The logon server could not validate the logon.";
2803     case NERR_ACFNotFound:
2804       return "The security database could not be found.";
2805     case NERR_GroupNotFound:
2806       return "The group name could not be found.";
2807     case NERR_UserNotFound:
2808       return "The user name could not be found.";
2809     case NERR_ResourceNotFound:
2810       return "The resource name could not be found.";
2811     case NERR_GroupExists:
2812       return "The group already exists.";
2813     case NERR_UserExists:
2814       return "The user account already exists.";
2815     case NERR_ResourceExists:
2816       return "The resource permission list already exists.";
2817     case NERR_NotPrimary:
2818       return "This operation is only allowed on the primary domain controller of the domain.";
2819     case NERR_ACFNotLoaded:
2820       return "The security database has not been started.";
2821     case NERR_ACFNoRoom:
2822       return "There are too many names in the user accounts database.";
2823     case NERR_ACFFileIOFail:
2824       return "A disk I/O failure occurred.";
2825     case NERR_ACFTooManyLists:
2826       return "The limit of 64 entries per resource was exceeded.";
2827     case NERR_UserLogon:
2828       return "Deleting a user with a session is not allowed.";
2829     case NERR_ACFNoParent:
2830       return "The parent directory could not be located.";
2831     case NERR_CanNotGrowSegment:
2832       return "Unable to add to the security database session cache segment.";
2833     case NERR_SpeGroupOp:
2834       return "This operation is not allowed on this special group.";
2835     case NERR_NotInCache:
2836       return "This user is not cached in user accounts database session cache.";
2837     case NERR_UserInGroup:
2838       return "The user already belongs to this group.";
2839     case NERR_UserNotInGroup:
2840       return "The user does not belong to this group.";
2841     case NERR_AccountUndefined:
2842       return "This user account is undefined.";
2843     case NERR_AccountExpired:
2844       return "This user account has expired.";
2845     case NERR_InvalidWorkstation:
2846       return "The user is not allowed to log on from this workstation.";
2847     case NERR_InvalidLogonHours:
2848       return "The user is not allowed to log on at this time.";
2849     case NERR_PasswordExpired:
2850       return "The password of this user has expired.";
2851     case NERR_PasswordCantChange:
2852       return "The password of this user cannot change.";
2853     case NERR_PasswordHistConflict:
2854       return "This password cannot be used now.";
2855     case NERR_PasswordTooShort:
2856       return "The password does not meet the password policy requirements. Check the minimum password length, password complexity and password history requirements.";
2857     case NERR_PasswordTooRecent:
2858       return "The password of this user is too recent to change.";
2859     case NERR_InvalidDatabase:
2860       return "The security database is corrupted.";
2861     case NERR_DatabaseUpToDate:
2862       return "No updates are necessary to this replicant network/local security database.";
2863     case NERR_SyncRequired:
2864       return "This replicant database is outdated; synchronization is required.";
2865     case NERR_UseNotFound:
2866       return "The network connection could not be found.";
2867     case NERR_BadAsgType:
2868       return "This asg_type is invalid.";
2869     case NERR_DeviceIsShared:
2870       return "This device is currently being shared.";
2871     case NERR_NoComputerName:
2872       return "The computer name could not be added as a message alias. The name may already exist on the network.";
2873     case NERR_MsgAlreadyStarted:
2874       return "The Messenger service is already started.";
2875     case NERR_MsgInitFailed:
2876       return "The Messenger service failed to start.";
2877     case NERR_NameNotFound:
2878       return "The message alias could not be found on the network.";
2879     case NERR_AlreadyForwarded:
2880       return "This message alias has already been forwarded.";
2881     case NERR_AddForwarded:
2882       return "This message alias has been added but is still forwarded.";
2883     case NERR_AlreadyExists:
2884       return "This message alias already exists locally.";
2885     case NERR_TooManyNames:
2886       return "The maximum number of added message aliases has been exceeded.";
2887     case NERR_DelComputerName:
2888       return "The computer name could not be deleted.";
2889     case NERR_LocalForward:
2890       return "Messages cannot be forwarded back to the same workstation.";
2891     case NERR_GrpMsgProcessor:
2892       return "An error occurred in the domain message processor.";
2893     case NERR_PausedRemote:
2894       return "The message was sent, but the recipient has paused the Messenger service.";
2895     case NERR_BadReceive:
2896       return "The message was sent but not received.";
2897     case NERR_NameInUse:
2898       return "The message alias is currently in use. Try again later.";
2899     case NERR_MsgNotStarted:
2900       return "The Messenger service has not been started.";
2901     case NERR_NotLocalName:
2902       return "The name is not on the local computer.";
2903     case NERR_NoForwardName:
2904       return "The forwarded message alias could not be found on the network.";
2905     case NERR_RemoteFull:
2906       return "The message alias table on the remote station is full.";
2907     case NERR_NameNotForwarded:
2908       return "Messages for this alias are not currently being forwarded.";
2909     case NERR_TruncatedBroadcast:
2910       return "The broadcast message was truncated.";
2911     case NERR_InvalidDevice:
2912       return "This is an invalid device name.";
2913     case NERR_WriteFault:
2914       return "A write fault occurred.";
2915     case NERR_DuplicateName:
2916       return "A duplicate message alias exists on the network.";
2917     case NERR_DeleteLater:
2918       return "@W This message alias will be deleted later.";
2919     case NERR_IncompleteDel:
2920       return "The message alias was not successfully deleted from all networks.";
2921     case NERR_MultipleNets:
2922       return "This operation is not supported on computers with multiple networks.";
2923     case NERR_NetNameNotFound:
2924       return "This shared resource does not exist.";
2925     case NERR_DeviceNotShared:
2926       return "This device is not shared.";
2927     case NERR_ClientNameNotFound:
2928       return "A session does not exist with that computer name.";
2929     case NERR_FileIdNotFound:
2930       return "There is not an open file with that identification number.";
2931     case NERR_ExecFailure:
2932       return "A failure occurred when executing a remote administration command.";
2933     case NERR_TmpFile:
2934       return "A failure occurred when opening a remote temporary file.";
2935     case NERR_TooMuchData:
2936       return "The data returned from a remote administration command has been truncated to 64K.";
2937     case NERR_DeviceShareConflict:
2938       return "This device cannot be shared as both a spooled and a non-spooled resource.";
2939     case NERR_BrowserTableIncomplete:
2940       return "The information in the list of servers may be incorrect.";
2941     case NERR_NotLocalDomain:
2942       return "The computer is not active in this domain.";
2943 #ifdef NERR_IsDfsShare
2944
2945     case NERR_IsDfsShare:
2946       return "The share must be removed from the Distributed File System before it can be deleted.";
2947 #endif
2948
2949     case NERR_DevInvalidOpCode:
2950       return "The operation is invalid for this device.";
2951     case NERR_DevNotFound:
2952       return "This device cannot be shared.";
2953     case NERR_DevNotOpen:
2954       return "This device was not open.";
2955     case NERR_BadQueueDevString:
2956       return "This device name list is invalid.";
2957     case NERR_BadQueuePriority:
2958       return "The queue priority is invalid.";
2959     case NERR_NoCommDevs:
2960       return "There are no shared communication devices.";
2961     case NERR_QueueNotFound:
2962       return "The queue you specified does not exist.";
2963     case NERR_BadDevString:
2964       return "This list of devices is invalid.";
2965     case NERR_BadDev:
2966       return "The requested device is invalid.";
2967     case NERR_InUseBySpooler:
2968       return "This device is already in use by the spooler.";
2969     case NERR_CommDevInUse:
2970       return "This device is already in use as a communication device.";
2971     case NERR_InvalidComputer:
2972       return "This computer name is invalid.";
2973     case NERR_MaxLenExceeded:
2974       return "The string and prefix specified are too long.";
2975     case NERR_BadComponent:
2976       return "This path component is invalid.";
2977     case NERR_CantType:
2978       return "Could not determine the type of input.";
2979     case NERR_TooManyEntries:
2980       return "The buffer for types is not big enough.";
2981     case NERR_ProfileFileTooBig:
2982       return "Profile files cannot exceed 64K.";
2983     case NERR_ProfileOffset:
2984       return "The start offset is out of range.";
2985     case NERR_ProfileCleanup:
2986       return "The system cannot delete current connections to network resources.";
2987     case NERR_ProfileUnknownCmd:
2988       return "The system was unable to parse the command line in this file.";
2989     case NERR_ProfileLoadErr:
2990       return "An error occurred while loading the profile file.";
2991     case NERR_ProfileSaveErr:
2992       return "@W Errors occurred while saving the profile file. The profile was partially saved.";
2993     case NERR_LogOverflow:
2994       return "Log file %1 is full.";
2995     case NERR_LogFileChanged:
2996       return "This log file has changed between reads.";
2997     case NERR_LogFileCorrupt:
2998       return "Log file %1 is corrupt.";
2999     case NERR_SourceIsDir:
3000       return "The source path cannot be a directory.";
3001     case NERR_BadSource:
3002       return "The source path is illegal.";
3003     case NERR_BadDest:
3004       return "The destination path is illegal.";
3005     case NERR_DifferentServers:
3006       return "The source and destination paths are on different servers.";
3007     case NERR_RunSrvPaused:
3008       return "The Run server you requested is paused.";
3009     case NERR_ErrCommRunSrv:
3010       return "An error occurred when communicating with a Run server.";
3011     case NERR_ErrorExecingGhost:
3012       return "An error occurred when starting a background process.";
3013     case NERR_ShareNotFound:
3014       return "The shared resource you are connected to could not be found.";
3015     case NERR_InvalidLana:
3016       return "The LAN adapter number is invalid.";
3017     case NERR_OpenFiles:
3018       return "There are open files on the connection.";
3019     case NERR_ActiveConns:
3020       return "Active connections still exist.";
3021     case NERR_BadPasswordCore:
3022       return "This share name or password is invalid.";
3023     case NERR_DevInUse:
3024       return "The device is being accessed by an active process.";
3025     case NERR_LocalDrive:
3026       return "The drive letter is in use locally.";
3027     case NERR_AlertExists:
3028       return "The specified client is already registered for the specified event.";
3029     case NERR_TooManyAlerts:
3030       return "The alert table is full.";
3031     case NERR_NoSuchAlert:
3032       return "An invalid or nonexistent alert name was raised.";
3033     case NERR_BadRecipient:
3034       return "The alert recipient is invalid.";
3035     case NERR_AcctLimitExceeded:
3036       return "A user's session with this server has been deleted.";
3037     case NERR_InvalidLogSeek:
3038       return "The log file does not contain the requested record number.";
3039     case NERR_BadUasConfig:
3040       return "The user accounts database is not configured correctly.";
3041     case NERR_InvalidUASOp:
3042       return "This operation is not permitted when the Netlogon service is running.";
3043     case NERR_LastAdmin:
3044       return "This operation is not allowed on the last administrative account.";
3045     case NERR_DCNotFound:
3046       return "Could not find domain controller for this domain.";
3047     case NERR_LogonTrackingError:
3048       return "Could not set logon information for this user.";
3049     case NERR_NetlogonNotStarted:
3050       return "The Netlogon service has not been started.";
3051     case NERR_CanNotGrowUASFile:
3052       return "Unable to add to the user accounts database.";
3053     case NERR_TimeDiffAtDC:
3054       return "This server's clock is not synchronized with the primary domain controller's clock.";
3055     case NERR_PasswordMismatch:
3056       return "A password mismatch has been detected.";
3057     case NERR_NoSuchServer:
3058       return "The server identification does not specify a valid server.";
3059     case NERR_NoSuchSession:
3060       return "The session identification does not specify a valid session.";
3061     case NERR_NoSuchConnection:
3062       return "The connection identification does not specify a valid connection.";
3063     case NERR_TooManyServers:
3064       return "There is no space for another entry in the table of available servers.";
3065     case NERR_TooManySessions:
3066       return "The server has reached the maximum number of sessions it supports.";
3067     case NERR_TooManyConnections:
3068       return "The server has reached the maximum number of connections it supports.";
3069     case NERR_TooManyFiles:
3070       return "The server cannot open more files because it has reached its maximum number.";
3071     case NERR_NoAlternateServers:
3072       return "There are no alternate servers registered on this server.";
3073     case NERR_TryDownLevel:
3074       return "Try down-level (remote admin protocol) version of API instead.";
3075     case NERR_UPSDriverNotStarted:
3076       return "The UPS driver could not be accessed by the UPS service.";
3077     case NERR_UPSInvalidConfig:
3078       return "The UPS service is not configured correctly.";
3079     case NERR_UPSInvalidCommPort:
3080       return "The UPS service could not access the specified Comm Port.";
3081     case NERR_UPSSignalAsserted:
3082       return "The UPS indicated a line fail or low battery situation. Service not started.";
3083     case NERR_UPSShutdownFailed:
3084       return "The UPS service failed to perform a system shut down.";
3085     case NERR_BadDosRetCode:
3086       return "The program below returned an MS-DOS error code:";
3087     case NERR_ProgNeedsExtraMem:
3088       return "The program below needs more memory:";
3089     case NERR_BadDosFunction:
3090       return "The program below called an unsupported MS-DOS function:";
3091     case NERR_RemoteBootFailed:
3092       return "The workstation failed to boot.";
3093     case NERR_BadFileCheckSum:
3094       return "The file below is corrupt.";
3095     case NERR_NoRplBootSystem:
3096       return "No loader is specified in the boot-block definition file.";
3097     case NERR_RplLoadrNetBiosErr:
3098       return "NetBIOS returned an error:      The NCB and SMB are dumped above.";
3099     case NERR_RplLoadrDiskErr:
3100       return "A disk I/O error occurred.";
3101     case NERR_ImageParamErr:
3102       return "Image parameter substitution failed.";
3103     case NERR_TooManyImageParams:
3104       return "Too many image parameters cross disk sector boundaries.";
3105     case NERR_NonDosFloppyUsed:
3106       return "The image was not generated from an MS-DOS diskette formatted with /S.";
3107     case NERR_RplBootRestart:
3108       return "Remote boot will be restarted later.";
3109     case NERR_RplSrvrCallFailed:
3110       return "The call to the Remoteboot server failed.";
3111     case NERR_CantConnectRplSrvr:
3112       return "Cannot connect to the Remoteboot server.";
3113     case NERR_CantOpenImageFile:
3114       return "Cannot open image file on the Remoteboot server.";
3115     case NERR_CallingRplSrvr:
3116       return "Connecting to the Remoteboot server...";
3117     case NERR_StartingRplBoot:
3118       return "Connecting to the Remoteboot server...";
3119     case NERR_RplBootServiceTerm:
3120       return "Remote boot service was stopped; check the error log for the cause of the problem.";
3121     case NERR_RplBootStartFailed:
3122       return "Remote boot startup failed; check the error log for the cause of the problem.";
3123     case NERR_RPL_CONNECTED:
3124       return "A second connection to a Remoteboot resource is not allowed.";
3125     case NERR_BrowserConfiguredToNotRun:
3126       return "The browser service was configured with MaintainServerList=No.";
3127     case NERR_RplNoAdaptersStarted:
3128       return "Service failed to start since none of the network adapters started with this service.";
3129     case NERR_RplBadRegistry:
3130       return "Service failed to start due to bad startup information in the registry.";
3131     case NERR_RplBadDatabase:
3132       return "Service failed to start because its database is absent or corrupt.";
3133     case NERR_RplRplfilesShare:
3134       return "Service failed to start because RPLFILES share is absent.";
3135     case NERR_RplNotRplServer:
3136       return "Service failed to start because RPLUSER group is absent.";
3137     case NERR_RplCannotEnum:
3138       return "Cannot enumerate service records.";
3139     case NERR_RplWkstaInfoCorrupted:
3140       return "Workstation record information has been corrupted.";
3141     case NERR_RplWkstaNotFound:
3142       return "Workstation record was not found.";
3143     case NERR_RplWkstaNameUnavailable:
3144       return "Workstation name is in use by some other workstation.";
3145     case NERR_RplProfileInfoCorrupted:
3146       return "Profile record information has been corrupted.";
3147     case NERR_RplProfileNotFound:
3148       return "Profile record was not found.";
3149     case NERR_RplProfileNameUnavailable:
3150       return "Profile name is in use by some other profile.";
3151     case NERR_RplProfileNotEmpty:
3152       return "There are workstations using this profile.";
3153     case NERR_RplConfigInfoCorrupted:
3154       return "Configuration record information has been corrupted.";
3155     case NERR_RplConfigNotFound:
3156       return "Configuration record was not found.";
3157     case NERR_RplAdapterInfoCorrupted:
3158       return "Adapter ID record information has been corrupted.";
3159     case NERR_RplInternal:
3160       return "An internal service error has occurred.";
3161     case NERR_RplVendorInfoCorrupted:
3162       return "Vendor ID record information has been corrupted.";
3163     case NERR_RplBootInfoCorrupted:
3164       return "Boot block record information has been corrupted.";
3165     case NERR_RplWkstaNeedsUserAcct:
3166       return "The user account for this workstation record is missing.";
3167     case NERR_RplNeedsRPLUSERAcct:
3168       return "The RPLUSER local group could not be found.";
3169     case NERR_RplBootNotFound:
3170       return "Boot block record was not found.";
3171     case NERR_RplIncompatibleProfile:
3172       return "Chosen profile is incompatible with this workstation.";
3173     case NERR_RplAdapterNameUnavailable:
3174       return "Chosen network adapter ID is in use by some other workstation.";
3175     case NERR_RplConfigNotEmpty:
3176       return "There are profiles using this configuration.";
3177     case NERR_RplBootInUse:
3178       return "There are workstations, profiles, or configurations using this boot block.";
3179     case NERR_RplBackupDatabase:
3180       return "Service failed to backup Remoteboot database.";
3181     case NERR_RplAdapterNotFound:
3182       return "Adapter record was not found.";
3183     case NERR_RplVendorNotFound:
3184       return "Vendor record was not found.";
3185     case NERR_RplVendorNameUnavailable:
3186       return "Vendor name is in use by some other vendor record.";
3187     case NERR_RplBootNameUnavailable:
3188       return "(boot name, vendor ID) is in use by some other boot block record.";
3189     case NERR_RplConfigNameUnavailable:
3190       return "Configuration name is in use by some other configuration.";
3191     case NERR_DfsInternalCorruption:
3192       return "The internal database maintained by the Dfs service is corrupt.";
3193     case NERR_DfsVolumeDataCorrupt:
3194       return "One of the records in the internal Dfs database is corrupt.";
3195     case NERR_DfsNoSuchVolume:
3196       return "There is no DFS name whose entry path matches the input Entry Path.";
3197     case NERR_DfsVolumeAlreadyExists:
3198       return "A root or link with the given name already exists.";
3199     case NERR_DfsAlreadyShared:
3200       return "The server share specified is already shared in the Dfs.";
3201     case NERR_DfsNoSuchShare:
3202       return "The indicated server share does not support the indicated DFS namespace.";
3203     case NERR_DfsNotALeafVolume:
3204       return "The operation is not valid on this portion of the namespace.";
3205     case NERR_DfsLeafVolume:
3206       return "The operation is not valid on this portion of the namespace.";
3207     case NERR_DfsVolumeHasMultipleServers:
3208       return "The operation is ambiguous because the link has multiple servers.";
3209     case NERR_DfsCantCreateJunctionPoint:
3210       return "Unable to create a link.";
3211     case NERR_DfsServerNotDfsAware:
3212       return "The server is not Dfs Aware.";
3213     case NERR_DfsBadRenamePath:
3214       return "The specified rename target path is invalid.";
3215     case NERR_DfsVolumeIsOffline:
3216       return "The specified DFS link is offline.";
3217     case NERR_DfsNoSuchServer:
3218       return "The specified server is not a server for this link.";
3219     case NERR_DfsCyclicalName:
3220       return "A cycle in the Dfs name was detected.";
3221     case NERR_DfsNotSupportedInServerDfs:
3222       return "The operation is not supported on a server-based Dfs.";
3223     case NERR_DfsDuplicateService:
3224       return "This link is already supported by the specified server-share.";
3225     case NERR_DfsCantRemoveLastServerShare:
3226       return "Can't remove the last server-share supporting this root or link.";
3227     case NERR_DfsVolumeIsInterDfs:
3228       return "The operation is not supported for an Inter-DFS link.";
3229     case NERR_DfsInconsistent:
3230       return "The internal state of the Dfs Service has become inconsistent.";
3231     case NERR_DfsServerUpgraded:
3232       return "The Dfs Service has been installed on the specified server.";
3233     case NERR_DfsDataIsIdentical:
3234       return "The Dfs data being reconciled is identical.";
3235     case NERR_DfsCantRemoveDfsRoot:
3236       return "The DFS root cannot be deleted. Uninstall DFS if required.";
3237     case NERR_DfsChildOrParentInDfs:
3238       return "A child or parent directory of the share is already in a Dfs.";
3239     case NERR_DfsInternalError:
3240       return "Dfs internal error.";
3241       /* the following are not defined in mingw */
3242 #if 0
3243
3244     case NERR_SetupAlreadyJoined:
3245       return "This machine is already joined to a domain.";
3246     case NERR_SetupNotJoined:
3247       return "This machine is not currently joined to a domain.";
3248     case NERR_SetupDomainController:
3249       return "This machine is a domain controller and cannot be unjoined from a domain.";
3250     case NERR_DefaultJoinRequired:
3251       return "The destination domain controller does not support creating machine accounts in OUs.";
3252     case NERR_InvalidWorkgroupName:
3253       return "The specified workgroup name is invalid.";
3254     case NERR_NameUsesIncompatibleCodePage:
3255       return "The specified computer name is incompatible with the default language used on the domain controller.";
3256     case NERR_ComputerAccountNotFound:
3257       return "The specified computer account could not be found.";
3258     case NERR_PersonalSku:
3259       return "This version of Windows cannot be joined to a domain.";
3260     case NERR_PasswordMustChange:
3261       return "The password must change at the next logon.";
3262     case NERR_AccountLockedOut:
3263       return "The account is locked out.";
3264     case NERR_PasswordTooLong:
3265       return "The password is too long.";
3266     case NERR_PasswordNotComplexEnough:
3267       return "The password does not meet the complexity policy.";
3268     case NERR_PasswordFilterError:
3269       return "The password does not meet the requirements of the password filter DLLs.";
3270 #endif
3271
3272     }
3273   msg = strerror (error_number);
3274   if (msg == NULL)
3275     msg = "unknown";
3276
3277   return msg;
3278 #endif //DBUS_WINCE
3279 }
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289 /******************************************************************************
3290  
3291 Original CVS version of dbus-sysdeps.c
3292  
3293 ******************************************************************************/
3294 /* -*- mode: C; c-file-style: "gnu" -*- */
3295 /* dbus-sysdeps.c Wrappers around system/libc features (internal to D-Bus implementation)
3296  * 
3297  * Copyright (C) 2002, 2003  Red Hat, Inc.
3298  * Copyright (C) 2003 CodeFactory AB
3299  * Copyright (C) 2005 Novell, Inc.
3300  *
3301  * Licensed under the Academic Free License version 2.1
3302  * 
3303  * This program is free software; you can redistribute it and/or modify
3304  * it under the terms of the GNU General Public License as published by
3305  * the Free Software Foundation; either version 2 of the License, or
3306  * (at your option) any later version.
3307  *
3308  * This program is distributed in the hope that it will be useful,
3309  * but WITHOUT ANY WARRANTY; without even the implied warranty of
3310  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3311  * GNU General Public License for more details.
3312  * 
3313  * You should have received a copy of the GNU General Public License
3314  * along with this program; if not, write to the Free Software
3315  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
3316  *
3317  */
3318
3319
3320 /**
3321  * @addtogroup DBusInternalsUtils
3322  * @{
3323  */
3324
3325 int _dbus_mkdir (const char *path,
3326                  mode_t mode)
3327 {
3328   return _mkdir(path);
3329 }
3330
3331 /**
3332  * Exit the process, returning the given value.
3333  *
3334  * @param code the exit code
3335  */
3336 void
3337 _dbus_exit (int code)
3338 {
3339   _exit (code);
3340 }
3341
3342 /**
3343  * Creates a socket and connects to a socket at the given host 
3344  * and port. The connection fd is returned, and is set up as
3345  * nonblocking.
3346  *
3347  * @param host the host name to connect to, NULL for loopback
3348  * @param port the prot to connect to
3349  * @param error return location for error code
3350  * @returns connection file descriptor or -1 on error
3351  */
3352 int
3353 _dbus_connect_tcp_socket (const char     *host,
3354                           dbus_uint32_t   port,
3355                           DBusError      *error)
3356 {
3357   DBusSocket s;
3358   int handle;
3359   struct sockaddr_in addr;
3360   struct hostent *he;
3361   struct in_addr *haddr;
3362   struct in_addr ina;
3363
3364   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3365
3366   _dbus_win_startup_winsock ();
3367
3368   s.fd = socket (AF_INET, SOCK_STREAM, 0);
3369
3370   if (DBUS_SOCKET_IS_INVALID (s.fd))
3371     {
3372       DBUS_SOCKET_SET_ERRNO ();
3373       dbus_set_error (error,
3374                       _dbus_error_from_errno (errno),
3375                       "Failed to create socket: %s",
3376                       _dbus_strerror (errno));
3377
3378       return -1;
3379     }
3380
3381   if (host == NULL)
3382     {
3383       host = "localhost";
3384       ina.s_addr = htonl (INADDR_LOOPBACK);
3385       haddr = &ina;
3386     }
3387
3388   he = gethostbyname (host);
3389   if (he == NULL)
3390     {
3391       DBUS_SOCKET_SET_ERRNO ();
3392       dbus_set_error (error,
3393                       _dbus_error_from_errno (errno),
3394                       "Failed to lookup hostname: %s",
3395                       host);
3396       DBUS_CLOSE_SOCKET (s.fd);
3397       return -1;
3398     }
3399
3400   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
3401
3402   _DBUS_ZERO (addr);
3403   memcpy (&addr.sin_addr, haddr, sizeof(struct in_addr));
3404   addr.sin_family = AF_INET;
3405   addr.sin_port = htons (port);
3406
3407   if (DBUS_SOCKET_API_RETURNS_ERROR
3408       (connect (s.fd, (struct sockaddr*) &addr, sizeof (addr)) < 0))
3409     {
3410       DBUS_SOCKET_SET_ERRNO ();
3411       dbus_set_error (error,
3412                       _dbus_error_from_errno (errno),
3413                       "Failed to connect to socket %s:%d %s",
3414                       host, port, _dbus_strerror (errno));
3415
3416       DBUS_CLOSE_SOCKET (s.fd);
3417       s.fd = -1;
3418
3419       return -1;
3420     }
3421
3422   handle = _dbus_socket_to_handle (&s);
3423
3424   if (!_dbus_set_fd_nonblocking (handle, error))
3425     {
3426       _dbus_close_socket (handle, NULL);
3427       handle = -1;
3428
3429       return -1;
3430     }
3431
3432   return handle;
3433 }
3434
3435 void
3436 _dbus_daemon_init(const char *host, dbus_uint32_t port);
3437 /**
3438  * Creates a socket and binds it to the given port,
3439  * then listens on the socket. The socket is
3440  * set to be nonblocking. 
3441  * In case of port=0 a random free port is used and 
3442  * returned in the port parameter. 
3443  *
3444  * @param host the interface to listen on, NULL for loopback, empty for any
3445  * @param port the port to listen on, if zero a free port will be used 
3446  * @param error return location for errors
3447  * @returns the listening file descriptor or -1 on error
3448  */
3449
3450 int
3451 _dbus_listen_tcp_socket (const char     *host,
3452                          dbus_uint32_t  *port,
3453                          DBusError      *error)
3454 {
3455   DBusSocket slisten;
3456   int handle;
3457   struct sockaddr_in addr;
3458   struct hostent *he;
3459   struct in_addr *haddr;
3460   socklen_t len = (socklen_t) sizeof (struct sockaddr);
3461   struct in_addr ina;
3462
3463
3464   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3465
3466   _dbus_win_startup_winsock ();
3467
3468   slisten.fd = socket (AF_INET, SOCK_STREAM, 0);
3469
3470   if (DBUS_SOCKET_IS_INVALID (slisten.fd))
3471     {
3472       DBUS_SOCKET_SET_ERRNO ();
3473       dbus_set_error (error, _dbus_error_from_errno (errno),
3474                       "Failed to create socket \"%s:%d\": %s",
3475                       host, port, _dbus_strerror (errno));
3476       return -1;
3477     }
3478   if (host == NULL)
3479     {
3480       host = "localhost";
3481       ina.s_addr = htonl (INADDR_LOOPBACK);
3482       haddr = &ina;
3483     }
3484   else if (!host[0])
3485     {
3486       ina.s_addr = htonl (INADDR_ANY);
3487       haddr = &ina;
3488     }
3489   else
3490     {
3491       he = gethostbyname (host);
3492       if (he == NULL)
3493         {
3494           DBUS_SOCKET_SET_ERRNO ();
3495           dbus_set_error (error,
3496                           _dbus_error_from_errno (errno),
3497                           "Failed to lookup hostname: %s",
3498                           host);
3499           DBUS_CLOSE_SOCKET (slisten.fd);
3500           return -1;
3501         }
3502
3503       haddr = ((struct in_addr *) (he->h_addr_list)[0]);
3504     }
3505
3506   _DBUS_ZERO (addr);
3507   memcpy (&addr.sin_addr, haddr, sizeof (struct in_addr));
3508   addr.sin_family = AF_INET;
3509   addr.sin_port = htons (*port);
3510
3511   if (bind (slisten.fd, (struct sockaddr*) &addr, sizeof (struct sockaddr)))
3512     {
3513       DBUS_SOCKET_SET_ERRNO ();
3514       dbus_set_error (error, _dbus_error_from_errno (errno),
3515                       "Failed to bind socket \"%s:%d\": %s",
3516                       host, *port, _dbus_strerror (errno));
3517       DBUS_CLOSE_SOCKET (slisten.fd);
3518       return -1;
3519     }
3520
3521   if (DBUS_SOCKET_API_RETURNS_ERROR (listen (slisten.fd, 30 /* backlog */)))
3522     {
3523       DBUS_SOCKET_SET_ERRNO ();
3524       dbus_set_error (error, _dbus_error_from_errno (errno),
3525                       "Failed to listen on socket \"%s:%d\": %s",
3526                       host, *port, _dbus_strerror (errno));
3527       DBUS_CLOSE_SOCKET (slisten.fd);
3528       return -1;
3529     }
3530
3531   getsockname(slisten.fd, (struct sockaddr*) &addr, &len);
3532   *port = (dbus_uint32_t) ntohs(addr.sin_port);
3533   
3534   _dbus_daemon_init(host, ntohs(addr.sin_port));
3535
3536   handle = _dbus_socket_to_handle (&slisten);
3537
3538   if (!_dbus_set_fd_nonblocking (handle, error))
3539     {
3540       _dbus_close_socket (handle, NULL);
3541       return -1;
3542     }
3543
3544   return handle;
3545 }
3546
3547 /**
3548  * Accepts a connection on a listening socket.
3549  * Handles EINTR for you.
3550  *
3551  * @param listen_fd the listen file descriptor
3552  * @returns the connection fd of the client, or -1 on error
3553  */
3554 int
3555 _dbus_accept  (int listen_handle)
3556 {
3557   DBusSocket *slisten;
3558   DBusSocket sclient;
3559   struct sockaddr addr;
3560   socklen_t addrlen;
3561
3562   _dbus_handle_to_socket(listen_handle, &slisten);
3563
3564   addrlen = sizeof (addr);
3565
3566   //FIXME:  why do we not try it again on Windows?
3567 #if !defined(DBUS_WIN) && !defined(DBUS_WINCE)
3568 retry:
3569 #endif
3570
3571   sclient.fd = accept (slisten->fd, &addr, &addrlen);
3572
3573   if (DBUS_SOCKET_IS_INVALID (sclient.fd))
3574     {
3575       DBUS_SOCKET_SET_ERRNO ();
3576 #if !defined(DBUS_WIN) && !defined(DBUS_WINCE)
3577       if (errno == EINTR)
3578         goto retry;
3579 #else
3580       return -1;
3581 #endif
3582     }
3583
3584   return _dbus_socket_to_handle (&sclient);
3585 }
3586
3587
3588
3589 dbus_bool_t
3590 write_credentials_byte (int             server_fd,
3591                         DBusError      *error)
3592 {
3593   /* FIXME: for the session bus credentials shouldn't matter (?), but
3594    * for the system bus they are presumably essential. A rough outline
3595    * of a way to implement the credential transfer would be this:
3596    *
3597    * client waits to *read* a byte.
3598    *
3599    * server creates a named pipe with a random name, sends a byte
3600    * contining its length, and its name.
3601    *
3602    * client reads the name, connects to it (using Win32 API).
3603    *
3604    * server waits for connection to the named pipe, then calls
3605    * ImpersonateNamedPipeClient(), notes its now-current credentials,
3606    * calls RevertToSelf(), closes its handles to the named pipe, and
3607    * is done. (Maybe there is some other way to get the SID of a named
3608    * pipe client without having to use impersonation?)
3609    *
3610    * client closes its handles and is done.
3611    *
3612    */
3613
3614   return TRUE;
3615 }
3616
3617 /**
3618  * Reads a single byte which must be nul (an error occurs otherwise),
3619  * and reads unix credentials if available. Fills in pid/uid/gid with
3620  * -1 if no credentials are available. Return value indicates whether
3621  * a byte was read, not whether we got valid credentials. On some
3622  * systems, such as Linux, reading/writing the byte isn't actually
3623  * required, but we do it anyway just to avoid multiple codepaths.
3624  * 
3625  * Fails if no byte is available, so you must select() first.
3626  *
3627  * The point of the byte is that on some systems we have to
3628  * use sendmsg()/recvmsg() to transmit credentials.
3629  *
3630  * @param client_fd the client file descriptor
3631  * @param credentials struct to fill with credentials of client
3632  * @param error location to store error code
3633  * @returns #TRUE on success
3634  */
3635 dbus_bool_t
3636 _dbus_read_credentials_unix_socket  (int              client_fd,
3637                                      DBusCredentials *credentials,
3638                                      DBusError       *error)
3639 {
3640   /* FIXME bogus testing credentials */
3641   _dbus_credentials_from_current_process (credentials);
3642
3643   return TRUE;
3644 }
3645
3646 /**
3647 * Checks to make sure the given directory is 
3648 * private to the user 
3649 *
3650 * @param dir the name of the directory
3651 * @param error error return
3652 * @returns #FALSE on failure
3653 **/
3654 dbus_bool_t
3655 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
3656 {
3657   const char *directory;
3658   struct stat sb;
3659
3660   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3661
3662   return TRUE;
3663 }
3664
3665
3666 /**
3667  * Gets user info for the given user ID.
3668  *
3669  * @param info user info object to initialize
3670  * @param uid the user ID
3671  * @param error error return
3672  * @returns #TRUE on success
3673  */
3674 dbus_bool_t
3675 _dbus_user_info_fill_uid (DBusUserInfo *info,
3676                           dbus_uid_t    uid,
3677                           DBusError    *error)
3678 {
3679   return fill_user_info (info, uid,
3680                          NULL, error);
3681 }
3682
3683 /**
3684  * Gets user info for the given username.
3685  *
3686  * @param info user info object to initialize
3687  * @param username the username
3688  * @param error error return
3689  * @returns #TRUE on success
3690  */
3691 dbus_bool_t
3692 _dbus_user_info_fill (DBusUserInfo     *info,
3693                       const DBusString *username,
3694                       DBusError        *error)
3695 {
3696   return fill_user_info (info, DBUS_UID_UNSET,
3697                          username, error);
3698 }
3699
3700
3701 dbus_bool_t
3702 fill_user_info (DBusUserInfo       *info,
3703                 dbus_uid_t          uid,
3704                 const DBusString   *username,
3705                 DBusError          *error)
3706 {
3707   const char *username_c;
3708
3709   /* exactly one of username/uid provided */
3710   _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
3711   _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
3712
3713   info->uid = DBUS_UID_UNSET;
3714   info->primary_gid = DBUS_GID_UNSET;
3715   info->group_ids = NULL;
3716   info->n_group_ids = 0;
3717   info->username = NULL;
3718   info->homedir = NULL;
3719
3720   if (username != NULL)
3721     username_c = _dbus_string_get_const_data (username);
3722   else
3723     username_c = NULL;
3724
3725   if (uid != DBUS_UID_UNSET)
3726     {
3727       if (!fill_win_user_info_from_uid (uid, info, error))
3728         {
3729           _dbus_verbose("%s after fill_win_user_info_from_uid\n",__FUNCTION__);
3730           return FALSE;
3731         }
3732     }
3733   else
3734     {
3735       wchar_t *wname = _dbus_win_utf8_to_utf16 (username_c, error);
3736
3737       if (!wname)
3738         return FALSE;
3739
3740       if (!fill_win_user_info_from_name (wname, info, error))
3741         {
3742           dbus_free (wname);
3743           return FALSE;
3744         }
3745       dbus_free (wname);
3746     }
3747
3748   return TRUE;
3749 }
3750
3751
3752 /**
3753  * Appends the given filename to the given directory.
3754  *
3755  * @todo it might be cute to collapse multiple '/' such as "foo//"
3756  * concat "//bar"
3757  *
3758  * @param dir the directory name
3759  * @param next_component the filename
3760  * @returns #TRUE on success
3761  */
3762 dbus_bool_t
3763 _dbus_concat_dir_and_file (DBusString       *dir,
3764                            const DBusString *next_component)
3765 {
3766   dbus_bool_t dir_ends_in_slash;
3767   dbus_bool_t file_starts_with_slash;
3768
3769   if (_dbus_string_get_length (dir) == 0 ||
3770       _dbus_string_get_length (next_component) == 0)
3771     return TRUE;
3772
3773   dir_ends_in_slash =
3774     ('/' == _dbus_string_get_byte (dir, _dbus_string_get_length (dir) - 1) ||
3775      '\\' == _dbus_string_get_byte (dir, _dbus_string_get_length (dir) - 1));
3776
3777   file_starts_with_slash =
3778     ('/' == _dbus_string_get_byte (next_component, 0) ||
3779      '\\' == _dbus_string_get_byte (next_component, 0));
3780
3781   if (dir_ends_in_slash && file_starts_with_slash)
3782     {
3783       _dbus_string_shorten (dir, 1);
3784     }
3785   else if (!(dir_ends_in_slash || file_starts_with_slash))
3786     {
3787       if (!_dbus_string_append_byte (dir, '\\'))
3788         return FALSE;
3789     }
3790
3791   return _dbus_string_copy (next_component, 0, dir,
3792                             _dbus_string_get_length (dir));
3793 }
3794
3795
3796
3797
3798 /**
3799  * Gets our process ID
3800  * @returns process ID
3801  */
3802 unsigned long
3803 _dbus_getpid (void)
3804 {
3805   return GetCurrentProcessId ();
3806 }
3807
3808 /** nanoseconds in a second */
3809 #define NANOSECONDS_PER_SECOND       1000000000
3810 /** microseconds in a second */
3811 #define MICROSECONDS_PER_SECOND      1000000
3812 /** milliseconds in a second */
3813 #define MILLISECONDS_PER_SECOND      1000
3814 /** nanoseconds in a millisecond */
3815 #define NANOSECONDS_PER_MILLISECOND  1000000
3816 /** microseconds in a millisecond */
3817 #define MICROSECONDS_PER_MILLISECOND 1000
3818
3819 /**
3820  * Sleeps the given number of milliseconds.
3821  * @param milliseconds number of milliseconds
3822  */
3823 void
3824 _dbus_sleep_milliseconds (int milliseconds)
3825 {
3826   Sleep (milliseconds);
3827 }
3828
3829
3830 /**
3831  * Get current time, as in gettimeofday().
3832  *
3833  * @param tv_sec return location for number of seconds
3834  * @param tv_usec return location for number of microseconds
3835  */
3836 void
3837 _dbus_get_current_time (long *tv_sec,
3838                         long *tv_usec)
3839 {
3840   FILETIME ft;
3841   dbus_uint64_t *time64 = (dbus_uint64_t *) &ft;
3842
3843   GetSystemTimeAsFileTime (&ft);
3844
3845   /* Convert from 100s of nanoseconds since 1601-01-01
3846   * to Unix epoch. Yes, this is Y2038 unsafe.
3847   */
3848   *time64 -= DBUS_INT64_CONSTANT (116444736000000000);
3849   *time64 /= 10;
3850
3851   if (tv_sec)
3852     *tv_sec = *time64 / 1000000;
3853
3854   if (tv_usec)
3855     *tv_usec = *time64 % 1000000;
3856 }
3857
3858
3859 /**
3860  * signal (SIGPIPE, SIG_IGN);
3861  */
3862 void
3863 _dbus_disable_sigpipe (void)
3864 {
3865     _dbus_verbose("FIXME: implement _dbus_disable_sigpipe (void)\n");
3866 }
3867
3868 /**
3869  * Gets the credentials of the current process.
3870  *
3871  * @param credentials credentials to fill in.
3872  */
3873 void
3874 _dbus_credentials_from_current_process (DBusCredentials *credentials)
3875 {
3876   credentials->pid = _dbus_getpid ();
3877   credentials->uid = _dbus_getuid ();
3878   credentials->gid = _dbus_getgid ();
3879 }
3880
3881 /**
3882  * Appends the contents of the given file to the string,
3883  * returning error code. At the moment, won't open a file
3884  * more than a megabyte in size.
3885  *
3886  * @param str the string to append to
3887  * @param filename filename to load
3888  * @param error place to set an error
3889  * @returns #FALSE if error was set
3890  */
3891 dbus_bool_t
3892 _dbus_file_get_contents (DBusString       *str,
3893                          const DBusString *filename,
3894                          DBusError        *error)
3895 {
3896   DBusFile file;
3897   struct stat sb;
3898   int orig_len;
3899   int total;
3900   const char *filename_c;
3901
3902   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3903
3904   filename_c = _dbus_string_get_const_data (filename);
3905
3906   /* O_BINARY useful on Cygwin and Win32 */
3907   if (!_dbus_open_file (&file, filename_c, O_RDONLY | O_BINARY, -1))
3908     {
3909       dbus_set_error (error, _dbus_error_from_errno (errno),
3910                       "Failed to open \"%s\": %s",
3911                       filename_c,
3912                       _dbus_strerror (errno));
3913       return FALSE;
3914     }
3915
3916   if (!_dbus_fstat (&file, &sb))
3917     {
3918       dbus_set_error (error, _dbus_error_from_errno (errno),
3919                       "Failed to stat \"%s\": %s",
3920                       filename_c,
3921                       _dbus_strerror (errno));
3922
3923       _dbus_verbose ("fstat() failed: %s",
3924                      _dbus_strerror (errno));
3925
3926       _dbus_close_file (&file, NULL);
3927
3928       return FALSE;
3929     }
3930
3931   if (sb.st_size > _DBUS_ONE_MEGABYTE)
3932     {
3933       dbus_set_error (error, DBUS_ERROR_FAILED,
3934                       "File size %lu of \"%s\" is too large.",
3935                       (unsigned long) sb.st_size, filename_c);
3936       _dbus_close_file (&file, NULL);
3937       return FALSE;
3938     }
3939
3940   total = 0;
3941   orig_len = _dbus_string_get_length (str);
3942   if (sb.st_size > 0 && S_ISREG (sb.st_mode))
3943     {
3944       int bytes_read;
3945
3946       while (total < (int) sb.st_size)
3947         {
3948           bytes_read = _dbus_read_file (&file, str,
3949                                         sb.st_size - total);
3950           if (bytes_read <= 0)
3951             {
3952               dbus_set_error (error, _dbus_error_from_errno (errno),
3953                               "Error reading \"%s\": %s",
3954                               filename_c,
3955                               _dbus_strerror (errno));
3956
3957               _dbus_verbose ("read() failed: %s",
3958                              _dbus_strerror (errno));
3959
3960               _dbus_close_file (&file, NULL);
3961               _dbus_string_set_length (str, orig_len);
3962               return FALSE;
3963             }
3964           else
3965             total += bytes_read;
3966         }
3967
3968       _dbus_close_file (&file, NULL);
3969       return TRUE;
3970     }
3971   else if (sb.st_size != 0)
3972     {
3973       _dbus_verbose ("Can only open regular files at the moment.\n");
3974       dbus_set_error (error, DBUS_ERROR_FAILED,
3975                       "\"%s\" is not a regular file",
3976                       filename_c);
3977       _dbus_close_file (&file, NULL);
3978       return FALSE;
3979     }
3980   else
3981     {
3982       _dbus_close_file (&file, NULL);
3983       return TRUE;
3984     }
3985 }
3986
3987 /**
3988  * Writes a string out to a file. If the file exists,
3989  * it will be atomically overwritten by the new data.
3990  *
3991  * @param str the string to write out
3992  * @param filename the file to save string to
3993  * @param error error to be filled in on failure
3994  * @returns #FALSE on failure
3995  */
3996 dbus_bool_t
3997 _dbus_string_save_to_file (const DBusString *str,
3998                            const DBusString *filename,
3999                            DBusError        *error)
4000 {
4001   DBusFile file;
4002   int bytes_to_write;
4003   const char *filename_c;
4004   DBusString tmp_filename;
4005   const char *tmp_filename_c;
4006   int total;
4007   dbus_bool_t need_unlink;
4008   dbus_bool_t retval;
4009
4010   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4011
4012   retval = FALSE;
4013   need_unlink = FALSE;
4014
4015   if (!_dbus_string_init (&tmp_filename))
4016     {
4017       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
4018       return FALSE;
4019     }
4020
4021   if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
4022     {
4023       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
4024       _dbus_string_free (&tmp_filename);
4025       return FALSE;
4026     }
4027
4028   if (!_dbus_string_append (&tmp_filename, "."))
4029     {
4030       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
4031       _dbus_string_free (&tmp_filename);
4032       return FALSE;
4033     }
4034
4035 #define N_TMP_FILENAME_RANDOM_BYTES 8
4036   if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
4037     {
4038       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
4039       _dbus_string_free (&tmp_filename);
4040       return FALSE;
4041     }
4042
4043   filename_c = _dbus_string_get_const_data (filename);
4044   tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
4045
4046   if (!_dbus_open_file (&file, tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
4047                         0600))
4048     {
4049       dbus_set_error (error, _dbus_error_from_errno (errno),
4050                       "Could not create %s: %s", tmp_filename_c,
4051                       _dbus_strerror (errno));
4052       goto out;
4053     }
4054
4055   need_unlink = TRUE;
4056
4057   total = 0;
4058   bytes_to_write = _dbus_string_get_length (str);
4059
4060   while (total < bytes_to_write)
4061     {
4062       int bytes_written;
4063
4064       bytes_written = _dbus_write_file (&file, str, total,
4065                                         bytes_to_write - total);
4066
4067       if (bytes_written <= 0)
4068         {
4069           dbus_set_error (error, _dbus_error_from_errno (errno),
4070                           "Could not write to %s: %s", tmp_filename_c,
4071                           _dbus_strerror (errno));
4072
4073           goto out;
4074         }
4075
4076       total += bytes_written;
4077     }
4078
4079   if (!_dbus_close_file (&file, NULL))
4080     {
4081       dbus_set_error (error, _dbus_error_from_errno (errno),
4082                       "Could not close file %s: %s",
4083                       tmp_filename_c, _dbus_strerror (errno));
4084
4085       goto out;
4086     }
4087
4088
4089   if ((unlink (filename_c) == -1 && errno != ENOENT) ||
4090        rename (tmp_filename_c, filename_c) < 0)
4091     {
4092       dbus_set_error (error, _dbus_error_from_errno (errno),
4093                       "Could not rename %s to %s: %s",
4094                       tmp_filename_c, filename_c,
4095                       _dbus_strerror (errno));
4096
4097       goto out;
4098     }
4099
4100   need_unlink = FALSE;
4101
4102   retval = TRUE;
4103
4104 out:
4105   /* close first, then unlink, to prevent ".nfs34234235" garbage
4106    * files
4107    */
4108
4109   if (_dbus_is_valid_file(&file))
4110     _dbus_close_file (&file, NULL);
4111
4112   if (need_unlink && unlink (tmp_filename_c) < 0)
4113     _dbus_verbose ("Failed to unlink temp file %s: %s\n",
4114                    tmp_filename_c, _dbus_strerror (errno));
4115
4116   _dbus_string_free (&tmp_filename);
4117
4118   if (!retval)
4119     _DBUS_ASSERT_ERROR_IS_SET (error);
4120
4121   return retval;
4122 }
4123
4124
4125 /** Creates the given file, failing if the file already exists.
4126  *
4127  * @param filename the filename
4128  * @param error error location
4129  * @returns #TRUE if we created the file and it didn't exist
4130  */
4131 dbus_bool_t
4132 _dbus_create_file_exclusively (const DBusString *filename,
4133                                DBusError        *error)
4134 {
4135   DBusFile file;
4136   const char *filename_c;
4137
4138   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4139
4140   filename_c = _dbus_string_get_const_data (filename);
4141
4142   if (!_dbus_open_file (&file, filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
4143                         0600))
4144     {
4145       dbus_set_error (error,
4146                       DBUS_ERROR_FAILED,
4147                       "Could not create file %s: %s\n",
4148                       filename_c,
4149                       _dbus_strerror (errno));
4150       return FALSE;
4151     }
4152
4153   if (!_dbus_close_file (&file, NULL))
4154     {
4155       dbus_set_error (error,
4156                       DBUS_ERROR_FAILED,
4157                       "Could not close file %s: %s\n",
4158                       filename_c,
4159                       _dbus_strerror (errno));
4160       return FALSE;
4161     }
4162
4163   return TRUE;
4164 }
4165
4166
4167 /**
4168  * Creates a directory; succeeds if the directory
4169  * is created or already existed.
4170  *
4171  * @param filename directory filename
4172  * @param error initialized error object
4173  * @returns #TRUE on success
4174  */
4175 dbus_bool_t
4176 _dbus_create_directory (const DBusString *filename,
4177                         DBusError        *error)
4178 {
4179   const char *filename_c;
4180
4181   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4182
4183   filename_c = _dbus_string_get_const_data (filename);
4184
4185   if (_dbus_mkdir (filename_c, 0700) < 0)
4186     {
4187       if (errno == EEXIST)
4188         return TRUE;
4189
4190       dbus_set_error (error, DBUS_ERROR_FAILED,
4191                       "Failed to create directory %s: %s\n",
4192                       filename_c, _dbus_strerror (errno));
4193       return FALSE;
4194     }
4195   else
4196     return TRUE;
4197 }
4198
4199
4200 static void
4201 pseudorandom_generate_random_bytes_buffer (char *buffer,
4202     int   n_bytes)
4203 {
4204   long tv_usec;
4205   int i;
4206
4207   /* fall back to pseudorandom */
4208   _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
4209                  n_bytes);
4210
4211   _dbus_get_current_time (NULL, &tv_usec);
4212   srand (tv_usec);
4213
4214   i = 0;
4215   while (i < n_bytes)
4216     {
4217       double r;
4218       unsigned int b;
4219
4220       r = rand ();
4221       b = (r / (double) RAND_MAX) * 255.0;
4222
4223       buffer[i] = b;
4224
4225       ++i;
4226     }
4227 }
4228
4229 static dbus_bool_t
4230 pseudorandom_generate_random_bytes (DBusString *str,
4231                                     int         n_bytes)
4232 {
4233   int old_len;
4234   char *p;
4235
4236   old_len = _dbus_string_get_length (str);
4237
4238   if (!_dbus_string_lengthen (str, n_bytes))
4239     return FALSE;
4240
4241   p = _dbus_string_get_data_len (str, old_len, n_bytes);
4242
4243   pseudorandom_generate_random_bytes_buffer (p, n_bytes);
4244
4245   return TRUE;
4246 }
4247
4248 /**
4249  * Gets the temporary files directory by inspecting the environment variables 
4250  * TMPDIR, TMP, and TEMP in that order. If none of those are set "/tmp" is returned
4251  *
4252  * @returns location of temp directory
4253  */
4254 const char*
4255 _dbus_get_tmpdir(void)
4256 {
4257   static const char* tmpdir = NULL;
4258
4259   if (tmpdir == NULL)
4260     {
4261       if (tmpdir == NULL)
4262         tmpdir = getenv("TMP");
4263       if (tmpdir == NULL)
4264         tmpdir = getenv("TEMP");
4265       if (tmpdir == NULL)
4266         tmpdir = getenv("TMPDIR");
4267       if (tmpdir == NULL)
4268           tmpdir = "C:\\Temp";
4269     }
4270
4271   _dbus_assert(tmpdir != NULL);
4272
4273   return tmpdir;
4274 }
4275
4276
4277 /**
4278  * Deletes the given file.
4279  *
4280  * @param filename the filename
4281  * @param error error location
4282  * 
4283  * @returns #TRUE if unlink() succeeded
4284  */
4285 dbus_bool_t
4286 _dbus_delete_file (const DBusString *filename,
4287                    DBusError        *error)
4288 {
4289   const char *filename_c;
4290
4291   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4292
4293   filename_c = _dbus_string_get_const_data (filename);
4294
4295   if (unlink (filename_c) < 0)
4296     {
4297       dbus_set_error (error, DBUS_ERROR_FAILED,
4298                       "Failed to delete file %s: %s\n",
4299                       filename_c, _dbus_strerror (errno));
4300       return FALSE;
4301     }
4302   else
4303     return TRUE;
4304 }
4305
4306 /**
4307  * Generates the given number of random bytes,
4308  * using the best mechanism we can come up with.
4309  *
4310  * @param str the string
4311  * @param n_bytes the number of random bytes to append to string
4312  * @returns #TRUE on success, #FALSE if no memory
4313  */
4314 dbus_bool_t
4315 _dbus_generate_random_bytes (DBusString *str,
4316                              int         n_bytes)
4317 {
4318   return pseudorandom_generate_random_bytes (str, n_bytes);
4319 }
4320
4321 #if !defined (DBUS_DISABLE_ASSERT) || defined(DBUS_BUILD_TESTS)
4322
4323 #ifdef _MSC_VER
4324 # ifdef BACKTRACES
4325 #  undef BACKTRACES
4326 # endif
4327 #else
4328 # define BACKTRACES
4329 #endif
4330
4331 #ifdef BACKTRACES
4332 /*
4333  * Backtrace Generator
4334  *
4335  * Copyright 2004 Eric Poech
4336  * Copyright 2004 Robert Shearman
4337  *
4338  * This library is free software; you can redistribute it and/or
4339  * modify it under the terms of the GNU Lesser General Public
4340  * License as published by the Free Software Foundation; either
4341  * version 2.1 of the License, or (at your option) any later version.
4342  *
4343  * This library is distributed in the hope that it will be useful,
4344  * but WITHOUT ANY WARRANTY; without even the implied warranty of
4345  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
4346  * Lesser General Public License for more details.
4347  *
4348  * You should have received a copy of the GNU Lesser General Public
4349  * License along with this library; if not, write to the Free Software
4350  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
4351  */
4352
4353 #include <winver.h>
4354 #include <imagehlp.h>
4355 #include <stdio.h>
4356
4357 #define DPRINTF _dbus_warn
4358
4359 #ifdef _MSC_VER
4360 #define BOOL int
4361
4362 #define __i386__
4363 #endif
4364
4365 //#define MAKE_FUNCPTR(f) static typeof(f) * p##f
4366
4367 //MAKE_FUNCPTR(StackWalk);
4368 //MAKE_FUNCPTR(SymGetModuleBase);
4369 //MAKE_FUNCPTR(SymFunctionTableAccess);
4370 //MAKE_FUNCPTR(SymInitialize);
4371 //MAKE_FUNCPTR(SymGetSymFromAddr);
4372 //MAKE_FUNCPTR(SymGetModuleInfo);
4373 static BOOL (WINAPI *pStackWalk)(
4374   DWORD MachineType,
4375   HANDLE hProcess,
4376   HANDLE hThread,
4377   LPSTACKFRAME StackFrame,
4378   PVOID ContextRecord,
4379   PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
4380   PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
4381   PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
4382   PTRANSLATE_ADDRESS_ROUTINE TranslateAddress
4383 );
4384 static DWORD (WINAPI *pSymGetModuleBase)(
4385   HANDLE hProcess,
4386   DWORD dwAddr
4387 );
4388 static PVOID  (WINAPI *pSymFunctionTableAccess)(
4389   HANDLE hProcess,
4390   DWORD AddrBase
4391 );
4392 static BOOL  (WINAPI *pSymInitialize)(
4393   HANDLE hProcess,
4394   PSTR UserSearchPath,
4395   BOOL fInvadeProcess
4396 );
4397 static BOOL  (WINAPI *pSymGetSymFromAddr)(
4398   HANDLE hProcess,
4399   DWORD Address,
4400   PDWORD Displacement,
4401   PIMAGEHLP_SYMBOL Symbol
4402 );
4403 static BOOL  (WINAPI *pSymGetModuleInfo)(
4404   HANDLE hProcess,
4405   DWORD dwAddr,
4406   PIMAGEHLP_MODULE ModuleInfo
4407 );
4408 static DWORD  (WINAPI *pSymSetOptions)(
4409   DWORD SymOptions
4410 );
4411
4412
4413 static BOOL init_backtrace()
4414 {
4415     HMODULE hmodDbgHelp = LoadLibraryA("dbghelp");
4416 /*
4417     #define GETFUNC(x) \
4418     p##x = (typeof(x)*)GetProcAddress(hmodDbgHelp, #x); \
4419     if (!p##x) \
4420     { \
4421         return FALSE; \
4422     }
4423     */
4424
4425
4426 //    GETFUNC(StackWalk);
4427 //    GETFUNC(SymGetModuleBase);
4428 //    GETFUNC(SymFunctionTableAccess);
4429 //    GETFUNC(SymInitialize);
4430 //    GETFUNC(SymGetSymFromAddr);
4431 //    GETFUNC(SymGetModuleInfo);
4432
4433 #define FUNC(x) #x
4434
4435       pStackWalk = (BOOL  (WINAPI *)(
4436 DWORD MachineType,
4437 HANDLE hProcess,
4438 HANDLE hThread,
4439 LPSTACKFRAME StackFrame,
4440 PVOID ContextRecord,
4441 PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
4442 PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
4443 PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
4444 PTRANSLATE_ADDRESS_ROUTINE TranslateAddress
4445 ))GetProcAddress (hmodDbgHelp, FUNC(StackWalk));
4446     pSymGetModuleBase=(DWORD  (WINAPI *)(
4447   HANDLE hProcess,
4448   DWORD dwAddr
4449 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleBase));
4450     pSymFunctionTableAccess=(PVOID  (WINAPI *)(
4451   HANDLE hProcess,
4452   DWORD AddrBase
4453 ))GetProcAddress (hmodDbgHelp, FUNC(SymFunctionTableAccess));
4454     pSymInitialize = (BOOL  (WINAPI *)(
4455   HANDLE hProcess,
4456   PSTR UserSearchPath,
4457   BOOL fInvadeProcess
4458 ))GetProcAddress (hmodDbgHelp, FUNC(SymInitialize));
4459     pSymGetSymFromAddr = (BOOL  (WINAPI *)(
4460   HANDLE hProcess,
4461   DWORD Address,
4462   PDWORD Displacement,
4463   PIMAGEHLP_SYMBOL Symbol
4464 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetSymFromAddr));
4465     pSymGetModuleInfo = (BOOL  (WINAPI *)(
4466   HANDLE hProcess,
4467   DWORD dwAddr,
4468   PIMAGEHLP_MODULE ModuleInfo
4469 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleInfo));
4470 pSymSetOptions = (DWORD  (WINAPI *)(
4471 DWORD SymOptions
4472 ))GetProcAddress (hmodDbgHelp, FUNC(SymSetOptions));
4473
4474
4475     pSymSetOptions(SYMOPT_UNDNAME);
4476
4477     pSymInitialize(GetCurrentProcess(), NULL, TRUE);
4478
4479     return TRUE;
4480 }
4481
4482 static void dump_backtrace_for_thread(HANDLE hThread)
4483 {
4484     STACKFRAME sf;
4485     CONTEXT context;
4486     DWORD dwImageType;
4487
4488     if (!pStackWalk)
4489         if (!init_backtrace())
4490             return;
4491
4492     /* can't use this function for current thread as GetThreadContext
4493      * doesn't support getting context from current thread */
4494     if (hThread == GetCurrentThread())
4495         return;
4496
4497     DPRINTF("Backtrace:\n");
4498
4499     memset(&context, 0, sizeof(context));
4500     context.ContextFlags = CONTEXT_FULL;
4501
4502     SuspendThread(hThread);
4503
4504     if (!GetThreadContext(hThread, &context))
4505     {
4506         DPRINTF("Couldn't get thread context (error %ld)\n", GetLastError());
4507         ResumeThread(hThread);
4508         return;
4509     }
4510
4511     memset(&sf, 0, sizeof(sf));
4512
4513 #ifdef __i386__
4514     sf.AddrFrame.Offset = context.Ebp;
4515     sf.AddrFrame.Mode = AddrModeFlat;
4516     sf.AddrPC.Offset = context.Eip;
4517     sf.AddrPC.Mode = AddrModeFlat;
4518     dwImageType = IMAGE_FILE_MACHINE_I386;
4519 #else
4520 # error You need to fill in the STACKFRAME structure for your architecture
4521 #endif
4522
4523     while (pStackWalk(dwImageType, GetCurrentProcess(),
4524                      hThread, &sf, &context, NULL, pSymFunctionTableAccess,
4525                      pSymGetModuleBase, NULL))
4526     {
4527         BYTE buffer[256];
4528         IMAGEHLP_SYMBOL * pSymbol = (IMAGEHLP_SYMBOL *)buffer;
4529         DWORD dwDisplacement;
4530
4531         pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
4532         pSymbol->MaxNameLength = sizeof(buffer) - sizeof(IMAGEHLP_SYMBOL) + 1;
4533
4534         if (!pSymGetSymFromAddr(GetCurrentProcess(), sf.AddrPC.Offset,
4535                                 &dwDisplacement, pSymbol))
4536         {
4537             IMAGEHLP_MODULE ModuleInfo;
4538             ModuleInfo.SizeOfStruct = sizeof(ModuleInfo);
4539
4540             if (!pSymGetModuleInfo(GetCurrentProcess(), sf.AddrPC.Offset,
4541                                    &ModuleInfo))
4542                 DPRINTF("1\t%p\n", (void*)sf.AddrPC.Offset);
4543             else
4544                 DPRINTF("2\t%s+0x%lx\n", ModuleInfo.ImageName,
4545                     sf.AddrPC.Offset - ModuleInfo.BaseOfImage);
4546         }
4547         else if (dwDisplacement)
4548             DPRINTF("3\t%s+0x%lx\n", pSymbol->Name, dwDisplacement);
4549         else
4550             DPRINTF("4\t%s\n", pSymbol->Name);
4551     }
4552
4553     ResumeThread(hThread);
4554 }
4555
4556 static DWORD WINAPI dump_thread_proc(LPVOID lpParameter)
4557 {
4558     dump_backtrace_for_thread((HANDLE)lpParameter);
4559     return 0;
4560 }
4561
4562 /* cannot get valid context from current thread, so we have to execute
4563  * backtrace from another thread */
4564 static void dump_backtrace()
4565 {
4566     HANDLE hCurrentThread;
4567     HANDLE hThread;
4568     DWORD dwThreadId;
4569     DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
4570         GetCurrentProcess(), &hCurrentThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
4571     hThread = CreateThread(NULL, 0, dump_thread_proc, (LPVOID)hCurrentThread,
4572         0, &dwThreadId);
4573     WaitForSingleObject(hThread, INFINITE);
4574     CloseHandle(hThread);
4575     CloseHandle(hCurrentThread);
4576 }
4577
4578 void _dbus_print_backtrace(void)
4579 {
4580   init_backtrace();
4581   dump_backtrace();
4582 }
4583 #else
4584 void _dbus_print_backtrace(void)
4585 {
4586   _dbus_verbose ("  D-Bus not compiled with backtrace support\n");
4587 }
4588 #endif
4589
4590 /**
4591  * Sends a single nul byte with our UNIX credentials as ancillary
4592  * data.  Returns #TRUE if the data was successfully written.  On
4593  * systems that don't support sending credentials, just writes a byte,
4594  * doesn't send any credentials.  On some systems, such as Linux,
4595  * reading/writing the byte isn't actually required, but we do it
4596  * anyway just to avoid multiple codepaths.
4597  *
4598  * Fails if no byte can be written, so you must select() first.
4599  *
4600  * The point of the byte is that on some systems we have to
4601  * use sendmsg()/recvmsg() to transmit credentials.
4602  *
4603  * @param server_fd file descriptor for connection to server
4604  * @param error return location for error code
4605  * @returns #TRUE if the byte was sent
4606  */
4607 dbus_bool_t
4608 _dbus_send_credentials_unix_socket  (int              server_fd,
4609                                      DBusError       *error)
4610 {
4611   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4612
4613   if (write_credentials_byte (server_fd, error))
4614     return TRUE;
4615   else
4616     return FALSE;
4617 }
4618
4619 static dbus_uint32_t fromAscii(char ascii)
4620 {
4621     if(ascii >= '0' && ascii <= '9')
4622         return ascii - '0';
4623     if(ascii >= 'A' && ascii <= 'F')
4624         return ascii - 'A' + 10;
4625     if(ascii >= 'a' && ascii <= 'f')
4626         return ascii - 'a' + 10;
4627     return 0;    
4628 }
4629
4630 dbus_bool_t _dbus_read_local_machine_uuid   (DBusGUID         *machine_id,
4631                                              dbus_bool_t       create_if_not_found,
4632                                              DBusError        *error)
4633 {
4634 #ifdef DBUS_WINCE
4635         return TRUE;
4636   // TODO
4637 #else
4638     HW_PROFILE_INFOA info;
4639     char *lpc = &info.szHwProfileGuid[0];
4640     dbus_uint32_t u;
4641
4642     //  the hw-profile guid lives long enough
4643     if(!GetCurrentHwProfileA(&info))
4644       {
4645         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); // FIXME
4646         return FALSE;  
4647       }
4648
4649     // Form: {12340001-4980-1920-6788-123456789012}
4650     lpc++;
4651     // 12340001
4652     u = ((fromAscii(lpc[0]) <<  0) |
4653          (fromAscii(lpc[1]) <<  4) |
4654          (fromAscii(lpc[2]) <<  8) |
4655          (fromAscii(lpc[3]) << 12) |
4656          (fromAscii(lpc[4]) << 16) |
4657          (fromAscii(lpc[5]) << 20) |
4658          (fromAscii(lpc[6]) << 24) |
4659          (fromAscii(lpc[7]) << 28));
4660     machine_id->as_uint32s[0] = u;
4661
4662     lpc += 9;
4663     // 4980-1920
4664     u = ((fromAscii(lpc[0]) <<  0) |
4665          (fromAscii(lpc[1]) <<  4) |
4666          (fromAscii(lpc[2]) <<  8) |
4667          (fromAscii(lpc[3]) << 12) |
4668          (fromAscii(lpc[5]) << 16) |
4669          (fromAscii(lpc[6]) << 20) |
4670          (fromAscii(lpc[7]) << 24) |
4671          (fromAscii(lpc[8]) << 28));
4672     machine_id->as_uint32s[1] = u;
4673     
4674     lpc += 10;
4675     // 6788-1234
4676     u = ((fromAscii(lpc[0]) <<  0) |
4677          (fromAscii(lpc[1]) <<  4) |
4678          (fromAscii(lpc[2]) <<  8) |
4679          (fromAscii(lpc[3]) << 12) |
4680          (fromAscii(lpc[5]) << 16) |
4681          (fromAscii(lpc[6]) << 20) |
4682          (fromAscii(lpc[7]) << 24) |
4683          (fromAscii(lpc[8]) << 28));
4684     machine_id->as_uint32s[2] = u;
4685     
4686     lpc += 9;
4687     // 56789012
4688     u = ((fromAscii(lpc[0]) <<  0) |
4689          (fromAscii(lpc[1]) <<  4) |
4690          (fromAscii(lpc[2]) <<  8) |
4691          (fromAscii(lpc[3]) << 12) |
4692          (fromAscii(lpc[4]) << 16) |
4693          (fromAscii(lpc[5]) << 20) |
4694          (fromAscii(lpc[6]) << 24) |
4695          (fromAscii(lpc[7]) << 28));
4696     machine_id->as_uint32s[3] = u;
4697 #endif
4698     return TRUE;
4699 }
4700
4701 static
4702 HANDLE _dbus_global_lock (const char *mutexname)
4703 {
4704   HANDLE mutex;
4705   DWORD gotMutex;
4706
4707   mutex = CreateMutex( NULL, FALSE, mutexname );
4708   if( !mutex )
4709     {
4710       return FALSE;
4711     }
4712
4713    gotMutex = WaitForSingleObject( mutex, INFINITE );
4714    switch( gotMutex )
4715      {
4716        case WAIT_ABANDONED:
4717                ReleaseMutex (mutex);
4718                CloseHandle (mutex);
4719                return 0;
4720        case WAIT_FAILED:
4721        case WAIT_TIMEOUT:
4722                return 0;
4723      }
4724
4725    return mutex;
4726 }
4727
4728 static
4729 void _dbus_global_unlock (HANDLE mutex)
4730 {
4731   ReleaseMutex (mutex);
4732   CloseHandle (mutex); 
4733 }
4734
4735 // for proper cleanup in dbus-daemon
4736 static HANDLE hDBusDaemonMutex = NULL;
4737 static HANDLE hDBusSharedMem = NULL;
4738 // sync _dbus_daemon_init, _dbus_daemon_uninit and _dbus_daemon_already_runs
4739 static const char *cUniqueDBusInitMutex = "UniqueDBusInitMutex";
4740 // sync _dbus_get_autolaunch_address
4741 static const char *cDBusAutolaunchMutex = "DBusAutolaunchMutex";
4742 // mutex to determine if dbus-daemon is already started (per user)
4743 static const char *cDBusDaemonMutex = "DBusDaemonMutex";
4744 // named shm for dbus adress info (per user)
4745 static const char *cDBusDaemonAddressInfo = "DBusDaemonAddressInfo";
4746
4747 void
4748 _dbus_daemon_init(const char *host, dbus_uint32_t port)
4749 {
4750   HANDLE lock;
4751   const char *adr = NULL;
4752   char szUserName[64];
4753   DWORD dwUserNameSize = sizeof(szUserName);
4754   char szDBusDaemonMutex[128];
4755   char szDBusDaemonAddressInfo[128];
4756   char szAddress[128];
4757
4758   _dbus_assert(host);
4759   _dbus_assert(port);
4760
4761   _snprintf(szAddress, sizeof(szAddress) - 1, "tcp:host=%s,port=%d", host, port);
4762
4763   _dbus_assert( GetUserName(szUserName, &dwUserNameSize) != 0);
4764   _snprintf(szDBusDaemonMutex, sizeof(szDBusDaemonMutex) - 1, "%s:%s",
4765             cDBusDaemonMutex, szUserName);
4766   _snprintf(szDBusDaemonAddressInfo, sizeof(szDBusDaemonAddressInfo) - 1, "%s:%s",
4767             cDBusDaemonAddressInfo, szUserName);
4768
4769   // before _dbus_global_lock to keep correct lock/release order
4770   hDBusDaemonMutex = CreateMutex( NULL, FALSE, szDBusDaemonMutex );
4771
4772   _dbus_assert(WaitForSingleObject( hDBusDaemonMutex, 1000 ) == WAIT_OBJECT_0);
4773
4774   // sync _dbus_daemon_init, _dbus_daemon_uninit and _dbus_daemon_already_runs
4775   lock = _dbus_global_lock( cUniqueDBusInitMutex );
4776
4777   // create shm
4778   hDBusSharedMem = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
4779                                       0, strlen( szAddress ) + 1, szDBusDaemonAddressInfo );
4780   _dbus_assert( hDBusSharedMem );
4781
4782   adr = MapViewOfFile( hDBusSharedMem, FILE_MAP_WRITE, 0, 0, 0 );
4783
4784   _dbus_assert( adr );
4785
4786   strcpy(adr, szAddress);
4787
4788   // cleanup
4789   UnmapViewOfFile( adr );
4790
4791   _dbus_global_unlock( lock );
4792 }
4793
4794 void
4795 _dbus_daemon_release()
4796 {
4797   HANDLE lock;
4798
4799   // sync _dbus_daemon_init, _dbus_daemon_uninit and _dbus_daemon_already_runs
4800   lock = _dbus_global_lock( cUniqueDBusInitMutex );
4801
4802   CloseHandle( hDBusSharedMem );
4803
4804   hDBusSharedMem = NULL;
4805
4806   ReleaseMutex( hDBusDaemonMutex );
4807
4808   CloseHandle( hDBusDaemonMutex );
4809
4810   hDBusDaemonMutex = NULL;
4811
4812   _dbus_global_unlock( lock );
4813 }
4814
4815 static dbus_bool_t
4816 _dbus_get_autolaunch_shm(DBusString *adress)
4817 {
4818   HANDLE sharedMem;
4819   const char *adr;
4820   char szUserName[64];
4821   DWORD dwUserNameSize = sizeof(szUserName);
4822   char szDBusDaemonAddressInfo[128];
4823
4824   if( !GetUserName(szUserName, &dwUserNameSize) )
4825       return FALSE;
4826   _snprintf(szDBusDaemonAddressInfo, sizeof(szDBusDaemonAddressInfo) - 1, "%s:%s",
4827             cDBusDaemonAddressInfo, szUserName);
4828
4829   // read shm
4830   do {
4831       // we know that dbus-daemon is available, so we wait until shm is available
4832       sharedMem = OpenFileMapping( FILE_MAP_READ, FALSE, szDBusDaemonAddressInfo );
4833       if( sharedMem == 0 )
4834           Sleep( 100 );
4835   } while( sharedMem == 0 );
4836
4837   if( sharedMem == 0 )
4838       return FALSE;
4839
4840   adr = MapViewOfFile( sharedMem, FILE_MAP_READ, 0, 0, 0 );
4841
4842   if( adr == 0 )
4843       return FALSE;
4844
4845   _dbus_string_init( adress );
4846
4847   _dbus_string_append( adress, adr ); 
4848
4849   // cleanup
4850   UnmapViewOfFile( adr );
4851
4852   CloseHandle( sharedMem );
4853
4854   return TRUE;
4855 }
4856
4857 static dbus_bool_t
4858 _dbus_daemon_already_runs (DBusString *adress)
4859 {
4860   HANDLE lock;
4861   HANDLE daemon;
4862   dbus_bool_t bRet = TRUE;
4863   char szUserName[64];
4864   DWORD dwUserNameSize = sizeof(szUserName);
4865   char szDBusDaemonMutex[128];
4866
4867   // sync _dbus_daemon_init, _dbus_daemon_uninit and _dbus_daemon_already_runs
4868   lock = _dbus_global_lock( cUniqueDBusInitMutex );
4869
4870   if( !GetUserName(szUserName, &dwUserNameSize) )
4871       return FALSE;
4872   _snprintf(szDBusDaemonMutex, sizeof(szDBusDaemonMutex) - 1, "%s:%s",
4873             cDBusDaemonMutex, szUserName);
4874
4875   // do checks
4876   daemon = CreateMutex( NULL, FALSE, szDBusDaemonMutex );
4877   if(WaitForSingleObject( daemon, 10 ) != WAIT_TIMEOUT)
4878     {
4879       ReleaseMutex (daemon);
4880       CloseHandle (daemon);
4881
4882       _dbus_global_unlock( lock );
4883       return FALSE;
4884     }
4885
4886   // read shm
4887   bRet = _dbus_get_autolaunch_shm( adress );
4888
4889   // cleanup
4890   CloseHandle ( daemon );
4891
4892   _dbus_global_unlock( lock );
4893
4894   return bRet;
4895 }
4896
4897 dbus_bool_t
4898 _dbus_get_autolaunch_address (DBusString *address, 
4899                               DBusError *error)
4900 {
4901   HANDLE mutex;
4902   STARTUPINFOA si;
4903   PROCESS_INFORMATION pi;
4904   dbus_bool_t retval = FALSE;
4905   LPSTR lpFile;
4906   char dbus_exe_path[MAX_PATH];
4907   char dbus_args[MAX_PATH * 2];
4908
4909   mutex = _dbus_global_lock ( cDBusAutolaunchMutex );
4910
4911   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4912
4913   if (_dbus_daemon_already_runs(address))
4914     {
4915         printf("dbus daemon already exists\n");
4916         retval = TRUE;
4917         goto out;
4918     }
4919
4920   if (!SearchPathA(NULL, "dbus-daemon.exe", NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile))
4921     {
4922       printf ("could not find dbus-daemon executable\n");
4923       goto out;
4924     }
4925
4926   // Create process
4927   ZeroMemory( &si, sizeof(si) );
4928   si.cb = sizeof(si);
4929   ZeroMemory( &pi, sizeof(pi) );
4930
4931   _snprintf(dbus_args, sizeof(dbus_args) - 1, "\"%s\" %s", dbus_exe_path,  " --session");
4932
4933 //  argv[i] = "--config-file=bus\\session.conf";
4934   printf("create process \"%s\" %s\n", dbus_exe_path, dbus_args);
4935   if(CreateProcessA(dbus_exe_path, dbus_args, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
4936     {
4937       retval = TRUE;
4938
4939       // Wait until started (see _dbus_get_autolaunch_shm())
4940       WaitForInputIdle(pi.hProcess, INFINITE);
4941
4942       retval = _dbus_get_autolaunch_shm( address );
4943     } else {
4944       retval = FALSE;
4945     }
4946   
4947 out:
4948   if (retval)
4949     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4950   else
4951     _DBUS_ASSERT_ERROR_IS_SET (error);
4952   
4953   _dbus_global_unlock (mutex);
4954
4955   return retval;
4956  }
4957
4958
4959 /** Makes the file readable by every user in the system.
4960  *
4961  * @param filename the filename
4962  * @param error error location
4963  * @returns #TRUE if the file's permissions could be changed.
4964  */
4965 dbus_bool_t
4966 _dbus_make_file_world_readable(const DBusString *filename,
4967                                DBusError *error)
4968 {
4969   // TODO
4970   return TRUE;
4971 }
4972
4973
4974 #define DBUS_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
4975
4976 // @TODO: this function is duplicated from dbus-sysdeps-unix.c
4977 //        and differs only in the path separator, may be we should 
4978 //        use a dbus path separator variable
4979
4980 #define _dbus_path_seperator ";"
4981
4982 static dbus_bool_t
4983 split_paths_and_append (DBusString *dirs, 
4984                         const char *suffix, 
4985                         DBusList **dir_list)
4986 {
4987    int start;
4988    int i;
4989    int len;
4990    char *cpath;
4991    const DBusString file_suffix;
4992
4993    start = 0;
4994    i = 0;
4995
4996    _dbus_string_init_const (&file_suffix, suffix);
4997
4998    len = _dbus_string_get_length (dirs);
4999
5000    while (_dbus_string_find (dirs, start, _dbus_path_seperator, &i))
5001      {
5002        DBusString path;
5003
5004        if (!_dbus_string_init (&path))
5005           goto oom;
5006
5007        if (!_dbus_string_copy_len (dirs,
5008                                    start,
5009                                    i - start,
5010                                    &path,
5011                                    0))
5012           {
5013             _dbus_string_free (&path);
5014             goto oom;
5015           }
5016
5017         _dbus_string_chop_white (&path);
5018
5019         /* check for an empty path */
5020         if (_dbus_string_get_length (&path) == 0)
5021           goto next;
5022
5023         if (!_dbus_concat_dir_and_file (&path,
5024                                         &file_suffix))
5025           {
5026             _dbus_string_free (&path);
5027             goto oom;
5028           }
5029
5030         if (!_dbus_string_copy_data(&path, &cpath))
5031           {
5032             _dbus_string_free (&path);
5033             goto oom;
5034           }
5035
5036         if (!_dbus_list_append (dir_list, cpath))
5037           {
5038             _dbus_string_free (&path);              
5039             dbus_free (cpath);
5040             goto oom;
5041           }
5042
5043        next:
5044         _dbus_string_free (&path);
5045         start = i + 1;
5046     } 
5047       
5048   if (start != len)
5049     { 
5050       DBusString path;
5051
5052       if (!_dbus_string_init (&path))
5053         goto oom;
5054
5055       if (!_dbus_string_copy_len (dirs,
5056                                   start,
5057                                   len - start,
5058                                   &path,
5059                                   0))
5060         {
5061           _dbus_string_free (&path);
5062           goto oom;
5063         }
5064
5065       if (!_dbus_concat_dir_and_file (&path,
5066                                       &file_suffix))
5067         {
5068           _dbus_string_free (&path);
5069           goto oom;
5070         }
5071
5072       if (!_dbus_string_copy_data(&path, &cpath))
5073         {
5074           _dbus_string_free (&path);
5075           goto oom;
5076         }
5077
5078       if (!_dbus_list_append (dir_list, cpath))
5079         {
5080           _dbus_string_free (&path);              
5081           dbus_free (cpath);
5082           goto oom;
5083         }
5084
5085       _dbus_string_free (&path); 
5086     }
5087
5088   return TRUE;
5089
5090  oom:
5091   _dbus_list_foreach (dir_list, (DBusForeachFunction)dbus_free, NULL); 
5092   _dbus_list_clear (dir_list);
5093   return FALSE;
5094 }
5095
5096 /**
5097  * Returns the standard directories for a session bus to look for service 
5098  * activation files 
5099  *
5100  * On Windows this should be data directories:
5101  *
5102  * %CommonProgramFiles%/dbus
5103  *
5104  * and
5105  *
5106  * DBUS_DATADIR
5107  *
5108  * @param dirs the directory list we are returning
5109  * @returns #FALSE on OOM 
5110  */
5111
5112 dbus_bool_t 
5113 _dbus_get_standard_session_servicedirs (DBusList **dirs)
5114 {
5115   const char *common_progs;
5116   DBusString servicedir_path;
5117
5118   if (!_dbus_string_init (&servicedir_path))
5119     return FALSE;
5120
5121   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR";"))
5122         goto oom;
5123
5124   common_progs = _dbus_getenv ("CommonProgramFiles");
5125
5126   if (common_progs != NULL)
5127     {
5128       if (!_dbus_string_append (&servicedir_path, common_progs))
5129         goto oom;
5130
5131       if (!_dbus_string_append (&servicedir_path, ";"))
5132         goto oom;
5133     }
5134
5135   if (!split_paths_and_append (&servicedir_path, 
5136                                DBUS_STANDARD_SESSION_SERVICEDIR, 
5137                                dirs))
5138     goto oom;
5139
5140   _dbus_string_free (&servicedir_path);  
5141   return TRUE;
5142
5143  oom:
5144   _dbus_string_free (&servicedir_path);
5145   return FALSE;
5146 }
5147
5148 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
5149
5150 /**
5151  * Atomically increments an integer
5152  *
5153  * @param atomic pointer to the integer to increment
5154  * @returns the value before incrementing
5155  *
5156  */
5157 dbus_int32_t
5158 _dbus_atomic_inc (DBusAtomic *atomic)
5159 {
5160   // +/- 1 is needed here!
5161   return InterlockedIncrement (&atomic->value) - 1;
5162 }
5163
5164 /**
5165  * Atomically decrement an integer
5166  *
5167  * @param atomic pointer to the integer to decrement
5168  * @returns the value before decrementing
5169  *
5170  */
5171 dbus_int32_t
5172 _dbus_atomic_dec (DBusAtomic *atomic)
5173 {
5174   // +/- 1 is needed here!
5175   return InterlockedDecrement (&atomic->value) + 1;
5176 }
5177
5178 #endif /* asserts or tests enabled */
5179
5180 /** @} end of sysdeps-win */
5181
5182 /* tests in dbus-sysdeps-util.c */