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