Use INVALID_HANDLE_VALUE, not NULL.
[platform/upstream/dbus.git] / dbus / dbus-sysdeps-win.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
26  *
27  */
28
29 #define STRSAFE_NO_DEPRECATE
30
31 #ifndef DBUS_WINCE
32 #ifndef _WIN32_WINNT
33 #define _WIN32_WINNT 0x0501
34 #endif
35 #endif
36
37 #include "dbus-internals.h"
38 #include "dbus-sysdeps.h"
39 #include "dbus-threads.h"
40 #include "dbus-protocol.h"
41 #include "dbus-string.h"
42 #include "dbus-sysdeps-win.h"
43 #include "dbus-protocol.h"
44 #include "dbus-hash.h"
45 #include "dbus-sockets-win.h"
46 #include "dbus-list.h"
47 #include "dbus-nonce.h"
48 #include "dbus-credentials.h"
49
50 #include <windows.h>
51 #include <ws2tcpip.h>
52 #include <wincrypt.h>
53
54 /* Declarations missing in mingw's headers */
55 extern BOOL WINAPI ConvertStringSidToSidA (LPCSTR  StringSid, PSID *Sid);
56 extern BOOL WINAPI ConvertSidToStringSidA (PSID Sid, LPSTR *StringSid);
57
58 #include <fcntl.h>
59
60 #include <process.h>
61 #include <stdio.h>
62 #include <io.h>
63
64 #include <string.h>
65 #include <mbstring.h>
66 #include <errno.h>
67 #include <sys/stat.h>
68 #include <sys/types.h>
69
70 #ifdef HAVE_WSPIAPI_H
71 // needed for w2k compatibility (getaddrinfo/freeaddrinfo/getnameinfo)
72 #ifdef __GNUC__
73 #define _inline
74 #include "wspiapi.h"
75 #else
76 #include <wspiapi.h>
77 #endif
78 #endif // HAVE_WSPIAPI_H
79
80 #ifndef O_BINARY
81 #define O_BINARY 0
82 #endif
83
84 typedef int socklen_t;
85
86 char*
87 _dbus_win_error_string (int error_number)
88 {
89   char *msg;
90
91   FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
92                  FORMAT_MESSAGE_IGNORE_INSERTS |
93                  FORMAT_MESSAGE_FROM_SYSTEM,
94                  NULL, error_number, 0,
95                  (LPSTR) &msg, 0, NULL);
96
97   if (msg[strlen (msg) - 1] == '\n')
98     msg[strlen (msg) - 1] = '\0';
99   if (msg[strlen (msg) - 1] == '\r')
100     msg[strlen (msg) - 1] = '\0';
101
102   return msg;
103 }
104
105 void
106 _dbus_win_free_error_string (char *string)
107 {
108   LocalFree (string);
109 }
110
111 /**
112  * Socket interface
113  *
114  */
115
116 /**
117  * Thin wrapper around the read() system call that appends
118  * the data it reads to the DBusString buffer. It appends
119  * up to the given count, and returns the same value
120  * and same errno as read(). The only exception is that
121  * _dbus_read_socket() handles EINTR for you. 
122  * _dbus_read_socket() can return ENOMEM, even though 
123  * regular UNIX read doesn't.
124  *
125  * @param fd the file descriptor to read from
126  * @param buffer the buffer to append data to
127  * @param count the amount of data to read
128  * @returns the number of bytes read or -1
129  */
130
131 int
132 _dbus_read_socket (int               fd,
133                    DBusString       *buffer,
134                    int               count)
135 {
136   int bytes_read;
137   int start;
138   char *data;
139
140   _dbus_assert (count >= 0);
141
142   start = _dbus_string_get_length (buffer);
143
144   if (!_dbus_string_lengthen (buffer, count))
145     {
146       errno = ENOMEM;
147       return -1;
148     }
149
150   data = _dbus_string_get_data_len (buffer, start, count);
151
152  again:
153  
154   _dbus_verbose ("recv: count=%d fd=%d\n", count, fd);
155   bytes_read = recv (fd, data, count, 0);
156   
157   if (bytes_read == SOCKET_ERROR)
158         {
159           DBUS_SOCKET_SET_ERRNO();
160           _dbus_verbose ("recv: failed: %s (%d)\n", _dbus_strerror (errno), errno);
161           bytes_read = -1;
162         }
163         else
164           _dbus_verbose ("recv: = %d\n", bytes_read);
165
166   if (bytes_read < 0)
167     {
168       if (errno == EINTR)
169         goto again;
170       else      
171         {
172           /* put length back (note that this doesn't actually realloc anything) */
173           _dbus_string_set_length (buffer, start);
174           return -1;
175         }
176     }
177   else
178     {
179       /* put length back (doesn't actually realloc) */
180       _dbus_string_set_length (buffer, start + bytes_read);
181
182 #if 0
183       if (bytes_read > 0)
184         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
185 #endif
186
187       return bytes_read;
188     }
189 }
190
191 /**
192  * Thin wrapper around the write() system call that writes a part of a
193  * DBusString and handles EINTR for you.
194  * 
195  * @param fd the file descriptor to write
196  * @param buffer the buffer to write data from
197  * @param start the first byte in the buffer to write
198  * @param len the number of bytes to try to write
199  * @returns the number of bytes written or -1 on error
200  */
201 int
202 _dbus_write_socket (int               fd,
203                     const DBusString *buffer,
204                     int               start,
205                     int               len)
206 {
207   const char *data;
208   int bytes_written;
209
210   data = _dbus_string_get_const_data_len (buffer, start, len);
211
212  again:
213
214   _dbus_verbose ("send: len=%d fd=%d\n", len, fd);
215   bytes_written = send (fd, data, len, 0);
216
217   if (bytes_written == SOCKET_ERROR)
218     {
219       DBUS_SOCKET_SET_ERRNO();
220       _dbus_verbose ("send: failed: %s\n", _dbus_strerror (errno));
221       bytes_written = -1;
222     }
223     else
224       _dbus_verbose ("send: = %d\n", bytes_written);
225
226   if (bytes_written < 0 && errno == EINTR)
227     goto again;
228     
229 #if 0
230   if (bytes_written > 0)
231     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
232 #endif
233
234   return bytes_written;
235 }
236
237
238 /**
239  * Closes a file descriptor.
240  *
241  * @param fd the file descriptor
242  * @param error error object
243  * @returns #FALSE if error set
244  */
245 dbus_bool_t
246 _dbus_close_socket (int        fd,
247                     DBusError *error)
248 {
249   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
250
251  again:
252   if (closesocket (fd) == SOCKET_ERROR)
253     {
254       DBUS_SOCKET_SET_ERRNO ();
255       
256       if (errno == EINTR)
257         goto again;
258         
259       dbus_set_error (error, _dbus_error_from_errno (errno),
260                       "Could not close socket: socket=%d, , %s",
261                       fd, _dbus_strerror (errno));
262       return FALSE;
263     }
264   _dbus_verbose ("_dbus_close_socket: socket=%d, \n", fd);
265
266   return TRUE;
267 }
268
269 /**
270  * Sets the file descriptor to be close
271  * on exec. Should be called for all file
272  * descriptors in D-Bus code.
273  *
274  * @param fd the file descriptor
275  */
276 void
277 _dbus_fd_set_close_on_exec (int handle)
278 {
279   if ( !SetHandleInformation( (HANDLE) handle,
280                         HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE,
281                         0 /*disable both flags*/ ) )
282     {
283       _dbus_win_warn_win_error ("Disabling socket handle inheritance failed:", GetLastError());
284     }
285 }
286
287 /**
288  * Sets a file descriptor to be nonblocking.
289  *
290  * @param fd the file descriptor.
291  * @param error address of error location.
292  * @returns #TRUE on success.
293  */
294 dbus_bool_t
295 _dbus_set_fd_nonblocking (int             handle,
296                           DBusError      *error)
297 {
298   u_long one = 1;
299
300   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
301
302   if (ioctlsocket (handle, FIONBIO, &one) == SOCKET_ERROR)
303     {
304       dbus_set_error (error, _dbus_error_from_errno (WSAGetLastError ()),
305                       "Failed to set socket %d:%d to nonblocking: %s", handle,
306                       _dbus_strerror (WSAGetLastError ()));
307       return FALSE;
308     }
309
310   return TRUE;
311 }
312
313
314 /**
315  * Like _dbus_write() but will use writev() if possible
316  * to write both buffers in sequence. The return value
317  * is the number of bytes written in the first buffer,
318  * plus the number written in the second. If the first
319  * buffer is written successfully and an error occurs
320  * writing the second, the number of bytes in the first
321  * is returned (i.e. the error is ignored), on systems that
322  * don't have writev. Handles EINTR for you.
323  * The second buffer may be #NULL.
324  *
325  * @param fd the file descriptor
326  * @param buffer1 first buffer
327  * @param start1 first byte to write in first buffer
328  * @param len1 number of bytes to write from first buffer
329  * @param buffer2 second buffer, or #NULL
330  * @param start2 first byte to write in second buffer
331  * @param len2 number of bytes to write in second buffer
332  * @returns total bytes written from both buffers, or -1 on error
333  */
334 int
335 _dbus_write_socket_two (int               fd,
336                         const DBusString *buffer1,
337                         int               start1,
338                         int               len1,
339                         const DBusString *buffer2,
340                         int               start2,
341                         int               len2)
342 {
343   WSABUF vectors[2];
344   const char *data1;
345   const char *data2;
346   int rc;
347   DWORD bytes_written;
348
349   _dbus_assert (buffer1 != NULL);
350   _dbus_assert (start1 >= 0);
351   _dbus_assert (start2 >= 0);
352   _dbus_assert (len1 >= 0);
353   _dbus_assert (len2 >= 0);
354
355
356   data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
357
358   if (buffer2 != NULL)
359     data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
360   else
361     {
362       data2 = NULL;
363       start2 = 0;
364       len2 = 0;
365     }
366
367   vectors[0].buf = (char*) data1;
368   vectors[0].len = len1;
369   vectors[1].buf = (char*) data2;
370   vectors[1].len = len2;
371
372  again:
373  
374   _dbus_verbose ("WSASend: len1+2=%d+%d fd=%d\n", len1, len2, fd);
375   rc = WSASend (fd, 
376                 vectors,
377                 data2 ? 2 : 1, 
378                 &bytes_written,
379                 0, 
380                 NULL, 
381                 NULL);
382                 
383   if (rc < 0)
384     {
385       DBUS_SOCKET_SET_ERRNO ();
386       _dbus_verbose ("WSASend: failed: %s\n", _dbus_strerror (errno));
387       bytes_written = -1;
388     }
389   else
390     _dbus_verbose ("WSASend: = %ld\n", bytes_written);
391     
392   if (bytes_written < 0 && errno == EINTR)
393     goto again;
394       
395   return bytes_written;
396 }
397
398 dbus_bool_t
399 _dbus_socket_is_invalid (int fd)
400 {
401     return fd == INVALID_SOCKET ? TRUE : FALSE;
402 }
403
404 #if 0
405
406 /**
407  * Opens the client side of a Windows named pipe. The connection D-BUS
408  * file descriptor index is returned. It is set up as nonblocking.
409  * 
410  * @param path the path to named pipe socket
411  * @param error return location for error code
412  * @returns connection D-BUS file descriptor or -1 on error
413  */
414 int
415 _dbus_connect_named_pipe (const char     *path,
416                           DBusError      *error)
417 {
418   _dbus_assert_not_reached ("not implemented");
419 }
420
421 #endif
422
423
424
425 void
426 _dbus_win_startup_winsock (void)
427 {
428   /* Straight from MSDN, deuglified */
429
430   static dbus_bool_t beenhere = FALSE;
431
432   WORD wVersionRequested;
433   WSADATA wsaData;
434   int err;
435
436   if (beenhere)
437     return;
438
439   wVersionRequested = MAKEWORD (2, 0);
440
441   err = WSAStartup (wVersionRequested, &wsaData);
442   if (err != 0)
443     {
444       _dbus_assert_not_reached ("Could not initialize WinSock");
445       _dbus_abort ();
446     }
447
448   /* Confirm that the WinSock DLL supports 2.0.  Note that if the DLL
449    * supports versions greater than 2.0 in addition to 2.0, it will
450    * still return 2.0 in wVersion since that is the version we
451    * requested.
452    */
453   if (LOBYTE (wsaData.wVersion) != 2 ||
454       HIBYTE (wsaData.wVersion) != 0)
455     {
456       _dbus_assert_not_reached ("No usable WinSock found");
457       _dbus_abort ();
458     }
459
460   beenhere = TRUE;
461 }
462
463
464
465
466
467
468
469
470
471 /************************************************************************
472  
473  UTF / string code
474  
475  ************************************************************************/
476
477 /**
478  * Measure the message length without terminating nul 
479  */
480 int _dbus_printf_string_upper_bound (const char *format,
481                                      va_list args)
482 {
483   /* MSVCRT's vsnprintf semantics are a bit different */
484   char buf[1024];
485   int bufsize;
486   int len;
487
488   bufsize = sizeof (buf);
489   len = _vsnprintf (buf, bufsize - 1, format, args);
490
491   while (len == -1) /* try again */
492     {
493       char *p;
494
495       bufsize *= 2;
496
497       p = malloc (bufsize);
498       len = _vsnprintf (p, bufsize - 1, format, args);
499       free (p);
500     }
501
502   return len;
503 }
504
505
506 /**
507  * Returns the UTF-16 form of a UTF-8 string. The result should be
508  * freed with dbus_free() when no longer needed.
509  *
510  * @param str the UTF-8 string
511  * @param error return location for error code
512  */
513 wchar_t *
514 _dbus_win_utf8_to_utf16 (const char *str,
515                          DBusError  *error)
516 {
517   DBusString s;
518   int n;
519   wchar_t *retval;
520
521   _dbus_string_init_const (&s, str);
522
523   if (!_dbus_string_validate_utf8 (&s, 0, _dbus_string_get_length (&s)))
524     {
525       dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid UTF-8");
526       return NULL;
527     }
528
529   n = MultiByteToWideChar (CP_UTF8, 0, str, -1, NULL, 0);
530
531   if (n == 0)
532     {
533       _dbus_win_set_error_from_win_error (error, GetLastError ());
534       return NULL;
535     }
536
537   retval = dbus_new (wchar_t, n);
538
539   if (!retval)
540     {
541       _DBUS_SET_OOM (error);
542       return NULL;
543     }
544
545   if (MultiByteToWideChar (CP_UTF8, 0, str, -1, retval, n) != n)
546     {
547       dbus_free (retval);
548       dbus_set_error_const (error, DBUS_ERROR_FAILED, "MultiByteToWideChar inconsistency");
549       return NULL;
550     }
551
552   return retval;
553 }
554
555 /**
556  * Returns the UTF-8 form of a UTF-16 string. The result should be
557  * freed with dbus_free() when no longer needed.
558  *
559  * @param str the UTF-16 string
560  * @param error return location for error code
561  */
562 char *
563 _dbus_win_utf16_to_utf8 (const wchar_t *str,
564                          DBusError     *error)
565 {
566   int n;
567   char *retval;
568
569   n = WideCharToMultiByte (CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
570
571   if (n == 0)
572     {
573       _dbus_win_set_error_from_win_error (error, GetLastError ());
574       return NULL;
575     }
576
577   retval = dbus_malloc (n);
578
579   if (!retval)
580     {
581       _DBUS_SET_OOM (error);
582       return NULL;
583     }
584
585   if (WideCharToMultiByte (CP_UTF8, 0, str, -1, retval, n, NULL, NULL) != n)
586     {
587       dbus_free (retval);
588       dbus_set_error_const (error, DBUS_ERROR_FAILED, "WideCharToMultiByte inconsistency");
589       return NULL;
590     }
591
592   return retval;
593 }
594
595
596
597
598
599
600 /************************************************************************
601  
602  
603  ************************************************************************/
604
605 dbus_bool_t
606 _dbus_win_account_to_sid (const wchar_t *waccount,
607                           void           **ppsid,
608                           DBusError       *error)
609 {
610   dbus_bool_t retval = FALSE;
611   DWORD sid_length, wdomain_length;
612   SID_NAME_USE use;
613   wchar_t *wdomain;
614
615   *ppsid = NULL;
616
617   sid_length = 0;
618   wdomain_length = 0;
619   if (!LookupAccountNameW (NULL, waccount, NULL, &sid_length,
620                            NULL, &wdomain_length, &use) &&
621       GetLastError () != ERROR_INSUFFICIENT_BUFFER)
622     {
623       _dbus_win_set_error_from_win_error (error, GetLastError ());
624       return FALSE;
625     }
626
627   *ppsid = dbus_malloc (sid_length);
628   if (!*ppsid)
629     {
630       _DBUS_SET_OOM (error);
631       return FALSE;
632     }
633
634   wdomain = dbus_new (wchar_t, wdomain_length);
635   if (!wdomain)
636     {
637       _DBUS_SET_OOM (error);
638       goto out1;
639     }
640
641   if (!LookupAccountNameW (NULL, waccount, (PSID) *ppsid, &sid_length,
642                            wdomain, &wdomain_length, &use))
643     {
644       _dbus_win_set_error_from_win_error (error, GetLastError ());
645       goto out2;
646     }
647
648   if (!IsValidSid ((PSID) *ppsid))
649     {
650       dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid SID");
651       goto out2;
652     }
653
654   retval = TRUE;
655
656 out2:
657   dbus_free (wdomain);
658 out1:
659   if (!retval)
660     {
661       dbus_free (*ppsid);
662       *ppsid = NULL;
663     }
664
665   return retval;
666 }
667
668 /** @} end of sysdeps-win */
669
670
671 /**
672  * The only reason this is separate from _dbus_getpid() is to allow it
673  * on Windows for logging but not for other purposes.
674  * 
675  * @returns process ID to put in log messages
676  */
677 unsigned long
678 _dbus_pid_for_log (void)
679 {
680   return _dbus_getpid ();
681 }
682
683 /** Gets our SID
684  * @param points to sid buffer, need to be freed with LocalFree()
685  * @returns process sid
686  */
687 static dbus_bool_t
688 _dbus_getsid(char **sid)
689 {
690   HANDLE process_token = INVALID_HANDLE_VALUE;
691   TOKEN_USER *token_user = NULL;
692   DWORD n;
693   PSID psid;
694   int retval = FALSE;
695   
696   if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &process_token)) 
697     {
698       _dbus_win_warn_win_error ("OpenProcessToken failed", GetLastError ());
699       goto failed;
700     }
701   if ((!GetTokenInformation (process_token, TokenUser, NULL, 0, &n)
702             && GetLastError () != ERROR_INSUFFICIENT_BUFFER)
703            || (token_user = alloca (n)) == NULL
704            || !GetTokenInformation (process_token, TokenUser, token_user, n, &n))
705     {
706       _dbus_win_warn_win_error ("GetTokenInformation failed", GetLastError ());
707       goto failed;
708     }
709   psid = token_user->User.Sid;
710   if (!IsValidSid (psid))
711     {
712       _dbus_verbose("%s invalid sid\n",__FUNCTION__);
713       goto failed;
714     }
715   if (!ConvertSidToStringSidA (psid, sid))
716     {
717       _dbus_verbose("%s invalid sid\n",__FUNCTION__);
718       goto failed;
719     }
720 //okay:
721   retval = TRUE;
722
723 failed:
724   if (process_token != INVALID_HANDLE_VALUE)
725     CloseHandle (process_token);
726
727   _dbus_verbose("_dbus_getsid() returns %d\n",retval);
728   return retval;
729 }
730
731 /************************************************************************
732  
733  pipes
734  
735  ************************************************************************/
736
737 /**
738  * Creates a full-duplex pipe (as in socketpair()).
739  * Sets both ends of the pipe nonblocking.
740  *
741  * @todo libdbus only uses this for the debug-pipe server, so in
742  * principle it could be in dbus-sysdeps-util.c, except that
743  * dbus-sysdeps-util.c isn't in libdbus when tests are enabled and the
744  * debug-pipe server is used.
745  * 
746  * @param fd1 return location for one end
747  * @param fd2 return location for the other end
748  * @param blocking #TRUE if pipe should be blocking
749  * @param error error return
750  * @returns #FALSE on failure (if error is set)
751  */
752 dbus_bool_t
753 _dbus_full_duplex_pipe (int        *fd1,
754                         int        *fd2,
755                         dbus_bool_t blocking,
756                         DBusError  *error)
757 {
758   SOCKET temp, socket1 = -1, socket2 = -1;
759   struct sockaddr_in saddr;
760   int len;
761   u_long arg;
762   fd_set read_set, write_set;
763   struct timeval tv;
764
765   _dbus_win_startup_winsock ();
766
767   temp = socket (AF_INET, SOCK_STREAM, 0);
768   if (temp == INVALID_SOCKET)
769     {
770       DBUS_SOCKET_SET_ERRNO ();
771       goto out0;
772     }
773
774   arg = 1;
775   if (ioctlsocket (temp, FIONBIO, &arg) == SOCKET_ERROR)
776     {
777       DBUS_SOCKET_SET_ERRNO ();
778       goto out0;
779     }
780
781   _DBUS_ZERO (saddr);
782   saddr.sin_family = AF_INET;
783   saddr.sin_port = 0;
784   saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
785
786   if (bind (temp, (struct sockaddr *)&saddr, sizeof (saddr)))
787     {
788       DBUS_SOCKET_SET_ERRNO ();
789       goto out0;
790     }
791
792   if (listen (temp, 1) == SOCKET_ERROR)
793     {
794       DBUS_SOCKET_SET_ERRNO ();
795       goto out0;
796     }
797
798   len = sizeof (saddr);
799   if (getsockname (temp, (struct sockaddr *)&saddr, &len))
800     {
801       DBUS_SOCKET_SET_ERRNO ();
802       goto out0;
803     }
804
805   socket1 = socket (AF_INET, SOCK_STREAM, 0);
806   if (socket1 == INVALID_SOCKET)
807     {
808       DBUS_SOCKET_SET_ERRNO ();
809       goto out0;
810     }
811
812   arg = 1;
813   if (ioctlsocket (socket1, FIONBIO, &arg) == SOCKET_ERROR)
814     {
815       DBUS_SOCKET_SET_ERRNO ();
816       goto out1;
817     }
818
819   if (connect (socket1, (struct sockaddr  *)&saddr, len) != SOCKET_ERROR ||
820       WSAGetLastError () != WSAEWOULDBLOCK)
821     {
822       DBUS_SOCKET_SET_ERRNO ();
823       goto out1;
824     }
825
826   FD_ZERO (&read_set);
827   FD_SET (temp, &read_set);
828
829   tv.tv_sec = 0;
830   tv.tv_usec = 0;
831
832   if (select (0, &read_set, NULL, NULL, NULL) == SOCKET_ERROR)
833     {
834       DBUS_SOCKET_SET_ERRNO ();
835       goto out1;
836     }
837
838   _dbus_assert (FD_ISSET (temp, &read_set));
839
840   socket2 = accept (temp, (struct sockaddr *) &saddr, &len);
841   if (socket2 == INVALID_SOCKET)
842     {
843       DBUS_SOCKET_SET_ERRNO ();
844       goto out1;
845     }
846
847   FD_ZERO (&write_set);
848   FD_SET (socket1, &write_set);
849
850   tv.tv_sec = 0;
851   tv.tv_usec = 0;
852
853   if (select (0, NULL, &write_set, NULL, NULL) == SOCKET_ERROR)
854     {
855       DBUS_SOCKET_SET_ERRNO ();
856       goto out2;
857     }
858
859   _dbus_assert (FD_ISSET (socket1, &write_set));
860
861   if (blocking)
862     {
863       arg = 0;
864       if (ioctlsocket (socket1, FIONBIO, &arg) == SOCKET_ERROR)
865         {
866           DBUS_SOCKET_SET_ERRNO ();
867           goto out2;
868         }
869
870       arg = 0;
871       if (ioctlsocket (socket2, FIONBIO, &arg) == SOCKET_ERROR)
872         {
873           DBUS_SOCKET_SET_ERRNO ();
874           goto out2;
875         }
876     }
877   else
878     {
879       arg = 1;
880       if (ioctlsocket (socket2, FIONBIO, &arg) == SOCKET_ERROR)
881         {
882           DBUS_SOCKET_SET_ERRNO ();
883           goto out2;
884         }
885     }
886
887   *fd1 = socket1;
888   *fd2 = socket2;
889
890   _dbus_verbose ("full-duplex pipe %d:%d <-> %d:%d\n",
891                  *fd1, socket1, *fd2, socket2);
892
893   closesocket (temp);
894
895   return TRUE;
896
897 out2:
898   closesocket (socket2);
899 out1:
900   closesocket (socket1);
901 out0:
902   closesocket (temp);
903
904   dbus_set_error (error, _dbus_error_from_errno (errno),
905                   "Could not setup socket pair: %s",
906                   _dbus_strerror (errno));
907
908   return FALSE;
909 }
910
911 /**
912  * Wrapper for poll().
913  *
914  * @param fds the file descriptors to poll
915  * @param n_fds number of descriptors in the array
916  * @param timeout_milliseconds timeout or -1 for infinite
917  * @returns numbers of fds with revents, or <0 on error
918  */
919 int
920 _dbus_poll (DBusPollFD *fds,
921             int         n_fds,
922             int         timeout_milliseconds)
923 {
924 #define USE_CHRIS_IMPL 0
925
926 #if USE_CHRIS_IMPL
927
928 #define DBUS_POLL_CHAR_BUFFER_SIZE 2000
929   char msg[DBUS_POLL_CHAR_BUFFER_SIZE];
930   char *msgp;
931
932   int ret = 0;
933   int i;
934   struct timeval tv;
935   int ready;
936
937 #define DBUS_STACK_WSAEVENTS 256
938   WSAEVENT eventsOnStack[DBUS_STACK_WSAEVENTS];
939   WSAEVENT *pEvents = NULL;
940   if (n_fds > DBUS_STACK_WSAEVENTS)
941     pEvents = calloc(sizeof(WSAEVENT), n_fds);
942   else
943     pEvents = eventsOnStack;
944
945
946 #ifdef DBUS_ENABLE_VERBOSE_MODE
947   msgp = msg;
948   msgp += sprintf (msgp, "WSAEventSelect: to=%d\n\t", timeout_milliseconds);
949   for (i = 0; i < n_fds; i++)
950     {
951       static dbus_bool_t warned = FALSE;
952       DBusPollFD *fdp = &fds[i];
953
954
955       if (fdp->events & _DBUS_POLLIN)
956         msgp += sprintf (msgp, "R:%d ", fdp->fd);
957
958       if (fdp->events & _DBUS_POLLOUT)
959         msgp += sprintf (msgp, "W:%d ", fdp->fd);
960
961       msgp += sprintf (msgp, "E:%d\n\t", fdp->fd);
962
963       // FIXME: more robust code for long  msg
964       //        create on heap when msg[] becomes too small
965       if (msgp >= msg + DBUS_POLL_CHAR_BUFFER_SIZE)
966         {
967           _dbus_assert_not_reached ("buffer overflow in _dbus_poll");
968         }
969     }
970
971   msgp += sprintf (msgp, "\n");
972   _dbus_verbose ("%s",msg);
973 #endif
974   for (i = 0; i < n_fds; i++)
975     {
976       DBusPollFD *fdp = &fds[i];
977       WSAEVENT ev;
978       long lNetworkEvents = FD_OOB;
979
980       ev = WSACreateEvent();
981
982       if (fdp->events & _DBUS_POLLIN)
983         lNetworkEvents |= FD_READ | FD_ACCEPT | FD_CLOSE;
984
985       if (fdp->events & _DBUS_POLLOUT)
986         lNetworkEvents |= FD_WRITE | FD_CONNECT;
987
988       WSAEventSelect(fdp->fd, ev, lNetworkEvents);
989
990       pEvents[i] = ev;
991     }
992
993
994   ready = WSAWaitForMultipleEvents (n_fds, pEvents, FALSE, timeout_milliseconds, FALSE);
995
996   if (DBUS_SOCKET_API_RETURNS_ERROR (ready))
997     {
998       DBUS_SOCKET_SET_ERRNO ();
999       if (errno != WSAEWOULDBLOCK)
1000         _dbus_verbose ("WSAWaitForMultipleEvents: failed: %s\n", strerror (errno));
1001       ret = -1;
1002     }
1003   else if (ready == WSA_WAIT_TIMEOUT)
1004     {
1005       _dbus_verbose ("WSAWaitForMultipleEvents: WSA_WAIT_TIMEOUT\n");
1006       ret = 0;
1007     }
1008   else if (ready >= WSA_WAIT_EVENT_0 && ready < (int)(WSA_WAIT_EVENT_0 + n_fds))
1009     {
1010       msgp = msg;
1011       msgp += sprintf (msgp, "WSAWaitForMultipleEvents: =%d\n\t", ready);
1012
1013       for (i = 0; i < n_fds; i++)
1014         {
1015           DBusPollFD *fdp = &fds[i];
1016           WSANETWORKEVENTS ne;
1017
1018           fdp->revents = 0;
1019
1020           WSAEnumNetworkEvents(fdp->fd, pEvents[i], &ne);
1021
1022           if (ne.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
1023             fdp->revents |= _DBUS_POLLIN;
1024
1025           if (ne.lNetworkEvents & (FD_WRITE | FD_CONNECT))
1026             fdp->revents |= _DBUS_POLLOUT;
1027
1028           if (ne.lNetworkEvents & (FD_OOB))
1029             fdp->revents |= _DBUS_POLLERR;
1030
1031           if (ne.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
1032               msgp += sprintf (msgp, "R:%d ", fdp->fd);
1033
1034           if (ne.lNetworkEvents & (FD_WRITE | FD_CONNECT))
1035               msgp += sprintf (msgp, "W:%d ", fdp->fd);
1036
1037           if (ne.lNetworkEvents & (FD_OOB))
1038               msgp += sprintf (msgp, "E:%d ", fdp->fd);
1039
1040           msgp += sprintf (msgp, "lNetworkEvents:%d ", ne.lNetworkEvents);
1041
1042           if(ne.lNetworkEvents)
1043             ret++;
1044
1045           WSAEventSelect(fdp->fd, pEvents[i], 0);
1046         }
1047
1048       msgp += sprintf (msgp, "\n");
1049       _dbus_verbose ("%s",msg);
1050     }
1051   else
1052     {
1053       _dbus_verbose ("WSAWaitForMultipleEvents: failed for unknown reason!");
1054       ret = -1;
1055     }
1056
1057   for(i = 0; i < n_fds; i++)
1058     {
1059       WSACloseEvent(pEvents[i]);
1060     }
1061
1062   if (n_fds > DBUS_STACK_WSAEVENTS)
1063     free(pEvents);
1064
1065   return ret;
1066
1067 #else   /* USE_CHRIS_IMPL */
1068
1069 #define DBUS_POLL_CHAR_BUFFER_SIZE 2000
1070   char msg[DBUS_POLL_CHAR_BUFFER_SIZE];
1071   char *msgp;
1072
1073   fd_set read_set, write_set, err_set;
1074   int max_fd = 0;
1075   int i;
1076   struct timeval tv;
1077   int ready;
1078
1079   FD_ZERO (&read_set);
1080   FD_ZERO (&write_set);
1081   FD_ZERO (&err_set);
1082
1083
1084 #ifdef DBUS_ENABLE_VERBOSE_MODE
1085   msgp = msg;
1086   msgp += sprintf (msgp, "select: to=%d\n\t", timeout_milliseconds);
1087   for (i = 0; i < n_fds; i++)
1088     {
1089       static dbus_bool_t warned = FALSE;
1090       DBusPollFD *fdp = &fds[i];
1091
1092
1093       if (fdp->events & _DBUS_POLLIN)
1094         msgp += sprintf (msgp, "R:%d ", fdp->fd);
1095
1096       if (fdp->events & _DBUS_POLLOUT)
1097         msgp += sprintf (msgp, "W:%d ", fdp->fd);
1098
1099       msgp += sprintf (msgp, "E:%d\n\t", fdp->fd);
1100
1101       // FIXME: more robust code for long  msg
1102       //        create on heap when msg[] becomes too small
1103       if (msgp >= msg + DBUS_POLL_CHAR_BUFFER_SIZE)
1104         {
1105           _dbus_assert_not_reached ("buffer overflow in _dbus_poll");
1106         }
1107     }
1108
1109   msgp += sprintf (msgp, "\n");
1110   _dbus_verbose ("%s",msg);
1111 #endif
1112   for (i = 0; i < n_fds; i++)
1113     {
1114       DBusPollFD *fdp = &fds[i]; 
1115
1116       if (fdp->events & _DBUS_POLLIN)
1117         FD_SET (fdp->fd, &read_set);
1118
1119       if (fdp->events & _DBUS_POLLOUT)
1120         FD_SET (fdp->fd, &write_set);
1121
1122       FD_SET (fdp->fd, &err_set);
1123
1124       max_fd = MAX (max_fd, fdp->fd);
1125     }
1126
1127
1128   tv.tv_sec = timeout_milliseconds / 1000;
1129   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
1130
1131   ready = select (max_fd + 1, &read_set, &write_set, &err_set,
1132                   timeout_milliseconds < 0 ? NULL : &tv);
1133
1134   if (DBUS_SOCKET_API_RETURNS_ERROR (ready))
1135     {
1136       DBUS_SOCKET_SET_ERRNO ();
1137       if (errno != WSAEWOULDBLOCK)
1138         _dbus_verbose ("select: failed: %s\n", _dbus_strerror (errno));
1139     }
1140   else if (ready == 0)
1141     _dbus_verbose ("select: = 0\n");
1142   else
1143     if (ready > 0)
1144       {
1145 #ifdef DBUS_ENABLE_VERBOSE_MODE
1146         msgp = msg;
1147         msgp += sprintf (msgp, "select: = %d:\n\t", ready);
1148
1149         for (i = 0; i < n_fds; i++)
1150           {
1151             DBusPollFD *fdp = &fds[i];
1152
1153             if (FD_ISSET (fdp->fd, &read_set))
1154               msgp += sprintf (msgp, "R:%d ", fdp->fd);
1155
1156             if (FD_ISSET (fdp->fd, &write_set))
1157               msgp += sprintf (msgp, "W:%d ", fdp->fd);
1158
1159             if (FD_ISSET (fdp->fd, &err_set))
1160               msgp += sprintf (msgp, "E:%d\n\t", fdp->fd);
1161           }
1162         msgp += sprintf (msgp, "\n");
1163         _dbus_verbose ("%s",msg);
1164 #endif
1165
1166         for (i = 0; i < n_fds; i++)
1167           {
1168             DBusPollFD *fdp = &fds[i];
1169
1170             fdp->revents = 0;
1171
1172             if (FD_ISSET (fdp->fd, &read_set))
1173               fdp->revents |= _DBUS_POLLIN;
1174
1175             if (FD_ISSET (fdp->fd, &write_set))
1176               fdp->revents |= _DBUS_POLLOUT;
1177
1178             if (FD_ISSET (fdp->fd, &err_set))
1179               fdp->revents |= _DBUS_POLLERR;
1180           }
1181       }
1182   return ready;
1183 #endif  /* USE_CHRIS_IMPL */
1184 }
1185
1186
1187
1188
1189 /******************************************************************************
1190  
1191 Original CVS version of dbus-sysdeps.c
1192  
1193 ******************************************************************************/
1194 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
1195 /* dbus-sysdeps.c Wrappers around system/libc features (internal to D-Bus implementation)
1196  * 
1197  * Copyright (C) 2002, 2003  Red Hat, Inc.
1198  * Copyright (C) 2003 CodeFactory AB
1199  * Copyright (C) 2005 Novell, Inc.
1200  *
1201  * Licensed under the Academic Free License version 2.1
1202  * 
1203  * This program is free software; you can redistribute it and/or modify
1204  * it under the terms of the GNU General Public License as published by
1205  * the Free Software Foundation; either version 2 of the License, or
1206  * (at your option) any later version.
1207  *
1208  * This program is distributed in the hope that it will be useful,
1209  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1210  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1211  * GNU General Public License for more details.
1212  * 
1213  * You should have received a copy of the GNU General Public License
1214  * along with this program; if not, write to the Free Software
1215  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
1216  *
1217  */
1218
1219
1220 /**
1221  * Exit the process, returning the given value.
1222  *
1223  * @param code the exit code
1224  */
1225 void
1226 _dbus_exit (int code)
1227 {
1228   _exit (code);
1229 }
1230
1231 /**
1232  * Creates a socket and connects to a socket at the given host 
1233  * and port. The connection fd is returned, and is set up as
1234  * nonblocking.
1235  *
1236  * @param host the host name to connect to
1237  * @param port the port to connect to
1238  * @param family the address family to listen on, NULL for all
1239  * @param error return location for error code
1240  * @returns connection file descriptor or -1 on error
1241  */
1242 int
1243 _dbus_connect_tcp_socket (const char     *host,
1244                           const char     *port,
1245                           const char     *family,
1246                           DBusError      *error)
1247 {
1248   return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
1249 }
1250
1251 int
1252 _dbus_connect_tcp_socket_with_nonce (const char     *host,
1253                                      const char     *port,
1254                                      const char     *family,
1255                                      const char     *noncefile,
1256                                      DBusError      *error)
1257 {
1258   int fd = -1, res;
1259   struct addrinfo hints;
1260   struct addrinfo *ai, *tmp;
1261
1262   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1263
1264   _dbus_win_startup_winsock ();
1265
1266   fd = socket (AF_INET, SOCK_STREAM, 0);
1267
1268   if (DBUS_SOCKET_IS_INVALID (fd))
1269     {
1270       DBUS_SOCKET_SET_ERRNO ();
1271       dbus_set_error (error,
1272                       _dbus_error_from_errno (errno),
1273                       "Failed to create socket: %s",
1274                       _dbus_strerror (errno));
1275
1276       return -1;
1277     }
1278
1279   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1280
1281   _DBUS_ZERO (hints);
1282
1283   if (!family)
1284     hints.ai_family = AF_UNSPEC;
1285   else if (!strcmp(family, "ipv4"))
1286     hints.ai_family = AF_INET;
1287   else if (!strcmp(family, "ipv6"))
1288     hints.ai_family = AF_INET6;
1289   else
1290     {
1291       dbus_set_error (error,
1292                       _dbus_error_from_errno (errno),
1293                       "Unknown address family %s", family);
1294       return -1;
1295     }
1296   hints.ai_protocol = IPPROTO_TCP;
1297   hints.ai_socktype = SOCK_STREAM;
1298 #ifdef AI_ADDRCONFIG
1299   hints.ai_flags = AI_ADDRCONFIG;
1300 #else
1301   hints.ai_flags = 0;
1302 #endif
1303
1304   if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
1305     {
1306       dbus_set_error (error,
1307                       _dbus_error_from_errno (errno),
1308                       "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1309                       host, port, gai_strerror(res), res);
1310       closesocket (fd);
1311       return -1;
1312     }
1313
1314   tmp = ai;
1315   while (tmp)
1316     {
1317       if ((fd = socket (tmp->ai_family, SOCK_STREAM, 0)) < 0)
1318         {
1319           freeaddrinfo(ai);
1320       dbus_set_error (error,
1321                       _dbus_error_from_errno (errno),
1322                          "Failed to open socket: %s",
1323                          _dbus_strerror (errno));
1324           return -1;
1325         }
1326       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1327
1328       if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) != 0)
1329         {
1330           closesocket(fd);
1331       fd = -1;
1332           tmp = tmp->ai_next;
1333           continue;
1334         }
1335
1336       break;
1337     }
1338   freeaddrinfo(ai);
1339
1340   if (fd == -1)
1341     {
1342       dbus_set_error (error,
1343                       _dbus_error_from_errno (errno),
1344                       "Failed to connect to socket \"%s:%s\" %s",
1345                       host, port, _dbus_strerror(errno));
1346       return -1;
1347     }
1348
1349   if ( noncefile != NULL )
1350     {
1351       DBusString noncefileStr;
1352       dbus_bool_t ret;
1353       if (!_dbus_string_init (&noncefileStr) ||
1354           !_dbus_string_append(&noncefileStr, noncefile))
1355         {
1356           closesocket (fd);
1357           dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1358           return -1;
1359        }
1360
1361       ret = _dbus_send_nonce (fd, &noncefileStr, error);
1362
1363       _dbus_string_free (&noncefileStr);
1364
1365       if (!ret)
1366     {
1367       closesocket (fd);
1368           return -1;
1369         }
1370     }
1371
1372   if (!_dbus_set_fd_nonblocking (fd, error) )
1373     {
1374       closesocket (fd);
1375       return -1;
1376     }
1377
1378   return fd;
1379 }
1380
1381 /**
1382  * Creates a socket and binds it to the given path, then listens on
1383  * the socket. The socket is set to be nonblocking.  In case of port=0
1384  * a random free port is used and returned in the port parameter.
1385  * If inaddr_any is specified, the hostname is ignored.
1386  *
1387  * @param host the host name to listen on
1388  * @param port the port to listen on, if zero a free port will be used 
1389  * @param family the address family to listen on, NULL for all
1390  * @param retport string to return the actual port listened on
1391  * @param fds_p location to store returned file descriptors
1392  * @param error return location for errors
1393  * @returns the number of listening file descriptors or -1 on error
1394  */
1395
1396 int
1397 _dbus_listen_tcp_socket (const char     *host,
1398                          const char     *port,
1399                          const char     *family,
1400                          DBusString     *retport,
1401                          int           **fds_p,
1402                          DBusError      *error)
1403 {
1404   int nlisten_fd = 0, *listen_fd = NULL, res, i, port_num = -1;
1405   struct addrinfo hints;
1406   struct addrinfo *ai, *tmp;
1407
1408   // On Vista, sockaddr_gen must be a sockaddr_in6, and not a sockaddr_in6_old
1409   //That's required for family == IPv6(which is the default on Vista if family is not given)
1410   //So we use our own union instead of sockaddr_gen:
1411
1412   typedef union {
1413         struct sockaddr Address;
1414         struct sockaddr_in AddressIn;
1415         struct sockaddr_in6 AddressIn6;
1416   } mysockaddr_gen;
1417
1418   *fds_p = NULL;
1419   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1420
1421   _dbus_win_startup_winsock ();
1422
1423   _DBUS_ZERO (hints);
1424
1425   if (!family)
1426     hints.ai_family = AF_UNSPEC;
1427   else if (!strcmp(family, "ipv4"))
1428     hints.ai_family = AF_INET;
1429   else if (!strcmp(family, "ipv6"))
1430     hints.ai_family = AF_INET6;
1431   else
1432     {
1433       dbus_set_error (error,
1434                       _dbus_error_from_errno (errno),
1435                       "Unknown address family %s", family);
1436       return -1;
1437     }
1438
1439   hints.ai_protocol = IPPROTO_TCP;
1440   hints.ai_socktype = SOCK_STREAM;
1441 #ifdef AI_ADDRCONFIG
1442   hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
1443 #else
1444   hints.ai_flags = AI_PASSIVE;
1445 #endif
1446
1447  redo_lookup_with_port:
1448   if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
1449     {
1450       dbus_set_error (error,
1451                       _dbus_error_from_errno (errno),
1452                       "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1453                       host ? host : "*", port, gai_strerror(res), res);
1454       return -1;
1455     }
1456
1457   tmp = ai;
1458   while (tmp)
1459     {
1460       int fd = -1, *newlisten_fd;
1461       if ((fd = socket (tmp->ai_family, SOCK_STREAM, 0)) < 0)
1462         {
1463           dbus_set_error (error,
1464                           _dbus_error_from_errno (errno),
1465                          "Failed to open socket: %s",
1466                          _dbus_strerror (errno));
1467           goto failed;
1468         }
1469       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1470
1471       if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) == SOCKET_ERROR)
1472         {
1473           closesocket (fd);
1474           dbus_set_error (error, _dbus_error_from_errno (errno),
1475                           "Failed to bind socket \"%s:%s\": %s",
1476                           host ? host : "*", port, _dbus_strerror (errno));
1477           goto failed;
1478     }
1479
1480       if (listen (fd, 30 /* backlog */) == SOCKET_ERROR)
1481         {
1482           closesocket (fd);
1483           dbus_set_error (error, _dbus_error_from_errno (errno),
1484                           "Failed to listen on socket \"%s:%s\": %s",
1485                           host ? host : "*", port, _dbus_strerror (errno));
1486           goto failed;
1487         }
1488
1489       newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1));
1490       if (!newlisten_fd)
1491     {
1492           closesocket (fd);
1493       dbus_set_error (error, _dbus_error_from_errno (errno),
1494                           "Failed to allocate file handle array: %s",
1495                           _dbus_strerror (errno));
1496           goto failed;
1497     }
1498       listen_fd = newlisten_fd;
1499       listen_fd[nlisten_fd] = fd;
1500       nlisten_fd++;
1501
1502       if (!_dbus_string_get_length(retport))
1503         {
1504           /* If the user didn't specify a port, or used 0, then
1505              the kernel chooses a port. After the first address
1506              is bound to, we need to force all remaining addresses
1507              to use the same port */
1508           if (!port || !strcmp(port, "0"))
1509             {
1510               mysockaddr_gen addr;
1511               socklen_t addrlen = sizeof(addr);
1512               char portbuf[10];
1513
1514               if ((res = getsockname(fd, &addr.Address, &addrlen)) != 0)
1515     {
1516       dbus_set_error (error, _dbus_error_from_errno (errno),
1517                                   "Failed to resolve port \"%s:%s\": %s (%d)",
1518                                   host ? host : "*", port, gai_strerror(res), res);
1519                   goto failed;
1520                 }
1521               snprintf( portbuf, sizeof( portbuf ) - 1, "%d", addr.AddressIn.sin_port );
1522               if (!_dbus_string_append(retport, portbuf))
1523                 {
1524                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1525                   goto failed;
1526     }
1527
1528               /* Release current address list & redo lookup */
1529               port = _dbus_string_get_const_data(retport);
1530               freeaddrinfo(ai);
1531               goto redo_lookup_with_port;
1532             }
1533           else
1534             {
1535               if (!_dbus_string_append(retport, port))
1536                 {
1537                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1538                     goto failed;
1539                 }
1540             }
1541         }
1542   
1543       tmp = tmp->ai_next;
1544     }
1545   freeaddrinfo(ai);
1546   ai = NULL;
1547
1548   if (!nlisten_fd)
1549     {
1550       errno = WSAEADDRINUSE;
1551       dbus_set_error (error, _dbus_error_from_errno (errno),
1552                       "Failed to bind socket \"%s:%s\": %s",
1553                       host ? host : "*", port, _dbus_strerror (errno));
1554       return -1;
1555     }
1556
1557   sscanf(_dbus_string_get_const_data(retport), "%d", &port_num);
1558
1559   for (i = 0 ; i < nlisten_fd ; i++)
1560     {
1561       if (!_dbus_set_fd_nonblocking (listen_fd[i], error))
1562         {
1563           goto failed;
1564         }
1565     }
1566
1567   *fds_p = listen_fd;
1568
1569   return nlisten_fd;
1570
1571  failed:
1572   if (ai)
1573     freeaddrinfo(ai);
1574   for (i = 0 ; i < nlisten_fd ; i++)
1575     closesocket (listen_fd[i]);
1576   dbus_free(listen_fd);
1577   return -1;
1578 }
1579
1580
1581 /**
1582  * Accepts a connection on a listening socket.
1583  * Handles EINTR for you.
1584  *
1585  * @param listen_fd the listen file descriptor
1586  * @returns the connection fd of the client, or -1 on error
1587  */
1588 int
1589 _dbus_accept  (int listen_fd)
1590 {
1591   int client_fd;
1592
1593  retry:
1594   client_fd = accept (listen_fd, NULL, NULL);
1595
1596   if (DBUS_SOCKET_IS_INVALID (client_fd))
1597     {
1598       DBUS_SOCKET_SET_ERRNO ();
1599       if (errno == EINTR)
1600         goto retry;
1601     }
1602
1603   _dbus_verbose ("client fd %d accepted\n", client_fd);
1604   
1605   return client_fd;
1606 }
1607
1608
1609
1610
1611 dbus_bool_t
1612 _dbus_send_credentials_socket (int            handle,
1613                         DBusError      *error)
1614 {
1615 /* FIXME: for the session bus credentials shouldn't matter (?), but
1616  * for the system bus they are presumably essential. A rough outline
1617  * of a way to implement the credential transfer would be this:
1618  *
1619  * client waits to *read* a byte.
1620  *
1621  * server creates a named pipe with a random name, sends a byte
1622  * contining its length, and its name.
1623  *
1624  * client reads the name, connects to it (using Win32 API).
1625  *
1626  * server waits for connection to the named pipe, then calls
1627  * ImpersonateNamedPipeClient(), notes its now-current credentials,
1628  * calls RevertToSelf(), closes its handles to the named pipe, and
1629  * is done. (Maybe there is some other way to get the SID of a named
1630  * pipe client without having to use impersonation?)
1631  *
1632  * client closes its handles and is done.
1633  * 
1634  * Ralf: Why not sending credentials over the given this connection ?
1635  * Using named pipes makes it impossible to be connected from a unix client.  
1636  *
1637  */
1638   int bytes_written;
1639   DBusString buf; 
1640
1641   _dbus_string_init_const_len (&buf, "\0", 1);
1642 again:
1643   bytes_written = _dbus_write_socket (handle, &buf, 0, 1 );
1644
1645   if (bytes_written < 0 && errno == EINTR)
1646     goto again;
1647
1648   if (bytes_written < 0)
1649     {
1650       dbus_set_error (error, _dbus_error_from_errno (errno),
1651                       "Failed to write credentials byte: %s",
1652                      _dbus_strerror (errno));
1653       return FALSE;
1654     }
1655   else if (bytes_written == 0)
1656     {
1657       dbus_set_error (error, DBUS_ERROR_IO_ERROR,
1658                       "wrote zero bytes writing credentials byte");
1659       return FALSE;
1660     }
1661   else
1662     {
1663       _dbus_assert (bytes_written == 1);
1664       _dbus_verbose ("wrote 1 zero byte, credential sending isn't implemented yet\n");
1665       return TRUE;
1666     }
1667   return TRUE;
1668 }
1669
1670 /**
1671  * Reads a single byte which must be nul (an error occurs otherwise),
1672  * and reads unix credentials if available. Fills in pid/uid/gid with
1673  * -1 if no credentials are available. Return value indicates whether
1674  * a byte was read, not whether we got valid credentials. On some
1675  * systems, such as Linux, reading/writing the byte isn't actually
1676  * required, but we do it anyway just to avoid multiple codepaths.
1677  * 
1678  * Fails if no byte is available, so you must select() first.
1679  *
1680  * The point of the byte is that on some systems we have to
1681  * use sendmsg()/recvmsg() to transmit credentials.
1682  *
1683  * @param client_fd the client file descriptor
1684  * @param credentials struct to fill with credentials of client
1685  * @param error location to store error code
1686  * @returns #TRUE on success
1687  */
1688 dbus_bool_t
1689 _dbus_read_credentials_socket  (int              handle,
1690                                 DBusCredentials *credentials,
1691                                 DBusError       *error)
1692 {
1693   int bytes_read = 0;
1694   DBusString buf;
1695   
1696   // could fail due too OOM
1697   if (_dbus_string_init(&buf))
1698     {
1699       bytes_read = _dbus_read_socket(handle, &buf, 1 );
1700
1701       if (bytes_read > 0) 
1702         _dbus_verbose("got one zero byte from server");
1703
1704       _dbus_string_free(&buf);
1705     }
1706
1707   _dbus_credentials_add_from_current_process (credentials);
1708   _dbus_verbose("FIXME: get faked credentials from current process");
1709
1710   return TRUE;
1711 }
1712
1713 /**
1714 * Checks to make sure the given directory is 
1715 * private to the user 
1716 *
1717 * @param dir the name of the directory
1718 * @param error error return
1719 * @returns #FALSE on failure
1720 **/
1721 dbus_bool_t
1722 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
1723 {
1724   const char *directory;
1725   struct stat sb;
1726
1727   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1728
1729   return TRUE;
1730 }
1731
1732
1733 /**
1734  * Appends the given filename to the given directory.
1735  *
1736  * @todo it might be cute to collapse multiple '/' such as "foo//"
1737  * concat "//bar"
1738  *
1739  * @param dir the directory name
1740  * @param next_component the filename
1741  * @returns #TRUE on success
1742  */
1743 dbus_bool_t
1744 _dbus_concat_dir_and_file (DBusString       *dir,
1745                            const DBusString *next_component)
1746 {
1747   dbus_bool_t dir_ends_in_slash;
1748   dbus_bool_t file_starts_with_slash;
1749
1750   if (_dbus_string_get_length (dir) == 0 ||
1751       _dbus_string_get_length (next_component) == 0)
1752     return TRUE;
1753
1754   dir_ends_in_slash =
1755     ('/' == _dbus_string_get_byte (dir, _dbus_string_get_length (dir) - 1) ||
1756      '\\' == _dbus_string_get_byte (dir, _dbus_string_get_length (dir) - 1));
1757
1758   file_starts_with_slash =
1759     ('/' == _dbus_string_get_byte (next_component, 0) ||
1760      '\\' == _dbus_string_get_byte (next_component, 0));
1761
1762   if (dir_ends_in_slash && file_starts_with_slash)
1763     {
1764       _dbus_string_shorten (dir, 1);
1765     }
1766   else if (!(dir_ends_in_slash || file_starts_with_slash))
1767     {
1768       if (!_dbus_string_append_byte (dir, '\\'))
1769         return FALSE;
1770     }
1771
1772   return _dbus_string_copy (next_component, 0, dir,
1773                             _dbus_string_get_length (dir));
1774 }
1775
1776 /*---------------- DBusCredentials ----------------------------------*/
1777
1778 /**
1779  * Adds the credentials corresponding to the given username.
1780  *
1781  * @param credentials credentials to fill in 
1782  * @param username the username
1783  * @returns #TRUE if the username existed and we got some credentials
1784  */
1785 dbus_bool_t
1786 _dbus_credentials_add_from_user (DBusCredentials  *credentials,
1787                                      const DBusString *username)
1788 {
1789   return _dbus_credentials_add_windows_sid (credentials,
1790                     _dbus_string_get_const_data(username));
1791 }
1792
1793 /**
1794  * Adds the credentials of the current process to the
1795  * passed-in credentials object.
1796  *
1797  * @param credentials credentials to add to
1798  * @returns #FALSE if no memory; does not properly roll back on failure, so only some credentials may have been added
1799  */
1800
1801 dbus_bool_t
1802 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
1803 {
1804   dbus_bool_t retval = FALSE;
1805   char *sid = NULL;
1806
1807   if (!_dbus_getsid(&sid))
1808     goto failed;
1809
1810   if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid()))
1811     goto failed;
1812
1813   if (!_dbus_credentials_add_windows_sid (credentials,sid))
1814     goto failed;
1815
1816   retval = TRUE;
1817   goto end;
1818 failed:
1819   retval = FALSE;
1820 end:
1821   if (sid)
1822     LocalFree(sid);
1823
1824   return retval;
1825 }
1826
1827 /**
1828  * Append to the string the identity we would like to have when we
1829  * authenticate, on UNIX this is the current process UID and on
1830  * Windows something else, probably a Windows SID string.  No escaping
1831  * is required, that is done in dbus-auth.c. The username here
1832  * need not be anything human-readable, it can be the machine-readable
1833  * form i.e. a user id.
1834  * 
1835  * @param str the string to append to
1836  * @returns #FALSE on no memory
1837  * @todo to which class belongs this 
1838  */
1839 dbus_bool_t
1840 _dbus_append_user_from_current_process (DBusString *str)
1841 {
1842   dbus_bool_t retval = FALSE;
1843   char *sid = NULL;
1844
1845   if (!_dbus_getsid(&sid))
1846     return FALSE;
1847
1848   retval = _dbus_string_append (str,sid);
1849
1850   LocalFree(sid);
1851   return retval;
1852 }
1853
1854 /**
1855  * Gets our process ID
1856  * @returns process ID
1857  */
1858 dbus_pid_t
1859 _dbus_getpid (void)
1860 {
1861   return GetCurrentProcessId ();
1862 }
1863
1864 /** nanoseconds in a second */
1865 #define NANOSECONDS_PER_SECOND       1000000000
1866 /** microseconds in a second */
1867 #define MICROSECONDS_PER_SECOND      1000000
1868 /** milliseconds in a second */
1869 #define MILLISECONDS_PER_SECOND      1000
1870 /** nanoseconds in a millisecond */
1871 #define NANOSECONDS_PER_MILLISECOND  1000000
1872 /** microseconds in a millisecond */
1873 #define MICROSECONDS_PER_MILLISECOND 1000
1874
1875 /**
1876  * Sleeps the given number of milliseconds.
1877  * @param milliseconds number of milliseconds
1878  */
1879 void
1880 _dbus_sleep_milliseconds (int milliseconds)
1881 {
1882   Sleep (milliseconds);
1883 }
1884
1885
1886 /**
1887  * Get current time, as in gettimeofday().
1888  *
1889  * @param tv_sec return location for number of seconds
1890  * @param tv_usec return location for number of microseconds
1891  */
1892 void
1893 _dbus_get_current_time (long *tv_sec,
1894                         long *tv_usec)
1895 {
1896   FILETIME ft;
1897   dbus_uint64_t time64;
1898
1899   GetSystemTimeAsFileTime (&ft);
1900
1901   memcpy (&time64, &ft, sizeof (time64));
1902
1903   /* Convert from 100s of nanoseconds since 1601-01-01
1904   * to Unix epoch. Yes, this is Y2038 unsafe.
1905   */
1906   time64 -= DBUS_INT64_CONSTANT (116444736000000000);
1907   time64 /= 10;
1908
1909   if (tv_sec)
1910     *tv_sec = time64 / 1000000;
1911
1912   if (tv_usec)
1913     *tv_usec = time64 % 1000000;
1914 }
1915
1916
1917 /**
1918  * signal (SIGPIPE, SIG_IGN);
1919  */
1920 void
1921 _dbus_disable_sigpipe (void)
1922 {
1923 }
1924
1925 /**
1926  * Creates a directory; succeeds if the directory
1927  * is created or already existed.
1928  *
1929  * @param filename directory filename
1930  * @param error initialized error object
1931  * @returns #TRUE on success
1932  */
1933 dbus_bool_t
1934 _dbus_create_directory (const DBusString *filename,
1935                         DBusError        *error)
1936 {
1937   const char *filename_c;
1938
1939   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1940
1941   filename_c = _dbus_string_get_const_data (filename);
1942
1943   if (!CreateDirectory (filename_c, NULL))
1944     {
1945       if (GetLastError () == ERROR_ALREADY_EXISTS)
1946         return TRUE;
1947
1948       dbus_set_error (error, DBUS_ERROR_FAILED,
1949                       "Failed to create directory %s: %s\n",
1950                       filename_c, strerror (errno));
1951       return FALSE;
1952     }
1953   else
1954     return TRUE;
1955 }
1956
1957
1958 /**
1959  * Generates the given number of random bytes,
1960  * using the best mechanism we can come up with.
1961  *
1962  * @param str the string
1963  * @param n_bytes the number of random bytes to append to string
1964  * @returns #TRUE on success, #FALSE if no memory
1965  */
1966 dbus_bool_t
1967 _dbus_generate_random_bytes (DBusString *str,
1968                              int         n_bytes)
1969 {
1970   int old_len;
1971   char *p;
1972   HCRYPTPROV hprov;
1973
1974   old_len = _dbus_string_get_length (str);
1975
1976   if (!_dbus_string_lengthen (str, n_bytes))
1977     return FALSE;
1978
1979   p = _dbus_string_get_data_len (str, old_len, n_bytes);
1980
1981   if (!CryptAcquireContext (&hprov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
1982     return FALSE;
1983
1984   if (!CryptGenRandom (hprov, n_bytes, p))
1985     {
1986       CryptReleaseContext (hprov, 0);
1987       return FALSE;
1988     }
1989
1990   CryptReleaseContext (hprov, 0);
1991
1992   return TRUE;
1993 }
1994
1995 /**
1996  * Gets the temporary files directory by inspecting the environment variables 
1997  * TMPDIR, TMP, and TEMP in that order. If none of those are set "/tmp" is returned
1998  *
1999  * @returns location of temp directory
2000  */
2001 const char*
2002 _dbus_get_tmpdir(void)
2003 {
2004   static const char* tmpdir = NULL;
2005   static char buf[1000];
2006
2007   if (tmpdir == NULL)
2008     {
2009       char *last_slash;
2010
2011       if (!GetTempPath (sizeof (buf), buf))
2012         {
2013           _dbus_warn ("GetTempPath failed\n");
2014           _dbus_abort ();
2015         }
2016
2017       /* Drop terminating backslash or slash */
2018       last_slash = _mbsrchr (buf, '\\');
2019       if (last_slash > buf && last_slash[1] == '\0')
2020         last_slash[0] = '\0';
2021       last_slash = _mbsrchr (buf, '/');
2022       if (last_slash > buf && last_slash[1] == '\0')
2023         last_slash[0] = '\0';
2024
2025       tmpdir = buf;
2026     }
2027
2028   _dbus_assert(tmpdir != NULL);
2029
2030   return tmpdir;
2031 }
2032
2033
2034 /**
2035  * Deletes the given file.
2036  *
2037  * @param filename the filename
2038  * @param error error location
2039  * 
2040  * @returns #TRUE if unlink() succeeded
2041  */
2042 dbus_bool_t
2043 _dbus_delete_file (const DBusString *filename,
2044                    DBusError        *error)
2045 {
2046   const char *filename_c;
2047
2048   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2049
2050   filename_c = _dbus_string_get_const_data (filename);
2051
2052   if (_unlink (filename_c) < 0)
2053     {
2054       dbus_set_error (error, DBUS_ERROR_FAILED,
2055                       "Failed to delete file %s: %s\n",
2056                       filename_c, strerror (errno));
2057       return FALSE;
2058     }
2059   else
2060     return TRUE;
2061 }
2062
2063 #if !defined (DBUS_DISABLE_ASSERT) || defined(DBUS_BUILD_TESTS)
2064
2065 #ifdef _MSC_VER
2066 # ifdef BACKTRACES
2067 #  undef BACKTRACES
2068 # endif
2069 #else
2070 # define BACKTRACES
2071 #endif
2072
2073 #ifdef BACKTRACES
2074 /*
2075  * Backtrace Generator
2076  *
2077  * Copyright 2004 Eric Poech
2078  * Copyright 2004 Robert Shearman
2079  *
2080  * This library is free software; you can redistribute it and/or
2081  * modify it under the terms of the GNU Lesser General Public
2082  * License as published by the Free Software Foundation; either
2083  * version 2.1 of the License, or (at your option) any later version.
2084  *
2085  * This library is distributed in the hope that it will be useful,
2086  * but WITHOUT ANY WARRANTY; without even the implied warranty of
2087  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2088  * Lesser General Public License for more details.
2089  *
2090  * You should have received a copy of the GNU Lesser General Public
2091  * License along with this library; if not, write to the Free Software
2092  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
2093  */
2094
2095 #include <winver.h>
2096 #include <imagehlp.h>
2097 #include <stdio.h>
2098
2099 #define DPRINTF _dbus_warn
2100
2101 #ifdef _MSC_VER
2102 #define BOOL int
2103
2104 #define __i386__
2105 #endif
2106
2107 //#define MAKE_FUNCPTR(f) static typeof(f) * p##f
2108
2109 //MAKE_FUNCPTR(StackWalk);
2110 //MAKE_FUNCPTR(SymGetModuleBase);
2111 //MAKE_FUNCPTR(SymFunctionTableAccess);
2112 //MAKE_FUNCPTR(SymInitialize);
2113 //MAKE_FUNCPTR(SymGetSymFromAddr);
2114 //MAKE_FUNCPTR(SymGetModuleInfo);
2115 static BOOL (WINAPI *pStackWalk)(
2116   DWORD MachineType,
2117   HANDLE hProcess,
2118   HANDLE hThread,
2119   LPSTACKFRAME StackFrame,
2120   PVOID ContextRecord,
2121   PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
2122   PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
2123   PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
2124   PTRANSLATE_ADDRESS_ROUTINE TranslateAddress
2125 );
2126 static DWORD (WINAPI *pSymGetModuleBase)(
2127   HANDLE hProcess,
2128   DWORD dwAddr
2129 );
2130 static PVOID  (WINAPI *pSymFunctionTableAccess)(
2131   HANDLE hProcess,
2132   DWORD AddrBase
2133 );
2134 static BOOL  (WINAPI *pSymInitialize)(
2135   HANDLE hProcess,
2136   PSTR UserSearchPath,
2137   BOOL fInvadeProcess
2138 );
2139 static BOOL  (WINAPI *pSymGetSymFromAddr)(
2140   HANDLE hProcess,
2141   DWORD Address,
2142   PDWORD Displacement,
2143   PIMAGEHLP_SYMBOL Symbol
2144 );
2145 static BOOL  (WINAPI *pSymGetModuleInfo)(
2146   HANDLE hProcess,
2147   DWORD dwAddr,
2148   PIMAGEHLP_MODULE ModuleInfo
2149 );
2150 static DWORD  (WINAPI *pSymSetOptions)(
2151   DWORD SymOptions
2152 );
2153
2154
2155 static BOOL init_backtrace()
2156 {
2157     HMODULE hmodDbgHelp = LoadLibraryA("dbghelp");
2158 /*
2159     #define GETFUNC(x) \
2160     p##x = (typeof(x)*)GetProcAddress(hmodDbgHelp, #x); \
2161     if (!p##x) \
2162     { \
2163         return FALSE; \
2164     }
2165     */
2166
2167
2168 //    GETFUNC(StackWalk);
2169 //    GETFUNC(SymGetModuleBase);
2170 //    GETFUNC(SymFunctionTableAccess);
2171 //    GETFUNC(SymInitialize);
2172 //    GETFUNC(SymGetSymFromAddr);
2173 //    GETFUNC(SymGetModuleInfo);
2174
2175 #define FUNC(x) #x
2176
2177       pStackWalk = (BOOL  (WINAPI *)(
2178 DWORD MachineType,
2179 HANDLE hProcess,
2180 HANDLE hThread,
2181 LPSTACKFRAME StackFrame,
2182 PVOID ContextRecord,
2183 PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
2184 PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
2185 PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
2186 PTRANSLATE_ADDRESS_ROUTINE TranslateAddress
2187 ))GetProcAddress (hmodDbgHelp, FUNC(StackWalk));
2188     pSymGetModuleBase=(DWORD  (WINAPI *)(
2189   HANDLE hProcess,
2190   DWORD dwAddr
2191 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleBase));
2192     pSymFunctionTableAccess=(PVOID  (WINAPI *)(
2193   HANDLE hProcess,
2194   DWORD AddrBase
2195 ))GetProcAddress (hmodDbgHelp, FUNC(SymFunctionTableAccess));
2196     pSymInitialize = (BOOL  (WINAPI *)(
2197   HANDLE hProcess,
2198   PSTR UserSearchPath,
2199   BOOL fInvadeProcess
2200 ))GetProcAddress (hmodDbgHelp, FUNC(SymInitialize));
2201     pSymGetSymFromAddr = (BOOL  (WINAPI *)(
2202   HANDLE hProcess,
2203   DWORD Address,
2204   PDWORD Displacement,
2205   PIMAGEHLP_SYMBOL Symbol
2206 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetSymFromAddr));
2207     pSymGetModuleInfo = (BOOL  (WINAPI *)(
2208   HANDLE hProcess,
2209   DWORD dwAddr,
2210   PIMAGEHLP_MODULE ModuleInfo
2211 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleInfo));
2212 pSymSetOptions = (DWORD  (WINAPI *)(
2213 DWORD SymOptions
2214 ))GetProcAddress (hmodDbgHelp, FUNC(SymSetOptions));
2215
2216
2217     pSymSetOptions(SYMOPT_UNDNAME);
2218
2219     pSymInitialize(GetCurrentProcess(), NULL, TRUE);
2220
2221     return TRUE;
2222 }
2223
2224 static void dump_backtrace_for_thread(HANDLE hThread)
2225 {
2226     STACKFRAME sf;
2227     CONTEXT context;
2228     DWORD dwImageType;
2229
2230     if (!pStackWalk)
2231         if (!init_backtrace())
2232             return;
2233
2234     /* can't use this function for current thread as GetThreadContext
2235      * doesn't support getting context from current thread */
2236     if (hThread == GetCurrentThread())
2237         return;
2238
2239     DPRINTF("Backtrace:\n");
2240
2241     _DBUS_ZERO(context);
2242     context.ContextFlags = CONTEXT_FULL;
2243
2244     SuspendThread(hThread);
2245
2246     if (!GetThreadContext(hThread, &context))
2247     {
2248         DPRINTF("Couldn't get thread context (error %ld)\n", GetLastError());
2249         ResumeThread(hThread);
2250         return;
2251     }
2252
2253     _DBUS_ZERO(sf);
2254
2255 #ifdef __i386__
2256     sf.AddrFrame.Offset = context.Ebp;
2257     sf.AddrFrame.Mode = AddrModeFlat;
2258     sf.AddrPC.Offset = context.Eip;
2259     sf.AddrPC.Mode = AddrModeFlat;
2260     dwImageType = IMAGE_FILE_MACHINE_I386;
2261 #else
2262 # error You need to fill in the STACKFRAME structure for your architecture
2263 #endif
2264
2265     while (pStackWalk(dwImageType, GetCurrentProcess(),
2266                      hThread, &sf, &context, NULL, pSymFunctionTableAccess,
2267                      pSymGetModuleBase, NULL))
2268     {
2269         BYTE buffer[256];
2270         IMAGEHLP_SYMBOL * pSymbol = (IMAGEHLP_SYMBOL *)buffer;
2271         DWORD dwDisplacement;
2272
2273         pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
2274         pSymbol->MaxNameLength = sizeof(buffer) - sizeof(IMAGEHLP_SYMBOL) + 1;
2275
2276         if (!pSymGetSymFromAddr(GetCurrentProcess(), sf.AddrPC.Offset,
2277                                 &dwDisplacement, pSymbol))
2278         {
2279             IMAGEHLP_MODULE ModuleInfo;
2280             ModuleInfo.SizeOfStruct = sizeof(ModuleInfo);
2281
2282             if (!pSymGetModuleInfo(GetCurrentProcess(), sf.AddrPC.Offset,
2283                                    &ModuleInfo))
2284                 DPRINTF("1\t%p\n", (void*)sf.AddrPC.Offset);
2285             else
2286                 DPRINTF("2\t%s+0x%lx\n", ModuleInfo.ImageName,
2287                     sf.AddrPC.Offset - ModuleInfo.BaseOfImage);
2288         }
2289         else if (dwDisplacement)
2290             DPRINTF("3\t%s+0x%lx\n", pSymbol->Name, dwDisplacement);
2291         else
2292             DPRINTF("4\t%s\n", pSymbol->Name);
2293     }
2294
2295     ResumeThread(hThread);
2296 }
2297
2298 static DWORD WINAPI dump_thread_proc(LPVOID lpParameter)
2299 {
2300     dump_backtrace_for_thread((HANDLE)lpParameter);
2301     return 0;
2302 }
2303
2304 /* cannot get valid context from current thread, so we have to execute
2305  * backtrace from another thread */
2306 static void dump_backtrace()
2307 {
2308     HANDLE hCurrentThread;
2309     HANDLE hThread;
2310     DWORD dwThreadId;
2311     DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
2312         GetCurrentProcess(), &hCurrentThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
2313     hThread = CreateThread(NULL, 0, dump_thread_proc, (LPVOID)hCurrentThread,
2314         0, &dwThreadId);
2315     WaitForSingleObject(hThread, INFINITE);
2316     CloseHandle(hThread);
2317     CloseHandle(hCurrentThread);
2318 }
2319
2320 void _dbus_print_backtrace(void)
2321 {
2322   init_backtrace();
2323   dump_backtrace();
2324 }
2325 #else
2326 void _dbus_print_backtrace(void)
2327 {
2328   _dbus_verbose ("  D-Bus not compiled with backtrace support\n");
2329 }
2330 #endif
2331
2332 static dbus_uint32_t fromAscii(char ascii)
2333 {
2334     if(ascii >= '0' && ascii <= '9')
2335         return ascii - '0';
2336     if(ascii >= 'A' && ascii <= 'F')
2337         return ascii - 'A' + 10;
2338     if(ascii >= 'a' && ascii <= 'f')
2339         return ascii - 'a' + 10;
2340     return 0;    
2341 }
2342
2343 dbus_bool_t _dbus_read_local_machine_uuid   (DBusGUID         *machine_id,
2344                                              dbus_bool_t       create_if_not_found,
2345                                              DBusError        *error)
2346 {
2347 #ifdef DBUS_WINCE
2348         return TRUE;
2349   // TODO
2350 #else
2351     HW_PROFILE_INFOA info;
2352     char *lpc = &info.szHwProfileGuid[0];
2353     dbus_uint32_t u;
2354
2355     //  the hw-profile guid lives long enough
2356     if(!GetCurrentHwProfileA(&info))
2357       {
2358         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); // FIXME
2359         return FALSE;  
2360       }
2361
2362     // Form: {12340001-4980-1920-6788-123456789012}
2363     lpc++;
2364     // 12340001
2365     u = ((fromAscii(lpc[0]) <<  0) |
2366          (fromAscii(lpc[1]) <<  4) |
2367          (fromAscii(lpc[2]) <<  8) |
2368          (fromAscii(lpc[3]) << 12) |
2369          (fromAscii(lpc[4]) << 16) |
2370          (fromAscii(lpc[5]) << 20) |
2371          (fromAscii(lpc[6]) << 24) |
2372          (fromAscii(lpc[7]) << 28));
2373     machine_id->as_uint32s[0] = u;
2374
2375     lpc += 9;
2376     // 4980-1920
2377     u = ((fromAscii(lpc[0]) <<  0) |
2378          (fromAscii(lpc[1]) <<  4) |
2379          (fromAscii(lpc[2]) <<  8) |
2380          (fromAscii(lpc[3]) << 12) |
2381          (fromAscii(lpc[5]) << 16) |
2382          (fromAscii(lpc[6]) << 20) |
2383          (fromAscii(lpc[7]) << 24) |
2384          (fromAscii(lpc[8]) << 28));
2385     machine_id->as_uint32s[1] = u;
2386     
2387     lpc += 10;
2388     // 6788-1234
2389     u = ((fromAscii(lpc[0]) <<  0) |
2390          (fromAscii(lpc[1]) <<  4) |
2391          (fromAscii(lpc[2]) <<  8) |
2392          (fromAscii(lpc[3]) << 12) |
2393          (fromAscii(lpc[5]) << 16) |
2394          (fromAscii(lpc[6]) << 20) |
2395          (fromAscii(lpc[7]) << 24) |
2396          (fromAscii(lpc[8]) << 28));
2397     machine_id->as_uint32s[2] = u;
2398     
2399     lpc += 9;
2400     // 56789012
2401     u = ((fromAscii(lpc[0]) <<  0) |
2402          (fromAscii(lpc[1]) <<  4) |
2403          (fromAscii(lpc[2]) <<  8) |
2404          (fromAscii(lpc[3]) << 12) |
2405          (fromAscii(lpc[4]) << 16) |
2406          (fromAscii(lpc[5]) << 20) |
2407          (fromAscii(lpc[6]) << 24) |
2408          (fromAscii(lpc[7]) << 28));
2409     machine_id->as_uint32s[3] = u;
2410 #endif
2411     return TRUE;
2412 }
2413
2414 static
2415 HANDLE _dbus_global_lock (const char *mutexname)
2416 {
2417   HANDLE mutex;
2418   DWORD gotMutex;
2419
2420   mutex = CreateMutex( NULL, FALSE, mutexname );
2421   if( !mutex )
2422     {
2423       return FALSE;
2424     }
2425
2426    gotMutex = WaitForSingleObject( mutex, INFINITE );
2427    switch( gotMutex )
2428      {
2429        case WAIT_ABANDONED:
2430                ReleaseMutex (mutex);
2431                CloseHandle (mutex);
2432                return 0;
2433        case WAIT_FAILED:
2434        case WAIT_TIMEOUT:
2435                return 0;
2436      }
2437
2438    return mutex;
2439 }
2440
2441 static
2442 void _dbus_global_unlock (HANDLE mutex)
2443 {
2444   ReleaseMutex (mutex);
2445   CloseHandle (mutex); 
2446 }
2447
2448 // for proper cleanup in dbus-daemon
2449 static HANDLE hDBusDaemonMutex = NULL;
2450 static HANDLE hDBusSharedMem = NULL;
2451 // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
2452 static const char *cUniqueDBusInitMutex = "UniqueDBusInitMutex";
2453 // sync _dbus_get_autolaunch_address
2454 static const char *cDBusAutolaunchMutex = "DBusAutolaunchMutex";
2455 // mutex to determine if dbus-daemon is already started (per user)
2456 static const char *cDBusDaemonMutex = "DBusDaemonMutex";
2457 // named shm for dbus adress info (per user)
2458 #ifdef _DEBUG
2459 static const char *cDBusDaemonAddressInfo = "DBusDaemonAddressInfoDebug";
2460 #else
2461 static const char *cDBusDaemonAddressInfo = "DBusDaemonAddressInfo";
2462 #endif
2463
2464
2465 void
2466 _dbus_daemon_publish_session_bus_address (const char* address)
2467 {
2468   HANDLE lock;
2469   char *shared_addr = NULL;
2470   DWORD ret;
2471
2472   _dbus_assert (address);
2473   // before _dbus_global_lock to keep correct lock/release order
2474   hDBusDaemonMutex = CreateMutex( NULL, FALSE, cDBusDaemonMutex );
2475   ret = WaitForSingleObject( hDBusDaemonMutex, 1000 );
2476   if ( ret != WAIT_OBJECT_0 ) {
2477     _dbus_warn("Could not lock mutex %s (return code %d). daemon already running? Bus address not published.\n", cDBusDaemonMutex, ret );
2478     return;
2479   }
2480
2481   // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
2482   lock = _dbus_global_lock( cUniqueDBusInitMutex );
2483
2484   // create shm
2485   hDBusSharedMem = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
2486                                       0, strlen( address ) + 1, cDBusDaemonAddressInfo );
2487   _dbus_assert( hDBusSharedMem );
2488
2489   shared_addr = MapViewOfFile( hDBusSharedMem, FILE_MAP_WRITE, 0, 0, 0 );
2490
2491   _dbus_assert (shared_addr);
2492
2493   strcpy( shared_addr, address);
2494
2495   // cleanup
2496   UnmapViewOfFile( shared_addr );
2497
2498   _dbus_global_unlock( lock );
2499 }
2500
2501 void
2502 _dbus_daemon_unpublish_session_bus_address (void)
2503 {
2504   HANDLE lock;
2505
2506   // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
2507   lock = _dbus_global_lock( cUniqueDBusInitMutex );
2508
2509   CloseHandle( hDBusSharedMem );
2510
2511   hDBusSharedMem = NULL;
2512
2513   ReleaseMutex( hDBusDaemonMutex );
2514
2515   CloseHandle( hDBusDaemonMutex );
2516
2517   hDBusDaemonMutex = NULL;
2518
2519   _dbus_global_unlock( lock );
2520 }
2521
2522 static dbus_bool_t
2523 _dbus_get_autolaunch_shm (DBusString *address)
2524 {
2525   HANDLE sharedMem;
2526   char *shared_addr;
2527   int i;
2528
2529   // read shm
2530   for(i=0;i<20;++i) {
2531       // we know that dbus-daemon is available, so we wait until shm is available
2532       sharedMem = OpenFileMapping( FILE_MAP_READ, FALSE, cDBusDaemonAddressInfo );
2533       if( sharedMem == 0 )
2534           Sleep( 100 );
2535       if ( sharedMem != 0)
2536           break;
2537   }
2538
2539   if( sharedMem == 0 )
2540       return FALSE;
2541
2542   shared_addr = MapViewOfFile( sharedMem, FILE_MAP_READ, 0, 0, 0 );
2543
2544   if( !shared_addr )
2545       return FALSE;
2546
2547   _dbus_string_init( address );
2548
2549   _dbus_string_append( address, shared_addr );
2550
2551   // cleanup
2552   UnmapViewOfFile( shared_addr );
2553
2554   CloseHandle( sharedMem );
2555
2556   return TRUE;
2557 }
2558
2559 static dbus_bool_t
2560 _dbus_daemon_already_runs (DBusString *address)
2561 {
2562   HANDLE lock;
2563   HANDLE daemon;
2564   dbus_bool_t bRet = TRUE;
2565
2566   // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
2567   lock = _dbus_global_lock( cUniqueDBusInitMutex );
2568
2569   // do checks
2570   daemon = CreateMutex( NULL, FALSE, cDBusDaemonMutex );
2571   if(WaitForSingleObject( daemon, 10 ) != WAIT_TIMEOUT)
2572     {
2573       ReleaseMutex (daemon);
2574       CloseHandle (daemon);
2575
2576       _dbus_global_unlock( lock );
2577       return FALSE;
2578     }
2579
2580   // read shm
2581   bRet = _dbus_get_autolaunch_shm( address );
2582
2583   // cleanup
2584   CloseHandle ( daemon );
2585
2586   _dbus_global_unlock( lock );
2587
2588   return bRet;
2589 }
2590
2591 dbus_bool_t
2592 _dbus_get_autolaunch_address (DBusString *address, 
2593                               DBusError *error)
2594 {
2595   HANDLE mutex;
2596   STARTUPINFOA si;
2597   PROCESS_INFORMATION pi;
2598   dbus_bool_t retval = FALSE;
2599   LPSTR lpFile;
2600   char dbus_exe_path[MAX_PATH];
2601   char dbus_args[MAX_PATH * 2];
2602   const char * daemon_name = DBUS_DAEMON_NAME ".exe";
2603
2604   mutex = _dbus_global_lock ( cDBusAutolaunchMutex );
2605
2606   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2607
2608   if (_dbus_daemon_already_runs(address))
2609     {
2610         _dbus_verbose("found already running dbus daemon\n");
2611         retval = TRUE;
2612         goto out;
2613     }
2614
2615   if (!SearchPathA(NULL, daemon_name, NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile))
2616     {
2617       printf ("please add the path to %s to your PATH environment variable\n", daemon_name);
2618       printf ("or start the daemon manually\n\n");
2619       printf ("");
2620       goto out;
2621     }
2622
2623   // Create process
2624   ZeroMemory( &si, sizeof(si) );
2625   si.cb = sizeof(si);
2626   ZeroMemory( &pi, sizeof(pi) );
2627
2628   _snprintf(dbus_args, sizeof(dbus_args) - 1, "\"%s\" %s", dbus_exe_path,  " --session");
2629
2630 //  argv[i] = "--config-file=bus\\session.conf";
2631 //  printf("create process \"%s\" %s\n", dbus_exe_path, dbus_args);
2632   if(CreateProcessA(dbus_exe_path, dbus_args, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
2633     {
2634
2635       retval = _dbus_get_autolaunch_shm( address );
2636     }
2637   
2638   if (retval == FALSE)
2639     dbus_set_error_const (error, DBUS_ERROR_FAILED, "Failed to launch dbus-daemon");
2640
2641 out:
2642   if (retval)
2643     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2644   else
2645     _DBUS_ASSERT_ERROR_IS_SET (error);
2646   
2647   _dbus_global_unlock (mutex);
2648
2649   return retval;
2650  }
2651
2652
2653 /** Makes the file readable by every user in the system.
2654  *
2655  * @param filename the filename
2656  * @param error error location
2657  * @returns #TRUE if the file's permissions could be changed.
2658  */
2659 dbus_bool_t
2660 _dbus_make_file_world_readable(const DBusString *filename,
2661                                DBusError *error)
2662 {
2663   // TODO
2664   return TRUE;
2665 }
2666
2667
2668 #define DBUS_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
2669 #define DBUS_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
2670
2671 /**
2672  * Returns the standard directories for a session bus to look for service 
2673  * activation files 
2674  *
2675  * On Windows this should be data directories:
2676  *
2677  * %CommonProgramFiles%/dbus
2678  *
2679  * and
2680  *
2681  * DBUS_DATADIR
2682  *
2683  * @param dirs the directory list we are returning
2684  * @returns #FALSE on OOM 
2685  */
2686
2687 dbus_bool_t 
2688 _dbus_get_standard_session_servicedirs (DBusList **dirs)
2689 {
2690   const char *common_progs;
2691   DBusString servicedir_path;
2692
2693   if (!_dbus_string_init (&servicedir_path))
2694     return FALSE;
2695
2696   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR _DBUS_PATH_SEPARATOR))
2697         goto oom;
2698
2699   common_progs = _dbus_getenv ("CommonProgramFiles");
2700
2701   if (common_progs != NULL)
2702     {
2703       if (!_dbus_string_append (&servicedir_path, common_progs))
2704         goto oom;
2705
2706       if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR))
2707         goto oom;
2708     }
2709
2710   if (!_dbus_split_paths_and_append (&servicedir_path, 
2711                                DBUS_STANDARD_SESSION_SERVICEDIR, 
2712                                dirs))
2713     goto oom;
2714
2715   _dbus_string_free (&servicedir_path);  
2716   return TRUE;
2717
2718  oom:
2719   _dbus_string_free (&servicedir_path);
2720   return FALSE;
2721 }
2722
2723 /**
2724  * Returns the standard directories for a system bus to look for service
2725  * activation files
2726  *
2727  * On UNIX this should be the standard xdg freedesktop.org data directories:
2728  *
2729  * XDG_DATA_DIRS=${XDG_DATA_DIRS-/usr/local/share:/usr/share}
2730  *
2731  * and
2732  *
2733  * DBUS_DATADIR
2734  *
2735  * On Windows there is no system bus and this function can return nothing.
2736  *
2737  * @param dirs the directory list we are returning
2738  * @returns #FALSE on OOM
2739  */
2740
2741 dbus_bool_t
2742 _dbus_get_standard_system_servicedirs (DBusList **dirs)
2743 {
2744   *dirs = NULL;
2745   return TRUE;
2746 }
2747
2748 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
2749
2750 /**
2751  * Atomically increments an integer
2752  *
2753  * @param atomic pointer to the integer to increment
2754  * @returns the value before incrementing
2755  *
2756  */
2757 dbus_int32_t
2758 _dbus_atomic_inc (DBusAtomic *atomic)
2759 {
2760   // +/- 1 is needed here!
2761   // no volatile argument with mingw
2762   return InterlockedIncrement (&atomic->value) - 1;
2763 }
2764
2765 /**
2766  * Atomically decrement an integer
2767  *
2768  * @param atomic pointer to the integer to decrement
2769  * @returns the value before decrementing
2770  *
2771  */
2772 dbus_int32_t
2773 _dbus_atomic_dec (DBusAtomic *atomic)
2774 {
2775   // +/- 1 is needed here!
2776   // no volatile argument with mingw
2777   return InterlockedDecrement (&atomic->value) + 1;
2778 }
2779
2780 #endif /* asserts or tests enabled */
2781
2782 /**
2783  * Called when the bus daemon is signaled to reload its configuration; any
2784  * caches should be nuked. Of course any caches that need explicit reload
2785  * are probably broken, but c'est la vie.
2786  *
2787  * 
2788  */
2789 void
2790 _dbus_flush_caches (void)
2791 {
2792 }
2793
2794 /**
2795  * See if errno is EAGAIN or EWOULDBLOCK (this has to be done differently
2796  * for Winsock so is abstracted)
2797  *
2798  * @returns #TRUE if errno == EAGAIN or errno == EWOULDBLOCK
2799  */
2800 dbus_bool_t
2801 _dbus_get_is_errno_eagain_or_ewouldblock (void)
2802 {
2803   return errno == WSAEWOULDBLOCK;
2804 }
2805
2806 /**
2807  * return the absolute path of the dbus installation 
2808  *
2809  * @param s buffer for installation path
2810  * @param len length of buffer
2811  * @returns #FALSE on failure
2812  */
2813 static dbus_bool_t
2814 _dbus_get_install_root(char *prefix, int len)
2815 {
2816     //To find the prefix, we cut the filename and also \bin\ if present
2817     char* p = 0;
2818     int i;
2819     DWORD pathLength;
2820     char *lastSlash;
2821     SetLastError( 0 );
2822     pathLength = GetModuleFileName(_dbus_win_get_dll_hmodule(), prefix, len);
2823     if ( pathLength == 0 || GetLastError() != 0 ) {
2824         *prefix = '\0';
2825         return FALSE;
2826     }
2827     lastSlash = _mbsrchr(prefix, '\\');
2828     if (lastSlash == NULL) {
2829         *prefix = '\0';
2830         return FALSE;
2831     }
2832     //cut off binary name
2833     lastSlash[1] = 0;
2834
2835     //cut possible "\\bin"
2836
2837     //this fails if we are in a double-byte system codepage and the
2838     //folder's name happens to end with the *bytes*
2839     //"\\bin"... (I.e. the second byte of some Han character and then
2840     //the Latin "bin", but that is not likely I think...
2841     if (lastSlash - prefix >= 4 && strnicmp(lastSlash - 4, "\\bin", 4) == 0)
2842         lastSlash[-3] = 0;
2843     else if (lastSlash - prefix >= 10 && strnicmp(lastSlash - 10, "\\bin\\debug", 10) == 0)
2844         lastSlash[-9] = 0;
2845     else if (lastSlash - prefix >= 12 && strnicmp(lastSlash - 12, "\\bin\\release", 12) == 0)
2846         lastSlash[-11] = 0;
2847
2848     return TRUE;
2849 }
2850
2851 /** 
2852   find config file either from installation or build root according to 
2853   the following path layout 
2854     install-root/
2855       bin/dbus-daemon[d].exe
2856       etc/<config-file>.conf *or* etc/dbus-1/<config-file>.conf
2857       (the former above is what dbus4win uses, the latter above is
2858       what a "normal" Unix-style "make install" uses)
2859
2860     build-root/
2861       bin/dbus-daemon[d].exe
2862       bus/<config-file>.conf 
2863 */
2864 dbus_bool_t 
2865 _dbus_get_config_file_name(DBusString *config_file, char *s)
2866 {
2867   char path[MAX_PATH*2];
2868   int path_size = sizeof(path);
2869
2870   if (!_dbus_get_install_root(path,path_size))
2871     return FALSE;
2872
2873   if(strlen(s) + 4 + strlen(path) > sizeof(path)-2)
2874     return FALSE;
2875   strcat(path,"etc\\");
2876   strcat(path,s);
2877   if (_dbus_file_exists(path)) 
2878     {
2879       // find path from executable 
2880       if (!_dbus_string_append (config_file, path))
2881         return FALSE;
2882     }
2883   else 
2884     {
2885       if (!_dbus_get_install_root(path,path_size))
2886         return FALSE;
2887       if(strlen(s) + 11 + strlen(path) > sizeof(path)-2)
2888         return FALSE;
2889       strcat(path,"etc\\dbus-1\\");
2890       strcat(path,s);
2891   
2892       if (_dbus_file_exists(path)) 
2893         {
2894           if (!_dbus_string_append (config_file, path))
2895             return FALSE;
2896         }
2897       else
2898         {
2899           if (!_dbus_get_install_root(path,path_size))
2900             return FALSE;
2901           if(strlen(s) + 4 + strlen(path) > sizeof(path)-2)
2902             return FALSE;
2903           strcat(path,"bus\\");
2904           strcat(path,s);
2905           
2906           if (_dbus_file_exists(path)) 
2907             {
2908               if (!_dbus_string_append (config_file, path))
2909                 return FALSE;
2910             }
2911         }
2912     }
2913   return TRUE;
2914 }    
2915
2916 /**
2917  * Append the absolute path of the system.conf file
2918  * (there is no system bus on Windows so this can just
2919  * return FALSE and print a warning or something)
2920  * 
2921  * @param str the string to append to
2922  * @returns #FALSE if no memory
2923  */
2924 dbus_bool_t
2925 _dbus_append_system_config_file (DBusString *str)
2926 {
2927   return _dbus_get_config_file_name(str, "system.conf");
2928 }
2929
2930 /**
2931  * Append the absolute path of the session.conf file.
2932  * 
2933  * @param str the string to append to
2934  * @returns #FALSE if no memory
2935  */
2936 dbus_bool_t
2937 _dbus_append_session_config_file (DBusString *str)
2938 {
2939   return _dbus_get_config_file_name(str, "session.conf");
2940 }
2941
2942 /* See comment in dbus-sysdeps-unix.c */
2943 dbus_bool_t
2944 _dbus_lookup_session_address (dbus_bool_t *supported,
2945                               DBusString  *address,
2946                               DBusError   *error)
2947 {
2948   /* Probably fill this in with something based on COM? */
2949   *supported = FALSE;
2950   return TRUE;
2951 }
2952
2953 /**
2954  * Appends the directory in which a keyring for the given credentials
2955  * should be stored.  The credentials should have either a Windows or
2956  * UNIX user in them.  The directory should be an absolute path.
2957  *
2958  * On UNIX the directory is ~/.dbus-keyrings while on Windows it should probably
2959  * be something else, since the dotfile convention is not normal on Windows.
2960  * 
2961  * @param directory string to append directory to
2962  * @param credentials credentials the directory should be for
2963  *  
2964  * @returns #FALSE on no memory
2965  */
2966 dbus_bool_t
2967 _dbus_append_keyring_directory_for_credentials (DBusString      *directory,
2968                                                 DBusCredentials *credentials)
2969 {
2970   DBusString homedir;
2971   DBusString dotdir;
2972   dbus_uid_t uid;
2973   const char *homepath;
2974
2975   _dbus_assert (credentials != NULL);
2976   _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
2977   
2978   if (!_dbus_string_init (&homedir))
2979     return FALSE;
2980
2981   homepath = _dbus_getenv("HOMEPATH");
2982   if (homepath != NULL && *homepath != '\0')
2983     {
2984       _dbus_string_append(&homedir,homepath);
2985     }
2986   
2987 #ifdef DBUS_BUILD_TESTS
2988   {
2989     const char *override;
2990     
2991     override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
2992     if (override != NULL && *override != '\0')
2993       {
2994         _dbus_string_set_length (&homedir, 0);
2995         if (!_dbus_string_append (&homedir, override))
2996           goto failed;
2997
2998         _dbus_verbose ("Using fake homedir for testing: %s\n",
2999                        _dbus_string_get_const_data (&homedir));
3000       }
3001     else
3002       {
3003         static dbus_bool_t already_warned = FALSE;
3004         if (!already_warned)
3005           {
3006             _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
3007             already_warned = TRUE;
3008           }
3009       }
3010   }
3011 #endif
3012
3013   _dbus_string_init_const (&dotdir, ".dbus-keyrings");
3014   if (!_dbus_concat_dir_and_file (&homedir,
3015                                   &dotdir))
3016     goto failed;
3017   
3018   if (!_dbus_string_copy (&homedir, 0,
3019                           directory, _dbus_string_get_length (directory))) {
3020     goto failed;
3021   }
3022
3023   _dbus_string_free (&homedir);
3024   return TRUE;
3025   
3026  failed: 
3027   _dbus_string_free (&homedir);
3028   return FALSE;
3029 }
3030
3031 /** Checks if a file exists
3032 *
3033 * @param file full path to the file
3034 * @returns #TRUE if file exists
3035 */
3036 dbus_bool_t 
3037 _dbus_file_exists (const char *file)
3038 {
3039   DWORD attributes = GetFileAttributes (file);
3040
3041   if (attributes != INVALID_FILE_ATTRIBUTES && GetLastError() != ERROR_PATH_NOT_FOUND)
3042     return TRUE;
3043   else
3044     return FALSE;  
3045 }
3046
3047 /**
3048  * A wrapper around strerror() because some platforms
3049  * may be lame and not have strerror().
3050  *
3051  * @param error_number errno.
3052  * @returns error description.
3053  */
3054 const char*
3055 _dbus_strerror (int error_number)
3056 {
3057 #ifdef DBUS_WINCE
3058   // TODO
3059   return "unknown";
3060 #else
3061   const char *msg;
3062
3063   switch (error_number)
3064     {
3065     case WSAEINTR:
3066       return "Interrupted function call";
3067     case WSAEACCES:
3068       return "Permission denied";
3069     case WSAEFAULT:
3070       return "Bad address";
3071     case WSAEINVAL:
3072       return "Invalid argument";
3073     case WSAEMFILE:
3074       return "Too many open files";
3075     case WSAEWOULDBLOCK:
3076       return "Resource temporarily unavailable";
3077     case WSAEINPROGRESS:
3078       return "Operation now in progress";
3079     case WSAEALREADY:
3080       return "Operation already in progress";
3081     case WSAENOTSOCK:
3082       return "Socket operation on nonsocket";
3083     case WSAEDESTADDRREQ:
3084       return "Destination address required";
3085     case WSAEMSGSIZE:
3086       return "Message too long";
3087     case WSAEPROTOTYPE:
3088       return "Protocol wrong type for socket";
3089     case WSAENOPROTOOPT:
3090       return "Bad protocol option";
3091     case WSAEPROTONOSUPPORT:
3092       return "Protocol not supported";
3093     case WSAESOCKTNOSUPPORT:
3094       return "Socket type not supported";
3095     case WSAEOPNOTSUPP:
3096       return "Operation not supported";
3097     case WSAEPFNOSUPPORT:
3098       return "Protocol family not supported";
3099     case WSAEAFNOSUPPORT:
3100       return "Address family not supported by protocol family";
3101     case WSAEADDRINUSE:
3102       return "Address already in use";
3103     case WSAEADDRNOTAVAIL:
3104       return "Cannot assign requested address";
3105     case WSAENETDOWN:
3106       return "Network is down";
3107     case WSAENETUNREACH:
3108       return "Network is unreachable";
3109     case WSAENETRESET:
3110       return "Network dropped connection on reset";
3111     case WSAECONNABORTED:
3112       return "Software caused connection abort";
3113     case WSAECONNRESET:
3114       return "Connection reset by peer";
3115     case WSAENOBUFS:
3116       return "No buffer space available";
3117     case WSAEISCONN:
3118       return "Socket is already connected";
3119     case WSAENOTCONN:
3120       return "Socket is not connected";
3121     case WSAESHUTDOWN:
3122       return "Cannot send after socket shutdown";
3123     case WSAETIMEDOUT:
3124       return "Connection timed out";
3125     case WSAECONNREFUSED:
3126       return "Connection refused";
3127     case WSAEHOSTDOWN:
3128       return "Host is down";
3129     case WSAEHOSTUNREACH:
3130       return "No route to host";
3131     case WSAEPROCLIM:
3132       return "Too many processes";
3133     case WSAEDISCON:
3134       return "Graceful shutdown in progress";
3135     case WSATYPE_NOT_FOUND:
3136       return "Class type not found";
3137     case WSAHOST_NOT_FOUND:
3138       return "Host not found";
3139     case WSATRY_AGAIN:
3140       return "Nonauthoritative host not found";
3141     case WSANO_RECOVERY:
3142       return "This is a nonrecoverable error";
3143     case WSANO_DATA:
3144       return "Valid name, no data record of requested type";
3145     case WSA_INVALID_HANDLE:
3146       return "Specified event object handle is invalid";
3147     case WSA_INVALID_PARAMETER:
3148       return "One or more parameters are invalid";
3149     case WSA_IO_INCOMPLETE:
3150       return "Overlapped I/O event object not in signaled state";
3151     case WSA_IO_PENDING:
3152       return "Overlapped operations will complete later";
3153     case WSA_NOT_ENOUGH_MEMORY:
3154       return "Insufficient memory available";
3155     case WSA_OPERATION_ABORTED:
3156       return "Overlapped operation aborted";
3157 #ifdef WSAINVALIDPROCTABLE
3158
3159     case WSAINVALIDPROCTABLE:
3160       return "Invalid procedure table from service provider";
3161 #endif
3162 #ifdef WSAINVALIDPROVIDER
3163
3164     case WSAINVALIDPROVIDER:
3165       return "Invalid service provider version number";
3166 #endif
3167 #ifdef WSAPROVIDERFAILEDINIT
3168
3169     case WSAPROVIDERFAILEDINIT:
3170       return "Unable to initialize a service provider";
3171 #endif
3172
3173     case WSASYSCALLFAILURE:
3174       return "System call failure";
3175     }
3176   msg = strerror (error_number);
3177   if (msg == NULL)
3178     msg = "unknown";
3179
3180   return msg;
3181 #endif //DBUS_WINCE
3182 }
3183
3184 /**
3185  * Assigns an error name and message corresponding to a Win32 error
3186  * code to a DBusError. Does nothing if error is #NULL.
3187  *
3188  * @param error the error.
3189  * @param code the Win32 error code
3190  */
3191 void
3192 _dbus_win_set_error_from_win_error (DBusError *error,
3193                                     int        code)
3194 {
3195   char *msg;
3196
3197   /* As we want the English message, use the A API */
3198   FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
3199                   FORMAT_MESSAGE_IGNORE_INSERTS |
3200                   FORMAT_MESSAGE_FROM_SYSTEM,
3201                   NULL, code, MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US),
3202                   (LPTSTR) &msg, 0, NULL);
3203   if (msg)
3204     {
3205       char *msg_copy;
3206
3207       msg_copy = dbus_malloc (strlen (msg));
3208       strcpy (msg_copy, msg);
3209       LocalFree (msg);
3210
3211       dbus_set_error (error, "win32.error", "%s", msg_copy);
3212     }
3213   else
3214     dbus_set_error (error, "win32.error", "Unknown error code %d or FormatMessage failed", code);
3215 }
3216
3217 void
3218 _dbus_win_warn_win_error (const char *message,
3219                           int         code)
3220 {
3221   DBusError error;
3222
3223   dbus_error_init (&error);
3224   _dbus_win_set_error_from_win_error (&error, code);
3225   _dbus_warn ("%s: %s\n", message, error.message);
3226   dbus_error_free (&error);
3227 }
3228
3229 /**
3230  * Removes a directory; Directory must be empty
3231  *
3232  * @param filename directory filename
3233  * @param error initialized error object
3234  * @returns #TRUE on success
3235  */
3236 dbus_bool_t
3237 _dbus_delete_directory (const DBusString *filename,
3238                         DBusError        *error)
3239 {
3240   const char *filename_c;
3241
3242   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3243
3244   filename_c = _dbus_string_get_const_data (filename);
3245
3246   if (_rmdir (filename_c) != 0)
3247     {
3248       dbus_set_error (error, DBUS_ERROR_FAILED,
3249                       "Failed to remove directory %s: %s\n",
3250                       filename_c, strerror (errno));
3251       return FALSE;
3252     }
3253
3254   return TRUE;
3255 }
3256
3257 /** @} end of sysdeps-win */
3258 /* tests in dbus-sysdeps-util.c */
3259