D-Bus  1.7.6
dbus-sysdeps-win.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-sysdeps.c Wrappers around system/libc features (internal to D-BUS implementation)
3  *
4  * Copyright (C) 2002, 2003 Red Hat, Inc.
5  * Copyright (C) 2003 CodeFactory AB
6  * Copyright (C) 2005 Novell, Inc.
7  * Copyright (C) 2006 Peter Kümmel <syntheticpp@gmx.net>
8  * Copyright (C) 2006 Christian Ehrlicher <ch.ehrlicher@gmx.de>
9  * Copyright (C) 2006-2013 Ralf Habacker <ralf.habacker@freenet.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-sha.h"
41 #include "dbus-sysdeps.h"
42 #include "dbus-threads.h"
43 #include "dbus-protocol.h"
44 #include "dbus-string.h"
45 #include "dbus-sysdeps.h"
46 #include "dbus-sysdeps-win.h"
47 #include "dbus-protocol.h"
48 #include "dbus-hash.h"
49 #include "dbus-sockets-win.h"
50 #include "dbus-list.h"
51 #include "dbus-nonce.h"
52 #include "dbus-credentials.h"
53 
54 #include <windows.h>
55 #include <ws2tcpip.h>
56 #include <wincrypt.h>
57 #include <iphlpapi.h>
58 
59 /* Declarations missing in mingw's and windows sdk 7.0 headers */
60 extern BOOL WINAPI ConvertStringSidToSidA (LPCSTR StringSid, PSID *Sid);
61 extern BOOL WINAPI ConvertSidToStringSidA (PSID Sid, LPSTR *StringSid);
62 
63 #include <stdio.h>
64 
65 #include <string.h>
66 #if HAVE_ERRNO_H
67 #include <errno.h>
68 #endif
69 #ifndef DBUS_WINCE
70 #include <mbstring.h>
71 #include <sys/stat.h>
72 #include <sys/types.h>
73 #endif
74 
75 #ifdef HAVE_WS2TCPIP_H
76 /* getaddrinfo for Windows CE (and Windows). */
77 #include <ws2tcpip.h>
78 #endif
79 
80 #ifndef O_BINARY
81 #define O_BINARY 0
82 #endif
83 
84 typedef int socklen_t;
85 
86 
87 void
88 _dbus_win_set_errno (int err)
89 {
90 #ifdef DBUS_WINCE
91  SetLastError (err);
92 #else
93  errno = err;
94 #endif
95 }
96 
97 static BOOL is_winxp_sp3_or_lower();
98 
99 /*
100  * _MIB_TCPROW_EX and friends are not available in system headers
101  * and are mapped to attribute identical ...OWNER_PID typedefs.
102  */
103 typedef MIB_TCPROW_OWNER_PID _MIB_TCPROW_EX;
104 typedef MIB_TCPTABLE_OWNER_PID MIB_TCPTABLE_EX;
105 typedef PMIB_TCPTABLE_OWNER_PID PMIB_TCPTABLE_EX;
106 typedef DWORD (WINAPI *ProcAllocateAndGetTcpExtTableFromStack)(PMIB_TCPTABLE_EX*,BOOL,HANDLE,DWORD,DWORD);
107 static ProcAllocateAndGetTcpExtTableFromStack lpfnAllocateAndGetTcpExTableFromStack = NULL;
108 
114 static BOOL
115 load_ex_ip_helper_procedures(void)
116 {
117  HMODULE hModule = LoadLibrary ("iphlpapi.dll");
118  if (hModule == NULL)
119  {
120  _dbus_verbose ("could not load iphlpapi.dll\n");
121  return FALSE;
122  }
123 
124  lpfnAllocateAndGetTcpExTableFromStack = (ProcAllocateAndGetTcpExtTableFromStack)GetProcAddress (hModule, "AllocateAndGetTcpExTableFromStack");
125  if (lpfnAllocateAndGetTcpExTableFromStack == NULL)
126  {
127  _dbus_verbose ("could not find function AllocateAndGetTcpExTableFromStack in iphlpapi.dll\n");
128  return FALSE;
129  }
130  return TRUE;
131 }
132 
139 static dbus_pid_t
140 get_pid_from_extended_tcp_table(int peer_port)
141 {
142  dbus_pid_t result;
143  DWORD errorCode, size, i;
144  MIB_TCPTABLE_OWNER_PID *tcp_table;
145 
146  if ((errorCode =
147  GetExtendedTcpTable (NULL, &size, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0)) == ERROR_INSUFFICIENT_BUFFER)
148  {
149  tcp_table = (MIB_TCPTABLE_OWNER_PID *) dbus_malloc (size);
150  if (tcp_table == NULL)
151  {
152  _dbus_verbose ("Error allocating memory\n");
153  return 0;
154  }
155  }
156  else
157  {
158  _dbus_win_warn_win_error ("unexpected error returned from GetExtendedTcpTable", errorCode);
159  return 0;
160  }
161 
162  if ((errorCode = GetExtendedTcpTable (tcp_table, &size, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0)) != NO_ERROR)
163  {
164  _dbus_verbose ("Error fetching tcp table %d\n", (int)errorCode);
165  dbus_free (tcp_table);
166  return 0;
167  }
168 
169  result = 0;
170  for (i = 0; i < tcp_table->dwNumEntries; i++)
171  {
172  MIB_TCPROW_OWNER_PID *p = &tcp_table->table[i];
173  int local_address = ntohl (p->dwLocalAddr);
174  int local_port = ntohs (p->dwLocalPort);
175  if (p->dwState == MIB_TCP_STATE_ESTAB
176  && local_address == INADDR_LOOPBACK && local_port == peer_port)
177  result = p->dwOwningPid;
178  }
179 
180  dbus_free (tcp_table);
181  _dbus_verbose ("got pid %lu\n", result);
182  return result;
183 }
184 
192 static dbus_pid_t
193 get_pid_from_tcp_ex_table(int peer_port)
194 {
195  dbus_pid_t result;
196  DWORD errorCode, i;
197  PMIB_TCPTABLE_EX tcp_table = NULL;
198 
199  if (!load_ex_ip_helper_procedures ())
200  {
201  _dbus_verbose
202  ("Error not been able to load iphelper procedures\n");
203  return 0;
204  }
205 
206  errorCode = lpfnAllocateAndGetTcpExTableFromStack (&tcp_table, TRUE, GetProcessHeap(), 0, 2);
207 
208  if (errorCode != NO_ERROR)
209  {
210  _dbus_verbose
211  ("Error not been able to call AllocateAndGetTcpExTableFromStack()\n");
212  return 0;
213  }
214 
215  result = 0;
216  for (i = 0; i < tcp_table->dwNumEntries; i++)
217  {
218  _MIB_TCPROW_EX *p = &tcp_table->table[i];
219  int local_port = ntohs (p->dwLocalPort);
220  int local_address = ntohl (p->dwLocalAddr);
221  if (local_address == INADDR_LOOPBACK && local_port == peer_port)
222  {
223  result = p->dwOwningPid;
224  break;
225  }
226  }
227 
228  HeapFree (GetProcessHeap(), 0, tcp_table);
229  _dbus_verbose ("got pid %lu\n", result);
230  return result;
231 }
232 
238 static dbus_pid_t
239 _dbus_get_peer_pid_from_tcp_handle (int handle)
240 {
241  struct sockaddr_storage addr;
242  socklen_t len = sizeof (addr);
243  int peer_port;
244 
245  dbus_pid_t result;
246  dbus_bool_t is_localhost = FALSE;
247 
248  getpeername (handle, (struct sockaddr *) &addr, &len);
249 
250  if (addr.ss_family == AF_INET)
251  {
252  struct sockaddr_in *s = (struct sockaddr_in *) &addr;
253  peer_port = ntohs (s->sin_port);
254  is_localhost = (ntohl (s->sin_addr.s_addr) == INADDR_LOOPBACK);
255  }
256  else if (addr.ss_family == AF_INET6)
257  {
258  _dbus_verbose ("FIXME [61922]: IPV6 support not working on windows\n");
259  return 0;
260  /*
261  struct sockaddr_in6 *s = (struct sockaddr_in6 * )&addr;
262  peer_port = ntohs (s->sin6_port);
263  is_localhost = (memcmp(s->sin6_addr.s6_addr, in6addr_loopback.s6_addr, 16) == 0);
264  _dbus_verbose ("IPV6 %08x %08x\n", s->sin6_addr.s6_addr, in6addr_loopback.s6_addr);
265  */
266  }
267  else
268  {
269  _dbus_verbose ("no idea what address family %d is\n", addr.ss_family);
270  return 0;
271  }
272 
273  if (!is_localhost)
274  {
275  _dbus_verbose ("could not fetch process id from remote process\n");
276  return 0;
277  }
278 
279  if (peer_port == 0)
280  {
281  _dbus_verbose
282  ("Error not been able to fetch tcp peer port from connection\n");
283  return 0;
284  }
285 
286  _dbus_verbose ("trying to get peers pid");
287 
288  result = get_pid_from_extended_tcp_table (peer_port);
289  if (result > 0)
290  return result;
291  result = get_pid_from_tcp_ex_table (peer_port);
292  return result;
293 }
294 
295 /* Convert GetLastError() to a dbus error. */
296 const char*
297 _dbus_win_error_from_last_error (void)
298 {
299  switch (GetLastError())
300  {
301  case 0:
302  return DBUS_ERROR_FAILED;
303 
304  case ERROR_NO_MORE_FILES:
305  case ERROR_TOO_MANY_OPEN_FILES:
306  return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
307 
308  case ERROR_ACCESS_DENIED:
309  case ERROR_CANNOT_MAKE:
311 
312  case ERROR_NOT_ENOUGH_MEMORY:
313  return DBUS_ERROR_NO_MEMORY;
314 
315  case ERROR_FILE_EXISTS:
316  return DBUS_ERROR_FILE_EXISTS;
317 
318  case ERROR_FILE_NOT_FOUND:
319  case ERROR_PATH_NOT_FOUND:
321  }
322 
323  return DBUS_ERROR_FAILED;
324 }
325 
326 
327 char*
328 _dbus_win_error_string (int error_number)
329 {
330  char *msg;
331 
332  FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
333  FORMAT_MESSAGE_IGNORE_INSERTS |
334  FORMAT_MESSAGE_FROM_SYSTEM,
335  NULL, error_number, 0,
336  (LPSTR) &msg, 0, NULL);
337 
338  if (msg[strlen (msg) - 1] == '\n')
339  msg[strlen (msg) - 1] = '\0';
340  if (msg[strlen (msg) - 1] == '\r')
341  msg[strlen (msg) - 1] = '\0';
342 
343  return msg;
344 }
345 
346 void
347 _dbus_win_free_error_string (char *string)
348 {
349  LocalFree (string);
350 }
351 
372 int
374  DBusString *buffer,
375  int count)
376 {
377  int bytes_read;
378  int start;
379  char *data;
380 
381  _dbus_assert (count >= 0);
382 
383  start = _dbus_string_get_length (buffer);
384 
385  if (!_dbus_string_lengthen (buffer, count))
386  {
387  _dbus_win_set_errno (ENOMEM);
388  return -1;
389  }
390 
391  data = _dbus_string_get_data_len (buffer, start, count);
392 
393  again:
394 
395  _dbus_verbose ("recv: count=%d fd=%d\n", count, fd);
396  bytes_read = recv (fd, data, count, 0);
397 
398  if (bytes_read == SOCKET_ERROR)
399  {
400  DBUS_SOCKET_SET_ERRNO();
401  _dbus_verbose ("recv: failed: %s (%d)\n", _dbus_strerror (errno), errno);
402  bytes_read = -1;
403  }
404  else
405  _dbus_verbose ("recv: = %d\n", bytes_read);
406 
407  if (bytes_read < 0)
408  {
409  if (errno == EINTR)
410  goto again;
411  else
412  {
413  /* put length back (note that this doesn't actually realloc anything) */
414  _dbus_string_set_length (buffer, start);
415  return -1;
416  }
417  }
418  else
419  {
420  /* put length back (doesn't actually realloc) */
421  _dbus_string_set_length (buffer, start + bytes_read);
422 
423 #if 0
424  if (bytes_read > 0)
425  _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
426 #endif
427 
428  return bytes_read;
429  }
430 }
431 
442 int
444  const DBusString *buffer,
445  int start,
446  int len)
447 {
448  const char *data;
449  int bytes_written;
450 
451  data = _dbus_string_get_const_data_len (buffer, start, len);
452 
453  again:
454 
455  _dbus_verbose ("send: len=%d fd=%d\n", len, fd);
456  bytes_written = send (fd, data, len, 0);
457 
458  if (bytes_written == SOCKET_ERROR)
459  {
460  DBUS_SOCKET_SET_ERRNO();
461  _dbus_verbose ("send: failed: %s\n", _dbus_strerror_from_errno ());
462  bytes_written = -1;
463  }
464  else
465  _dbus_verbose ("send: = %d\n", bytes_written);
466 
467  if (bytes_written < 0 && errno == EINTR)
468  goto again;
469 
470 #if 0
471  if (bytes_written > 0)
472  _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
473 #endif
474 
475  return bytes_written;
476 }
477 
478 
488  DBusError *error)
489 {
490  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
491 
492  again:
493  if (closesocket (fd) == SOCKET_ERROR)
494  {
495  DBUS_SOCKET_SET_ERRNO ();
496 
497  if (errno == EINTR)
498  goto again;
499 
500  dbus_set_error (error, _dbus_error_from_errno (errno),
501  "Could not close socket: socket=%d, , %s",
503  return FALSE;
504  }
505  _dbus_verbose ("_dbus_close_socket: socket=%d, \n", fd);
506 
507  return TRUE;
508 }
509 
517 void
518 _dbus_fd_set_close_on_exec (intptr_t handle)
519 {
520  if ( !SetHandleInformation( (HANDLE) handle,
521  HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE,
522  0 /*disable both flags*/ ) )
523  {
524  _dbus_win_warn_win_error ("Disabling socket handle inheritance failed:", GetLastError());
525  }
526 }
527 
536 _dbus_set_fd_nonblocking (int handle,
537  DBusError *error)
538 {
539  u_long one = 1;
540 
541  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
542 
543  if (ioctlsocket (handle, FIONBIO, &one) == SOCKET_ERROR)
544  {
545  DBUS_SOCKET_SET_ERRNO ();
546  dbus_set_error (error, _dbus_error_from_errno (errno),
547  "Failed to set socket %d:%d to nonblocking: %s", handle,
549  return FALSE;
550  }
551 
552  return TRUE;
553 }
554 
555 
576 int
578  const DBusString *buffer1,
579  int start1,
580  int len1,
581  const DBusString *buffer2,
582  int start2,
583  int len2)
584 {
585  WSABUF vectors[2];
586  const char *data1;
587  const char *data2;
588  int rc;
589  DWORD bytes_written;
590 
591  _dbus_assert (buffer1 != NULL);
592  _dbus_assert (start1 >= 0);
593  _dbus_assert (start2 >= 0);
594  _dbus_assert (len1 >= 0);
595  _dbus_assert (len2 >= 0);
596 
597 
598  data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
599 
600  if (buffer2 != NULL)
601  data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
602  else
603  {
604  data2 = NULL;
605  start2 = 0;
606  len2 = 0;
607  }
608 
609  vectors[0].buf = (char*) data1;
610  vectors[0].len = len1;
611  vectors[1].buf = (char*) data2;
612  vectors[1].len = len2;
613 
614  again:
615 
616  _dbus_verbose ("WSASend: len1+2=%d+%d fd=%d\n", len1, len2, fd);
617  rc = WSASend (fd,
618  vectors,
619  data2 ? 2 : 1,
620  &bytes_written,
621  0,
622  NULL,
623  NULL);
624 
625  if (rc == SOCKET_ERROR)
626  {
627  DBUS_SOCKET_SET_ERRNO ();
628  _dbus_verbose ("WSASend: failed: %s\n", _dbus_strerror_from_errno ());
629  bytes_written = -1;
630  }
631  else
632  _dbus_verbose ("WSASend: = %ld\n", bytes_written);
633 
634  if (bytes_written < 0 && errno == EINTR)
635  goto again;
636 
637  return bytes_written;
638 }
639 
641 _dbus_socket_is_invalid (int fd)
642 {
643  return fd == INVALID_SOCKET ? TRUE : FALSE;
644 }
645 
646 #if 0
647 
656 int
657 _dbus_connect_named_pipe (const char *path,
658  DBusError *error)
659 {
660  _dbus_assert_not_reached ("not implemented");
661 }
662 
663 #endif
664 
669 _dbus_win_startup_winsock (void)
670 {
671  /* Straight from MSDN, deuglified */
672 
673  /* Protected by _DBUS_LOCK_sysdeps */
674  static dbus_bool_t beenhere = FALSE;
675 
676  WORD wVersionRequested;
677  WSADATA wsaData;
678  int err;
679 
680  if (!_DBUS_LOCK (sysdeps))
681  return FALSE;
682 
683  if (beenhere)
684  goto out;
685 
686  wVersionRequested = MAKEWORD (2, 0);
687 
688  err = WSAStartup (wVersionRequested, &wsaData);
689  if (err != 0)
690  {
691  _dbus_assert_not_reached ("Could not initialize WinSock");
692  _dbus_abort ();
693  }
694 
695  /* Confirm that the WinSock DLL supports 2.0. Note that if the DLL
696  * supports versions greater than 2.0 in addition to 2.0, it will
697  * still return 2.0 in wVersion since that is the version we
698  * requested.
699  */
700  if (LOBYTE (wsaData.wVersion) != 2 ||
701  HIBYTE (wsaData.wVersion) != 0)
702  {
703  _dbus_assert_not_reached ("No usable WinSock found");
704  _dbus_abort ();
705  }
706 
707  beenhere = TRUE;
708 
709 out:
710  _DBUS_UNLOCK (sysdeps);
711  return TRUE;
712 }
713 
714 
715 
716 
717 
718 
719 
720 
721 
722 /************************************************************************
723 
724  UTF / string code
725 
726  ************************************************************************/
727 
731 int _dbus_printf_string_upper_bound (const char *format,
732  va_list args)
733 {
734  /* MSVCRT's vsnprintf semantics are a bit different */
735  char buf[1024];
736  int bufsize;
737  int len;
738  va_list args_copy;
739 
740  bufsize = sizeof (buf);
741  DBUS_VA_COPY (args_copy, args);
742  len = _vsnprintf (buf, bufsize - 1, format, args_copy);
743  va_end (args_copy);
744 
745  while (len == -1) /* try again */
746  {
747  char *p;
748 
749  bufsize *= 2;
750 
751  p = malloc (bufsize);
752 
753  if (p == NULL)
754  return -1;
755 
756  DBUS_VA_COPY (args_copy, args);
757  len = _vsnprintf (p, bufsize - 1, format, args_copy);
758  va_end (args_copy);
759  free (p);
760  }
761 
762  return len;
763 }
764 
765 
773 wchar_t *
774 _dbus_win_utf8_to_utf16 (const char *str,
775  DBusError *error)
776 {
777  DBusString s;
778  int n;
779  wchar_t *retval;
780 
781  _dbus_string_init_const (&s, str);
782 
783  if (!_dbus_string_validate_utf8 (&s, 0, _dbus_string_get_length (&s)))
784  {
785  dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid UTF-8");
786  return NULL;
787  }
788 
789  n = MultiByteToWideChar (CP_UTF8, 0, str, -1, NULL, 0);
790 
791  if (n == 0)
792  {
793  _dbus_win_set_error_from_win_error (error, GetLastError ());
794  return NULL;
795  }
796 
797  retval = dbus_new (wchar_t, n);
798 
799  if (!retval)
800  {
801  _DBUS_SET_OOM (error);
802  return NULL;
803  }
804 
805  if (MultiByteToWideChar (CP_UTF8, 0, str, -1, retval, n) != n)
806  {
807  dbus_free (retval);
808  dbus_set_error_const (error, DBUS_ERROR_FAILED, "MultiByteToWideChar inconsistency");
809  return NULL;
810  }
811 
812  return retval;
813 }
814 
822 char *
823 _dbus_win_utf16_to_utf8 (const wchar_t *str,
824  DBusError *error)
825 {
826  int n;
827  char *retval;
828 
829  n = WideCharToMultiByte (CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
830 
831  if (n == 0)
832  {
833  _dbus_win_set_error_from_win_error (error, GetLastError ());
834  return NULL;
835  }
836 
837  retval = dbus_malloc (n);
838 
839  if (!retval)
840  {
841  _DBUS_SET_OOM (error);
842  return NULL;
843  }
844 
845  if (WideCharToMultiByte (CP_UTF8, 0, str, -1, retval, n, NULL, NULL) != n)
846  {
847  dbus_free (retval);
848  dbus_set_error_const (error, DBUS_ERROR_FAILED, "WideCharToMultiByte inconsistency");
849  return NULL;
850  }
851 
852  return retval;
853 }
854 
855 
856 
857 
858 
859 
860 /************************************************************************
861 
862 
863  ************************************************************************/
864 
866 _dbus_win_account_to_sid (const wchar_t *waccount,
867  void **ppsid,
868  DBusError *error)
869 {
870  dbus_bool_t retval = FALSE;
871  DWORD sid_length, wdomain_length;
872  SID_NAME_USE use;
873  wchar_t *wdomain;
874 
875  *ppsid = NULL;
876 
877  sid_length = 0;
878  wdomain_length = 0;
879  if (!LookupAccountNameW (NULL, waccount, NULL, &sid_length,
880  NULL, &wdomain_length, &use) &&
881  GetLastError () != ERROR_INSUFFICIENT_BUFFER)
882  {
883  _dbus_win_set_error_from_win_error (error, GetLastError ());
884  return FALSE;
885  }
886 
887  *ppsid = dbus_malloc (sid_length);
888  if (!*ppsid)
889  {
890  _DBUS_SET_OOM (error);
891  return FALSE;
892  }
893 
894  wdomain = dbus_new (wchar_t, wdomain_length);
895  if (!wdomain)
896  {
897  _DBUS_SET_OOM (error);
898  goto out1;
899  }
900 
901  if (!LookupAccountNameW (NULL, waccount, (PSID) *ppsid, &sid_length,
902  wdomain, &wdomain_length, &use))
903  {
904  _dbus_win_set_error_from_win_error (error, GetLastError ());
905  goto out2;
906  }
907 
908  if (!IsValidSid ((PSID) *ppsid))
909  {
910  dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid SID");
911  goto out2;
912  }
913 
914  retval = TRUE;
915 
916 out2:
917  dbus_free (wdomain);
918 out1:
919  if (!retval)
920  {
921  dbus_free (*ppsid);
922  *ppsid = NULL;
923  }
924 
925  return retval;
926 }
927 
937 unsigned long
939 {
940  return _dbus_getpid ();
941 }
942 
943 #ifndef DBUS_WINCE
944 
945 static BOOL is_winxp_sp3_or_lower()
946 {
947  OSVERSIONINFOEX osvi;
948  DWORDLONG dwlConditionMask = 0;
949  int op=VER_LESS_EQUAL;
950 
951  // Initialize the OSVERSIONINFOEX structure.
952 
953  ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
954  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
955  osvi.dwMajorVersion = 5;
956  osvi.dwMinorVersion = 1;
957  osvi.wServicePackMajor = 3;
958  osvi.wServicePackMinor = 0;
959 
960  // Initialize the condition mask.
961 
962  VER_SET_CONDITION( dwlConditionMask, VER_MAJORVERSION, op );
963  VER_SET_CONDITION( dwlConditionMask, VER_MINORVERSION, op );
964  VER_SET_CONDITION( dwlConditionMask, VER_SERVICEPACKMAJOR, op );
965  VER_SET_CONDITION( dwlConditionMask, VER_SERVICEPACKMINOR, op );
966 
967  // Perform the test.
968 
969  return VerifyVersionInfo(
970  &osvi,
971  VER_MAJORVERSION | VER_MINORVERSION |
972  VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
973  dwlConditionMask);
974 }
975 
981 static dbus_bool_t
982 _dbus_getsid(char **sid, dbus_pid_t process_id)
983 {
984  HANDLE process_token = INVALID_HANDLE_VALUE;
985  TOKEN_USER *token_user = NULL;
986  DWORD n;
987  PSID psid;
988  int retval = FALSE;
989 
990  HANDLE process_handle = OpenProcess(is_winxp_sp3_or_lower() ? PROCESS_QUERY_INFORMATION : PROCESS_QUERY_LIMITED_INFORMATION, FALSE, process_id);
991 
992  if (!OpenProcessToken (process_handle, TOKEN_QUERY, &process_token))
993  {
994  _dbus_win_warn_win_error ("OpenProcessToken failed", GetLastError ());
995  goto failed;
996  }
997  if ((!GetTokenInformation (process_token, TokenUser, NULL, 0, &n)
998  && GetLastError () != ERROR_INSUFFICIENT_BUFFER)
999  || (token_user = alloca (n)) == NULL
1000  || !GetTokenInformation (process_token, TokenUser, token_user, n, &n))
1001  {
1002  _dbus_win_warn_win_error ("GetTokenInformation failed", GetLastError ());
1003  goto failed;
1004  }
1005  psid = token_user->User.Sid;
1006  if (!IsValidSid (psid))
1007  {
1008  _dbus_verbose("%s invalid sid\n",__FUNCTION__);
1009  goto failed;
1010  }
1011  if (!ConvertSidToStringSidA (psid, sid))
1012  {
1013  _dbus_verbose("%s invalid sid\n",__FUNCTION__);
1014  goto failed;
1015  }
1016 //okay:
1017  retval = TRUE;
1018 
1019 failed:
1020  CloseHandle (process_handle);
1021  if (process_token != INVALID_HANDLE_VALUE)
1022  CloseHandle (process_token);
1023 
1024  _dbus_verbose("_dbus_getsid() got '%s' and returns %d\n", *sid, retval);
1025  return retval;
1026 }
1027 #endif
1028 
1029 /************************************************************************
1030 
1031  pipes
1032 
1033  ************************************************************************/
1034 
1047  int *fd2,
1048  dbus_bool_t blocking,
1049  DBusError *error)
1050 {
1051  SOCKET temp, socket1 = -1, socket2 = -1;
1052  struct sockaddr_in saddr;
1053  int len;
1054  u_long arg;
1055 
1056  if (!_dbus_win_startup_winsock ())
1057  {
1058  _DBUS_SET_OOM (error);
1059  return FALSE;
1060  }
1061 
1062  temp = socket (AF_INET, SOCK_STREAM, 0);
1063  if (temp == INVALID_SOCKET)
1064  {
1065  DBUS_SOCKET_SET_ERRNO ();
1066  goto out0;
1067  }
1068 
1069  _DBUS_ZERO (saddr);
1070  saddr.sin_family = AF_INET;
1071  saddr.sin_port = 0;
1072  saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
1073 
1074  if (bind (temp, (struct sockaddr *)&saddr, sizeof (saddr)) == SOCKET_ERROR)
1075  {
1076  DBUS_SOCKET_SET_ERRNO ();
1077  goto out0;
1078  }
1079 
1080  if (listen (temp, 1) == SOCKET_ERROR)
1081  {
1082  DBUS_SOCKET_SET_ERRNO ();
1083  goto out0;
1084  }
1085 
1086  len = sizeof (saddr);
1087  if (getsockname (temp, (struct sockaddr *)&saddr, &len) == SOCKET_ERROR)
1088  {
1089  DBUS_SOCKET_SET_ERRNO ();
1090  goto out0;
1091  }
1092 
1093  socket1 = socket (AF_INET, SOCK_STREAM, 0);
1094  if (socket1 == INVALID_SOCKET)
1095  {
1096  DBUS_SOCKET_SET_ERRNO ();
1097  goto out0;
1098  }
1099 
1100  if (connect (socket1, (struct sockaddr *)&saddr, len) == SOCKET_ERROR)
1101  {
1102  DBUS_SOCKET_SET_ERRNO ();
1103  goto out1;
1104  }
1105 
1106  socket2 = accept (temp, (struct sockaddr *) &saddr, &len);
1107  if (socket2 == INVALID_SOCKET)
1108  {
1109  DBUS_SOCKET_SET_ERRNO ();
1110  goto out1;
1111  }
1112 
1113  if (!blocking)
1114  {
1115  arg = 1;
1116  if (ioctlsocket (socket1, FIONBIO, &arg) == SOCKET_ERROR)
1117  {
1118  DBUS_SOCKET_SET_ERRNO ();
1119  goto out2;
1120  }
1121 
1122  arg = 1;
1123  if (ioctlsocket (socket2, FIONBIO, &arg) == SOCKET_ERROR)
1124  {
1125  DBUS_SOCKET_SET_ERRNO ();
1126  goto out2;
1127  }
1128  }
1129 
1130  *fd1 = socket1;
1131  *fd2 = socket2;
1132 
1133  _dbus_verbose ("full-duplex pipe %d:%d <-> %d:%d\n",
1134  *fd1, socket1, *fd2, socket2);
1135 
1136  closesocket (temp);
1137 
1138  return TRUE;
1139 
1140 out2:
1141  closesocket (socket2);
1142 out1:
1143  closesocket (socket1);
1144 out0:
1145  closesocket (temp);
1146 
1147  dbus_set_error (error, _dbus_error_from_errno (errno),
1148  "Could not setup socket pair: %s",
1150 
1151  return FALSE;
1152 }
1153 
1162 int
1164  int n_fds,
1165  int timeout_milliseconds)
1166 {
1167 #define USE_CHRIS_IMPL 0
1168 
1169 #if USE_CHRIS_IMPL
1170 
1171 #define DBUS_POLL_CHAR_BUFFER_SIZE 2000
1172  char msg[DBUS_POLL_CHAR_BUFFER_SIZE];
1173  char *msgp;
1174 
1175  int ret = 0;
1176  int i;
1177  struct timeval tv;
1178  int ready;
1179 
1180 #define DBUS_STACK_WSAEVENTS 256
1181  WSAEVENT eventsOnStack[DBUS_STACK_WSAEVENTS];
1182  WSAEVENT *pEvents = NULL;
1183  if (n_fds > DBUS_STACK_WSAEVENTS)
1184  pEvents = calloc(sizeof(WSAEVENT), n_fds);
1185  else
1186  pEvents = eventsOnStack;
1187 
1188 
1189 #ifdef DBUS_ENABLE_VERBOSE_MODE
1190  msgp = msg;
1191  msgp += sprintf (msgp, "WSAEventSelect: to=%d\n\t", timeout_milliseconds);
1192  for (i = 0; i < n_fds; i++)
1193  {
1194  DBusPollFD *fdp = &fds[i];
1195 
1196 
1197  if (fdp->events & _DBUS_POLLIN)
1198  msgp += sprintf (msgp, "R:%d ", fdp->fd);
1199 
1200  if (fdp->events & _DBUS_POLLOUT)
1201  msgp += sprintf (msgp, "W:%d ", fdp->fd);
1202 
1203  msgp += sprintf (msgp, "E:%d\n\t", fdp->fd);
1204 
1205  // FIXME: more robust code for long msg
1206  // create on heap when msg[] becomes too small
1207  if (msgp >= msg + DBUS_POLL_CHAR_BUFFER_SIZE)
1208  {
1209  _dbus_assert_not_reached ("buffer overflow in _dbus_poll");
1210  }
1211  }
1212 
1213  msgp += sprintf (msgp, "\n");
1214  _dbus_verbose ("%s",msg);
1215 #endif
1216  for (i = 0; i < n_fds; i++)
1217  {
1218  DBusPollFD *fdp = &fds[i];
1219  WSAEVENT ev;
1220  long lNetworkEvents = FD_OOB;
1221 
1222  ev = WSACreateEvent();
1223 
1224  if (fdp->events & _DBUS_POLLIN)
1225  lNetworkEvents |= FD_READ | FD_ACCEPT | FD_CLOSE;
1226 
1227  if (fdp->events & _DBUS_POLLOUT)
1228  lNetworkEvents |= FD_WRITE | FD_CONNECT;
1229 
1230  WSAEventSelect(fdp->fd, ev, lNetworkEvents);
1231 
1232  pEvents[i] = ev;
1233  }
1234 
1235 
1236  ready = WSAWaitForMultipleEvents (n_fds, pEvents, FALSE, timeout_milliseconds, FALSE);
1237 
1238  if (DBUS_SOCKET_API_RETURNS_ERROR (ready))
1239  {
1240  DBUS_SOCKET_SET_ERRNO ();
1241  if (errno != WSAEWOULDBLOCK)
1242  _dbus_verbose ("WSAWaitForMultipleEvents: failed: %s\n", _dbus_strerror_from_errno ());
1243  ret = -1;
1244  }
1245  else if (ready == WSA_WAIT_TIMEOUT)
1246  {
1247  _dbus_verbose ("WSAWaitForMultipleEvents: WSA_WAIT_TIMEOUT\n");
1248  ret = 0;
1249  }
1250  else if (ready >= WSA_WAIT_EVENT_0 && ready < (int)(WSA_WAIT_EVENT_0 + n_fds))
1251  {
1252  msgp = msg;
1253  msgp += sprintf (msgp, "WSAWaitForMultipleEvents: =%d\n\t", ready);
1254 
1255  for (i = 0; i < n_fds; i++)
1256  {
1257  DBusPollFD *fdp = &fds[i];
1258  WSANETWORKEVENTS ne;
1259 
1260  fdp->revents = 0;
1261 
1262  WSAEnumNetworkEvents(fdp->fd, pEvents[i], &ne);
1263 
1264  if (ne.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
1265  fdp->revents |= _DBUS_POLLIN;
1266 
1267  if (ne.lNetworkEvents & (FD_WRITE | FD_CONNECT))
1268  fdp->revents |= _DBUS_POLLOUT;
1269 
1270  if (ne.lNetworkEvents & (FD_OOB))
1271  fdp->revents |= _DBUS_POLLERR;
1272 
1273  if (ne.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
1274  msgp += sprintf (msgp, "R:%d ", fdp->fd);
1275 
1276  if (ne.lNetworkEvents & (FD_WRITE | FD_CONNECT))
1277  msgp += sprintf (msgp, "W:%d ", fdp->fd);
1278 
1279  if (ne.lNetworkEvents & (FD_OOB))
1280  msgp += sprintf (msgp, "E:%d ", fdp->fd);
1281 
1282  msgp += sprintf (msgp, "lNetworkEvents:%d ", ne.lNetworkEvents);
1283 
1284  if(ne.lNetworkEvents)
1285  ret++;
1286 
1287  WSAEventSelect(fdp->fd, pEvents[i], 0);
1288  }
1289 
1290  msgp += sprintf (msgp, "\n");
1291  _dbus_verbose ("%s",msg);
1292  }
1293  else
1294  {
1295  _dbus_verbose ("WSAWaitForMultipleEvents: failed for unknown reason!");
1296  ret = -1;
1297  }
1298 
1299  for(i = 0; i < n_fds; i++)
1300  {
1301  WSACloseEvent(pEvents[i]);
1302  }
1303 
1304  if (n_fds > DBUS_STACK_WSAEVENTS)
1305  free(pEvents);
1306 
1307  return ret;
1308 
1309 #else /* USE_CHRIS_IMPL */
1310 
1311 #define DBUS_POLL_CHAR_BUFFER_SIZE 2000
1312  char msg[DBUS_POLL_CHAR_BUFFER_SIZE];
1313  char *msgp;
1314 
1315  fd_set read_set, write_set, err_set;
1316  int max_fd = 0;
1317  int i;
1318  struct timeval tv;
1319  int ready;
1320 
1321  FD_ZERO (&read_set);
1322  FD_ZERO (&write_set);
1323  FD_ZERO (&err_set);
1324 
1325 
1326 #ifdef DBUS_ENABLE_VERBOSE_MODE
1327  msgp = msg;
1328  msgp += sprintf (msgp, "select: to=%d\n\t", timeout_milliseconds);
1329  for (i = 0; i < n_fds; i++)
1330  {
1331  DBusPollFD *fdp = &fds[i];
1332 
1333 
1334  if (fdp->events & _DBUS_POLLIN)
1335  msgp += sprintf (msgp, "R:%d ", fdp->fd);
1336 
1337  if (fdp->events & _DBUS_POLLOUT)
1338  msgp += sprintf (msgp, "W:%d ", fdp->fd);
1339 
1340  msgp += sprintf (msgp, "E:%d\n\t", fdp->fd);
1341 
1342  // FIXME: more robust code for long msg
1343  // create on heap when msg[] becomes too small
1344  if (msgp >= msg + DBUS_POLL_CHAR_BUFFER_SIZE)
1345  {
1346  _dbus_assert_not_reached ("buffer overflow in _dbus_poll");
1347  }
1348  }
1349 
1350  msgp += sprintf (msgp, "\n");
1351  _dbus_verbose ("%s",msg);
1352 #endif
1353  for (i = 0; i < n_fds; i++)
1354  {
1355  DBusPollFD *fdp = &fds[i];
1356 
1357  if (fdp->events & _DBUS_POLLIN)
1358  FD_SET (fdp->fd, &read_set);
1359 
1360  if (fdp->events & _DBUS_POLLOUT)
1361  FD_SET (fdp->fd, &write_set);
1362 
1363  FD_SET (fdp->fd, &err_set);
1364 
1365  max_fd = MAX (max_fd, fdp->fd);
1366  }
1367 
1368  // Avoid random lockups with send(), for lack of a better solution so far
1369  tv.tv_sec = timeout_milliseconds < 0 ? 1 : timeout_milliseconds / 1000;
1370  tv.tv_usec = timeout_milliseconds < 0 ? 0 : (timeout_milliseconds % 1000) * 1000;
1371 
1372  ready = select (max_fd + 1, &read_set, &write_set, &err_set, &tv);
1373 
1374  if (DBUS_SOCKET_API_RETURNS_ERROR (ready))
1375  {
1376  DBUS_SOCKET_SET_ERRNO ();
1377  if (errno != WSAEWOULDBLOCK)
1378  _dbus_verbose ("select: failed: %s\n", _dbus_strerror_from_errno ());
1379  }
1380  else if (ready == 0)
1381  _dbus_verbose ("select: = 0\n");
1382  else
1383  if (ready > 0)
1384  {
1385 #ifdef DBUS_ENABLE_VERBOSE_MODE
1386  msgp = msg;
1387  msgp += sprintf (msgp, "select: = %d:\n\t", ready);
1388 
1389  for (i = 0; i < n_fds; i++)
1390  {
1391  DBusPollFD *fdp = &fds[i];
1392 
1393  if (FD_ISSET (fdp->fd, &read_set))
1394  msgp += sprintf (msgp, "R:%d ", fdp->fd);
1395 
1396  if (FD_ISSET (fdp->fd, &write_set))
1397  msgp += sprintf (msgp, "W:%d ", fdp->fd);
1398 
1399  if (FD_ISSET (fdp->fd, &err_set))
1400  msgp += sprintf (msgp, "E:%d\n\t", fdp->fd);
1401  }
1402  msgp += sprintf (msgp, "\n");
1403  _dbus_verbose ("%s",msg);
1404 #endif
1405 
1406  for (i = 0; i < n_fds; i++)
1407  {
1408  DBusPollFD *fdp = &fds[i];
1409 
1410  fdp->revents = 0;
1411 
1412  if (FD_ISSET (fdp->fd, &read_set))
1413  fdp->revents |= _DBUS_POLLIN;
1414 
1415  if (FD_ISSET (fdp->fd, &write_set))
1416  fdp->revents |= _DBUS_POLLOUT;
1417 
1418  if (FD_ISSET (fdp->fd, &err_set))
1419  fdp->revents |= _DBUS_POLLERR;
1420  }
1421  }
1422  return ready;
1423 #endif /* USE_CHRIS_IMPL */
1424 }
1425 
1426 
1427 
1428 
1429 /******************************************************************************
1430 
1431 Original CVS version of dbus-sysdeps.c
1432 
1433 ******************************************************************************/
1434 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
1435 /* dbus-sysdeps.c Wrappers around system/libc features (internal to D-Bus implementation)
1436  *
1437  * Copyright (C) 2002, 2003 Red Hat, Inc.
1438  * Copyright (C) 2003 CodeFactory AB
1439  * Copyright (C) 2005 Novell, Inc.
1440  *
1441  * Licensed under the Academic Free License version 2.1
1442  *
1443  * This program is free software; you can redistribute it and/or modify
1444  * it under the terms of the GNU General Public License as published by
1445  * the Free Software Foundation; either version 2 of the License, or
1446  * (at your option) any later version.
1447  *
1448  * This program is distributed in the hope that it will be useful,
1449  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1450  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1451  * GNU General Public License for more details.
1452  *
1453  * You should have received a copy of the GNU General Public License
1454  * along with this program; if not, write to the Free Software
1455  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1456  *
1457  */
1458 
1459 
1465 void
1466 _dbus_exit (int code)
1467 {
1468  _exit (code);
1469 }
1470 
1482 int
1483 _dbus_connect_tcp_socket (const char *host,
1484  const char *port,
1485  const char *family,
1486  DBusError *error)
1487 {
1488  return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
1489 }
1490 
1491 int
1492 _dbus_connect_tcp_socket_with_nonce (const char *host,
1493  const char *port,
1494  const char *family,
1495  const char *noncefile,
1496  DBusError *error)
1497 {
1498  int fd = -1, res;
1499  struct addrinfo hints;
1500  struct addrinfo *ai, *tmp;
1501 
1502  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1503 
1504  if (!_dbus_win_startup_winsock ())
1505  {
1506  _DBUS_SET_OOM (error);
1507  return -1;
1508  }
1509 
1510  _DBUS_ZERO (hints);
1511 
1512  if (!family)
1513  hints.ai_family = AF_UNSPEC;
1514  else if (!strcmp(family, "ipv4"))
1515  hints.ai_family = AF_INET;
1516  else if (!strcmp(family, "ipv6"))
1517  hints.ai_family = AF_INET6;
1518  else
1519  {
1520  dbus_set_error (error,
1522  "Unknown address family %s", family);
1523  return -1;
1524  }
1525  hints.ai_protocol = IPPROTO_TCP;
1526  hints.ai_socktype = SOCK_STREAM;
1527 #ifdef AI_ADDRCONFIG
1528  hints.ai_flags = AI_ADDRCONFIG;
1529 #else
1530  hints.ai_flags = 0;
1531 #endif
1532 
1533  if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
1534  {
1535  dbus_set_error (error,
1536  _dbus_error_from_errno (res),
1537  "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1538  host, port, _dbus_strerror(res), res);
1539  return -1;
1540  }
1541 
1542  tmp = ai;
1543  while (tmp)
1544  {
1545  if ((fd = socket (tmp->ai_family, SOCK_STREAM, 0)) == INVALID_SOCKET)
1546  {
1547  DBUS_SOCKET_SET_ERRNO ();
1548  dbus_set_error (error,
1549  _dbus_error_from_errno (errno),
1550  "Failed to open socket: %s",
1552  freeaddrinfo(ai);
1553  return -1;
1554  }
1555  _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1556 
1557  if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) == SOCKET_ERROR)
1558  {
1559  DBUS_SOCKET_SET_ERRNO ();
1560  closesocket(fd);
1561  fd = -1;
1562  tmp = tmp->ai_next;
1563  continue;
1564  }
1565 
1566  break;
1567  }
1568  freeaddrinfo(ai);
1569 
1570  if (fd == -1)
1571  {
1572  dbus_set_error (error,
1573  _dbus_error_from_errno (errno),
1574  "Failed to connect to socket \"%s:%s\" %s",
1575  host, port, _dbus_strerror_from_errno ());
1576  return -1;
1577  }
1578 
1579  if (noncefile != NULL)
1580  {
1581  DBusString noncefileStr;
1582  dbus_bool_t ret;
1583  if (!_dbus_string_init (&noncefileStr) ||
1584  !_dbus_string_append(&noncefileStr, noncefile))
1585  {
1586  closesocket (fd);
1588  return -1;
1589  }
1590 
1591  ret = _dbus_send_nonce (fd, &noncefileStr, error);
1592 
1593  _dbus_string_free (&noncefileStr);
1594 
1595  if (!ret)
1596  {
1597  closesocket (fd);
1598  return -1;
1599  }
1600  }
1601 
1603 
1604  if (!_dbus_set_fd_nonblocking (fd, error))
1605  {
1606  closesocket (fd);
1607  return -1;
1608  }
1609 
1610  return fd;
1611 }
1612 
1628 int
1629 _dbus_listen_tcp_socket (const char *host,
1630  const char *port,
1631  const char *family,
1632  DBusString *retport,
1633  int **fds_p,
1634  DBusError *error)
1635 {
1636  int nlisten_fd = 0, *listen_fd = NULL, res, i, port_num = -1;
1637  struct addrinfo hints;
1638  struct addrinfo *ai, *tmp;
1639 
1640  // On Vista, sockaddr_gen must be a sockaddr_in6, and not a sockaddr_in6_old
1641  //That's required for family == IPv6(which is the default on Vista if family is not given)
1642  //So we use our own union instead of sockaddr_gen:
1643 
1644  typedef union {
1645  struct sockaddr Address;
1646  struct sockaddr_in AddressIn;
1647  struct sockaddr_in6 AddressIn6;
1648  } mysockaddr_gen;
1649 
1650  *fds_p = NULL;
1651  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1652 
1653  if (!_dbus_win_startup_winsock ())
1654  {
1655  _DBUS_SET_OOM (error);
1656  return -1;
1657  }
1658 
1659  _DBUS_ZERO (hints);
1660 
1661  if (!family)
1662  hints.ai_family = AF_UNSPEC;
1663  else if (!strcmp(family, "ipv4"))
1664  hints.ai_family = AF_INET;
1665  else if (!strcmp(family, "ipv6"))
1666  hints.ai_family = AF_INET6;
1667  else
1668  {
1669  dbus_set_error (error,
1671  "Unknown address family %s", family);
1672  return -1;
1673  }
1674 
1675  hints.ai_protocol = IPPROTO_TCP;
1676  hints.ai_socktype = SOCK_STREAM;
1677 #ifdef AI_ADDRCONFIG
1678  hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
1679 #else
1680  hints.ai_flags = AI_PASSIVE;
1681 #endif
1682 
1683  redo_lookup_with_port:
1684  if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
1685  {
1686  dbus_set_error (error,
1687  _dbus_error_from_errno (res),
1688  "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1689  host ? host : "*", port, _dbus_strerror(res), res);
1690  return -1;
1691  }
1692 
1693  tmp = ai;
1694  while (tmp)
1695  {
1696  int fd = -1, *newlisten_fd;
1697  if ((fd = socket (tmp->ai_family, SOCK_STREAM, 0)) == INVALID_SOCKET)
1698  {
1699  DBUS_SOCKET_SET_ERRNO ();
1700  dbus_set_error (error,
1701  _dbus_error_from_errno (errno),
1702  "Failed to open socket: %s",
1704  goto failed;
1705  }
1706  _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1707 
1708  if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) == SOCKET_ERROR)
1709  {
1710  DBUS_SOCKET_SET_ERRNO ();
1711  dbus_set_error (error, _dbus_error_from_errno (errno),
1712  "Failed to bind socket \"%s:%s\": %s",
1713  host ? host : "*", port, _dbus_strerror_from_errno ());
1714  closesocket (fd);
1715  goto failed;
1716  }
1717 
1718  if (listen (fd, 30 /* backlog */) == SOCKET_ERROR)
1719  {
1720  DBUS_SOCKET_SET_ERRNO ();
1721  dbus_set_error (error, _dbus_error_from_errno (errno),
1722  "Failed to listen on socket \"%s:%s\": %s",
1723  host ? host : "*", port, _dbus_strerror_from_errno ());
1724  closesocket (fd);
1725  goto failed;
1726  }
1727 
1728  newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1));
1729  if (!newlisten_fd)
1730  {
1731  closesocket (fd);
1733  "Failed to allocate file handle array");
1734  goto failed;
1735  }
1736  listen_fd = newlisten_fd;
1737  listen_fd[nlisten_fd] = fd;
1738  nlisten_fd++;
1739 
1740  if (!_dbus_string_get_length(retport))
1741  {
1742  /* If the user didn't specify a port, or used 0, then
1743  the kernel chooses a port. After the first address
1744  is bound to, we need to force all remaining addresses
1745  to use the same port */
1746  if (!port || !strcmp(port, "0"))
1747  {
1748  mysockaddr_gen addr;
1749  socklen_t addrlen = sizeof(addr);
1750  char portbuf[10];
1751 
1752  if (getsockname(fd, &addr.Address, &addrlen) == SOCKET_ERROR)
1753  {
1754  DBUS_SOCKET_SET_ERRNO ();
1755  dbus_set_error (error, _dbus_error_from_errno (errno),
1756  "Failed to resolve port \"%s:%s\": %s",
1757  host ? host : "*", port, _dbus_strerror_from_errno());
1758  goto failed;
1759  }
1760  snprintf( portbuf, sizeof( portbuf ) - 1, "%d", addr.AddressIn.sin_port );
1761  if (!_dbus_string_append(retport, portbuf))
1762  {
1764  goto failed;
1765  }
1766 
1767  /* Release current address list & redo lookup */
1768  port = _dbus_string_get_const_data(retport);
1769  freeaddrinfo(ai);
1770  goto redo_lookup_with_port;
1771  }
1772  else
1773  {
1774  if (!_dbus_string_append(retport, port))
1775  {
1777  goto failed;
1778  }
1779  }
1780  }
1781 
1782  tmp = tmp->ai_next;
1783  }
1784  freeaddrinfo(ai);
1785  ai = NULL;
1786 
1787  if (!nlisten_fd)
1788  {
1789  _dbus_win_set_errno (WSAEADDRINUSE);
1790  dbus_set_error (error, _dbus_error_from_errno (errno),
1791  "Failed to bind socket \"%s:%s\": %s",
1792  host ? host : "*", port, _dbus_strerror_from_errno ());
1793  return -1;
1794  }
1795 
1796  sscanf(_dbus_string_get_const_data(retport), "%d", &port_num);
1797 
1798  for (i = 0 ; i < nlisten_fd ; i++)
1799  {
1800  _dbus_fd_set_close_on_exec (listen_fd[i]);
1801  if (!_dbus_set_fd_nonblocking (listen_fd[i], error))
1802  {
1803  goto failed;
1804  }
1805  }
1806 
1807  *fds_p = listen_fd;
1808 
1809  return nlisten_fd;
1810 
1811  failed:
1812  if (ai)
1813  freeaddrinfo(ai);
1814  for (i = 0 ; i < nlisten_fd ; i++)
1815  closesocket (listen_fd[i]);
1816  dbus_free(listen_fd);
1817  return -1;
1818 }
1819 
1820 
1828 int
1829 _dbus_accept (int listen_fd)
1830 {
1831  int client_fd;
1832 
1833  retry:
1834  client_fd = accept (listen_fd, NULL, NULL);
1835 
1836  if (DBUS_SOCKET_IS_INVALID (client_fd))
1837  {
1838  DBUS_SOCKET_SET_ERRNO ();
1839  if (errno == EINTR)
1840  goto retry;
1841  }
1842 
1843  _dbus_verbose ("client fd %d accepted\n", client_fd);
1844 
1845  return client_fd;
1846 }
1847 
1848 
1849 
1850 
1853  DBusError *error)
1854 {
1855 /* FIXME: for the session bus credentials shouldn't matter (?), but
1856  * for the system bus they are presumably essential. A rough outline
1857  * of a way to implement the credential transfer would be this:
1858  *
1859  * client waits to *read* a byte.
1860  *
1861  * server creates a named pipe with a random name, sends a byte
1862  * contining its length, and its name.
1863  *
1864  * client reads the name, connects to it (using Win32 API).
1865  *
1866  * server waits for connection to the named pipe, then calls
1867  * ImpersonateNamedPipeClient(), notes its now-current credentials,
1868  * calls RevertToSelf(), closes its handles to the named pipe, and
1869  * is done. (Maybe there is some other way to get the SID of a named
1870  * pipe client without having to use impersonation?)
1871  *
1872  * client closes its handles and is done.
1873  *
1874  * Ralf: Why not sending credentials over the given this connection ?
1875  * Using named pipes makes it impossible to be connected from a unix client.
1876  *
1877  */
1878  int bytes_written;
1879  DBusString buf;
1880 
1881  _dbus_string_init_const_len (&buf, "\0", 1);
1882 again:
1883  bytes_written = _dbus_write_socket (handle, &buf, 0, 1 );
1884 
1885  if (bytes_written < 0 && errno == EINTR)
1886  goto again;
1887 
1888  if (bytes_written < 0)
1889  {
1890  dbus_set_error (error, _dbus_error_from_errno (errno),
1891  "Failed to write credentials byte: %s",
1893  return FALSE;
1894  }
1895  else if (bytes_written == 0)
1896  {
1898  "wrote zero bytes writing credentials byte");
1899  return FALSE;
1900  }
1901  else
1902  {
1903  _dbus_assert (bytes_written == 1);
1904  _dbus_verbose ("wrote 1 zero byte, credential sending isn't implemented yet\n");
1905  return TRUE;
1906  }
1907  return TRUE;
1908 }
1909 
1930  DBusCredentials *credentials,
1931  DBusError *error)
1932 {
1933  int bytes_read = 0;
1934  DBusString buf;
1935 
1936  char *sid = NULL;
1937  dbus_pid_t pid;
1938  int retval = FALSE;
1939 
1940  // could fail due too OOM
1941  if (_dbus_string_init (&buf))
1942  {
1943  bytes_read = _dbus_read_socket (handle, &buf, 1 );
1944 
1945  if (bytes_read > 0)
1946  _dbus_verbose ("got one zero byte from server\n");
1947 
1948  _dbus_string_free (&buf);
1949  }
1950 
1951  pid = _dbus_get_peer_pid_from_tcp_handle (handle);
1952  if (pid == 0)
1953  return TRUE;
1954 
1955  _dbus_credentials_add_pid (credentials, pid);
1956 
1957  if (_dbus_getsid (&sid, pid))
1958  {
1959  if (!_dbus_credentials_add_windows_sid (credentials, sid))
1960  goto out;
1961  }
1962 
1963  retval = TRUE;
1964 
1965 out:
1966  if (sid)
1967  LocalFree (sid);
1968 
1969  return retval;
1970 }
1971 
1982 {
1983  /* TODO */
1984  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1985  return TRUE;
1986 }
1987 
1988 
2001  const DBusString *next_component)
2002 {
2003  dbus_bool_t dir_ends_in_slash;
2004  dbus_bool_t file_starts_with_slash;
2005 
2006  if (_dbus_string_get_length (dir) == 0 ||
2007  _dbus_string_get_length (next_component) == 0)
2008  return TRUE;
2009 
2010  dir_ends_in_slash =
2011  ('/' == _dbus_string_get_byte (dir, _dbus_string_get_length (dir) - 1) ||
2012  '\\' == _dbus_string_get_byte (dir, _dbus_string_get_length (dir) - 1));
2013 
2014  file_starts_with_slash =
2015  ('/' == _dbus_string_get_byte (next_component, 0) ||
2016  '\\' == _dbus_string_get_byte (next_component, 0));
2017 
2018  if (dir_ends_in_slash && file_starts_with_slash)
2019  {
2020  _dbus_string_shorten (dir, 1);
2021  }
2022  else if (!(dir_ends_in_slash || file_starts_with_slash))
2023  {
2024  if (!_dbus_string_append_byte (dir, '\\'))
2025  return FALSE;
2026  }
2027 
2028  return _dbus_string_copy (next_component, 0, dir,
2029  _dbus_string_get_length (dir));
2030 }
2031 
2032 /*---------------- DBusCredentials ----------------------------------*/
2033 
2043  const DBusString *username)
2044 {
2045  return _dbus_credentials_add_windows_sid (credentials,
2046  _dbus_string_get_const_data(username));
2047 }
2048 
2059 {
2060  dbus_bool_t retval = FALSE;
2061  char *sid = NULL;
2062 
2063  if (!_dbus_getsid(&sid, _dbus_getpid()))
2064  goto failed;
2065 
2066  if (!_dbus_credentials_add_pid (credentials, _dbus_getpid()))
2067  goto failed;
2068 
2069  if (!_dbus_credentials_add_windows_sid (credentials,sid))
2070  goto failed;
2071 
2072  retval = TRUE;
2073  goto end;
2074 failed:
2075  retval = FALSE;
2076 end:
2077  if (sid)
2078  LocalFree(sid);
2079 
2080  return retval;
2081 }
2082 
2097 {
2098  dbus_bool_t retval = FALSE;
2099  char *sid = NULL;
2100 
2101  if (!_dbus_getsid(&sid, _dbus_getpid()))
2102  return FALSE;
2103 
2104  retval = _dbus_string_append (str,sid);
2105 
2106  LocalFree(sid);
2107  return retval;
2108 }
2109 
2114 dbus_pid_t
2116 {
2117  return GetCurrentProcessId ();
2118 }
2119 
2121 #define NANOSECONDS_PER_SECOND 1000000000
2122 
2123 #define MICROSECONDS_PER_SECOND 1000000
2124 
2125 #define MILLISECONDS_PER_SECOND 1000
2126 
2127 #define NANOSECONDS_PER_MILLISECOND 1000000
2128 
2129 #define MICROSECONDS_PER_MILLISECOND 1000
2130 
2135 void
2136 _dbus_sleep_milliseconds (int milliseconds)
2137 {
2138  Sleep (milliseconds);
2139 }
2140 
2141 
2149 void
2150 _dbus_get_real_time (long *tv_sec,
2151  long *tv_usec)
2152 {
2153  FILETIME ft;
2154  dbus_uint64_t time64;
2155 
2156  GetSystemTimeAsFileTime (&ft);
2157 
2158  memcpy (&time64, &ft, sizeof (time64));
2159 
2160  /* Convert from 100s of nanoseconds since 1601-01-01
2161  * to Unix epoch. Yes, this is Y2038 unsafe.
2162  */
2163  time64 -= DBUS_INT64_CONSTANT (116444736000000000);
2164  time64 /= 10;
2165 
2166  if (tv_sec)
2167  *tv_sec = time64 / 1000000;
2168 
2169  if (tv_usec)
2170  *tv_usec = time64 % 1000000;
2171 }
2172 
2180 void
2182  long *tv_usec)
2183 {
2184  /* no implementation yet, fall back to wall-clock time */
2185  _dbus_get_real_time (tv_sec, tv_usec);
2186 }
2187 
2191 void
2193 {
2194 }
2195 
2206  DBusError *error)
2207 {
2208  const char *filename_c;
2209 
2210  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2211 
2212  filename_c = _dbus_string_get_const_data (filename);
2213 
2214  if (!CreateDirectoryA (filename_c, NULL))
2215  {
2216  if (GetLastError () == ERROR_ALREADY_EXISTS)
2217  return TRUE;
2218 
2220  "Failed to create directory %s: %s\n",
2221  filename_c, _dbus_strerror_from_errno ());
2222  return FALSE;
2223  }
2224  else
2225  return TRUE;
2226 }
2227 
2228 
2239  int n_bytes)
2240 {
2241  int old_len;
2242  char *p;
2243  HCRYPTPROV hprov;
2244 
2245  old_len = _dbus_string_get_length (str);
2246 
2247  if (!_dbus_string_lengthen (str, n_bytes))
2248  return FALSE;
2249 
2250  p = _dbus_string_get_data_len (str, old_len, n_bytes);
2251 
2252  if (!CryptAcquireContext (&hprov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
2253  return FALSE;
2254 
2255  if (!CryptGenRandom (hprov, n_bytes, p))
2256  {
2257  CryptReleaseContext (hprov, 0);
2258  return FALSE;
2259  }
2260 
2261  CryptReleaseContext (hprov, 0);
2262 
2263  return TRUE;
2264 }
2265 
2272 const char*
2274 {
2275  /* Protected by _DBUS_LOCK_sysdeps */
2276  static const char* tmpdir = NULL;
2277  static char buf[1000];
2278 
2279  if (!_DBUS_LOCK (sysdeps))
2280  return NULL;
2281 
2282  if (tmpdir == NULL)
2283  {
2284  char *last_slash;
2285 
2286  if (!GetTempPathA (sizeof (buf), buf))
2287  {
2288  _dbus_warn ("GetTempPath failed\n");
2289  _dbus_abort ();
2290  }
2291 
2292  /* Drop terminating backslash or slash */
2293  last_slash = _mbsrchr (buf, '\\');
2294  if (last_slash > buf && last_slash[1] == '\0')
2295  last_slash[0] = '\0';
2296  last_slash = _mbsrchr (buf, '/');
2297  if (last_slash > buf && last_slash[1] == '\0')
2298  last_slash[0] = '\0';
2299 
2300  tmpdir = buf;
2301  }
2302 
2303  _DBUS_UNLOCK (sysdeps);
2304 
2305  _dbus_assert(tmpdir != NULL);
2306 
2307  return tmpdir;
2308 }
2309 
2310 
2321  DBusError *error)
2322 {
2323  const char *filename_c;
2324 
2325  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2326 
2327  filename_c = _dbus_string_get_const_data (filename);
2328 
2329  if (DeleteFileA (filename_c) == 0)
2330  {
2332  "Failed to delete file %s: %s\n",
2333  filename_c, _dbus_strerror_from_errno ());
2334  return FALSE;
2335  }
2336  else
2337  return TRUE;
2338 }
2339 
2340 #if !defined (DBUS_DISABLE_ASSERT) || defined(DBUS_ENABLE_EMBEDDED_TESTS)
2341 
2342 #if defined(_MSC_VER) || defined(DBUS_WINCE)
2343 # ifdef BACKTRACES
2344 # undef BACKTRACES
2345 # endif
2346 #else
2347 # define BACKTRACES
2348 #endif
2349 
2350 #ifdef BACKTRACES
2351 /*
2352  * Backtrace Generator
2353  *
2354  * Copyright 2004 Eric Poech
2355  * Copyright 2004 Robert Shearman
2356  *
2357  * This library is free software; you can redistribute it and/or
2358  * modify it under the terms of the GNU Lesser General Public
2359  * License as published by the Free Software Foundation; either
2360  * version 2.1 of the License, or (at your option) any later version.
2361  *
2362  * This library is distributed in the hope that it will be useful,
2363  * but WITHOUT ANY WARRANTY; without even the implied warranty of
2364  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2365  * Lesser General Public License for more details.
2366  *
2367  * You should have received a copy of the GNU Lesser General Public
2368  * License along with this library; if not, write to the Free Software
2369  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2370  */
2371 
2372 #include <winver.h>
2373 #include <imagehlp.h>
2374 #include <stdio.h>
2375 
2376 #define DPRINTF _dbus_warn
2377 
2378 #ifdef _MSC_VER
2379 #define BOOL int
2380 
2381 #define __i386__
2382 #endif
2383 
2384 //#define MAKE_FUNCPTR(f) static typeof(f) * p##f
2385 
2386 //MAKE_FUNCPTR(StackWalk);
2387 //MAKE_FUNCPTR(SymGetModuleBase);
2388 //MAKE_FUNCPTR(SymFunctionTableAccess);
2389 //MAKE_FUNCPTR(SymInitialize);
2390 //MAKE_FUNCPTR(SymGetSymFromAddr);
2391 //MAKE_FUNCPTR(SymGetModuleInfo);
2392 static BOOL (WINAPI *pStackWalk)(
2393  DWORD MachineType,
2394  HANDLE hProcess,
2395  HANDLE hThread,
2396  LPSTACKFRAME StackFrame,
2397  PVOID ContextRecord,
2398  PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
2399  PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
2400  PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
2401  PTRANSLATE_ADDRESS_ROUTINE TranslateAddress
2402 );
2403 #ifdef _WIN64
2404 static DWORD64 (WINAPI *pSymGetModuleBase)(
2405  HANDLE hProcess,
2406  DWORD64 dwAddr
2407 );
2408 static PVOID (WINAPI *pSymFunctionTableAccess)(
2409  HANDLE hProcess,
2410  DWORD64 AddrBase
2411 );
2412 #else
2413 static DWORD (WINAPI *pSymGetModuleBase)(
2414  HANDLE hProcess,
2415  DWORD dwAddr
2416 );
2417 static PVOID (WINAPI *pSymFunctionTableAccess)(
2418  HANDLE hProcess,
2419  DWORD AddrBase
2420 );
2421 #endif
2422 static BOOL (WINAPI *pSymInitialize)(
2423  HANDLE hProcess,
2424  PSTR UserSearchPath,
2425  BOOL fInvadeProcess
2426 );
2427 static BOOL (WINAPI *pSymGetSymFromAddr)(
2428  HANDLE hProcess,
2429  DWORD Address,
2430  PDWORD Displacement,
2431  PIMAGEHLP_SYMBOL Symbol
2432 );
2433 static BOOL (WINAPI *pSymGetModuleInfo)(
2434  HANDLE hProcess,
2435  DWORD dwAddr,
2436  PIMAGEHLP_MODULE ModuleInfo
2437 );
2438 static DWORD (WINAPI *pSymSetOptions)(
2439  DWORD SymOptions
2440 );
2441 
2442 
2443 static BOOL init_backtrace()
2444 {
2445  HMODULE hmodDbgHelp = LoadLibraryA("dbghelp");
2446 /*
2447  #define GETFUNC(x) \
2448  p##x = (typeof(x)*)GetProcAddress(hmodDbgHelp, #x); \
2449  if (!p##x) \
2450  { \
2451  return FALSE; \
2452  }
2453  */
2454 
2455 
2456 // GETFUNC(StackWalk);
2457 // GETFUNC(SymGetModuleBase);
2458 // GETFUNC(SymFunctionTableAccess);
2459 // GETFUNC(SymInitialize);
2460 // GETFUNC(SymGetSymFromAddr);
2461 // GETFUNC(SymGetModuleInfo);
2462 
2463 #define FUNC(x) #x
2464 
2465  pStackWalk = (BOOL (WINAPI *)(
2466 DWORD MachineType,
2467 HANDLE hProcess,
2468 HANDLE hThread,
2469 LPSTACKFRAME StackFrame,
2470 PVOID ContextRecord,
2471 PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
2472 PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
2473 PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
2474 PTRANSLATE_ADDRESS_ROUTINE TranslateAddress
2475 ))GetProcAddress (hmodDbgHelp, FUNC(StackWalk));
2476 #ifdef _WIN64
2477  pSymGetModuleBase=(DWORD64 (WINAPI *)(
2478  HANDLE hProcess,
2479  DWORD64 dwAddr
2480 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleBase));
2481  pSymFunctionTableAccess=(PVOID (WINAPI *)(
2482  HANDLE hProcess,
2483  DWORD64 AddrBase
2484 ))GetProcAddress (hmodDbgHelp, FUNC(SymFunctionTableAccess));
2485 #else
2486  pSymGetModuleBase=(DWORD (WINAPI *)(
2487  HANDLE hProcess,
2488  DWORD dwAddr
2489 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleBase));
2490  pSymFunctionTableAccess=(PVOID (WINAPI *)(
2491  HANDLE hProcess,
2492  DWORD AddrBase
2493 ))GetProcAddress (hmodDbgHelp, FUNC(SymFunctionTableAccess));
2494 #endif
2495  pSymInitialize = (BOOL (WINAPI *)(
2496  HANDLE hProcess,
2497  PSTR UserSearchPath,
2498  BOOL fInvadeProcess
2499 ))GetProcAddress (hmodDbgHelp, FUNC(SymInitialize));
2500  pSymGetSymFromAddr = (BOOL (WINAPI *)(
2501  HANDLE hProcess,
2502  DWORD Address,
2503  PDWORD Displacement,
2504  PIMAGEHLP_SYMBOL Symbol
2505 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetSymFromAddr));
2506  pSymGetModuleInfo = (BOOL (WINAPI *)(
2507  HANDLE hProcess,
2508  DWORD dwAddr,
2509  PIMAGEHLP_MODULE ModuleInfo
2510 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleInfo));
2511 pSymSetOptions = (DWORD (WINAPI *)(
2512 DWORD SymOptions
2513 ))GetProcAddress (hmodDbgHelp, FUNC(SymSetOptions));
2514 
2515 
2516  pSymSetOptions(SYMOPT_UNDNAME);
2517 
2518  pSymInitialize(GetCurrentProcess(), NULL, TRUE);
2519 
2520  return TRUE;
2521 }
2522 
2523 static void dump_backtrace_for_thread(HANDLE hThread)
2524 {
2525  STACKFRAME sf;
2526  CONTEXT context;
2527  DWORD dwImageType;
2528 
2529  if (!pStackWalk)
2530  if (!init_backtrace())
2531  return;
2532 
2533  /* can't use this function for current thread as GetThreadContext
2534  * doesn't support getting context from current thread */
2535  if (hThread == GetCurrentThread())
2536  return;
2537 
2538  DPRINTF("Backtrace:\n");
2539 
2540  _DBUS_ZERO(context);
2541  context.ContextFlags = CONTEXT_FULL;
2542 
2543  SuspendThread(hThread);
2544 
2545  if (!GetThreadContext(hThread, &context))
2546  {
2547  DPRINTF("Couldn't get thread context (error %ld)\n", GetLastError());
2548  ResumeThread(hThread);
2549  return;
2550  }
2551 
2552  _DBUS_ZERO(sf);
2553 
2554 #ifdef __i386__
2555  sf.AddrFrame.Offset = context.Ebp;
2556  sf.AddrFrame.Mode = AddrModeFlat;
2557  sf.AddrPC.Offset = context.Eip;
2558  sf.AddrPC.Mode = AddrModeFlat;
2559  dwImageType = IMAGE_FILE_MACHINE_I386;
2560 #elif _M_X64
2561  dwImageType = IMAGE_FILE_MACHINE_AMD64;
2562  sf.AddrPC.Offset = context.Rip;
2563  sf.AddrPC.Mode = AddrModeFlat;
2564  sf.AddrFrame.Offset = context.Rsp;
2565  sf.AddrFrame.Mode = AddrModeFlat;
2566  sf.AddrStack.Offset = context.Rsp;
2567  sf.AddrStack.Mode = AddrModeFlat;
2568 #elif _M_IA64
2569  dwImageType = IMAGE_FILE_MACHINE_IA64;
2570  sf.AddrPC.Offset = context.StIIP;
2571  sf.AddrPC.Mode = AddrModeFlat;
2572  sf.AddrFrame.Offset = context.IntSp;
2573  sf.AddrFrame.Mode = AddrModeFlat;
2574  sf.AddrBStore.Offset= context.RsBSP;
2575  sf.AddrBStore.Mode = AddrModeFlat;
2576  sf.AddrStack.Offset = context.IntSp;
2577  sf.AddrStack.Mode = AddrModeFlat;
2578 #else
2579 # error You need to fill in the STACKFRAME structure for your architecture
2580 #endif
2581 
2582  while (pStackWalk(dwImageType, GetCurrentProcess(),
2583  hThread, &sf, &context, NULL, pSymFunctionTableAccess,
2584  pSymGetModuleBase, NULL))
2585  {
2586  BYTE buffer[256];
2587  IMAGEHLP_SYMBOL * pSymbol = (IMAGEHLP_SYMBOL *)buffer;
2588  DWORD dwDisplacement;
2589 
2590  pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
2591  pSymbol->MaxNameLength = sizeof(buffer) - sizeof(IMAGEHLP_SYMBOL) + 1;
2592 
2593  if (!pSymGetSymFromAddr(GetCurrentProcess(), sf.AddrPC.Offset,
2594  &dwDisplacement, pSymbol))
2595  {
2596  IMAGEHLP_MODULE ModuleInfo;
2597  ModuleInfo.SizeOfStruct = sizeof(ModuleInfo);
2598 
2599  if (!pSymGetModuleInfo(GetCurrentProcess(), sf.AddrPC.Offset,
2600  &ModuleInfo))
2601  DPRINTF("1\t%p\n", (void*)sf.AddrPC.Offset);
2602  else
2603  DPRINTF("2\t%s+0x%lx\n", ModuleInfo.ImageName,
2604  sf.AddrPC.Offset - ModuleInfo.BaseOfImage);
2605  }
2606  else if (dwDisplacement)
2607  DPRINTF("3\t%s+0x%lx\n", pSymbol->Name, dwDisplacement);
2608  else
2609  DPRINTF("4\t%s\n", pSymbol->Name);
2610  }
2611 
2612  ResumeThread(hThread);
2613 }
2614 
2615 static DWORD WINAPI dump_thread_proc(LPVOID lpParameter)
2616 {
2617  dump_backtrace_for_thread((HANDLE)lpParameter);
2618  return 0;
2619 }
2620 
2621 /* cannot get valid context from current thread, so we have to execute
2622  * backtrace from another thread */
2623 static void dump_backtrace()
2624 {
2625  HANDLE hCurrentThread;
2626  HANDLE hThread;
2627  DWORD dwThreadId;
2628  DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
2629  GetCurrentProcess(), &hCurrentThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
2630  hThread = CreateThread(NULL, 0, dump_thread_proc, (LPVOID)hCurrentThread,
2631  0, &dwThreadId);
2632  WaitForSingleObject(hThread, INFINITE);
2633  CloseHandle(hThread);
2634  CloseHandle(hCurrentThread);
2635 }
2636 #endif
2637 #endif /* asserts or tests enabled */
2638 
2639 #ifdef BACKTRACES
2641 {
2642  init_backtrace();
2643  dump_backtrace();
2644 }
2645 #else
2646 void _dbus_print_backtrace(void)
2647 {
2648  _dbus_verbose (" D-Bus not compiled with backtrace support\n");
2649 }
2650 #endif
2651 
2652 static dbus_uint32_t fromAscii(char ascii)
2653 {
2654  if(ascii >= '0' && ascii <= '9')
2655  return ascii - '0';
2656  if(ascii >= 'A' && ascii <= 'F')
2657  return ascii - 'A' + 10;
2658  if(ascii >= 'a' && ascii <= 'f')
2659  return ascii - 'a' + 10;
2660  return 0;
2661 }
2662 
2664  dbus_bool_t create_if_not_found,
2665  DBusError *error)
2666 {
2667 #ifdef DBUS_WINCE
2668  return TRUE;
2669  // TODO
2670 #else
2671  HW_PROFILE_INFOA info;
2672  char *lpc = &info.szHwProfileGuid[0];
2673  dbus_uint32_t u;
2674 
2675  // the hw-profile guid lives long enough
2676  if(!GetCurrentHwProfileA(&info))
2677  {
2678  dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); // FIXME
2679  return FALSE;
2680  }
2681 
2682  // Form: {12340001-4980-1920-6788-123456789012}
2683  lpc++;
2684  // 12340001
2685  u = ((fromAscii(lpc[0]) << 0) |
2686  (fromAscii(lpc[1]) << 4) |
2687  (fromAscii(lpc[2]) << 8) |
2688  (fromAscii(lpc[3]) << 12) |
2689  (fromAscii(lpc[4]) << 16) |
2690  (fromAscii(lpc[5]) << 20) |
2691  (fromAscii(lpc[6]) << 24) |
2692  (fromAscii(lpc[7]) << 28));
2693  machine_id->as_uint32s[0] = u;
2694 
2695  lpc += 9;
2696  // 4980-1920
2697  u = ((fromAscii(lpc[0]) << 0) |
2698  (fromAscii(lpc[1]) << 4) |
2699  (fromAscii(lpc[2]) << 8) |
2700  (fromAscii(lpc[3]) << 12) |
2701  (fromAscii(lpc[5]) << 16) |
2702  (fromAscii(lpc[6]) << 20) |
2703  (fromAscii(lpc[7]) << 24) |
2704  (fromAscii(lpc[8]) << 28));
2705  machine_id->as_uint32s[1] = u;
2706 
2707  lpc += 10;
2708  // 6788-1234
2709  u = ((fromAscii(lpc[0]) << 0) |
2710  (fromAscii(lpc[1]) << 4) |
2711  (fromAscii(lpc[2]) << 8) |
2712  (fromAscii(lpc[3]) << 12) |
2713  (fromAscii(lpc[5]) << 16) |
2714  (fromAscii(lpc[6]) << 20) |
2715  (fromAscii(lpc[7]) << 24) |
2716  (fromAscii(lpc[8]) << 28));
2717  machine_id->as_uint32s[2] = u;
2718 
2719  lpc += 9;
2720  // 56789012
2721  u = ((fromAscii(lpc[0]) << 0) |
2722  (fromAscii(lpc[1]) << 4) |
2723  (fromAscii(lpc[2]) << 8) |
2724  (fromAscii(lpc[3]) << 12) |
2725  (fromAscii(lpc[4]) << 16) |
2726  (fromAscii(lpc[5]) << 20) |
2727  (fromAscii(lpc[6]) << 24) |
2728  (fromAscii(lpc[7]) << 28));
2729  machine_id->as_uint32s[3] = u;
2730 #endif
2731  return TRUE;
2732 }
2733 
2734 static
2735 HANDLE _dbus_global_lock (const char *mutexname)
2736 {
2737  HANDLE mutex;
2738  DWORD gotMutex;
2739 
2740  mutex = CreateMutexA( NULL, FALSE, mutexname );
2741  if( !mutex )
2742  {
2743  return FALSE;
2744  }
2745 
2746  gotMutex = WaitForSingleObject( mutex, INFINITE );
2747  switch( gotMutex )
2748  {
2749  case WAIT_ABANDONED:
2750  ReleaseMutex (mutex);
2751  CloseHandle (mutex);
2752  return 0;
2753  case WAIT_FAILED:
2754  case WAIT_TIMEOUT:
2755  return 0;
2756  }
2757 
2758  return mutex;
2759 }
2760 
2761 static
2762 void _dbus_global_unlock (HANDLE mutex)
2763 {
2764  ReleaseMutex (mutex);
2765  CloseHandle (mutex);
2766 }
2767 
2768 // for proper cleanup in dbus-daemon
2769 static HANDLE hDBusDaemonMutex = NULL;
2770 static HANDLE hDBusSharedMem = NULL;
2771 // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
2772 static const char *cUniqueDBusInitMutex = "UniqueDBusInitMutex";
2773 // sync _dbus_get_autolaunch_address
2774 static const char *cDBusAutolaunchMutex = "DBusAutolaunchMutex";
2775 // mutex to determine if dbus-daemon is already started (per user)
2776 static const char *cDBusDaemonMutex = "DBusDaemonMutex";
2777 // named shm for dbus adress info (per user)
2778 static const char *cDBusDaemonAddressInfo = "DBusDaemonAddressInfo";
2779 
2780 static dbus_bool_t
2781 _dbus_get_install_root_as_hash(DBusString *out)
2782 {
2783  DBusString install_path;
2784 
2785  char path[MAX_PATH*2];
2786  int path_size = sizeof(path);
2787 
2788  if (!_dbus_get_install_root(path,path_size))
2789  return FALSE;
2790 
2791  _dbus_string_init(&install_path);
2792  _dbus_string_append(&install_path,path);
2793 
2794  _dbus_string_init(out);
2795  _dbus_string_tolower_ascii(&install_path,0,_dbus_string_get_length(&install_path));
2796 
2797  if (!_dbus_sha_compute (&install_path, out))
2798  return FALSE;
2799 
2800  return TRUE;
2801 }
2802 
2803 static dbus_bool_t
2804 _dbus_get_address_string (DBusString *out, const char *basestring, const char *scope)
2805 {
2806  _dbus_string_init(out);
2807  _dbus_string_append(out,basestring);
2808 
2809  if (!scope)
2810  {
2811  return TRUE;
2812  }
2813  else if (strcmp(scope,"*install-path") == 0
2814  // for 1.3 compatibility
2815  || strcmp(scope,"install-path") == 0)
2816  {
2817  DBusString temp;
2818  if (!_dbus_get_install_root_as_hash(&temp))
2819  {
2820  _dbus_string_free(out);
2821  return FALSE;
2822  }
2823  _dbus_string_append(out,"-");
2824  _dbus_string_append(out,_dbus_string_get_const_data(&temp));
2825  _dbus_string_free(&temp);
2826  }
2827  else if (strcmp(scope,"*user") == 0)
2828  {
2829  _dbus_string_append(out,"-");
2831  {
2832  _dbus_string_free(out);
2833  return FALSE;
2834  }
2835  }
2836  else if (strlen(scope) > 0)
2837  {
2838  _dbus_string_append(out,"-");
2839  _dbus_string_append(out,scope);
2840  return TRUE;
2841  }
2842  return TRUE;
2843 }
2844 
2845 static dbus_bool_t
2846 _dbus_get_shm_name (DBusString *out,const char *scope)
2847 {
2848  return _dbus_get_address_string (out,cDBusDaemonAddressInfo,scope);
2849 }
2850 
2851 static dbus_bool_t
2852 _dbus_get_mutex_name (DBusString *out,const char *scope)
2853 {
2854  return _dbus_get_address_string (out,cDBusDaemonMutex,scope);
2855 }
2856 
2858 _dbus_daemon_is_session_bus_address_published (const char *scope)
2859 {
2860  HANDLE lock;
2861  DBusString mutex_name;
2862 
2863  if (!_dbus_get_mutex_name(&mutex_name,scope))
2864  {
2865  _dbus_string_free( &mutex_name );
2866  return FALSE;
2867  }
2868 
2869  if (hDBusDaemonMutex)
2870  return TRUE;
2871 
2872  // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
2873  lock = _dbus_global_lock( cUniqueDBusInitMutex );
2874 
2875  // we use CreateMutex instead of OpenMutex because of possible race conditions,
2876  // see http://msdn.microsoft.com/en-us/library/ms684315%28VS.85%29.aspx
2877  hDBusDaemonMutex = CreateMutexA( NULL, FALSE, _dbus_string_get_const_data(&mutex_name) );
2878 
2879  /* The client uses mutex ownership to detect a running server, so the server should do so too.
2880  Fortunally the client deletes the mutex in the lock protected area, so checking presence
2881  will work too. */
2882 
2883  _dbus_global_unlock( lock );
2884 
2885  _dbus_string_free( &mutex_name );
2886 
2887  if (hDBusDaemonMutex == NULL)
2888  return FALSE;
2889  if (GetLastError() == ERROR_ALREADY_EXISTS)
2890  {
2891  CloseHandle(hDBusDaemonMutex);
2892  hDBusDaemonMutex = NULL;
2893  return TRUE;
2894  }
2895  // mutex wasn't created before, so return false.
2896  // We leave the mutex name allocated for later reusage
2897  // in _dbus_daemon_publish_session_bus_address.
2898  return FALSE;
2899 }
2900 
2902 _dbus_daemon_publish_session_bus_address (const char* address, const char *scope)
2903 {
2904  HANDLE lock;
2905  char *shared_addr = NULL;
2906  DBusString shm_name;
2907  DBusString mutex_name;
2908 
2909  _dbus_assert (address);
2910 
2911  if (!_dbus_get_mutex_name(&mutex_name,scope))
2912  {
2913  _dbus_string_free( &mutex_name );
2914  return FALSE;
2915  }
2916 
2917  // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
2918  lock = _dbus_global_lock( cUniqueDBusInitMutex );
2919 
2920  if (!hDBusDaemonMutex)
2921  {
2922  hDBusDaemonMutex = CreateMutexA( NULL, FALSE, _dbus_string_get_const_data(&mutex_name) );
2923  }
2924  _dbus_string_free( &mutex_name );
2925 
2926  // acquire the mutex
2927  if (WaitForSingleObject( hDBusDaemonMutex, 10 ) != WAIT_OBJECT_0)
2928  {
2929  _dbus_global_unlock( lock );
2930  CloseHandle( hDBusDaemonMutex );
2931  return FALSE;
2932  }
2933 
2934  if (!_dbus_get_shm_name(&shm_name,scope))
2935  {
2936  _dbus_string_free( &shm_name );
2937  _dbus_global_unlock( lock );
2938  return FALSE;
2939  }
2940 
2941  // create shm
2942  hDBusSharedMem = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
2943  0, strlen( address ) + 1, _dbus_string_get_const_data(&shm_name) );
2944  _dbus_assert( hDBusSharedMem );
2945 
2946  shared_addr = MapViewOfFile( hDBusSharedMem, FILE_MAP_WRITE, 0, 0, 0 );
2947 
2948  _dbus_assert (shared_addr);
2949 
2950  strcpy( shared_addr, address);
2951 
2952  // cleanup
2953  UnmapViewOfFile( shared_addr );
2954 
2955  _dbus_global_unlock( lock );
2956  _dbus_verbose( "published session bus address at %s\n",_dbus_string_get_const_data (&shm_name) );
2957 
2958  _dbus_string_free( &shm_name );
2959  return TRUE;
2960 }
2961 
2962 void
2963 _dbus_daemon_unpublish_session_bus_address (void)
2964 {
2965  HANDLE lock;
2966 
2967  // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
2968  lock = _dbus_global_lock( cUniqueDBusInitMutex );
2969 
2970  CloseHandle( hDBusSharedMem );
2971 
2972  hDBusSharedMem = NULL;
2973 
2974  ReleaseMutex( hDBusDaemonMutex );
2975 
2976  CloseHandle( hDBusDaemonMutex );
2977 
2978  hDBusDaemonMutex = NULL;
2979 
2980  _dbus_global_unlock( lock );
2981 }
2982 
2983 static dbus_bool_t
2984 _dbus_get_autolaunch_shm (DBusString *address, DBusString *shm_name)
2985 {
2986  HANDLE sharedMem;
2987  char *shared_addr;
2988  int i;
2989 
2990  // read shm
2991  for(i=0;i<20;++i) {
2992  // we know that dbus-daemon is available, so we wait until shm is available
2993  sharedMem = OpenFileMappingA( FILE_MAP_READ, FALSE, _dbus_string_get_const_data(shm_name));
2994  if( sharedMem == 0 )
2995  Sleep( 100 );
2996  if ( sharedMem != 0)
2997  break;
2998  }
2999 
3000  if( sharedMem == 0 )
3001  return FALSE;
3002 
3003  shared_addr = MapViewOfFile( sharedMem, FILE_MAP_READ, 0, 0, 0 );
3004 
3005  if( !shared_addr )
3006  return FALSE;
3007 
3008  _dbus_string_init( address );
3009 
3010  _dbus_string_append( address, shared_addr );
3011 
3012  // cleanup
3013  UnmapViewOfFile( shared_addr );
3014 
3015  CloseHandle( sharedMem );
3016 
3017  return TRUE;
3018 }
3019 
3020 static dbus_bool_t
3021 _dbus_daemon_already_runs (DBusString *address, DBusString *shm_name, const char *scope)
3022 {
3023  HANDLE lock;
3024  HANDLE daemon;
3025  DBusString mutex_name;
3026  dbus_bool_t bRet = TRUE;
3027 
3028  if (!_dbus_get_mutex_name(&mutex_name,scope))
3029  {
3030  _dbus_string_free( &mutex_name );
3031  return FALSE;
3032  }
3033 
3034  // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
3035  lock = _dbus_global_lock( cUniqueDBusInitMutex );
3036 
3037  // do checks
3038  daemon = CreateMutexA( NULL, FALSE, _dbus_string_get_const_data(&mutex_name) );
3039  if(WaitForSingleObject( daemon, 10 ) != WAIT_TIMEOUT)
3040  {
3041  ReleaseMutex (daemon);
3042  CloseHandle (daemon);
3043 
3044  _dbus_global_unlock( lock );
3045  _dbus_string_free( &mutex_name );
3046  return FALSE;
3047  }
3048 
3049  // read shm
3050  bRet = _dbus_get_autolaunch_shm( address, shm_name );
3051 
3052  // cleanup
3053  CloseHandle ( daemon );
3054 
3055  _dbus_global_unlock( lock );
3056  _dbus_string_free( &mutex_name );
3057 
3058  return bRet;
3059 }
3060 
3062 _dbus_get_autolaunch_address (const char *scope, DBusString *address,
3063  DBusError *error)
3064 {
3065  HANDLE mutex;
3066  STARTUPINFOA si;
3067  PROCESS_INFORMATION pi;
3068  dbus_bool_t retval = FALSE;
3069  LPSTR lpFile;
3070  char dbus_exe_path[MAX_PATH];
3071  char dbus_args[MAX_PATH * 2];
3072  const char * daemon_name = DBUS_DAEMON_NAME ".exe";
3073  DBusString shm_name;
3074 
3075  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3076 
3077  if (!_dbus_get_shm_name(&shm_name,scope))
3078  {
3079  dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not determine shm name");
3080  return FALSE;
3081  }
3082 
3083  mutex = _dbus_global_lock ( cDBusAutolaunchMutex );
3084 
3085  if (_dbus_daemon_already_runs(address,&shm_name,scope))
3086  {
3087  _dbus_verbose( "found running dbus daemon at %s\n",
3088  _dbus_string_get_const_data (&shm_name) );
3089  retval = TRUE;
3090  goto out;
3091  }
3092 
3093  if (!SearchPathA(NULL, daemon_name, NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile))
3094  {
3095  // Look in directory containing dbus shared library
3096  HMODULE hmod;
3097  char dbus_module_path[MAX_PATH];
3098  DWORD rc;
3099 
3100  _dbus_verbose( "did not found dbus daemon executable on default search path, "
3101  "trying path where dbus shared library is located");
3102 
3103  hmod = _dbus_win_get_dll_hmodule();
3104  rc = GetModuleFileNameA(hmod, dbus_module_path, sizeof(dbus_module_path));
3105  if (rc <= 0)
3106  {
3107  dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not retrieve dbus shared library file name");
3108  retval = FALSE;
3109  goto out;
3110  }
3111  else
3112  {
3113  char *ext_idx = strrchr(dbus_module_path, '\\');
3114  if (ext_idx)
3115  *ext_idx = '\0';
3116  if (!SearchPathA(dbus_module_path, daemon_name, NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile))
3117  {
3118  dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not find dbus-daemon executable");
3119  retval = FALSE;
3120  printf ("please add the path to %s to your PATH environment variable\n", daemon_name);
3121  printf ("or start the daemon manually\n\n");
3122  goto out;
3123  }
3124  _dbus_verbose( "found dbus daemon executable at %s",dbus_module_path);
3125  }
3126  }
3127 
3128 
3129  // Create process
3130  ZeroMemory( &si, sizeof(si) );
3131  si.cb = sizeof(si);
3132  ZeroMemory( &pi, sizeof(pi) );
3133 
3134  _snprintf(dbus_args, sizeof(dbus_args) - 1, "\"%s\" %s", dbus_exe_path, " --session");
3135 
3136 // argv[i] = "--config-file=bus\\session.conf";
3137 // printf("create process \"%s\" %s\n", dbus_exe_path, dbus_args);
3138  if(CreateProcessA(dbus_exe_path, dbus_args, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
3139  {
3140  CloseHandle (pi.hThread);
3141  CloseHandle (pi.hProcess);
3142  retval = _dbus_get_autolaunch_shm( address, &shm_name );
3143  if (retval == FALSE)
3144  dbus_set_error_const (error, DBUS_ERROR_FAILED, "Failed to get autolaunch address from launched dbus-daemon");
3145  }
3146  else
3147  {
3148  dbus_set_error_const (error, DBUS_ERROR_FAILED, "Failed to launch dbus-daemon");
3149  retval = FALSE;
3150  }
3151 
3152 out:
3153  if (retval)
3154  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3155  else
3156  _DBUS_ASSERT_ERROR_IS_SET (error);
3157 
3158  _dbus_global_unlock (mutex);
3159 
3160  return retval;
3161  }
3162 
3163 
3172  DBusError *error)
3173 {
3174  // TODO
3175  return TRUE;
3176 }
3177 
3185 dbus_int32_t
3187 {
3188  // +/- 1 is needed here!
3189  // no volatile argument with mingw
3190  return InterlockedIncrement (&atomic->value) - 1;
3191 }
3192 
3200 dbus_int32_t
3202 {
3203  // +/- 1 is needed here!
3204  // no volatile argument with mingw
3205  return InterlockedDecrement (&atomic->value) + 1;
3206 }
3207 
3215 dbus_int32_t
3217 {
3218  /* In this situation, GLib issues a MemoryBarrier() and then returns
3219  * atomic->value. However, mingw from mingw.org (not to be confused with
3220  * mingw-w64 from mingw-w64.sf.net) does not have MemoryBarrier in its
3221  * headers, so we have to get a memory barrier some other way.
3222  *
3223  * InterlockedIncrement is older, and is documented on MSDN to be a full
3224  * memory barrier, so let's use that.
3225  */
3226  long dummy = 0;
3227 
3228  InterlockedExchange (&dummy, 1);
3229 
3230  return atomic->value;
3231 }
3232 
3240 void
3242 {
3243 }
3244 
3253 {
3254  return errno == WSAEWOULDBLOCK;
3255 }
3256 
3265 _dbus_get_install_root(char *prefix, int len)
3266 {
3267  //To find the prefix, we cut the filename and also \bin\ if present
3268  DWORD pathLength;
3269  char *lastSlash;
3270  SetLastError( 0 );
3271  pathLength = GetModuleFileNameA(_dbus_win_get_dll_hmodule(), prefix, len);
3272  if ( pathLength == 0 || GetLastError() != 0 ) {
3273  *prefix = '\0';
3274  return FALSE;
3275  }
3276  lastSlash = _mbsrchr(prefix, '\\');
3277  if (lastSlash == NULL) {
3278  *prefix = '\0';
3279  return FALSE;
3280  }
3281  //cut off binary name
3282  lastSlash[1] = 0;
3283 
3284  //cut possible "\\bin"
3285 
3286  //this fails if we are in a double-byte system codepage and the
3287  //folder's name happens to end with the *bytes*
3288  //"\\bin"... (I.e. the second byte of some Han character and then
3289  //the Latin "bin", but that is not likely I think...
3290  if (lastSlash - prefix >= 4 && strnicmp(lastSlash - 4, "\\bin", 4) == 0)
3291  lastSlash[-3] = 0;
3292  else if (lastSlash - prefix >= 10 && strnicmp(lastSlash - 10, "\\bin\\debug", 10) == 0)
3293  lastSlash[-9] = 0;
3294  else if (lastSlash - prefix >= 12 && strnicmp(lastSlash - 12, "\\bin\\release", 12) == 0)
3295  lastSlash[-11] = 0;
3296 
3297  return TRUE;
3298 }
3299 
3313 dbus_bool_t
3314 _dbus_get_config_file_name(DBusString *config_file, char *s)
3315 {
3316  char path[MAX_PATH*2];
3317  int path_size = sizeof(path);
3318 
3319  if (!_dbus_get_install_root(path,path_size))
3320  return FALSE;
3321 
3322  if(strlen(s) + 4 + strlen(path) > sizeof(path)-2)
3323  return FALSE;
3324  strcat(path,"etc\\");
3325  strcat(path,s);
3326  if (_dbus_file_exists(path))
3327  {
3328  // find path from executable
3329  if (!_dbus_string_append (config_file, path))
3330  return FALSE;
3331  }
3332  else
3333  {
3334  if (!_dbus_get_install_root(path,path_size))
3335  return FALSE;
3336  if(strlen(s) + 11 + strlen(path) > sizeof(path)-2)
3337  return FALSE;
3338  strcat(path,"etc\\dbus-1\\");
3339  strcat(path,s);
3340 
3341  if (_dbus_file_exists(path))
3342  {
3343  if (!_dbus_string_append (config_file, path))
3344  return FALSE;
3345  }
3346  else
3347  {
3348  if (!_dbus_get_install_root(path,path_size))
3349  return FALSE;
3350  if(strlen(s) + 4 + strlen(path) > sizeof(path)-2)
3351  return FALSE;
3352  strcat(path,"bus\\");
3353  strcat(path,s);
3354 
3355  if (_dbus_file_exists(path))
3356  {
3357  if (!_dbus_string_append (config_file, path))
3358  return FALSE;
3359  }
3360  }
3361  }
3362  return TRUE;
3363 }
3364 
3365 /* See comment in dbus-sysdeps-unix.c */
3368  DBusString *address,
3369  DBusError *error)
3370 {
3371  /* Probably fill this in with something based on COM? */
3372  *supported = FALSE;
3373  return TRUE;
3374 }
3375 
3391  DBusCredentials *credentials)
3392 {
3393  DBusString homedir;
3394  DBusString dotdir;
3395  const char *homepath;
3396  const char *homedrive;
3397 
3398  _dbus_assert (credentials != NULL);
3400 
3401  if (!_dbus_string_init (&homedir))
3402  return FALSE;
3403 
3404  homedrive = _dbus_getenv("HOMEDRIVE");
3405  if (homedrive != NULL && *homedrive != '\0')
3406  {
3407  _dbus_string_append(&homedir,homedrive);
3408  }
3409 
3410  homepath = _dbus_getenv("HOMEPATH");
3411  if (homepath != NULL && *homepath != '\0')
3412  {
3413  _dbus_string_append(&homedir,homepath);
3414  }
3415 
3416 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
3417  {
3418  const char *override;
3419 
3420  override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
3421  if (override != NULL && *override != '\0')
3422  {
3423  _dbus_string_set_length (&homedir, 0);
3424  if (!_dbus_string_append (&homedir, override))
3425  goto failed;
3426 
3427  _dbus_verbose ("Using fake homedir for testing: %s\n",
3428  _dbus_string_get_const_data (&homedir));
3429  }
3430  else
3431  {
3432  /* Not strictly thread-safe, but if we fail at thread-safety here,
3433  * the worst that will happen is some extra warnings. */
3434  static dbus_bool_t already_warned = FALSE;
3435  if (!already_warned)
3436  {
3437  _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
3438  already_warned = TRUE;
3439  }
3440  }
3441  }
3442 #endif
3443 
3444 #ifdef DBUS_WINCE
3445  /* It's not possible to create a .something directory in Windows CE
3446  using the file explorer. */
3447 #define KEYRING_DIR "dbus-keyrings"
3448 #else
3449 #define KEYRING_DIR ".dbus-keyrings"
3450 #endif
3451 
3452  _dbus_string_init_const (&dotdir, KEYRING_DIR);
3453  if (!_dbus_concat_dir_and_file (&homedir,
3454  &dotdir))
3455  goto failed;
3456 
3457  if (!_dbus_string_copy (&homedir, 0,
3458  directory, _dbus_string_get_length (directory))) {
3459  goto failed;
3460  }
3461 
3462  _dbus_string_free (&homedir);
3463  return TRUE;
3464 
3465  failed:
3466  _dbus_string_free (&homedir);
3467  return FALSE;
3468 }
3469 
3475 dbus_bool_t
3476 _dbus_file_exists (const char *file)
3477 {
3478  DWORD attributes = GetFileAttributesA (file);
3479 
3480  if (attributes != INVALID_FILE_ATTRIBUTES && GetLastError() != ERROR_PATH_NOT_FOUND)
3481  return TRUE;
3482  else
3483  return FALSE;
3484 }
3485 
3493 const char*
3494 _dbus_strerror (int error_number)
3495 {
3496 #ifdef DBUS_WINCE
3497  // TODO
3498  return "unknown";
3499 #else
3500  const char *msg;
3501 
3502  switch (error_number)
3503  {
3504  case WSAEINTR:
3505  return "Interrupted function call";
3506  case WSAEACCES:
3507  return "Permission denied";
3508  case WSAEFAULT:
3509  return "Bad address";
3510  case WSAEINVAL:
3511  return "Invalid argument";
3512  case WSAEMFILE:
3513  return "Too many open files";
3514  case WSAEWOULDBLOCK:
3515  return "Resource temporarily unavailable";
3516  case WSAEINPROGRESS:
3517  return "Operation now in progress";
3518  case WSAEALREADY:
3519  return "Operation already in progress";
3520  case WSAENOTSOCK:
3521  return "Socket operation on nonsocket";
3522  case WSAEDESTADDRREQ:
3523  return "Destination address required";
3524  case WSAEMSGSIZE:
3525  return "Message too long";
3526  case WSAEPROTOTYPE:
3527  return "Protocol wrong type for socket";
3528  case WSAENOPROTOOPT:
3529  return "Bad protocol option";
3530  case WSAEPROTONOSUPPORT:
3531  return "Protocol not supported";
3532  case WSAESOCKTNOSUPPORT:
3533  return "Socket type not supported";
3534  case WSAEOPNOTSUPP:
3535  return "Operation not supported";
3536  case WSAEPFNOSUPPORT:
3537  return "Protocol family not supported";
3538  case WSAEAFNOSUPPORT:
3539  return "Address family not supported by protocol family";
3540  case WSAEADDRINUSE:
3541  return "Address already in use";
3542  case WSAEADDRNOTAVAIL:
3543  return "Cannot assign requested address";
3544  case WSAENETDOWN:
3545  return "Network is down";
3546  case WSAENETUNREACH:
3547  return "Network is unreachable";
3548  case WSAENETRESET:
3549  return "Network dropped connection on reset";
3550  case WSAECONNABORTED:
3551  return "Software caused connection abort";
3552  case WSAECONNRESET:
3553  return "Connection reset by peer";
3554  case WSAENOBUFS:
3555  return "No buffer space available";
3556  case WSAEISCONN:
3557  return "Socket is already connected";
3558  case WSAENOTCONN:
3559  return "Socket is not connected";
3560  case WSAESHUTDOWN:
3561  return "Cannot send after socket shutdown";
3562  case WSAETIMEDOUT:
3563  return "Connection timed out";
3564  case WSAECONNREFUSED:
3565  return "Connection refused";
3566  case WSAEHOSTDOWN:
3567  return "Host is down";
3568  case WSAEHOSTUNREACH:
3569  return "No route to host";
3570  case WSAEPROCLIM:
3571  return "Too many processes";
3572  case WSAEDISCON:
3573  return "Graceful shutdown in progress";
3574  case WSATYPE_NOT_FOUND:
3575  return "Class type not found";
3576  case WSAHOST_NOT_FOUND:
3577  return "Host not found";
3578  case WSATRY_AGAIN:
3579  return "Nonauthoritative host not found";
3580  case WSANO_RECOVERY:
3581  return "This is a nonrecoverable error";
3582  case WSANO_DATA:
3583  return "Valid name, no data record of requested type";
3584  case WSA_INVALID_HANDLE:
3585  return "Specified event object handle is invalid";
3586  case WSA_INVALID_PARAMETER:
3587  return "One or more parameters are invalid";
3588  case WSA_IO_INCOMPLETE:
3589  return "Overlapped I/O event object not in signaled state";
3590  case WSA_IO_PENDING:
3591  return "Overlapped operations will complete later";
3592  case WSA_NOT_ENOUGH_MEMORY:
3593  return "Insufficient memory available";
3594  case WSA_OPERATION_ABORTED:
3595  return "Overlapped operation aborted";
3596 #ifdef WSAINVALIDPROCTABLE
3597 
3598  case WSAINVALIDPROCTABLE:
3599  return "Invalid procedure table from service provider";
3600 #endif
3601 #ifdef WSAINVALIDPROVIDER
3602 
3603  case WSAINVALIDPROVIDER:
3604  return "Invalid service provider version number";
3605 #endif
3606 #ifdef WSAPROVIDERFAILEDINIT
3607 
3608  case WSAPROVIDERFAILEDINIT:
3609  return "Unable to initialize a service provider";
3610 #endif
3611 
3612  case WSASYSCALLFAILURE:
3613  return "System call failure";
3614  }
3615  msg = strerror (error_number);
3616  if (msg == NULL)
3617  msg = "unknown";
3618 
3619  return msg;
3620 #endif //DBUS_WINCE
3621 }
3622 
3630 void
3631 _dbus_win_set_error_from_win_error (DBusError *error,
3632  int code)
3633 {
3634  char *msg;
3635 
3636  /* As we want the English message, use the A API */
3637  FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
3638  FORMAT_MESSAGE_IGNORE_INSERTS |
3639  FORMAT_MESSAGE_FROM_SYSTEM,
3640  NULL, code, MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US),
3641  (LPSTR) &msg, 0, NULL);
3642  if (msg)
3643  {
3644  char *msg_copy;
3645 
3646  msg_copy = dbus_malloc (strlen (msg));
3647  strcpy (msg_copy, msg);
3648  LocalFree (msg);
3649 
3650  dbus_set_error (error, "win32.error", "%s", msg_copy);
3651  }
3652  else
3653  dbus_set_error (error, "win32.error", "Unknown error code %d or FormatMessage failed", code);
3654 }
3655 
3656 void
3657 _dbus_win_warn_win_error (const char *message,
3658  unsigned long code)
3659 {
3660  DBusError error;
3661 
3662  dbus_error_init (&error);
3663  _dbus_win_set_error_from_win_error (&error, code);
3664  _dbus_warn ("%s: %s\n", message, error.message);
3665  dbus_error_free (&error);
3666 }
3667 
3677  DBusError *error)
3678 {
3679  const char *filename_c;
3680 
3681  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3682 
3683  filename_c = _dbus_string_get_const_data (filename);
3684 
3685  if (RemoveDirectoryA (filename_c) == 0)
3686  {
3687  char *emsg = _dbus_win_error_string (GetLastError ());
3688  dbus_set_error (error, _dbus_win_error_from_last_error (),
3689  "Failed to remove directory %s: %s",
3690  filename_c, emsg);
3691  _dbus_win_free_error_string (emsg);
3692  return FALSE;
3693  }
3694 
3695  return TRUE;
3696 }
3697 
3706 {
3707  if (_dbus_string_get_length (filename) > 0)
3708  return _dbus_string_get_byte (filename, 1) == ':'
3709  || _dbus_string_get_byte (filename, 0) == '\\'
3710  || _dbus_string_get_byte (filename, 0) == '/';
3711  else
3712  return FALSE;
3713 }
3714 
3717 {
3718  return FALSE;
3719 }
3720 
3722 /* tests in dbus-sysdeps-util.c */
3723