Merge branch 'dbus-1.2'
[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 = NULL;
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 != NULL)
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 = (dbus_uint64_t *) &ft;
1898
1899   GetSystemTimeAsFileTime (&ft);
1900
1901   /* Convert from 100s of nanoseconds since 1601-01-01
1902   * to Unix epoch. Yes, this is Y2038 unsafe.
1903   */
1904   *time64 -= DBUS_INT64_CONSTANT (116444736000000000);
1905   *time64 /= 10;
1906
1907   if (tv_sec)
1908     *tv_sec = *time64 / 1000000;
1909
1910   if (tv_usec)
1911     *tv_usec = *time64 % 1000000;
1912 }
1913
1914
1915 /**
1916  * signal (SIGPIPE, SIG_IGN);
1917  */
1918 void
1919 _dbus_disable_sigpipe (void)
1920 {
1921 }
1922
1923 /**
1924  * Creates a directory; succeeds if the directory
1925  * is created or already existed.
1926  *
1927  * @param filename directory filename
1928  * @param error initialized error object
1929  * @returns #TRUE on success
1930  */
1931 dbus_bool_t
1932 _dbus_create_directory (const DBusString *filename,
1933                         DBusError        *error)
1934 {
1935   const char *filename_c;
1936
1937   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1938
1939   filename_c = _dbus_string_get_const_data (filename);
1940
1941   if (!CreateDirectory (filename_c, NULL))
1942     {
1943       if (GetLastError () == ERROR_ALREADY_EXISTS)
1944         return TRUE;
1945
1946       dbus_set_error (error, DBUS_ERROR_FAILED,
1947                       "Failed to create directory %s: %s\n",
1948                       filename_c, strerror (errno));
1949       return FALSE;
1950     }
1951   else
1952     return TRUE;
1953 }
1954
1955
1956 /**
1957  * Generates the given number of random bytes,
1958  * using the best mechanism we can come up with.
1959  *
1960  * @param str the string
1961  * @param n_bytes the number of random bytes to append to string
1962  * @returns #TRUE on success, #FALSE if no memory
1963  */
1964 dbus_bool_t
1965 _dbus_generate_random_bytes (DBusString *str,
1966                              int         n_bytes)
1967 {
1968   int old_len;
1969   char *p;
1970   HCRYPTPROV hprov;
1971
1972   old_len = _dbus_string_get_length (str);
1973
1974   if (!_dbus_string_lengthen (str, n_bytes))
1975     return FALSE;
1976
1977   p = _dbus_string_get_data_len (str, old_len, n_bytes);
1978
1979   if (!CryptAcquireContext (&hprov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
1980     return FALSE;
1981
1982   if (!CryptGenRandom (hprov, n_bytes, p))
1983     {
1984       CryptReleaseContext (hprov, 0);
1985       return FALSE;
1986     }
1987
1988   CryptReleaseContext (hprov, 0);
1989
1990   return TRUE;
1991 }
1992
1993 /**
1994  * Gets the temporary files directory by inspecting the environment variables 
1995  * TMPDIR, TMP, and TEMP in that order. If none of those are set "/tmp" is returned
1996  *
1997  * @returns location of temp directory
1998  */
1999 const char*
2000 _dbus_get_tmpdir(void)
2001 {
2002   static const char* tmpdir = NULL;
2003   static char buf[1000];
2004
2005   if (tmpdir == NULL)
2006     {
2007       char *last_slash;
2008
2009       if (!GetTempPath (sizeof (buf), buf))
2010         {
2011           _dbus_warn ("GetTempPath failed\n");
2012           _dbus_abort ();
2013         }
2014
2015       /* Drop terminating backslash or slash */
2016       last_slash = _mbsrchr (buf, '\\');
2017       if (last_slash > buf && last_slash[1] == '\0')
2018         last_slash[0] = '\0';
2019       last_slash = _mbsrchr (buf, '/');
2020       if (last_slash > buf && last_slash[1] == '\0')
2021         last_slash[0] = '\0';
2022
2023       tmpdir = buf;
2024     }
2025
2026   _dbus_assert(tmpdir != NULL);
2027
2028   return tmpdir;
2029 }
2030
2031
2032 /**
2033  * Deletes the given file.
2034  *
2035  * @param filename the filename
2036  * @param error error location
2037  * 
2038  * @returns #TRUE if unlink() succeeded
2039  */
2040 dbus_bool_t
2041 _dbus_delete_file (const DBusString *filename,
2042                    DBusError        *error)
2043 {
2044   const char *filename_c;
2045
2046   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2047
2048   filename_c = _dbus_string_get_const_data (filename);
2049
2050   if (_unlink (filename_c) < 0)
2051     {
2052       dbus_set_error (error, DBUS_ERROR_FAILED,
2053                       "Failed to delete file %s: %s\n",
2054                       filename_c, strerror (errno));
2055       return FALSE;
2056     }
2057   else
2058     return TRUE;
2059 }
2060
2061 #if !defined (DBUS_DISABLE_ASSERT) || defined(DBUS_BUILD_TESTS)
2062
2063 #ifdef _MSC_VER
2064 # ifdef BACKTRACES
2065 #  undef BACKTRACES
2066 # endif
2067 #else
2068 # define BACKTRACES
2069 #endif
2070
2071 #ifdef BACKTRACES
2072 /*
2073  * Backtrace Generator
2074  *
2075  * Copyright 2004 Eric Poech
2076  * Copyright 2004 Robert Shearman
2077  *
2078  * This library is free software; you can redistribute it and/or
2079  * modify it under the terms of the GNU Lesser General Public
2080  * License as published by the Free Software Foundation; either
2081  * version 2.1 of the License, or (at your option) any later version.
2082  *
2083  * This library is distributed in the hope that it will be useful,
2084  * but WITHOUT ANY WARRANTY; without even the implied warranty of
2085  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2086  * Lesser General Public License for more details.
2087  *
2088  * You should have received a copy of the GNU Lesser General Public
2089  * License along with this library; if not, write to the Free Software
2090  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
2091  */
2092
2093 #include <winver.h>
2094 #include <imagehlp.h>
2095 #include <stdio.h>
2096
2097 #define DPRINTF _dbus_warn
2098
2099 #ifdef _MSC_VER
2100 #define BOOL int
2101
2102 #define __i386__
2103 #endif
2104
2105 //#define MAKE_FUNCPTR(f) static typeof(f) * p##f
2106
2107 //MAKE_FUNCPTR(StackWalk);
2108 //MAKE_FUNCPTR(SymGetModuleBase);
2109 //MAKE_FUNCPTR(SymFunctionTableAccess);
2110 //MAKE_FUNCPTR(SymInitialize);
2111 //MAKE_FUNCPTR(SymGetSymFromAddr);
2112 //MAKE_FUNCPTR(SymGetModuleInfo);
2113 static BOOL (WINAPI *pStackWalk)(
2114   DWORD MachineType,
2115   HANDLE hProcess,
2116   HANDLE hThread,
2117   LPSTACKFRAME StackFrame,
2118   PVOID ContextRecord,
2119   PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
2120   PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
2121   PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
2122   PTRANSLATE_ADDRESS_ROUTINE TranslateAddress
2123 );
2124 static DWORD (WINAPI *pSymGetModuleBase)(
2125   HANDLE hProcess,
2126   DWORD dwAddr
2127 );
2128 static PVOID  (WINAPI *pSymFunctionTableAccess)(
2129   HANDLE hProcess,
2130   DWORD AddrBase
2131 );
2132 static BOOL  (WINAPI *pSymInitialize)(
2133   HANDLE hProcess,
2134   PSTR UserSearchPath,
2135   BOOL fInvadeProcess
2136 );
2137 static BOOL  (WINAPI *pSymGetSymFromAddr)(
2138   HANDLE hProcess,
2139   DWORD Address,
2140   PDWORD Displacement,
2141   PIMAGEHLP_SYMBOL Symbol
2142 );
2143 static BOOL  (WINAPI *pSymGetModuleInfo)(
2144   HANDLE hProcess,
2145   DWORD dwAddr,
2146   PIMAGEHLP_MODULE ModuleInfo
2147 );
2148 static DWORD  (WINAPI *pSymSetOptions)(
2149   DWORD SymOptions
2150 );
2151
2152
2153 static BOOL init_backtrace()
2154 {
2155     HMODULE hmodDbgHelp = LoadLibraryA("dbghelp");
2156 /*
2157     #define GETFUNC(x) \
2158     p##x = (typeof(x)*)GetProcAddress(hmodDbgHelp, #x); \
2159     if (!p##x) \
2160     { \
2161         return FALSE; \
2162     }
2163     */
2164
2165
2166 //    GETFUNC(StackWalk);
2167 //    GETFUNC(SymGetModuleBase);
2168 //    GETFUNC(SymFunctionTableAccess);
2169 //    GETFUNC(SymInitialize);
2170 //    GETFUNC(SymGetSymFromAddr);
2171 //    GETFUNC(SymGetModuleInfo);
2172
2173 #define FUNC(x) #x
2174
2175       pStackWalk = (BOOL  (WINAPI *)(
2176 DWORD MachineType,
2177 HANDLE hProcess,
2178 HANDLE hThread,
2179 LPSTACKFRAME StackFrame,
2180 PVOID ContextRecord,
2181 PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
2182 PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
2183 PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
2184 PTRANSLATE_ADDRESS_ROUTINE TranslateAddress
2185 ))GetProcAddress (hmodDbgHelp, FUNC(StackWalk));
2186     pSymGetModuleBase=(DWORD  (WINAPI *)(
2187   HANDLE hProcess,
2188   DWORD dwAddr
2189 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleBase));
2190     pSymFunctionTableAccess=(PVOID  (WINAPI *)(
2191   HANDLE hProcess,
2192   DWORD AddrBase
2193 ))GetProcAddress (hmodDbgHelp, FUNC(SymFunctionTableAccess));
2194     pSymInitialize = (BOOL  (WINAPI *)(
2195   HANDLE hProcess,
2196   PSTR UserSearchPath,
2197   BOOL fInvadeProcess
2198 ))GetProcAddress (hmodDbgHelp, FUNC(SymInitialize));
2199     pSymGetSymFromAddr = (BOOL  (WINAPI *)(
2200   HANDLE hProcess,
2201   DWORD Address,
2202   PDWORD Displacement,
2203   PIMAGEHLP_SYMBOL Symbol
2204 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetSymFromAddr));
2205     pSymGetModuleInfo = (BOOL  (WINAPI *)(
2206   HANDLE hProcess,
2207   DWORD dwAddr,
2208   PIMAGEHLP_MODULE ModuleInfo
2209 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleInfo));
2210 pSymSetOptions = (DWORD  (WINAPI *)(
2211 DWORD SymOptions
2212 ))GetProcAddress (hmodDbgHelp, FUNC(SymSetOptions));
2213
2214
2215     pSymSetOptions(SYMOPT_UNDNAME);
2216
2217     pSymInitialize(GetCurrentProcess(), NULL, TRUE);
2218
2219     return TRUE;
2220 }
2221
2222 static void dump_backtrace_for_thread(HANDLE hThread)
2223 {
2224     STACKFRAME sf;
2225     CONTEXT context;
2226     DWORD dwImageType;
2227
2228     if (!pStackWalk)
2229         if (!init_backtrace())
2230             return;
2231
2232     /* can't use this function for current thread as GetThreadContext
2233      * doesn't support getting context from current thread */
2234     if (hThread == GetCurrentThread())
2235         return;
2236
2237     DPRINTF("Backtrace:\n");
2238
2239     _DBUS_ZERO(context);
2240     context.ContextFlags = CONTEXT_FULL;
2241
2242     SuspendThread(hThread);
2243
2244     if (!GetThreadContext(hThread, &context))
2245     {
2246         DPRINTF("Couldn't get thread context (error %ld)\n", GetLastError());
2247         ResumeThread(hThread);
2248         return;
2249     }
2250
2251     _DBUS_ZERO(sf);
2252
2253 #ifdef __i386__
2254     sf.AddrFrame.Offset = context.Ebp;
2255     sf.AddrFrame.Mode = AddrModeFlat;
2256     sf.AddrPC.Offset = context.Eip;
2257     sf.AddrPC.Mode = AddrModeFlat;
2258     dwImageType = IMAGE_FILE_MACHINE_I386;
2259 #else
2260 # error You need to fill in the STACKFRAME structure for your architecture
2261 #endif
2262
2263     while (pStackWalk(dwImageType, GetCurrentProcess(),
2264                      hThread, &sf, &context, NULL, pSymFunctionTableAccess,
2265                      pSymGetModuleBase, NULL))
2266     {
2267         BYTE buffer[256];
2268         IMAGEHLP_SYMBOL * pSymbol = (IMAGEHLP_SYMBOL *)buffer;
2269         DWORD dwDisplacement;
2270
2271         pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
2272         pSymbol->MaxNameLength = sizeof(buffer) - sizeof(IMAGEHLP_SYMBOL) + 1;
2273
2274         if (!pSymGetSymFromAddr(GetCurrentProcess(), sf.AddrPC.Offset,
2275                                 &dwDisplacement, pSymbol))
2276         {
2277             IMAGEHLP_MODULE ModuleInfo;
2278             ModuleInfo.SizeOfStruct = sizeof(ModuleInfo);
2279
2280             if (!pSymGetModuleInfo(GetCurrentProcess(), sf.AddrPC.Offset,
2281                                    &ModuleInfo))
2282                 DPRINTF("1\t%p\n", (void*)sf.AddrPC.Offset);
2283             else
2284                 DPRINTF("2\t%s+0x%lx\n", ModuleInfo.ImageName,
2285                     sf.AddrPC.Offset - ModuleInfo.BaseOfImage);
2286         }
2287         else if (dwDisplacement)
2288             DPRINTF("3\t%s+0x%lx\n", pSymbol->Name, dwDisplacement);
2289         else
2290             DPRINTF("4\t%s\n", pSymbol->Name);
2291     }
2292
2293     ResumeThread(hThread);
2294 }
2295
2296 static DWORD WINAPI dump_thread_proc(LPVOID lpParameter)
2297 {
2298     dump_backtrace_for_thread((HANDLE)lpParameter);
2299     return 0;
2300 }
2301
2302 /* cannot get valid context from current thread, so we have to execute
2303  * backtrace from another thread */
2304 static void dump_backtrace()
2305 {
2306     HANDLE hCurrentThread;
2307     HANDLE hThread;
2308     DWORD dwThreadId;
2309     DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
2310         GetCurrentProcess(), &hCurrentThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
2311     hThread = CreateThread(NULL, 0, dump_thread_proc, (LPVOID)hCurrentThread,
2312         0, &dwThreadId);
2313     WaitForSingleObject(hThread, INFINITE);
2314     CloseHandle(hThread);
2315     CloseHandle(hCurrentThread);
2316 }
2317
2318 void _dbus_print_backtrace(void)
2319 {
2320   init_backtrace();
2321   dump_backtrace();
2322 }
2323 #else
2324 void _dbus_print_backtrace(void)
2325 {
2326   _dbus_verbose ("  D-Bus not compiled with backtrace support\n");
2327 }
2328 #endif
2329
2330 static dbus_uint32_t fromAscii(char ascii)
2331 {
2332     if(ascii >= '0' && ascii <= '9')
2333         return ascii - '0';
2334     if(ascii >= 'A' && ascii <= 'F')
2335         return ascii - 'A' + 10;
2336     if(ascii >= 'a' && ascii <= 'f')
2337         return ascii - 'a' + 10;
2338     return 0;    
2339 }
2340
2341 dbus_bool_t _dbus_read_local_machine_uuid   (DBusGUID         *machine_id,
2342                                              dbus_bool_t       create_if_not_found,
2343                                              DBusError        *error)
2344 {
2345 #ifdef DBUS_WINCE
2346         return TRUE;
2347   // TODO
2348 #else
2349     HW_PROFILE_INFOA info;
2350     char *lpc = &info.szHwProfileGuid[0];
2351     dbus_uint32_t u;
2352
2353     //  the hw-profile guid lives long enough
2354     if(!GetCurrentHwProfileA(&info))
2355       {
2356         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); // FIXME
2357         return FALSE;  
2358       }
2359
2360     // Form: {12340001-4980-1920-6788-123456789012}
2361     lpc++;
2362     // 12340001
2363     u = ((fromAscii(lpc[0]) <<  0) |
2364          (fromAscii(lpc[1]) <<  4) |
2365          (fromAscii(lpc[2]) <<  8) |
2366          (fromAscii(lpc[3]) << 12) |
2367          (fromAscii(lpc[4]) << 16) |
2368          (fromAscii(lpc[5]) << 20) |
2369          (fromAscii(lpc[6]) << 24) |
2370          (fromAscii(lpc[7]) << 28));
2371     machine_id->as_uint32s[0] = u;
2372
2373     lpc += 9;
2374     // 4980-1920
2375     u = ((fromAscii(lpc[0]) <<  0) |
2376          (fromAscii(lpc[1]) <<  4) |
2377          (fromAscii(lpc[2]) <<  8) |
2378          (fromAscii(lpc[3]) << 12) |
2379          (fromAscii(lpc[5]) << 16) |
2380          (fromAscii(lpc[6]) << 20) |
2381          (fromAscii(lpc[7]) << 24) |
2382          (fromAscii(lpc[8]) << 28));
2383     machine_id->as_uint32s[1] = u;
2384     
2385     lpc += 10;
2386     // 6788-1234
2387     u = ((fromAscii(lpc[0]) <<  0) |
2388          (fromAscii(lpc[1]) <<  4) |
2389          (fromAscii(lpc[2]) <<  8) |
2390          (fromAscii(lpc[3]) << 12) |
2391          (fromAscii(lpc[5]) << 16) |
2392          (fromAscii(lpc[6]) << 20) |
2393          (fromAscii(lpc[7]) << 24) |
2394          (fromAscii(lpc[8]) << 28));
2395     machine_id->as_uint32s[2] = u;
2396     
2397     lpc += 9;
2398     // 56789012
2399     u = ((fromAscii(lpc[0]) <<  0) |
2400          (fromAscii(lpc[1]) <<  4) |
2401          (fromAscii(lpc[2]) <<  8) |
2402          (fromAscii(lpc[3]) << 12) |
2403          (fromAscii(lpc[4]) << 16) |
2404          (fromAscii(lpc[5]) << 20) |
2405          (fromAscii(lpc[6]) << 24) |
2406          (fromAscii(lpc[7]) << 28));
2407     machine_id->as_uint32s[3] = u;
2408 #endif
2409     return TRUE;
2410 }
2411
2412 static
2413 HANDLE _dbus_global_lock (const char *mutexname)
2414 {
2415   HANDLE mutex;
2416   DWORD gotMutex;
2417
2418   mutex = CreateMutex( NULL, FALSE, mutexname );
2419   if( !mutex )
2420     {
2421       return FALSE;
2422     }
2423
2424    gotMutex = WaitForSingleObject( mutex, INFINITE );
2425    switch( gotMutex )
2426      {
2427        case WAIT_ABANDONED:
2428                ReleaseMutex (mutex);
2429                CloseHandle (mutex);
2430                return 0;
2431        case WAIT_FAILED:
2432        case WAIT_TIMEOUT:
2433                return 0;
2434      }
2435
2436    return mutex;
2437 }
2438
2439 static
2440 void _dbus_global_unlock (HANDLE mutex)
2441 {
2442   ReleaseMutex (mutex);
2443   CloseHandle (mutex); 
2444 }
2445
2446 // for proper cleanup in dbus-daemon
2447 static HANDLE hDBusDaemonMutex = NULL;
2448 static HANDLE hDBusSharedMem = NULL;
2449 // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
2450 static const char *cUniqueDBusInitMutex = "UniqueDBusInitMutex";
2451 // sync _dbus_get_autolaunch_address
2452 static const char *cDBusAutolaunchMutex = "DBusAutolaunchMutex";
2453 // mutex to determine if dbus-daemon is already started (per user)
2454 static const char *cDBusDaemonMutex = "DBusDaemonMutex";
2455 // named shm for dbus adress info (per user)
2456 #ifdef _DEBUG
2457 static const char *cDBusDaemonAddressInfo = "DBusDaemonAddressInfoDebug";
2458 #else
2459 static const char *cDBusDaemonAddressInfo = "DBusDaemonAddressInfo";
2460 #endif
2461
2462
2463 void
2464 _dbus_daemon_publish_session_bus_address (const char* address)
2465 {
2466   HANDLE lock;
2467   char *shared_addr = NULL;
2468   DWORD ret;
2469
2470   _dbus_assert (address);
2471   // before _dbus_global_lock to keep correct lock/release order
2472   hDBusDaemonMutex = CreateMutex( NULL, FALSE, cDBusDaemonMutex );
2473   ret = WaitForSingleObject( hDBusDaemonMutex, 1000 );
2474   if ( ret != WAIT_OBJECT_0 ) {
2475     _dbus_warn("Could not lock mutex %s (return code %d). daemon already running? Bus address not published.\n", cDBusDaemonMutex, ret );
2476     return;
2477   }
2478
2479   // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
2480   lock = _dbus_global_lock( cUniqueDBusInitMutex );
2481
2482   // create shm
2483   hDBusSharedMem = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
2484                                       0, strlen( address ) + 1, cDBusDaemonAddressInfo );
2485   _dbus_assert( hDBusSharedMem );
2486
2487   shared_addr = MapViewOfFile( hDBusSharedMem, FILE_MAP_WRITE, 0, 0, 0 );
2488
2489   _dbus_assert (shared_addr);
2490
2491   strcpy( shared_addr, address);
2492
2493   // cleanup
2494   UnmapViewOfFile( shared_addr );
2495
2496   _dbus_global_unlock( lock );
2497 }
2498
2499 void
2500 _dbus_daemon_unpublish_session_bus_address (void)
2501 {
2502   HANDLE lock;
2503
2504   // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
2505   lock = _dbus_global_lock( cUniqueDBusInitMutex );
2506
2507   CloseHandle( hDBusSharedMem );
2508
2509   hDBusSharedMem = NULL;
2510
2511   ReleaseMutex( hDBusDaemonMutex );
2512
2513   CloseHandle( hDBusDaemonMutex );
2514
2515   hDBusDaemonMutex = NULL;
2516
2517   _dbus_global_unlock( lock );
2518 }
2519
2520 static dbus_bool_t
2521 _dbus_get_autolaunch_shm (DBusString *address)
2522 {
2523   HANDLE sharedMem;
2524   char *shared_addr;
2525   int i;
2526
2527   // read shm
2528   for(i=0;i<20;++i) {
2529       // we know that dbus-daemon is available, so we wait until shm is available
2530       sharedMem = OpenFileMapping( FILE_MAP_READ, FALSE, cDBusDaemonAddressInfo );
2531       if( sharedMem == 0 )
2532           Sleep( 100 );
2533       if ( sharedMem != 0)
2534           break;
2535   }
2536
2537   if( sharedMem == 0 )
2538       return FALSE;
2539
2540   shared_addr = MapViewOfFile( sharedMem, FILE_MAP_READ, 0, 0, 0 );
2541
2542   if( !shared_addr )
2543       return FALSE;
2544
2545   _dbus_string_init( address );
2546
2547   _dbus_string_append( address, shared_addr );
2548
2549   // cleanup
2550   UnmapViewOfFile( shared_addr );
2551
2552   CloseHandle( sharedMem );
2553
2554   return TRUE;
2555 }
2556
2557 static dbus_bool_t
2558 _dbus_daemon_already_runs (DBusString *address)
2559 {
2560   HANDLE lock;
2561   HANDLE daemon;
2562   dbus_bool_t bRet = TRUE;
2563
2564   // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
2565   lock = _dbus_global_lock( cUniqueDBusInitMutex );
2566
2567   // do checks
2568   daemon = CreateMutex( NULL, FALSE, cDBusDaemonMutex );
2569   if(WaitForSingleObject( daemon, 10 ) != WAIT_TIMEOUT)
2570     {
2571       ReleaseMutex (daemon);
2572       CloseHandle (daemon);
2573
2574       _dbus_global_unlock( lock );
2575       return FALSE;
2576     }
2577
2578   // read shm
2579   bRet = _dbus_get_autolaunch_shm( address );
2580
2581   // cleanup
2582   CloseHandle ( daemon );
2583
2584   _dbus_global_unlock( lock );
2585
2586   return bRet;
2587 }
2588
2589 dbus_bool_t
2590 _dbus_get_autolaunch_address (DBusString *address, 
2591                               DBusError *error)
2592 {
2593   HANDLE mutex;
2594   STARTUPINFOA si;
2595   PROCESS_INFORMATION pi;
2596   dbus_bool_t retval = FALSE;
2597   LPSTR lpFile;
2598   char dbus_exe_path[MAX_PATH];
2599   char dbus_args[MAX_PATH * 2];
2600   const char * daemon_name = DBUS_DAEMON_NAME ".exe";
2601
2602   mutex = _dbus_global_lock ( cDBusAutolaunchMutex );
2603
2604   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2605
2606   if (_dbus_daemon_already_runs(address))
2607     {
2608         _dbus_verbose("found already running dbus daemon\n");
2609         retval = TRUE;
2610         goto out;
2611     }
2612
2613   if (!SearchPathA(NULL, daemon_name, NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile))
2614     {
2615       printf ("please add the path to %s to your PATH environment variable\n", daemon_name);
2616       printf ("or start the daemon manually\n\n");
2617       printf ("");
2618       goto out;
2619     }
2620
2621   // Create process
2622   ZeroMemory( &si, sizeof(si) );
2623   si.cb = sizeof(si);
2624   ZeroMemory( &pi, sizeof(pi) );
2625
2626   _snprintf(dbus_args, sizeof(dbus_args) - 1, "\"%s\" %s", dbus_exe_path,  " --session");
2627
2628 //  argv[i] = "--config-file=bus\\session.conf";
2629 //  printf("create process \"%s\" %s\n", dbus_exe_path, dbus_args);
2630   if(CreateProcessA(dbus_exe_path, dbus_args, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
2631     {
2632
2633       retval = _dbus_get_autolaunch_shm( address );
2634     }
2635   
2636   if (retval == FALSE)
2637     dbus_set_error_const (error, DBUS_ERROR_FAILED, "Failed to launch dbus-daemon");
2638
2639 out:
2640   if (retval)
2641     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2642   else
2643     _DBUS_ASSERT_ERROR_IS_SET (error);
2644   
2645   _dbus_global_unlock (mutex);
2646
2647   return retval;
2648  }
2649
2650
2651 /** Makes the file readable by every user in the system.
2652  *
2653  * @param filename the filename
2654  * @param error error location
2655  * @returns #TRUE if the file's permissions could be changed.
2656  */
2657 dbus_bool_t
2658 _dbus_make_file_world_readable(const DBusString *filename,
2659                                DBusError *error)
2660 {
2661   // TODO
2662   return TRUE;
2663 }
2664
2665
2666 #define DBUS_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
2667 #define DBUS_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
2668
2669 /**
2670  * Returns the standard directories for a session bus to look for service 
2671  * activation files 
2672  *
2673  * On Windows this should be data directories:
2674  *
2675  * %CommonProgramFiles%/dbus
2676  *
2677  * and
2678  *
2679  * DBUS_DATADIR
2680  *
2681  * @param dirs the directory list we are returning
2682  * @returns #FALSE on OOM 
2683  */
2684
2685 dbus_bool_t 
2686 _dbus_get_standard_session_servicedirs (DBusList **dirs)
2687 {
2688   const char *common_progs;
2689   DBusString servicedir_path;
2690
2691   if (!_dbus_string_init (&servicedir_path))
2692     return FALSE;
2693
2694   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR _DBUS_PATH_SEPARATOR))
2695         goto oom;
2696
2697   common_progs = _dbus_getenv ("CommonProgramFiles");
2698
2699   if (common_progs != NULL)
2700     {
2701       if (!_dbus_string_append (&servicedir_path, common_progs))
2702         goto oom;
2703
2704       if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR))
2705         goto oom;
2706     }
2707
2708   if (!_dbus_split_paths_and_append (&servicedir_path, 
2709                                DBUS_STANDARD_SESSION_SERVICEDIR, 
2710                                dirs))
2711     goto oom;
2712
2713   _dbus_string_free (&servicedir_path);  
2714   return TRUE;
2715
2716  oom:
2717   _dbus_string_free (&servicedir_path);
2718   return FALSE;
2719 }
2720
2721 /**
2722  * Returns the standard directories for a system bus to look for service
2723  * activation files
2724  *
2725  * On UNIX this should be the standard xdg freedesktop.org data directories:
2726  *
2727  * XDG_DATA_DIRS=${XDG_DATA_DIRS-/usr/local/share:/usr/share}
2728  *
2729  * and
2730  *
2731  * DBUS_DATADIR
2732  *
2733  * On Windows there is no system bus and this function can return nothing.
2734  *
2735  * @param dirs the directory list we are returning
2736  * @returns #FALSE on OOM
2737  */
2738
2739 dbus_bool_t
2740 _dbus_get_standard_system_servicedirs (DBusList **dirs)
2741 {
2742   *dirs = NULL;
2743   return TRUE;
2744 }
2745
2746 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
2747
2748 /**
2749  * Atomically increments an integer
2750  *
2751  * @param atomic pointer to the integer to increment
2752  * @returns the value before incrementing
2753  *
2754  */
2755 dbus_int32_t
2756 _dbus_atomic_inc (DBusAtomic *atomic)
2757 {
2758   // +/- 1 is needed here!
2759   // no volatile argument with mingw
2760   return InterlockedIncrement (&atomic->value) - 1;
2761 }
2762
2763 /**
2764  * Atomically decrement an integer
2765  *
2766  * @param atomic pointer to the integer to decrement
2767  * @returns the value before decrementing
2768  *
2769  */
2770 dbus_int32_t
2771 _dbus_atomic_dec (DBusAtomic *atomic)
2772 {
2773   // +/- 1 is needed here!
2774   // no volatile argument with mingw
2775   return InterlockedDecrement (&atomic->value) + 1;
2776 }
2777
2778 #endif /* asserts or tests enabled */
2779
2780 /**
2781  * Called when the bus daemon is signaled to reload its configuration; any
2782  * caches should be nuked. Of course any caches that need explicit reload
2783  * are probably broken, but c'est la vie.
2784  *
2785  * 
2786  */
2787 void
2788 _dbus_flush_caches (void)
2789 {
2790 }
2791
2792 /**
2793  * See if errno is EAGAIN or EWOULDBLOCK (this has to be done differently
2794  * for Winsock so is abstracted)
2795  *
2796  * @returns #TRUE if errno == EAGAIN or errno == EWOULDBLOCK
2797  */
2798 dbus_bool_t
2799 _dbus_get_is_errno_eagain_or_ewouldblock (void)
2800 {
2801   return errno == WSAEWOULDBLOCK;
2802 }
2803
2804 /**
2805  * return the absolute path of the dbus installation 
2806  *
2807  * @param s buffer for installation path
2808  * @param len length of buffer
2809  * @returns #FALSE on failure
2810  */
2811 static dbus_bool_t
2812 _dbus_get_install_root(char *prefix, int len)
2813 {
2814     //To find the prefix, we cut the filename and also \bin\ if present
2815     char* p = 0;
2816     int i;
2817     DWORD pathLength;
2818     char *lastSlash;
2819     SetLastError( 0 );
2820     pathLength = GetModuleFileName(_dbus_win_get_dll_hmodule(), prefix, len);
2821     if ( pathLength == 0 || GetLastError() != 0 ) {
2822         *prefix = '\0';
2823         return FALSE;
2824     }
2825     lastSlash = _mbsrchr(prefix, '\\');
2826     if (lastSlash == NULL) {
2827         *prefix = '\0';
2828         return FALSE;
2829     }
2830     //cut off binary name
2831     lastSlash[1] = 0;
2832
2833     //cut possible "\\bin"
2834
2835     //this fails if we are in a double-byte system codepage and the
2836     //folder's name happens to end with the *bytes*
2837     //"\\bin"... (I.e. the second byte of some Han character and then
2838     //the Latin "bin", but that is not likely I think...
2839     if (lastSlash - prefix >= 4 && strnicmp(lastSlash - 4, "\\bin", 4) == 0)
2840         lastSlash[-3] = 0;
2841     else if (lastSlash - prefix >= 10 && strnicmp(lastSlash - 10, "\\bin\\debug", 10) == 0)
2842         lastSlash[-9] = 0;
2843     else if (lastSlash - prefix >= 12 && strnicmp(lastSlash - 12, "\\bin\\release", 12) == 0)
2844         lastSlash[-11] = 0;
2845
2846     return TRUE;
2847 }
2848
2849 /** 
2850   find config file either from installation or build root according to 
2851   the following path layout 
2852     install-root/
2853       bin/dbus-daemon[d].exe
2854       etc/<config-file>.conf *or* etc/dbus-1/<config-file>.conf
2855       (the former above is what dbus4win uses, the latter above is
2856       what a "normal" Unix-style "make install" uses)
2857
2858     build-root/
2859       bin/dbus-daemon[d].exe
2860       bus/<config-file>.conf 
2861 */
2862 dbus_bool_t 
2863 _dbus_get_config_file_name(DBusString *config_file, char *s)
2864 {
2865   char path[MAX_PATH*2];
2866   int path_size = sizeof(path);
2867
2868   if (!_dbus_get_install_root(path,path_size))
2869     return FALSE;
2870
2871   if(strlen(s) + 4 + strlen(path) > sizeof(path)-2)
2872     return FALSE;
2873   strcat(path,"etc\\");
2874   strcat(path,s);
2875   if (_dbus_file_exists(path)) 
2876     {
2877       // find path from executable 
2878       if (!_dbus_string_append (config_file, path))
2879         return FALSE;
2880     }
2881   else 
2882     {
2883       if (!_dbus_get_install_root(path,path_size))
2884         return FALSE;
2885       if(strlen(s) + 11 + strlen(path) > sizeof(path)-2)
2886         return FALSE;
2887       strcat(path,"etc\\dbus-1\\");
2888       strcat(path,s);
2889   
2890       if (_dbus_file_exists(path)) 
2891         {
2892           if (!_dbus_string_append (config_file, path))
2893             return FALSE;
2894         }
2895       else
2896         {
2897           if (!_dbus_get_install_root(path,path_size))
2898             return FALSE;
2899           if(strlen(s) + 4 + strlen(path) > sizeof(path)-2)
2900             return FALSE;
2901           strcat(path,"bus\\");
2902           strcat(path,s);
2903           
2904           if (_dbus_file_exists(path)) 
2905             {
2906               if (!_dbus_string_append (config_file, path))
2907                 return FALSE;
2908             }
2909         }
2910     }
2911   return TRUE;
2912 }    
2913
2914 /**
2915  * Append the absolute path of the system.conf file
2916  * (there is no system bus on Windows so this can just
2917  * return FALSE and print a warning or something)
2918  * 
2919  * @param str the string to append to
2920  * @returns #FALSE if no memory
2921  */
2922 dbus_bool_t
2923 _dbus_append_system_config_file (DBusString *str)
2924 {
2925   return _dbus_get_config_file_name(str, "system.conf");
2926 }
2927
2928 /**
2929  * Append the absolute path of the session.conf file.
2930  * 
2931  * @param str the string to append to
2932  * @returns #FALSE if no memory
2933  */
2934 dbus_bool_t
2935 _dbus_append_session_config_file (DBusString *str)
2936 {
2937   return _dbus_get_config_file_name(str, "session.conf");
2938 }
2939
2940 /* See comment in dbus-sysdeps-unix.c */
2941 dbus_bool_t
2942 _dbus_lookup_session_address (dbus_bool_t *supported,
2943                               DBusString  *address,
2944                               DBusError   *error)
2945 {
2946   /* Probably fill this in with something based on COM? */
2947   *supported = FALSE;
2948   return TRUE;
2949 }
2950
2951 /**
2952  * Appends the directory in which a keyring for the given credentials
2953  * should be stored.  The credentials should have either a Windows or
2954  * UNIX user in them.  The directory should be an absolute path.
2955  *
2956  * On UNIX the directory is ~/.dbus-keyrings while on Windows it should probably
2957  * be something else, since the dotfile convention is not normal on Windows.
2958  * 
2959  * @param directory string to append directory to
2960  * @param credentials credentials the directory should be for
2961  *  
2962  * @returns #FALSE on no memory
2963  */
2964 dbus_bool_t
2965 _dbus_append_keyring_directory_for_credentials (DBusString      *directory,
2966                                                 DBusCredentials *credentials)
2967 {
2968   DBusString homedir;
2969   DBusString dotdir;
2970   dbus_uid_t uid;
2971   const char *homepath;
2972
2973   _dbus_assert (credentials != NULL);
2974   _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
2975   
2976   if (!_dbus_string_init (&homedir))
2977     return FALSE;
2978
2979   homepath = _dbus_getenv("HOMEPATH");
2980   if (homepath != NULL && *homepath != '\0')
2981     {
2982       _dbus_string_append(&homedir,homepath);
2983     }
2984   
2985 #ifdef DBUS_BUILD_TESTS
2986   {
2987     const char *override;
2988     
2989     override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
2990     if (override != NULL && *override != '\0')
2991       {
2992         _dbus_string_set_length (&homedir, 0);
2993         if (!_dbus_string_append (&homedir, override))
2994           goto failed;
2995
2996         _dbus_verbose ("Using fake homedir for testing: %s\n",
2997                        _dbus_string_get_const_data (&homedir));
2998       }
2999     else
3000       {
3001         static dbus_bool_t already_warned = FALSE;
3002         if (!already_warned)
3003           {
3004             _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
3005             already_warned = TRUE;
3006           }
3007       }
3008   }
3009 #endif
3010
3011   _dbus_string_init_const (&dotdir, ".dbus-keyrings");
3012   if (!_dbus_concat_dir_and_file (&homedir,
3013                                   &dotdir))
3014     goto failed;
3015   
3016   if (!_dbus_string_copy (&homedir, 0,
3017                           directory, _dbus_string_get_length (directory))) {
3018     goto failed;
3019   }
3020
3021   _dbus_string_free (&homedir);
3022   return TRUE;
3023   
3024  failed: 
3025   _dbus_string_free (&homedir);
3026   return FALSE;
3027 }
3028
3029 /** Checks if a file exists
3030 *
3031 * @param file full path to the file
3032 * @returns #TRUE if file exists
3033 */
3034 dbus_bool_t 
3035 _dbus_file_exists (const char *file)
3036 {
3037   DWORD attributes = GetFileAttributes (file);
3038
3039   if (attributes != INVALID_FILE_ATTRIBUTES && GetLastError() != ERROR_PATH_NOT_FOUND)
3040     return TRUE;
3041   else
3042     return FALSE;  
3043 }
3044
3045 /**
3046  * A wrapper around strerror() because some platforms
3047  * may be lame and not have strerror().
3048  *
3049  * @param error_number errno.
3050  * @returns error description.
3051  */
3052 const char*
3053 _dbus_strerror (int error_number)
3054 {
3055 #ifdef DBUS_WINCE
3056   // TODO
3057   return "unknown";
3058 #else
3059   const char *msg;
3060
3061   switch (error_number)
3062     {
3063     case WSAEINTR:
3064       return "Interrupted function call";
3065     case WSAEACCES:
3066       return "Permission denied";
3067     case WSAEFAULT:
3068       return "Bad address";
3069     case WSAEINVAL:
3070       return "Invalid argument";
3071     case WSAEMFILE:
3072       return "Too many open files";
3073     case WSAEWOULDBLOCK:
3074       return "Resource temporarily unavailable";
3075     case WSAEINPROGRESS:
3076       return "Operation now in progress";
3077     case WSAEALREADY:
3078       return "Operation already in progress";
3079     case WSAENOTSOCK:
3080       return "Socket operation on nonsocket";
3081     case WSAEDESTADDRREQ:
3082       return "Destination address required";
3083     case WSAEMSGSIZE:
3084       return "Message too long";
3085     case WSAEPROTOTYPE:
3086       return "Protocol wrong type for socket";
3087     case WSAENOPROTOOPT:
3088       return "Bad protocol option";
3089     case WSAEPROTONOSUPPORT:
3090       return "Protocol not supported";
3091     case WSAESOCKTNOSUPPORT:
3092       return "Socket type not supported";
3093     case WSAEOPNOTSUPP:
3094       return "Operation not supported";
3095     case WSAEPFNOSUPPORT:
3096       return "Protocol family not supported";
3097     case WSAEAFNOSUPPORT:
3098       return "Address family not supported by protocol family";
3099     case WSAEADDRINUSE:
3100       return "Address already in use";
3101     case WSAEADDRNOTAVAIL:
3102       return "Cannot assign requested address";
3103     case WSAENETDOWN:
3104       return "Network is down";
3105     case WSAENETUNREACH:
3106       return "Network is unreachable";
3107     case WSAENETRESET:
3108       return "Network dropped connection on reset";
3109     case WSAECONNABORTED:
3110       return "Software caused connection abort";
3111     case WSAECONNRESET:
3112       return "Connection reset by peer";
3113     case WSAENOBUFS:
3114       return "No buffer space available";
3115     case WSAEISCONN:
3116       return "Socket is already connected";
3117     case WSAENOTCONN:
3118       return "Socket is not connected";
3119     case WSAESHUTDOWN:
3120       return "Cannot send after socket shutdown";
3121     case WSAETIMEDOUT:
3122       return "Connection timed out";
3123     case WSAECONNREFUSED:
3124       return "Connection refused";
3125     case WSAEHOSTDOWN:
3126       return "Host is down";
3127     case WSAEHOSTUNREACH:
3128       return "No route to host";
3129     case WSAEPROCLIM:
3130       return "Too many processes";
3131     case WSAEDISCON:
3132       return "Graceful shutdown in progress";
3133     case WSATYPE_NOT_FOUND:
3134       return "Class type not found";
3135     case WSAHOST_NOT_FOUND:
3136       return "Host not found";
3137     case WSATRY_AGAIN:
3138       return "Nonauthoritative host not found";
3139     case WSANO_RECOVERY:
3140       return "This is a nonrecoverable error";
3141     case WSANO_DATA:
3142       return "Valid name, no data record of requested type";
3143     case WSA_INVALID_HANDLE:
3144       return "Specified event object handle is invalid";
3145     case WSA_INVALID_PARAMETER:
3146       return "One or more parameters are invalid";
3147     case WSA_IO_INCOMPLETE:
3148       return "Overlapped I/O event object not in signaled state";
3149     case WSA_IO_PENDING:
3150       return "Overlapped operations will complete later";
3151     case WSA_NOT_ENOUGH_MEMORY:
3152       return "Insufficient memory available";
3153     case WSA_OPERATION_ABORTED:
3154       return "Overlapped operation aborted";
3155 #ifdef WSAINVALIDPROCTABLE
3156
3157     case WSAINVALIDPROCTABLE:
3158       return "Invalid procedure table from service provider";
3159 #endif
3160 #ifdef WSAINVALIDPROVIDER
3161
3162     case WSAINVALIDPROVIDER:
3163       return "Invalid service provider version number";
3164 #endif
3165 #ifdef WSAPROVIDERFAILEDINIT
3166
3167     case WSAPROVIDERFAILEDINIT:
3168       return "Unable to initialize a service provider";
3169 #endif
3170
3171     case WSASYSCALLFAILURE:
3172       return "System call failure";
3173     }
3174   msg = strerror (error_number);
3175   if (msg == NULL)
3176     msg = "unknown";
3177
3178   return msg;
3179 #endif //DBUS_WINCE
3180 }
3181
3182 /**
3183  * Assigns an error name and message corresponding to a Win32 error
3184  * code to a DBusError. Does nothing if error is #NULL.
3185  *
3186  * @param error the error.
3187  * @param code the Win32 error code
3188  */
3189 void
3190 _dbus_win_set_error_from_win_error (DBusError *error,
3191                                     int        code)
3192 {
3193   char *msg;
3194
3195   /* As we want the English message, use the A API */
3196   FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
3197                   FORMAT_MESSAGE_IGNORE_INSERTS |
3198                   FORMAT_MESSAGE_FROM_SYSTEM,
3199                   NULL, code, MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US),
3200                   (LPTSTR) &msg, 0, NULL);
3201   if (msg)
3202     {
3203       char *msg_copy;
3204
3205       msg_copy = dbus_malloc (strlen (msg));
3206       strcpy (msg_copy, msg);
3207       LocalFree (msg);
3208
3209       dbus_set_error (error, "win32.error", "%s", msg_copy);
3210     }
3211   else
3212     dbus_set_error (error, "win32.error", "Unknown error code %d or FormatMessage failed", code);
3213 }
3214
3215 void
3216 _dbus_win_warn_win_error (const char *message,
3217                           int         code)
3218 {
3219   DBusError error;
3220
3221   dbus_error_init (&error);
3222   _dbus_win_set_error_from_win_error (&error, code);
3223   _dbus_warn ("%s: %s\n", message, error.message);
3224   dbus_error_free (&error);
3225 }
3226
3227 /**
3228  * Removes a directory; Directory must be empty
3229  *
3230  * @param filename directory filename
3231  * @param error initialized error object
3232  * @returns #TRUE on success
3233  */
3234 dbus_bool_t
3235 _dbus_delete_directory (const DBusString *filename,
3236                         DBusError        *error)
3237 {
3238   const char *filename_c;
3239
3240   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3241
3242   filename_c = _dbus_string_get_const_data (filename);
3243
3244   if (_rmdir (filename_c) != 0)
3245     {
3246       dbus_set_error (error, DBUS_ERROR_FAILED,
3247                       "Failed to remove directory %s: %s\n",
3248                       filename_c, strerror (errno));
3249       return FALSE;
3250     }
3251
3252   return TRUE;
3253 }
3254
3255 /** @} end of sysdeps-win */
3256 /* tests in dbus-sysdeps-util.c */
3257