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