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