D-Bus  1.14.99
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-2021 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 #include "dbus-internals.h"
34 #include "dbus-sha.h"
35 #include "dbus-sysdeps.h"
36 #include "dbus-threads.h"
37 #include "dbus-protocol.h"
38 #include "dbus-string.h"
39 #include "dbus-sysdeps.h"
40 #include "dbus-sysdeps-win.h"
41 #include "dbus-protocol.h"
42 #include "dbus-hash.h"
43 #include "dbus-sockets-win.h"
44 #include "dbus-list.h"
45 #include "dbus-nonce.h"
46 #include "dbus-credentials.h"
47 
48 #include <windows.h>
49 #include <wincrypt.h>
50 #include <iphlpapi.h>
51 #ifdef HAVE_AFUNIX_H
52 #include <afunix.h>
53 #endif
54 
55 /* Declarations missing in mingw's and windows sdk 7.0 headers */
56 extern BOOL WINAPI ConvertStringSidToSidA (LPCSTR StringSid, PSID *Sid);
57 extern BOOL WINAPI ConvertSidToStringSidA (PSID Sid, LPSTR *StringSid);
58 
59 #include <stdio.h>
60 #include <stdlib.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 #ifndef O_BINARY
78 #define O_BINARY 0
79 #endif
80 
81 #ifndef PROCESS_QUERY_LIMITED_INFORMATION
82 /* MinGW32 < 4 does not define this value in its headers */
83 #define PROCESS_QUERY_LIMITED_INFORMATION (0x1000)
84 #endif
85 
86 typedef int socklen_t;
87 
88 /* uncomment to enable windows event based poll implementation */
89 //#define USE_CHRIS_IMPL
90 
91 void
92 _dbus_win_set_errno (int err)
93 {
94 #ifdef DBUS_WINCE
95  SetLastError (err);
96 #else
97  errno = err;
98 #endif
99 }
100 
101 static BOOL is_winxp_sp3_or_lower (void);
102 
103 /*
104  * _MIB_TCPROW_EX and friends are not available in system headers
105  * and are mapped to attribute identical ...OWNER_PID typedefs.
106  */
107 typedef MIB_TCPROW_OWNER_PID _MIB_TCPROW_EX;
108 typedef MIB_TCPTABLE_OWNER_PID MIB_TCPTABLE_EX;
109 typedef PMIB_TCPTABLE_OWNER_PID PMIB_TCPTABLE_EX;
110 typedef DWORD (WINAPI *ProcAllocateAndGetTcpExtTableFromStack)(PMIB_TCPTABLE_EX*,BOOL,HANDLE,DWORD,DWORD);
111 
112 /* Not protected by a lock, but if we miss a write, all that
113  * happens is that the lazy initialization will happen in two threads
114  * concurrently - it results in the same value either way so that's OK */
115 static ProcAllocateAndGetTcpExtTableFromStack lpfnAllocateAndGetTcpExTableFromStack = NULL;
116 
122 static BOOL
123 load_ex_ip_helper_procedures(void)
124 {
125  HMODULE hModule = LoadLibrary ("iphlpapi.dll");
126  if (hModule == NULL)
127  {
128  _dbus_verbose ("could not load iphlpapi.dll\n");
129  return FALSE;
130  }
131 
132  lpfnAllocateAndGetTcpExTableFromStack = (ProcAllocateAndGetTcpExtTableFromStack) (void (*)(void))GetProcAddress (hModule, "AllocateAndGetTcpExTableFromStack");
133  if (lpfnAllocateAndGetTcpExTableFromStack == NULL)
134  {
135  _dbus_verbose ("could not find function AllocateAndGetTcpExTableFromStack in iphlpapi.dll\n");
136  return FALSE;
137  }
138  return TRUE;
139 }
140 
147 static dbus_pid_t
148 get_pid_from_extended_tcp_table(int peer_port)
149 {
150  dbus_pid_t result;
151  DWORD errorCode, size = 0, i;
152  MIB_TCPTABLE_OWNER_PID *tcp_table;
153 
154  if ((errorCode =
155  GetExtendedTcpTable (NULL, &size, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0)) == ERROR_INSUFFICIENT_BUFFER)
156  {
157  tcp_table = (MIB_TCPTABLE_OWNER_PID *) dbus_malloc (size);
158  if (tcp_table == NULL)
159  {
160  _dbus_verbose ("Error allocating memory\n");
161  return 0;
162  }
163  }
164  else
165  {
166  _dbus_win_warn_win_error ("unexpected error returned from GetExtendedTcpTable", errorCode);
167  return 0;
168  }
169 
170  if ((errorCode = GetExtendedTcpTable (tcp_table, &size, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0)) != NO_ERROR)
171  {
172  _dbus_verbose ("Error fetching tcp table %d\n", (int)errorCode);
173  dbus_free (tcp_table);
174  return 0;
175  }
176 
177  result = 0;
178  for (i = 0; i < tcp_table->dwNumEntries; i++)
179  {
180  MIB_TCPROW_OWNER_PID *p = &tcp_table->table[i];
181  int local_address = ntohl (p->dwLocalAddr);
182  int local_port = ntohs (p->dwLocalPort);
183  if (p->dwState == MIB_TCP_STATE_ESTAB
184  && local_address == INADDR_LOOPBACK && local_port == peer_port)
185  result = p->dwOwningPid;
186  }
187 
188  dbus_free (tcp_table);
189  _dbus_verbose ("got pid %lu\n", result);
190  return result;
191 }
192 
200 static dbus_pid_t
201 get_pid_from_tcp_ex_table(int peer_port)
202 {
203  dbus_pid_t result;
204  DWORD errorCode, i;
205  PMIB_TCPTABLE_EX tcp_table = NULL;
206 
207  if (!load_ex_ip_helper_procedures ())
208  {
209  _dbus_verbose
210  ("Error not been able to load iphelper procedures\n");
211  return 0;
212  }
213 
214  errorCode = lpfnAllocateAndGetTcpExTableFromStack (&tcp_table, TRUE, GetProcessHeap(), 0, 2);
215 
216  if (errorCode != NO_ERROR)
217  {
218  _dbus_verbose
219  ("Error not been able to call AllocateAndGetTcpExTableFromStack()\n");
220  return 0;
221  }
222 
223  result = 0;
224  for (i = 0; i < tcp_table->dwNumEntries; i++)
225  {
226  _MIB_TCPROW_EX *p = &tcp_table->table[i];
227  int local_port = ntohs (p->dwLocalPort);
228  int local_address = ntohl (p->dwLocalAddr);
229  if (local_address == INADDR_LOOPBACK && local_port == peer_port)
230  {
231  result = p->dwOwningPid;
232  break;
233  }
234  }
235 
236  HeapFree (GetProcessHeap(), 0, tcp_table);
237  _dbus_verbose ("got pid %lu\n", result);
238  return result;
239 }
240 
246 static dbus_pid_t
247 _dbus_get_peer_pid_from_tcp_handle (int handle)
248 {
249  struct sockaddr_storage addr;
250  socklen_t len = sizeof (addr);
251  int peer_port;
252 
253  dbus_pid_t result;
254  dbus_bool_t is_localhost = FALSE;
255 
256  getpeername (handle, (struct sockaddr *) &addr, &len);
257 
258  if (addr.ss_family == AF_INET)
259  {
260  struct sockaddr_in *s = (struct sockaddr_in *) &addr;
261  peer_port = ntohs (s->sin_port);
262  is_localhost = (ntohl (s->sin_addr.s_addr) == INADDR_LOOPBACK);
263  }
264  else if (addr.ss_family == AF_INET6)
265  {
266  _dbus_verbose ("FIXME [61922]: IPV6 support not working on windows\n");
267  return 0;
268  /*
269  struct sockaddr_in6 *s = (struct sockaddr_in6 * )&addr;
270  peer_port = ntohs (s->sin6_port);
271  is_localhost = (memcmp(s->sin6_addr.s6_addr, in6addr_loopback.s6_addr, 16) == 0);
272  _dbus_verbose ("IPV6 %08x %08x\n", s->sin6_addr.s6_addr, in6addr_loopback.s6_addr);
273  */
274  }
275  else
276  {
277  _dbus_verbose ("no idea what address family %d is\n", addr.ss_family);
278  return 0;
279  }
280 
281  if (!is_localhost)
282  {
283  _dbus_verbose ("could not fetch process id from remote process\n");
284  return 0;
285  }
286 
287  if (peer_port == 0)
288  {
289  _dbus_verbose
290  ("Error not been able to fetch tcp peer port from connection\n");
291  return 0;
292  }
293 
294  _dbus_verbose ("trying to get peer's pid\n");
295 
296  result = get_pid_from_extended_tcp_table (peer_port);
297  if (result > 0)
298  return result;
299  result = get_pid_from_tcp_ex_table (peer_port);
300  return result;
301 }
302 
303 /* Convert GetLastError() to a dbus error. */
304 const char*
305 _dbus_win_error_from_last_error (void)
306 {
307  switch (GetLastError())
308  {
309  case 0:
310  return DBUS_ERROR_FAILED;
311 
312  case ERROR_NO_MORE_FILES:
313  case ERROR_TOO_MANY_OPEN_FILES:
314  return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
315 
316  case ERROR_ACCESS_DENIED:
317  case ERROR_CANNOT_MAKE:
319 
320  case ERROR_NOT_ENOUGH_MEMORY:
321  return DBUS_ERROR_NO_MEMORY;
322 
323  case ERROR_FILE_EXISTS:
324  return DBUS_ERROR_FILE_EXISTS;
325 
326  case ERROR_FILE_NOT_FOUND:
327  case ERROR_PATH_NOT_FOUND:
329 
330  default:
331  return DBUS_ERROR_FAILED;
332  }
333 }
334 
335 
336 char*
337 _dbus_win_error_string (int error_number)
338 {
339  char *msg;
340 
341  FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
342  FORMAT_MESSAGE_IGNORE_INSERTS |
343  FORMAT_MESSAGE_FROM_SYSTEM,
344  NULL, error_number, 0,
345  (LPSTR) &msg, 0, NULL);
346 
347  if (msg[strlen (msg) - 1] == '\n')
348  msg[strlen (msg) - 1] = '\0';
349  if (msg[strlen (msg) - 1] == '\r')
350  msg[strlen (msg) - 1] = '\0';
351 
352  return msg;
353 }
354 
355 void
356 _dbus_win_free_error_string (char *string)
357 {
358  LocalFree (string);
359 }
360 
381 int
383  DBusString *buffer,
384  int count)
385 {
386  int bytes_read;
387  int start;
388  char *data;
389 
390  _dbus_assert (count >= 0);
391 
392  start = _dbus_string_get_length (buffer);
393 
394  if (!_dbus_string_lengthen (buffer, count))
395  {
396  _dbus_win_set_errno (ENOMEM);
397  return -1;
398  }
399 
400  data = _dbus_string_get_data_len (buffer, start, count);
401 
402  again:
403 
404  _dbus_verbose ("recv: count=%d fd=%Iu\n", count, fd.sock);
405  bytes_read = recv (fd.sock, data, count, 0);
406 
407  if (bytes_read == SOCKET_ERROR)
408  {
409  DBUS_SOCKET_SET_ERRNO();
410  _dbus_verbose ("recv: failed: %s (%d)\n", _dbus_strerror (errno), errno);
411  bytes_read = -1;
412  }
413  else
414  _dbus_verbose ("recv: = %d\n", bytes_read);
415 
416  if (bytes_read < 0)
417  {
418  if (errno == EINTR)
419  goto again;
420  else
421  {
422  /* put length back (note that this doesn't actually realloc anything) */
423  _dbus_string_set_length (buffer, start);
424  return -1;
425  }
426  }
427  else
428  {
429  /* put length back (doesn't actually realloc) */
430  _dbus_string_set_length (buffer, start + bytes_read);
431 
432 #if 0
433  if (bytes_read > 0)
434  _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
435 #endif
436 
437  return bytes_read;
438  }
439 }
440 
451 int
453  const DBusString *buffer,
454  int start,
455  int len)
456 {
457  const char *data;
458  int bytes_written;
459 
460  data = _dbus_string_get_const_data_len (buffer, start, len);
461 
462  again:
463 
464  _dbus_verbose ("send: len=%d fd=%Iu\n", len, fd.sock);
465  bytes_written = send (fd.sock, data, len, 0);
466 
467  if (bytes_written == SOCKET_ERROR)
468  {
469  DBUS_SOCKET_SET_ERRNO();
470  _dbus_verbose ("send: failed: %s\n", _dbus_strerror_from_errno ());
471  bytes_written = -1;
472  }
473  else
474  _dbus_verbose ("send: = %d\n", bytes_written);
475 
476  if (bytes_written < 0 && errno == EINTR)
477  goto again;
478 
479 #if 0
480  if (bytes_written > 0)
481  _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
482 #endif
483 
484  return bytes_written;
485 }
486 
487 
497  DBusError *error)
498 {
499  _dbus_assert (fd != NULL);
500  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
501 
502  again:
503  if (closesocket (fd->sock) == SOCKET_ERROR)
504  {
505  DBUS_SOCKET_SET_ERRNO ();
506 
507  if (errno == EINTR)
508  goto again;
509 
510  dbus_set_error (error, _dbus_error_from_errno (errno),
511  "Could not close socket: socket=%Iu, , %s",
512  fd->sock, _dbus_strerror_from_errno ());
513  _dbus_socket_invalidate (fd);
514  return FALSE;
515  }
516  _dbus_verbose ("socket=%Iu, \n", fd->sock);
517 
518  _dbus_socket_invalidate (fd);
519  return TRUE;
520 }
521 
529 static void
530 _dbus_win_handle_set_close_on_exec (HANDLE handle)
531 {
532  if ( !SetHandleInformation( (HANDLE) handle,
533  HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE,
534  0 /*disable both flags*/ ) )
535  {
536  _dbus_win_warn_win_error ("Disabling socket handle inheritance failed:", GetLastError());
537  }
538 }
539 
549  DBusError *error)
550 {
551  u_long one = 1;
552 
553  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
554 
555  if (ioctlsocket (handle.sock, FIONBIO, &one) == SOCKET_ERROR)
556  {
557  DBUS_SOCKET_SET_ERRNO ();
558  dbus_set_error (error, _dbus_error_from_errno (errno),
559  "Failed to set socket %Iu to nonblocking: %s",
560  handle.sock, _dbus_strerror_from_errno ());
561  return FALSE;
562  }
563 
564  return TRUE;
565 }
566 
567 
588 int
590  const DBusString *buffer1,
591  int start1,
592  int len1,
593  const DBusString *buffer2,
594  int start2,
595  int len2)
596 {
597  WSABUF vectors[2];
598  const char *data1;
599  const char *data2;
600  int rc;
601  DWORD bytes_written;
602 
603  _dbus_assert (buffer1 != NULL);
604  _dbus_assert (start1 >= 0);
605  _dbus_assert (start2 >= 0);
606  _dbus_assert (len1 >= 0);
607  _dbus_assert (len2 >= 0);
608 
609 
610  data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
611 
612  if (buffer2 != NULL)
613  data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
614  else
615  {
616  data2 = NULL;
617  start2 = 0;
618  len2 = 0;
619  }
620 
621  vectors[0].buf = (char*) data1;
622  vectors[0].len = len1;
623  vectors[1].buf = (char*) data2;
624  vectors[1].len = len2;
625 
626  again:
627 
628  _dbus_verbose ("WSASend: len1+2=%d+%d fd=%Iu\n", len1, len2, fd.sock);
629  rc = WSASend (fd.sock,
630  vectors,
631  data2 ? 2 : 1,
632  &bytes_written,
633  0,
634  NULL,
635  NULL);
636 
637  if (rc == SOCKET_ERROR)
638  {
639  DBUS_SOCKET_SET_ERRNO ();
640  _dbus_verbose ("WSASend: failed: %s\n", _dbus_strerror_from_errno ());
641  bytes_written = (DWORD) -1;
642  }
643  else
644  _dbus_verbose ("WSASend: = %ld\n", bytes_written);
645 
646  if (bytes_written == (DWORD) -1 && errno == EINTR)
647  goto again;
648 
649  return bytes_written;
650 }
651 
652 #if 0
653 
662 int
663 _dbus_connect_named_pipe (const char *path,
664  DBusError *error)
665 {
666  _dbus_assert_not_reached ("not implemented");
667 }
668 
669 #endif
670 
675 _dbus_win_startup_winsock (void)
676 {
677  /* Straight from MSDN, deuglified */
678 
679  /* Protected by _DBUS_LOCK_sysdeps */
680  static dbus_bool_t beenhere = FALSE;
681 
682  WORD wVersionRequested;
683  WSADATA wsaData;
684  int err;
685 
686  if (!_DBUS_LOCK (sysdeps))
687  return FALSE;
688 
689  if (beenhere)
690  goto out;
691 
692  wVersionRequested = MAKEWORD (2, 0);
693 
694  err = WSAStartup (wVersionRequested, &wsaData);
695  if (err != 0)
696  {
697  _dbus_assert_not_reached ("Could not initialize WinSock");
698  _dbus_abort ();
699  }
700 
701  /* Confirm that the WinSock DLL supports 2.0. Note that if the DLL
702  * supports versions greater than 2.0 in addition to 2.0, it will
703  * still return 2.0 in wVersion since that is the version we
704  * requested.
705  */
706  if (LOBYTE (wsaData.wVersion) != 2 ||
707  HIBYTE (wsaData.wVersion) != 0)
708  {
709  _dbus_assert_not_reached ("No usable WinSock found");
710  _dbus_abort ();
711  }
712 
713  beenhere = TRUE;
714 
715 out:
716  _DBUS_UNLOCK (sysdeps);
717  return TRUE;
718 }
719 
720 
721 
722 
723 
724 
725 
726 
727 
728 /************************************************************************
729 
730  UTF / string code
731 
732  ************************************************************************/
733 
737 int _dbus_printf_string_upper_bound (const char *format,
738  va_list args)
739 {
740  /* MSVCRT's vsnprintf semantics are a bit different */
741  char buf[1024];
742  int bufsize;
743  int len;
744  va_list args_copy;
745 
746  bufsize = sizeof (buf);
747  DBUS_VA_COPY (args_copy, args);
748  len = _vsnprintf (buf, bufsize - 1, format, args_copy);
749  va_end (args_copy);
750 
751  while (len == -1) /* try again */
752  {
753  char *p;
754 
755  bufsize *= 2;
756 
757  p = malloc (bufsize);
758 
759  if (p == NULL)
760  return -1;
761 
762  DBUS_VA_COPY (args_copy, args);
763  len = _vsnprintf (p, bufsize - 1, format, args_copy);
764  va_end (args_copy);
765  free (p);
766  }
767 
768  return len;
769 }
770 
771 
779 wchar_t *
780 _dbus_win_utf8_to_utf16 (const char *str,
781  DBusError *error)
782 {
783  DBusString s;
784  int n;
785  wchar_t *retval;
786 
787  _dbus_string_init_const (&s, str);
788 
789  if (!_dbus_string_validate_utf8 (&s, 0, _dbus_string_get_length (&s)))
790  {
791  dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid UTF-8");
792  return NULL;
793  }
794 
795  n = MultiByteToWideChar (CP_UTF8, 0, str, -1, NULL, 0);
796 
797  if (n == 0)
798  {
799  _dbus_win_set_error_from_win_error (error, GetLastError ());
800  return NULL;
801  }
802 
803  retval = dbus_new (wchar_t, n);
804 
805  if (!retval)
806  {
807  _DBUS_SET_OOM (error);
808  return NULL;
809  }
810 
811  if (MultiByteToWideChar (CP_UTF8, 0, str, -1, retval, n) != n)
812  {
813  dbus_free (retval);
814  dbus_set_error_const (error, DBUS_ERROR_FAILED, "MultiByteToWideChar inconsistency");
815  return NULL;
816  }
817 
818  return retval;
819 }
820 
828 char *
829 _dbus_win_utf16_to_utf8 (const wchar_t *str,
830  DBusError *error)
831 {
832  int n;
833  char *retval;
834 
835  n = WideCharToMultiByte (CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
836 
837  if (n == 0)
838  {
839  _dbus_win_set_error_from_win_error (error, GetLastError ());
840  return NULL;
841  }
842 
843  retval = dbus_malloc (n);
844 
845  if (!retval)
846  {
847  _DBUS_SET_OOM (error);
848  return NULL;
849  }
850 
851  if (WideCharToMultiByte (CP_UTF8, 0, str, -1, retval, n, NULL, NULL) != n)
852  {
853  dbus_free (retval);
854  dbus_set_error_const (error, DBUS_ERROR_FAILED, "WideCharToMultiByte inconsistency");
855  return NULL;
856  }
857 
858  return retval;
859 }
860 
861 
862 
863 
864 
865 
866 /************************************************************************
867 
868 
869  ************************************************************************/
870 
872 _dbus_win_account_to_sid (const wchar_t *waccount,
873  void **ppsid,
874  DBusError *error)
875 {
876  dbus_bool_t retval = FALSE;
877  DWORD sid_length, wdomain_length;
878  SID_NAME_USE use;
879  wchar_t *wdomain;
880 
881  *ppsid = NULL;
882 
883  sid_length = 0;
884  wdomain_length = 0;
885  if (!LookupAccountNameW (NULL, waccount, NULL, &sid_length,
886  NULL, &wdomain_length, &use) &&
887  GetLastError () != ERROR_INSUFFICIENT_BUFFER)
888  {
889  _dbus_win_set_error_from_win_error (error, GetLastError ());
890  return FALSE;
891  }
892 
893  *ppsid = dbus_malloc (sid_length);
894  if (!*ppsid)
895  {
896  _DBUS_SET_OOM (error);
897  return FALSE;
898  }
899 
900  wdomain = dbus_new (wchar_t, wdomain_length);
901  if (!wdomain)
902  {
903  _DBUS_SET_OOM (error);
904  goto out1;
905  }
906 
907  if (!LookupAccountNameW (NULL, waccount, (PSID) *ppsid, &sid_length,
908  wdomain, &wdomain_length, &use))
909  {
910  _dbus_win_set_error_from_win_error (error, GetLastError ());
911  goto out2;
912  }
913 
914  if (!IsValidSid ((PSID) *ppsid))
915  {
916  dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid SID");
917  goto out2;
918  }
919 
920  retval = TRUE;
921 
922 out2:
923  dbus_free (wdomain);
924 out1:
925  if (!retval)
926  {
927  dbus_free (*ppsid);
928  *ppsid = NULL;
929  }
930 
931  return retval;
932 }
933 
943 unsigned long
945 {
946  return _dbus_getpid ();
947 }
948 
949 #ifndef DBUS_WINCE
950 
951 static BOOL
952 is_winxp_sp3_or_lower (void)
953 {
954  OSVERSIONINFOEX osvi;
955  DWORDLONG dwlConditionMask = 0;
956  int op=VER_LESS_EQUAL;
957 
958  // Initialize the OSVERSIONINFOEX structure.
959 
960  ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
961  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
962  osvi.dwMajorVersion = 5;
963  osvi.dwMinorVersion = 1;
964  osvi.wServicePackMajor = 3;
965  osvi.wServicePackMinor = 0;
966 
967  // Initialize the condition mask.
968 
969  VER_SET_CONDITION (dwlConditionMask, VER_MAJORVERSION, op);
970  VER_SET_CONDITION (dwlConditionMask, VER_MINORVERSION, op);
971  VER_SET_CONDITION (dwlConditionMask, VER_SERVICEPACKMAJOR, op);
972  VER_SET_CONDITION (dwlConditionMask, VER_SERVICEPACKMINOR, op);
973 
974  // Perform the test.
975 
976  return VerifyVersionInfo(
977  &osvi,
978  VER_MAJORVERSION | VER_MINORVERSION |
979  VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
980  dwlConditionMask);
981 }
982 
989 _dbus_getsid(char **sid, dbus_pid_t process_id)
990 {
991  HANDLE process_token = INVALID_HANDLE_VALUE;
992  TOKEN_USER *token_user = NULL;
993  DWORD n;
994  PSID psid;
995  int retval = FALSE;
996 
997  HANDLE process_handle;
998  if (process_id == 0)
999  process_handle = GetCurrentProcess();
1000  else if (is_winxp_sp3_or_lower())
1001  process_handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, process_id);
1002  else
1003  process_handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, process_id);
1004 
1005  if (!OpenProcessToken (process_handle, TOKEN_QUERY, &process_token))
1006  {
1007  _dbus_win_warn_win_error ("OpenProcessToken failed", GetLastError ());
1008  goto failed;
1009  }
1010  if ((!GetTokenInformation (process_token, TokenUser, NULL, 0, &n)
1011  && GetLastError () != ERROR_INSUFFICIENT_BUFFER)
1012  || (token_user = alloca (n)) == NULL
1013  || !GetTokenInformation (process_token, TokenUser, token_user, n, &n))
1014  {
1015  _dbus_win_warn_win_error ("GetTokenInformation failed", GetLastError ());
1016  goto failed;
1017  }
1018  psid = token_user->User.Sid;
1019  if (!IsValidSid (psid))
1020  {
1021  _dbus_verbose("%s invalid sid\n",__FUNCTION__);
1022  goto failed;
1023  }
1024  if (!ConvertSidToStringSidA (psid, sid))
1025  {
1026  _dbus_verbose("%s invalid sid\n",__FUNCTION__);
1027  goto failed;
1028  }
1029 //okay:
1030  retval = TRUE;
1031 
1032 failed:
1033  CloseHandle (process_handle);
1034  if (process_token != INVALID_HANDLE_VALUE)
1035  CloseHandle (process_token);
1036 
1037  _dbus_verbose("_dbus_getsid() got '%s' and returns %d\n", *sid, retval);
1038  return retval;
1039 }
1040 #endif
1041 
1042 /************************************************************************
1043 
1044  pipes
1045 
1046  ************************************************************************/
1047 
1062  DBusSocket *fd2,
1063  dbus_bool_t blocking,
1064  DBusError *error)
1065 {
1066  SOCKET temp, socket1 = -1, socket2 = -1;
1067  struct sockaddr_in saddr;
1068  int len;
1069  u_long arg;
1070 
1071  if (!_dbus_win_startup_winsock ())
1072  {
1073  _DBUS_SET_OOM (error);
1074  return FALSE;
1075  }
1076 
1077  temp = socket (AF_INET, SOCK_STREAM, 0);
1078  if (temp == INVALID_SOCKET)
1079  {
1080  DBUS_SOCKET_SET_ERRNO ();
1081  goto out0;
1082  }
1083 
1084  _DBUS_ZERO (saddr);
1085  saddr.sin_family = AF_INET;
1086  saddr.sin_port = 0;
1087  saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
1088 
1089  if (bind (temp, (struct sockaddr *)&saddr, sizeof (saddr)) == SOCKET_ERROR)
1090  {
1091  DBUS_SOCKET_SET_ERRNO ();
1092  goto out0;
1093  }
1094 
1095  if (listen (temp, 1) == SOCKET_ERROR)
1096  {
1097  DBUS_SOCKET_SET_ERRNO ();
1098  goto out0;
1099  }
1100 
1101  len = sizeof (saddr);
1102  if (getsockname (temp, (struct sockaddr *)&saddr, &len) == SOCKET_ERROR)
1103  {
1104  DBUS_SOCKET_SET_ERRNO ();
1105  goto out0;
1106  }
1107 
1108  socket1 = socket (AF_INET, SOCK_STREAM, 0);
1109  if (socket1 == INVALID_SOCKET)
1110  {
1111  DBUS_SOCKET_SET_ERRNO ();
1112  goto out0;
1113  }
1114 
1115  if (connect (socket1, (struct sockaddr *)&saddr, len) == SOCKET_ERROR)
1116  {
1117  DBUS_SOCKET_SET_ERRNO ();
1118  goto out1;
1119  }
1120 
1121  socket2 = accept (temp, (struct sockaddr *) &saddr, &len);
1122  if (socket2 == INVALID_SOCKET)
1123  {
1124  DBUS_SOCKET_SET_ERRNO ();
1125  goto out1;
1126  }
1127 
1128  if (!blocking)
1129  {
1130  arg = 1;
1131  if (ioctlsocket (socket1, FIONBIO, &arg) == SOCKET_ERROR)
1132  {
1133  DBUS_SOCKET_SET_ERRNO ();
1134  goto out2;
1135  }
1136 
1137  arg = 1;
1138  if (ioctlsocket (socket2, FIONBIO, &arg) == SOCKET_ERROR)
1139  {
1140  DBUS_SOCKET_SET_ERRNO ();
1141  goto out2;
1142  }
1143  }
1144 
1145  fd1->sock = socket1;
1146  fd2->sock = socket2;
1147 
1148  _dbus_verbose ("full-duplex pipe %Iu:%Iu <-> %Iu:%Iu\n",
1149  fd1->sock, socket1, fd2->sock, socket2);
1150 
1151  closesocket (temp);
1152 
1153  return TRUE;
1154 
1155 out2:
1156  closesocket (socket2);
1157 out1:
1158  closesocket (socket1);
1159 out0:
1160  closesocket (temp);
1161 
1162  dbus_set_error (error, _dbus_error_from_errno (errno),
1163  "Could not setup socket pair: %s",
1165 
1166  return FALSE;
1167 }
1168 
1169 #ifdef DBUS_ENABLE_VERBOSE_MODE
1170 static dbus_bool_t
1171 _dbus_dump_fd_events (DBusPollFD *fds, int n_fds)
1172 {
1173  DBusString msg = _DBUS_STRING_INIT_INVALID;
1174  dbus_bool_t result = FALSE;
1175  int i;
1176 
1177  if (!_dbus_string_init (&msg))
1178  goto oom;
1179 
1180  for (i = 0; i < n_fds; i++)
1181  {
1182  DBusPollFD *fdp = &fds[i];
1183  if (!_dbus_string_append (&msg, i > 0 ? "\n\t" : "\t"))
1184  goto oom;
1185 
1186  if ((fdp->events & _DBUS_POLLIN) &&
1187  !_dbus_string_append_printf (&msg, "R:%Iu ", fdp->fd.sock))
1188  goto oom;
1189 
1190  if ((fdp->events & _DBUS_POLLOUT) &&
1191  !_dbus_string_append_printf (&msg, "W:%Iu ", fdp->fd.sock))
1192  goto oom;
1193 
1194  if (!_dbus_string_append_printf (&msg, "E:%Iu", fdp->fd.sock))
1195  goto oom;
1196  }
1197 
1198  _dbus_verbose ("%s\n", _dbus_string_get_const_data (&msg));
1199  result = TRUE;
1200 oom:
1201  _dbus_string_free (&msg);
1202  return result;
1203 }
1204 
1205 #ifdef USE_CHRIS_IMPL
1206 static dbus_bool_t
1207 _dbus_dump_fd_revents (DBusPollFD *fds, int n_fds)
1208 {
1209  DBusString msg = _DBUS_STRING_INIT_INVALID;
1210  dbus_bool_t result = FALSE;
1211  int i;
1212 
1213  if (!_dbus_string_init (&msg))
1214  goto oom;
1215 
1216  for (i = 0; i < n_fds; i++)
1217  {
1218  DBusPollFD *fdp = &fds[i];
1219  if (!_dbus_string_append (&msg, i > 0 ? "\n\t" : "\t"))
1220  goto oom;
1221 
1222  if ((fdp->revents & _DBUS_POLLIN) &&
1223  !_dbus_string_append_printf (&msg, "R:%Iu ", fdp->fd.sock))
1224  goto oom;
1225 
1226  if ((fdp->revents & _DBUS_POLLOUT) &&
1227  !_dbus_string_append_printf (&msg, "W:%Iu ", fdp->fd.sock))
1228  goto oom;
1229 
1230  if ((fdp->revents & _DBUS_POLLERR) &&
1231  !_dbus_string_append_printf (&msg, "E:%Iu", fdp->fd.sock))
1232  goto oom;
1233  }
1234 
1235  _dbus_verbose ("%s\n", _dbus_string_get_const_data (&msg));
1236  result = TRUE;
1237 oom:
1238  _dbus_string_free (&msg);
1239  return result;
1240 }
1241 #else
1242 static dbus_bool_t
1243 _dbus_dump_fdset (DBusPollFD *fds, int n_fds, fd_set *read_set, fd_set *write_set, fd_set *err_set)
1244 {
1245  DBusString msg = _DBUS_STRING_INIT_INVALID;
1246  dbus_bool_t result = FALSE;
1247  int i;
1248 
1249  if (!_dbus_string_init (&msg))
1250  goto oom;
1251 
1252  for (i = 0; i < n_fds; i++)
1253  {
1254  DBusPollFD *fdp = &fds[i];
1255 
1256  if (!_dbus_string_append (&msg, i > 0 ? "\n\t" : "\t"))
1257  goto oom;
1258 
1259  if (FD_ISSET (fdp->fd.sock, read_set) &&
1260  !_dbus_string_append_printf (&msg, "R:%Iu ", fdp->fd.sock))
1261  goto oom;
1262 
1263  if (FD_ISSET (fdp->fd.sock, write_set) &&
1264  !_dbus_string_append_printf (&msg, "W:%Iu ", fdp->fd.sock))
1265  goto oom;
1266 
1267  if (FD_ISSET (fdp->fd.sock, err_set) &&
1268  !_dbus_string_append_printf (&msg, "E:%Iu", fdp->fd.sock))
1269  goto oom;
1270  }
1271  _dbus_verbose ("%s\n", _dbus_string_get_const_data (&msg));
1272  result = TRUE;
1273 oom:
1274  _dbus_string_free (&msg);
1275  return result;
1276 }
1277 #endif
1278 #endif
1279 
1280 #ifdef USE_CHRIS_IMPL
1289 static int
1290 _dbus_poll_events (DBusPollFD *fds,
1291  int n_fds,
1292  int timeout_milliseconds)
1293 {
1294  int ret = 0;
1295  int i;
1296  DWORD ready;
1297 
1298 #define DBUS_STACK_WSAEVENTS 256
1299  WSAEVENT eventsOnStack[DBUS_STACK_WSAEVENTS];
1300  WSAEVENT *pEvents = NULL;
1301  if (n_fds > DBUS_STACK_WSAEVENTS)
1302  pEvents = calloc(sizeof(WSAEVENT), n_fds);
1303  else
1304  pEvents = eventsOnStack;
1305 
1306  if (pEvents == NULL)
1307  {
1308  _dbus_win_set_errno (ENOMEM);
1309  ret = -1;
1310  goto oom;
1311  }
1312 
1313 #ifdef DBUS_ENABLE_VERBOSE_MODE
1314  _dbus_verbose ("_dbus_poll: to=%d", timeout_milliseconds);
1315  if (!_dbus_dump_fd_events (fds, n_fds))
1316  {
1317  _dbus_win_set_errno (ENOMEM);
1318  ret = -1;
1319  goto oom;
1320  }
1321 #endif
1322 
1323  for (i = 0; i < n_fds; i++)
1324  pEvents[i] = WSA_INVALID_EVENT;
1325 
1326  for (i = 0; i < n_fds; i++)
1327  {
1328  DBusPollFD *fdp = &fds[i];
1329  WSAEVENT ev;
1330  long lNetworkEvents = FD_OOB;
1331 
1332  ev = WSACreateEvent();
1333 
1334  if (fdp->events & _DBUS_POLLIN)
1335  lNetworkEvents |= FD_READ | FD_ACCEPT | FD_CLOSE;
1336 
1337  if (fdp->events & _DBUS_POLLOUT)
1338  lNetworkEvents |= FD_WRITE | FD_CONNECT;
1339 
1340  WSAEventSelect (fdp->fd.sock, ev, lNetworkEvents);
1341 
1342  pEvents[i] = ev;
1343  }
1344 
1345  ready = WSAWaitForMultipleEvents (n_fds, pEvents, FALSE, timeout_milliseconds, FALSE);
1346 
1347  if (ready == WSA_WAIT_FAILED)
1348  {
1349  DBUS_SOCKET_SET_ERRNO ();
1350  if (errno != WSAEWOULDBLOCK)
1351  _dbus_verbose ("WSAWaitForMultipleEvents: failed: %s\n", _dbus_strerror_from_errno ());
1352  ret = -1;
1353  }
1354  else if (ready == WSA_WAIT_TIMEOUT)
1355  {
1356  _dbus_verbose ("WSAWaitForMultipleEvents: WSA_WAIT_TIMEOUT\n");
1357  ret = 0;
1358  }
1359  else if (ready < (WSA_WAIT_EVENT_0 + n_fds))
1360  {
1361  for (i = 0; i < n_fds; i++)
1362  {
1363  DBusPollFD *fdp = &fds[i];
1364  WSANETWORKEVENTS ne;
1365 
1366  fdp->revents = 0;
1367 
1368  WSAEnumNetworkEvents (fdp->fd.sock, pEvents[i], &ne);
1369 
1370  if (ne.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
1371  fdp->revents |= _DBUS_POLLIN;
1372 
1373  if (ne.lNetworkEvents & (FD_WRITE | FD_CONNECT))
1374  fdp->revents |= _DBUS_POLLOUT;
1375 
1376  if (ne.lNetworkEvents & (FD_OOB))
1377  fdp->revents |= _DBUS_POLLERR;
1378 
1379  if(ne.lNetworkEvents)
1380  ret++;
1381 
1382  WSAEventSelect (fdp->fd.sock, pEvents[i], 0);
1383  }
1384 #ifdef DBUS_ENABLE_VERBOSE_MODE
1385  _dbus_verbose ("_dbus_poll: to=%d", timeout_milliseconds);
1386  if (!_dbus_dump_fd_revents (fds, n_fds))
1387  {
1388  _dbus_win_set_errno (ENOMEM);
1389  ret = -1;
1390  goto oom;
1391  }
1392 #endif
1393  }
1394  else
1395  {
1396  _dbus_verbose ("WSAWaitForMultipleEvents: failed for unknown reason!");
1397  ret = -1;
1398  }
1399 
1400 oom:
1401  if (pEvents != NULL)
1402  {
1403  for (i = 0; i < n_fds; i++)
1404  {
1405  if (pEvents[i] != WSA_INVALID_EVENT)
1406  WSACloseEvent (pEvents[i]);
1407  }
1408  if (n_fds > DBUS_STACK_WSAEVENTS)
1409  free (pEvents);
1410  }
1411 
1412  return ret;
1413 }
1414 #else
1423 static int
1424 _dbus_poll_select (DBusPollFD *fds,
1425  int n_fds,
1426  int timeout_milliseconds)
1427 {
1428  fd_set read_set, write_set, err_set;
1429  SOCKET max_fd = 0;
1430  int i;
1431  struct timeval tv;
1432  int ready;
1433 
1434  FD_ZERO (&read_set);
1435  FD_ZERO (&write_set);
1436  FD_ZERO (&err_set);
1437 #ifdef DBUS_ENABLE_VERBOSE_MODE
1438  _dbus_verbose("_dbus_poll: to=%d\n", timeout_milliseconds);
1439  if (!_dbus_dump_fd_events (fds, n_fds))
1440  return -1;
1441 #endif
1442 
1443  for (i = 0; i < n_fds; i++)
1444  {
1445  DBusPollFD *fdp = &fds[i];
1446 
1447  if (fdp->events & _DBUS_POLLIN)
1448  FD_SET (fdp->fd.sock, &read_set);
1449 
1450  if (fdp->events & _DBUS_POLLOUT)
1451  FD_SET (fdp->fd.sock, &write_set);
1452 
1453  FD_SET (fdp->fd.sock, &err_set);
1454 
1455  max_fd = MAX (max_fd, fdp->fd.sock);
1456  }
1457 
1458  // Avoid random lockups with send(), for lack of a better solution so far
1459  tv.tv_sec = timeout_milliseconds < 0 ? 1 : timeout_milliseconds / 1000;
1460  tv.tv_usec = timeout_milliseconds < 0 ? 0 : (timeout_milliseconds % 1000) * 1000;
1461 
1462  ready = select (max_fd + 1, &read_set, &write_set, &err_set, &tv);
1463 
1464  if (DBUS_SOCKET_API_RETURNS_ERROR (ready))
1465  {
1466  DBUS_SOCKET_SET_ERRNO ();
1467  if (errno != WSAEWOULDBLOCK)
1468  _dbus_verbose ("select: failed: %s\n", _dbus_strerror_from_errno ());
1469  }
1470  else if (ready == 0)
1471  _dbus_verbose ("select: = 0\n");
1472  else
1473  if (ready > 0)
1474  {
1475 #ifdef DBUS_ENABLE_VERBOSE_MODE
1476  _dbus_verbose ("select: to=%d\n", ready);
1477  if (!_dbus_dump_fdset (fds, n_fds, &read_set, &write_set, &err_set))
1478  {
1479  _dbus_win_set_errno (ENOMEM);
1480  return -1;
1481  }
1482 #endif
1483  for (i = 0; i < n_fds; i++)
1484  {
1485  DBusPollFD *fdp = &fds[i];
1486 
1487  fdp->revents = 0;
1488 
1489  if (FD_ISSET (fdp->fd.sock, &read_set))
1490  fdp->revents |= _DBUS_POLLIN;
1491 
1492  if (FD_ISSET (fdp->fd.sock, &write_set))
1493  fdp->revents |= _DBUS_POLLOUT;
1494 
1495  if (FD_ISSET (fdp->fd.sock, &err_set))
1496  fdp->revents |= _DBUS_POLLERR;
1497  }
1498  }
1499  return ready;
1500 }
1501 #endif
1502 
1511 int
1513  int n_fds,
1514  int timeout_milliseconds)
1515 {
1516 #ifdef USE_CHRIS_IMPL
1517  return _dbus_poll_events (fds, n_fds, timeout_milliseconds);
1518 #else
1519  return _dbus_poll_select (fds, n_fds, timeout_milliseconds);
1520 #endif
1521 }
1522 
1523 /******************************************************************************
1524 
1525 Original CVS version of dbus-sysdeps.c
1526 
1527 ******************************************************************************/
1528 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
1529 /* dbus-sysdeps.c Wrappers around system/libc features (internal to D-Bus implementation)
1530  *
1531  * Copyright (C) 2002, 2003 Red Hat, Inc.
1532  * Copyright (C) 2003 CodeFactory AB
1533  * Copyright (C) 2005 Novell, Inc.
1534  *
1535  * Licensed under the Academic Free License version 2.1
1536  *
1537  * This program is free software; you can redistribute it and/or modify
1538  * it under the terms of the GNU General Public License as published by
1539  * the Free Software Foundation; either version 2 of the License, or
1540  * (at your option) any later version.
1541  *
1542  * This program is distributed in the hope that it will be useful,
1543  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1544  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1545  * GNU General Public License for more details.
1546  *
1547  * You should have received a copy of the GNU General Public License
1548  * along with this program; if not, write to the Free Software
1549  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1550  *
1551  */
1552 
1553 
1559 void
1560 _dbus_exit (int code)
1561 {
1562  _exit (code);
1563 }
1564 
1576 DBusSocket
1577 _dbus_connect_tcp_socket (const char *host,
1578  const char *port,
1579  const char *family,
1580  DBusError *error)
1581 {
1582  return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
1583 }
1584 
1585 DBusSocket
1586 _dbus_connect_tcp_socket_with_nonce (const char *host,
1587  const char *port,
1588  const char *family,
1589  const char *noncefile,
1590  DBusError *error)
1591 {
1592  int saved_errno = 0;
1593  DBusList *connect_errors = NULL;
1594  DBusSocket fd = DBUS_SOCKET_INIT;
1595  int res;
1596  struct addrinfo hints;
1597  struct addrinfo *ai = NULL;
1598  const struct addrinfo *tmp;
1599  DBusError *connect_error;
1600 
1601  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1602 
1603  if (!_dbus_win_startup_winsock ())
1604  {
1605  _DBUS_SET_OOM (error);
1606  return _dbus_socket_get_invalid ();
1607  }
1608 
1609  _DBUS_ZERO (hints);
1610 
1611  if (!family)
1612  hints.ai_family = AF_UNSPEC;
1613  else if (!strcmp(family, "ipv4"))
1614  hints.ai_family = AF_INET;
1615  else if (!strcmp(family, "ipv6"))
1616  hints.ai_family = AF_INET6;
1617  else
1618  {
1619  dbus_set_error (error,
1621  "Unknown address family %s", family);
1622  return _dbus_socket_get_invalid ();
1623  }
1624  hints.ai_protocol = IPPROTO_TCP;
1625  hints.ai_socktype = SOCK_STREAM;
1626 #ifdef AI_ADDRCONFIG
1627  hints.ai_flags = AI_ADDRCONFIG;
1628 #else
1629  hints.ai_flags = 0;
1630 #endif
1631 
1632  if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
1633  {
1634  dbus_set_error (error,
1635  _dbus_error_from_errno (res),
1636  "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1637  host, port, _dbus_strerror (res), res);
1638  goto out;
1639  }
1640 
1641  tmp = ai;
1642  while (tmp)
1643  {
1644  if ((fd.sock = socket (tmp->ai_family, SOCK_STREAM, 0)) == INVALID_SOCKET)
1645  {
1646  saved_errno = _dbus_get_low_level_socket_errno ();
1647  dbus_set_error (error,
1648  _dbus_error_from_errno (saved_errno),
1649  "Failed to open socket: %s",
1650  _dbus_strerror (saved_errno));
1651  _dbus_assert (!_dbus_socket_is_valid (fd));
1652  goto out;
1653  }
1654  _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1655 
1656  if (connect (fd.sock, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) == SOCKET_ERROR)
1657  {
1658  saved_errno = _dbus_get_low_level_socket_errno ();
1659  _dbus_close_socket (&fd, NULL);
1660 
1661  connect_error = dbus_new0 (DBusError, 1);
1662 
1663  if (connect_error == NULL)
1664  {
1665  _DBUS_SET_OOM (error);
1666  goto out;
1667  }
1668 
1669  dbus_error_init (connect_error);
1670  _dbus_set_error_with_inet_sockaddr (connect_error,
1671  tmp->ai_addr, tmp->ai_addrlen,
1672  "Failed to connect to socket",
1673  saved_errno);
1674 
1675  if (!_dbus_list_append (&connect_errors, connect_error))
1676  {
1677  dbus_error_free (connect_error);
1678  dbus_free (connect_error);
1679  _DBUS_SET_OOM (error);
1680  goto out;
1681  }
1682 
1683  tmp = tmp->ai_next;
1684  continue;
1685  }
1686 
1687  break;
1688  }
1689 
1690  if (!_dbus_socket_is_valid (fd))
1691  {
1692  _dbus_combine_tcp_errors (&connect_errors, "Failed to connect",
1693  host, port, error);
1694  goto out;
1695  }
1696 
1697  if (noncefile != NULL)
1698  {
1699  DBusString noncefileStr;
1700  dbus_bool_t ret;
1701  _dbus_string_init_const (&noncefileStr, noncefile);
1702  ret = _dbus_send_nonce (fd, &noncefileStr, error);
1703 
1704  if (!ret)
1705  {
1706  _dbus_close_socket (&fd, NULL);
1707  goto out;
1708  }
1709  }
1710 
1711  /* Every SOCKET is also a HANDLE. */
1712  _dbus_win_handle_set_close_on_exec ((HANDLE) fd.sock);
1713 
1714  if (!_dbus_set_socket_nonblocking (fd, error))
1715  {
1716  _dbus_close_socket (&fd, NULL);
1717  goto out;
1718  }
1719 
1720 out:
1721  if (ai != NULL)
1722  freeaddrinfo (ai);
1723 
1724  while ((connect_error = _dbus_list_pop_first (&connect_errors)))
1725  {
1726  dbus_error_free (connect_error);
1727  dbus_free (connect_error);
1728  }
1729 
1730  return fd;
1731 }
1732 
1748 int
1749 _dbus_listen_tcp_socket (const char *host,
1750  const char *port,
1751  const char *family,
1752  DBusString *retport,
1753  const char **retfamily,
1754  DBusSocket **fds_p,
1755  DBusError *error)
1756 {
1757  int saved_errno;
1758  int nlisten_fd = 0, res, i, port_num = -1;
1759  DBusList *bind_errors = NULL;
1760  DBusError *bind_error = NULL;
1761  DBusSocket *listen_fd = NULL;
1762  struct addrinfo hints;
1763  struct addrinfo *ai, *tmp;
1764  dbus_bool_t have_ipv4 = FALSE;
1765  dbus_bool_t have_ipv6 = FALSE;
1766 
1767  // On Vista, sockaddr_gen must be a sockaddr_in6, and not a sockaddr_in6_old
1768  //That's required for family == IPv6(which is the default on Vista if family is not given)
1769  //So we use our own union instead of sockaddr_gen:
1770 
1771  typedef union {
1772  struct sockaddr Address;
1773  struct sockaddr_in AddressIn;
1774  struct sockaddr_in6 AddressIn6;
1775  } mysockaddr_gen;
1776 
1777  *fds_p = NULL;
1778  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1779 
1780  if (!_dbus_win_startup_winsock ())
1781  {
1782  _DBUS_SET_OOM (error);
1783  return -1;
1784  }
1785 
1786  _DBUS_ZERO (hints);
1787 
1788  if (!family)
1789  hints.ai_family = AF_UNSPEC;
1790  else if (!strcmp(family, "ipv4"))
1791  hints.ai_family = AF_INET;
1792  else if (!strcmp(family, "ipv6"))
1793  hints.ai_family = AF_INET6;
1794  else
1795  {
1796  dbus_set_error (error,
1798  "Unknown address family %s", family);
1799  return -1;
1800  }
1801 
1802  hints.ai_protocol = IPPROTO_TCP;
1803  hints.ai_socktype = SOCK_STREAM;
1804 #ifdef AI_ADDRCONFIG
1805  hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
1806 #else
1807  hints.ai_flags = AI_PASSIVE;
1808 #endif
1809 
1810  redo_lookup_with_port:
1811  ai = NULL;
1812  if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
1813  {
1814  dbus_set_error (error,
1815  _dbus_error_from_errno (res),
1816  "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1817  host ? host : "*", port, _dbus_strerror(res), res);
1818  return -1;
1819  }
1820 
1821  tmp = ai;
1822  while (tmp)
1823  {
1824  const int reuseaddr = 1, tcp_nodelay_on = 1;
1825  DBusSocket fd = DBUS_SOCKET_INIT, *newlisten_fd;
1826 
1827  if ((fd.sock = socket (tmp->ai_family, SOCK_STREAM, 0)) == INVALID_SOCKET)
1828  {
1829  saved_errno = _dbus_get_low_level_socket_errno ();
1830  dbus_set_error (error,
1831  _dbus_error_from_errno (saved_errno),
1832  "Failed to open socket: %s",
1833  _dbus_strerror (saved_errno));
1834  _dbus_assert (!_dbus_socket_is_valid (fd));
1835  goto failed;
1836  }
1837  _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1838 
1839  if (setsockopt (fd.sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuseaddr, sizeof(reuseaddr)) == SOCKET_ERROR)
1840  {
1841  saved_errno = _dbus_get_low_level_socket_errno ();
1842  _dbus_warn ("Failed to set socket option \"%s:%s\": %s",
1843  host ? host : "*", port, _dbus_strerror (saved_errno));
1844  }
1845 
1846  /* Nagle's algorithm imposes a huge delay on the initial messages
1847  going over TCP. */
1848  if (setsockopt (fd.sock, IPPROTO_TCP, TCP_NODELAY, (const char *)&tcp_nodelay_on, sizeof (tcp_nodelay_on)) == SOCKET_ERROR)
1849  {
1850  saved_errno = _dbus_get_low_level_socket_errno ();
1851  _dbus_warn ("Failed to set TCP_NODELAY socket option \"%s:%s\": %s",
1852  host ? host : "*", port, _dbus_strerror (saved_errno));
1853  }
1854 
1855  if (bind (fd.sock, (struct sockaddr *) tmp->ai_addr, tmp->ai_addrlen) == SOCKET_ERROR)
1856  {
1857  saved_errno = _dbus_get_low_level_socket_errno ();
1858  closesocket (fd.sock);
1859 
1860  /*
1861  * We don't treat this as a fatal error, because there might be
1862  * other addresses that we can listen on. In particular:
1863  *
1864  * - If saved_errno is WSAEADDRINUSE after we
1865  * "goto redo_lookup_with_port" after binding a port on one of the
1866  * possible addresses, we will try to bind that same port on
1867  * every address, including the same address again for a second
1868  * time, which will fail with WSAEADDRINUSE .
1869  *
1870  * - If saved_errno is WSAEADDRINUSE, it might be because binding to
1871  * an IPv6 address implicitly binds to a corresponding IPv4
1872  * address or vice versa.
1873  *
1874  * - If saved_errno is WSAEADDRNOTAVAIL when we asked for family
1875  * AF_UNSPEC, it might be because IPv6 is disabled for this
1876  * particular interface.
1877  */
1878  bind_error = dbus_new0 (DBusError, 1);
1879 
1880  if (bind_error == NULL)
1881  {
1882  _DBUS_SET_OOM (error);
1883  goto failed;
1884  }
1885 
1886  dbus_error_init (bind_error);
1887  _dbus_set_error_with_inet_sockaddr (bind_error, tmp->ai_addr, tmp->ai_addrlen,
1888  "Failed to bind socket",
1889  saved_errno);
1890 
1891  if (!_dbus_list_append (&bind_errors, bind_error))
1892  {
1893  dbus_error_free (bind_error);
1894  dbus_free (bind_error);
1895  _DBUS_SET_OOM (error);
1896  goto failed;
1897  }
1898 
1899  /* Try the next address, maybe it will work better */
1900  tmp = tmp->ai_next;
1901  continue;
1902  }
1903 
1904  if (listen (fd.sock, 30 /* backlog */) == SOCKET_ERROR)
1905  {
1906  saved_errno = _dbus_get_low_level_socket_errno ();
1907  closesocket (fd.sock);
1908  _dbus_set_error_with_inet_sockaddr (error, tmp->ai_addr, tmp->ai_addrlen,
1909  "Failed to listen on socket",
1910  saved_errno);
1911  goto failed;
1912  }
1913 
1914  newlisten_fd = dbus_realloc(listen_fd, sizeof(DBusSocket)*(nlisten_fd+1));
1915  if (!newlisten_fd)
1916  {
1917  closesocket (fd.sock);
1919  "Failed to allocate file handle array");
1920  goto failed;
1921  }
1922  listen_fd = newlisten_fd;
1923  listen_fd[nlisten_fd] = fd;
1924  nlisten_fd++;
1925 
1926  if (tmp->ai_addr->sa_family == AF_INET)
1927  have_ipv4 = TRUE;
1928  else if (tmp->ai_addr->sa_family == AF_INET6)
1929  have_ipv6 = TRUE;
1930 
1931  if (!_dbus_string_get_length(retport))
1932  {
1933  /* If the user didn't specify a port, or used 0, then
1934  the kernel chooses a port. After the first address
1935  is bound to, we need to force all remaining addresses
1936  to use the same port */
1937  if (!port || !strcmp(port, "0"))
1938  {
1939  mysockaddr_gen addr;
1940  socklen_t addrlen = sizeof(addr);
1941  char portbuf[NI_MAXSERV];
1942 
1943  if (getsockname (fd.sock, &addr.Address, &addrlen) == SOCKET_ERROR ||
1944  (res = getnameinfo (&addr.Address, addrlen, NULL, 0,
1945  portbuf, sizeof(portbuf),
1946  NI_NUMERICSERV)) != 0)
1947  {
1948  saved_errno = _dbus_get_low_level_socket_errno ();
1949  dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1950  "Failed to resolve port \"%s:%s\": %s",
1951  host ? host : "*", port, _dbus_strerror (saved_errno));
1952  goto failed;
1953  }
1954  if (!_dbus_string_append(retport, portbuf))
1955  {
1957  goto failed;
1958  }
1959 
1960  /* Release current address list & redo lookup */
1961  port = _dbus_string_get_const_data(retport);
1962  freeaddrinfo(ai);
1963  goto redo_lookup_with_port;
1964  }
1965  else
1966  {
1967  if (!_dbus_string_append(retport, port))
1968  {
1970  goto failed;
1971  }
1972  }
1973  }
1974 
1975  tmp = tmp->ai_next;
1976  }
1977  freeaddrinfo(ai);
1978  ai = NULL;
1979 
1980  if (!nlisten_fd)
1981  {
1982  _dbus_combine_tcp_errors (&bind_errors, "Failed to bind", host, port, error);
1983  goto failed;
1984  }
1985 
1986  if (have_ipv4 && !have_ipv6)
1987  *retfamily = "ipv4";
1988  else if (!have_ipv4 && have_ipv6)
1989  *retfamily = "ipv6";
1990 
1991  sscanf(_dbus_string_get_const_data(retport), "%d", &port_num);
1992 
1993  for (i = 0 ; i < nlisten_fd ; i++)
1994  {
1995  _dbus_win_handle_set_close_on_exec ((HANDLE) listen_fd[i].sock);
1996  if (!_dbus_set_socket_nonblocking (listen_fd[i], error))
1997  {
1998  goto failed;
1999  }
2000  }
2001 
2002  *fds_p = listen_fd;
2003 
2004  /* This list might be non-empty even on success, because we might be
2005  * ignoring WSAEADDRINUSE or WSAEADDRNOTAVAIL */
2006  while ((bind_error = _dbus_list_pop_first (&bind_errors)))
2007  {
2008  dbus_error_free (bind_error);
2009  dbus_free (bind_error);
2010  }
2011  return nlisten_fd;
2012 
2013  failed:
2014  if (ai)
2015  freeaddrinfo(ai);
2016  for (i = 0 ; i < nlisten_fd ; i++)
2017  closesocket (listen_fd[i].sock);
2018 
2019  while ((bind_error = _dbus_list_pop_first (&bind_errors)))
2020  {
2021  dbus_error_free (bind_error);
2022  dbus_free (bind_error);
2023  }
2024 
2025  dbus_free(listen_fd);
2026  return -1;
2027 }
2028 
2029 
2037 DBusSocket
2039 {
2040  DBusSocket client_fd;
2041 
2042  retry:
2043  client_fd.sock = accept (listen_fd.sock, NULL, NULL);
2044 
2045  if (!_dbus_socket_is_valid (client_fd))
2046  {
2047  DBUS_SOCKET_SET_ERRNO ();
2048  if (errno == EINTR)
2049  goto retry;
2050  }
2051 
2052  _dbus_verbose ("client fd %Iu accepted\n", client_fd.sock);
2053 
2054  return client_fd;
2055 }
2056 
2057 
2058 
2059 
2062  DBusError *error)
2063 {
2064 /* FIXME: for the session bus credentials shouldn't matter (?), but
2065  * for the system bus they are presumably essential. A rough outline
2066  * of a way to implement the credential transfer would be this:
2067  *
2068  * client waits to *read* a byte.
2069  *
2070  * server creates a named pipe with a random name, sends a byte
2071  * contining its length, and its name.
2072  *
2073  * client reads the name, connects to it (using Win32 API).
2074  *
2075  * server waits for connection to the named pipe, then calls
2076  * ImpersonateNamedPipeClient(), notes its now-current credentials,
2077  * calls RevertToSelf(), closes its handles to the named pipe, and
2078  * is done. (Maybe there is some other way to get the SID of a named
2079  * pipe client without having to use impersonation?)
2080  *
2081  * client closes its handles and is done.
2082  *
2083  * Ralf: Why not sending credentials over the given this connection ?
2084  * Using named pipes makes it impossible to be connected from a unix client.
2085  *
2086  */
2087  int bytes_written;
2088  DBusString buf;
2089 
2090  _dbus_string_init_const_len (&buf, "\0", 1);
2091 again:
2092  bytes_written = _dbus_write_socket (handle, &buf, 0, 1 );
2093 
2094  if (bytes_written < 0 && errno == EINTR)
2095  goto again;
2096 
2097  if (bytes_written < 0)
2098  {
2099  dbus_set_error (error, _dbus_error_from_errno (errno),
2100  "Failed to write credentials byte: %s",
2102  return FALSE;
2103  }
2104  else if (bytes_written == 0)
2105  {
2107  "wrote zero bytes writing credentials byte");
2108  return FALSE;
2109  }
2110  else
2111  {
2112  _dbus_assert (bytes_written == 1);
2113  _dbus_verbose ("wrote 1 zero byte, credential sending isn't implemented yet\n");
2114  return TRUE;
2115  }
2116  return TRUE;
2117 }
2118 
2119 #ifdef HAVE_AFUNIX_H
2120 /*
2121  * Returns false with no error set if the socket is non-AF_UNIX
2122  * (contrary to our usual convention).
2123  *
2124  * Returns false with an error set on failure to identify it.
2125  */
2126 static dbus_bool_t
2127 _dbus_socket_is_af_unix (DBusSocket s,
2128  DBusError *error)
2129 {
2130  struct sockaddr_un saddr;
2131  int len;
2132 
2133  len = sizeof (saddr);
2134  if (getsockname (s.sock, (struct sockaddr *)&saddr, &len) == SOCKET_ERROR)
2135  {
2136  DBUS_SOCKET_SET_ERRNO ();
2137  dbus_set_error (error, _dbus_error_from_errno (errno),
2138  "Failed to getsockname: %s",
2140  return FALSE;
2141  }
2142 
2143  return saddr.sun_family == AF_UNIX;
2144 }
2145 
2151 static dbus_pid_t
2152 _dbus_get_peer_pid_from_uds_handle (int handle)
2153 {
2154  DWORD pid, drc;
2155 
2156  if (WSAIoctl (handle, SIO_AF_UNIX_GETPEERPID,
2157  NULL, 0U,
2158  &pid, sizeof (pid), &drc,
2159  NULL, NULL) == SOCKET_ERROR)
2160  {
2161  _dbus_verbose ("failed to get peer's pid\n");
2162  return 0;
2163  }
2164 
2165  return pid;
2166 }
2167 #endif
2168 
2189  DBusCredentials *credentials,
2190  DBusError *error)
2191 {
2192  int bytes_read = 0;
2193  DBusString buf;
2194 #ifdef HAVE_AFUNIX_H
2195  dbus_bool_t uds = FALSE;
2196 #endif
2197 
2198  char *sid = NULL;
2199  dbus_pid_t pid;
2200  int retval = FALSE;
2201 
2202  // could fail due too OOM
2203  if (_dbus_string_init (&buf))
2204  {
2205  bytes_read = _dbus_read_socket (handle, &buf, 1 );
2206 
2207  if (bytes_read > 0)
2208  _dbus_verbose ("got one zero byte from server\n");
2209 
2210  _dbus_string_free (&buf);
2211  }
2212 
2213 #ifdef HAVE_AFUNIX_H
2214  uds = _dbus_socket_is_af_unix (handle, error);
2215  if (dbus_error_is_set (error))
2216  return FALSE;
2217 
2218  if (uds)
2219  pid = _dbus_get_peer_pid_from_uds_handle (handle.sock);
2220  else
2221 #endif
2222  pid = _dbus_get_peer_pid_from_tcp_handle (handle.sock);
2223  if (pid == 0)
2224  return TRUE;
2225 
2226  _dbus_credentials_add_pid (credentials, pid);
2227 
2228  if (_dbus_getsid (&sid, pid))
2229  {
2230  if (!_dbus_credentials_add_windows_sid (credentials, sid))
2231  goto out;
2232  }
2233 
2234  retval = TRUE;
2235 
2236 out:
2237  if (sid)
2238  LocalFree (sid);
2239 
2240  return retval;
2241 }
2242 
2253 {
2254  /* TODO */
2255  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2256  return TRUE;
2257 }
2258 
2259 
2272  const DBusString *next_component)
2273 {
2274  dbus_bool_t dir_ends_in_slash;
2275  dbus_bool_t file_starts_with_slash;
2276 
2277  if (_dbus_string_get_length (dir) == 0 ||
2278  _dbus_string_get_length (next_component) == 0)
2279  return TRUE;
2280 
2281  dir_ends_in_slash =
2282  ('/' == _dbus_string_get_byte (dir, _dbus_string_get_length (dir) - 1) ||
2283  '\\' == _dbus_string_get_byte (dir, _dbus_string_get_length (dir) - 1));
2284 
2285  file_starts_with_slash =
2286  ('/' == _dbus_string_get_byte (next_component, 0) ||
2287  '\\' == _dbus_string_get_byte (next_component, 0));
2288 
2289  if (dir_ends_in_slash && file_starts_with_slash)
2290  {
2291  _dbus_string_shorten (dir, 1);
2292  }
2293  else if (!(dir_ends_in_slash || file_starts_with_slash))
2294  {
2295  if (!_dbus_string_append_byte (dir, '\\'))
2296  return FALSE;
2297  }
2298 
2299  return _dbus_string_copy (next_component, 0, dir,
2300  _dbus_string_get_length (dir));
2301 }
2302 
2303 /*---------------- DBusCredentials ----------------------------------*/
2304 
2314  const DBusString *username,
2315  DBusCredentialsAddFlags flags,
2316  DBusError *error)
2317 {
2318  if (!_dbus_credentials_add_windows_sid (credentials,
2319  _dbus_string_get_const_data (username)))
2320  {
2321  _DBUS_SET_OOM (error);
2322  return FALSE;
2323  }
2324 
2325  return TRUE;
2326 }
2327 
2338 {
2339  dbus_bool_t retval = FALSE;
2340  char *sid = NULL;
2341 
2342  if (!_dbus_getsid(&sid, _dbus_getpid()))
2343  goto failed;
2344 
2345  if (!_dbus_credentials_add_pid (credentials, _dbus_getpid()))
2346  goto failed;
2347 
2348  if (!_dbus_credentials_add_windows_sid (credentials,sid))
2349  goto failed;
2350 
2351  retval = TRUE;
2352  goto end;
2353 failed:
2354  retval = FALSE;
2355 end:
2356  if (sid)
2357  LocalFree(sid);
2358 
2359  return retval;
2360 }
2361 
2376 {
2377  dbus_bool_t retval = FALSE;
2378  char *sid = NULL;
2379 
2380  if (!_dbus_getsid(&sid, _dbus_getpid()))
2381  return FALSE;
2382 
2383  retval = _dbus_string_append (str,sid);
2384 
2385  LocalFree(sid);
2386  return retval;
2387 }
2388 
2393 dbus_pid_t
2395 {
2396  return GetCurrentProcessId ();
2397 }
2398 
2402 dbus_uid_t
2404 {
2405  return DBUS_UID_UNSET;
2406 }
2407 
2409 #define NANOSECONDS_PER_SECOND 1000000000
2411 #define MICROSECONDS_PER_SECOND 1000000
2413 #define MILLISECONDS_PER_SECOND 1000
2415 #define NANOSECONDS_PER_MILLISECOND 1000000
2417 #define MICROSECONDS_PER_MILLISECOND 1000
2418 
2423 void
2424 _dbus_sleep_milliseconds (int milliseconds)
2425 {
2426  Sleep (milliseconds);
2427 }
2428 
2429 
2437 void
2438 _dbus_get_real_time (long *tv_sec,
2439  long *tv_usec)
2440 {
2441  FILETIME ft;
2442  dbus_uint64_t time64;
2443 
2444  GetSystemTimeAsFileTime (&ft);
2445 
2446  memcpy (&time64, &ft, sizeof (time64));
2447 
2448  /* Convert from 100s of nanoseconds since 1601-01-01
2449  * to Unix epoch. Yes, this is Y2038 unsafe.
2450  */
2451  time64 -= DBUS_INT64_CONSTANT (116444736000000000);
2452  time64 /= 10;
2453 
2454  if (tv_sec)
2455  *tv_sec = time64 / 1000000;
2456 
2457  if (tv_usec)
2458  *tv_usec = time64 % 1000000;
2459 }
2460 
2468 void
2470  long *tv_usec)
2471 {
2472  /* no implementation yet, fall back to wall-clock time */
2473  _dbus_get_real_time (tv_sec, tv_usec);
2474 }
2475 
2479 void
2481 {
2482 }
2483 
2494  DBusError *error)
2495 {
2496  const char *filename_c;
2497 
2498  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2499 
2500  filename_c = _dbus_string_get_const_data (filename);
2501 
2502  if (!CreateDirectoryA (filename_c, NULL))
2503  {
2505  "Failed to create directory %s: %s\n",
2506  filename_c, _dbus_strerror_from_errno ());
2507  return FALSE;
2508  }
2509  else
2510  return TRUE;
2511 }
2512 
2523  DBusError *error)
2524 {
2525  const char *filename_c;
2526 
2527  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2528 
2529  filename_c = _dbus_string_get_const_data (filename);
2530 
2531  if (!CreateDirectoryA (filename_c, NULL))
2532  {
2533  if (GetLastError () == ERROR_ALREADY_EXISTS)
2534  return TRUE;
2535 
2537  "Failed to create directory %s: %s\n",
2538  filename_c, _dbus_strerror_from_errno ());
2539  return FALSE;
2540  }
2541  else
2542  return TRUE;
2543 }
2544 
2545 
2557  int n_bytes,
2558  DBusError *error)
2559 {
2560  int old_len;
2561  unsigned char *p;
2562  HCRYPTPROV hprov;
2563 
2564  old_len = _dbus_string_get_length (str);
2565 
2566  if (!_dbus_string_lengthen (str, n_bytes))
2567  {
2568  _DBUS_SET_OOM (error);
2569  return FALSE;
2570  }
2571 
2572  p = _dbus_string_get_udata_len (str, old_len, n_bytes);
2573 
2574  if (!CryptAcquireContext (&hprov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
2575  {
2576  _DBUS_SET_OOM (error);
2577  return FALSE;
2578  }
2579 
2580  if (!CryptGenRandom (hprov, n_bytes, p))
2581  {
2582  _DBUS_SET_OOM (error);
2583  CryptReleaseContext (hprov, 0);
2584  return FALSE;
2585  }
2586 
2587  CryptReleaseContext (hprov, 0);
2588 
2589  return TRUE;
2590 }
2591 
2597 const char*
2599 {
2600  /* Protected by _DBUS_LOCK_sysdeps */
2601  static const char* tmpdir = NULL;
2602  static char buf[1000];
2603 
2604  if (!_DBUS_LOCK (sysdeps))
2605  return NULL;
2606 
2607  if (tmpdir == NULL)
2608  {
2609  unsigned char *last_slash;
2610  unsigned char *p = (unsigned char *)buf;
2611 
2612  if (!GetTempPathA (sizeof (buf), buf))
2613  {
2614  _dbus_warn ("GetTempPath failed");
2615  _dbus_abort ();
2616  }
2617 
2618  /* Drop terminating backslash or slash */
2619  last_slash = _mbsrchr (p, '\\');
2620  if (last_slash > p && last_slash[1] == '\0')
2621  last_slash[0] = '\0';
2622  last_slash = _mbsrchr (p, '/');
2623  if (last_slash > p && last_slash[1] == '\0')
2624  last_slash[0] = '\0';
2625 
2626  tmpdir = buf;
2627  }
2628 
2629  _DBUS_UNLOCK (sysdeps);
2630 
2631  _dbus_assert(tmpdir != NULL);
2632 
2633  return tmpdir;
2634 }
2635 
2636 
2647  DBusError *error)
2648 {
2649  const char *filename_c;
2650 
2651  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2652 
2653  filename_c = _dbus_string_get_const_data (filename);
2654 
2655  if (DeleteFileA (filename_c) == 0)
2656  {
2658  "Failed to delete file %s: %s\n",
2659  filename_c, _dbus_strerror_from_errno ());
2660  return FALSE;
2661  }
2662  else
2663  return TRUE;
2664 }
2665 
2666 #if !defined (DBUS_DISABLE_ASSERT) || defined(DBUS_ENABLE_EMBEDDED_TESTS)
2667 
2668 #if defined(_MSC_VER) || defined(DBUS_WINCE)
2669 # ifdef BACKTRACES
2670 # undef BACKTRACES
2671 # endif
2672 #else
2673 # define BACKTRACES
2674 #endif
2675 
2676 #ifdef BACKTRACES
2677 /*
2678  * Backtrace Generator
2679  *
2680  * Copyright 2004 Eric Poech
2681  * Copyright 2004 Robert Shearman
2682  *
2683  * This library is free software; you can redistribute it and/or
2684  * modify it under the terms of the GNU Lesser General Public
2685  * License as published by the Free Software Foundation; either
2686  * version 2.1 of the License, or (at your option) any later version.
2687  *
2688  * This library is distributed in the hope that it will be useful,
2689  * but WITHOUT ANY WARRANTY; without even the implied warranty of
2690  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2691  * Lesser General Public License for more details.
2692  *
2693  * You should have received a copy of the GNU Lesser General Public
2694  * License along with this library; if not, write to the Free Software
2695  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2696  */
2697 
2698 #include <winver.h>
2699 #include <imagehlp.h>
2700 #include <stdio.h>
2701 
2702 #define DPRINTF(fmt, ...) fprintf (stderr, fmt, ##__VA_ARGS__)
2703 
2704 #ifdef _MSC_VER
2705 #define BOOL int
2706 
2707 #define __i386__
2708 #endif
2709 
2710 static void dump_backtrace_for_thread (HANDLE hThread)
2711 {
2712  ADDRESS old_address;
2713  STACKFRAME sf;
2714  CONTEXT context;
2715  DWORD dwImageType;
2716  int i = 0;
2717 
2718  SymSetOptions (SYMOPT_UNDNAME | SYMOPT_LOAD_LINES);
2719  SymInitialize (GetCurrentProcess (), NULL, TRUE);
2720 
2721 
2722  /* can't use this function for current thread as GetThreadContext
2723  * doesn't support getting context from current thread */
2724  if (hThread == GetCurrentThread())
2725  return;
2726 
2727  DPRINTF ("Backtrace:\n");
2728 
2729  _DBUS_ZERO (old_address);
2730  _DBUS_ZERO (context);
2731  context.ContextFlags = CONTEXT_FULL;
2732 
2733  SuspendThread (hThread);
2734 
2735  if (!GetThreadContext (hThread, &context))
2736  {
2737  DPRINTF ("Couldn't get thread context (error %ld)\n", GetLastError ());
2738  ResumeThread (hThread);
2739  return;
2740  }
2741 
2742  _DBUS_ZERO (sf);
2743 
2744 #ifdef __i386__
2745  dwImageType = IMAGE_FILE_MACHINE_I386;
2746  sf.AddrFrame.Offset = context.Ebp;
2747  sf.AddrFrame.Mode = AddrModeFlat;
2748  sf.AddrPC.Offset = context.Eip;
2749  sf.AddrPC.Mode = AddrModeFlat;
2750 #elif defined(_M_X64)
2751  dwImageType = IMAGE_FILE_MACHINE_AMD64;
2752  sf.AddrPC.Offset = context.Rip;
2753  sf.AddrPC.Mode = AddrModeFlat;
2754  sf.AddrFrame.Offset = context.Rsp;
2755  sf.AddrFrame.Mode = AddrModeFlat;
2756  sf.AddrStack.Offset = context.Rsp;
2757  sf.AddrStack.Mode = AddrModeFlat;
2758 #elif defined(_M_IA64)
2759  dwImageType = IMAGE_FILE_MACHINE_IA64;
2760  sf.AddrPC.Offset = context.StIIP;
2761  sf.AddrPC.Mode = AddrModeFlat;
2762  sf.AddrFrame.Offset = context.IntSp;
2763  sf.AddrFrame.Mode = AddrModeFlat;
2764  sf.AddrBStore.Offset= context.RsBSP;
2765  sf.AddrBStore.Mode = AddrModeFlat;
2766  sf.AddrStack.Offset = context.IntSp;
2767  sf.AddrStack.Mode = AddrModeFlat;
2768 #else
2769 # error You need to fill in the STACKFRAME structure for your architecture
2770 #endif
2771 
2772  /*
2773  backtrace format
2774  <level> <address> <symbol>[+offset] [ '[' <file> ':' <line> ']' ] [ 'in' <module> ]
2775  example:
2776  6 0xf75ade6b wine_switch_to_stack+0x2a [/usr/src/debug/wine-snapshot/libs/wine/port.c:59] in libwine.so.1
2777  */
2778  while (StackWalk (dwImageType, GetCurrentProcess (),
2779  hThread, &sf, &context, NULL, SymFunctionTableAccess,
2780  SymGetModuleBase, NULL))
2781  {
2782  char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(char)];
2783  PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
2784  DWORD64 displacement;
2785  IMAGEHLP_LINE line;
2786  DWORD dwDisplacement;
2787  IMAGEHLP_MODULE moduleInfo;
2788 
2789  /*
2790  on Wine64 version 1.7.54, we get an infinite number of stack entries
2791  pointing to the same stack frame (_start+0x29 in <wine-loader>)
2792  see bug https://bugs.winehq.org/show_bug.cgi?id=39606
2793  */
2794 #ifndef __i386__
2795  if (old_address.Offset == sf.AddrPC.Offset)
2796  {
2797  break;
2798  }
2799 #endif
2800 
2801  pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
2802  pSymbol->MaxNameLen = MAX_SYM_NAME;
2803 
2804  if (SymFromAddr (GetCurrentProcess (), sf.AddrPC.Offset, &displacement, pSymbol))
2805  {
2806  if (displacement)
2807  DPRINTF ("%3d %s+0x%I64x", i++, pSymbol->Name, displacement);
2808  else
2809  DPRINTF ("%3d %s", i++, pSymbol->Name);
2810  }
2811  else
2812  DPRINTF ("%3d 0x%Ix", i++, sf.AddrPC.Offset);
2813 
2814  line.SizeOfStruct = sizeof(IMAGEHLP_LINE);
2815  if (SymGetLineFromAddr (GetCurrentProcess (), sf.AddrPC.Offset, &dwDisplacement, &line))
2816  {
2817  DPRINTF (" [%s:%ld]", line.FileName, line.LineNumber);
2818  }
2819 
2820  moduleInfo.SizeOfStruct = sizeof(moduleInfo);
2821  if (SymGetModuleInfo (GetCurrentProcess (), sf.AddrPC.Offset, &moduleInfo))
2822  {
2823  DPRINTF (" in %s", moduleInfo.ModuleName);
2824  }
2825  DPRINTF ("\n");
2826  old_address = sf.AddrPC;
2827  }
2828  ResumeThread (hThread);
2829 }
2830 
2831 static DWORD WINAPI dump_thread_proc (LPVOID lpParameter)
2832 {
2833  dump_backtrace_for_thread ((HANDLE) lpParameter);
2834  return 0;
2835 }
2836 
2837 /* cannot get valid context from current thread, so we have to execute
2838  * backtrace from another thread */
2839 static void
2840 dump_backtrace (void)
2841 {
2842  HANDLE hCurrentThread;
2843  HANDLE hThread;
2844  DWORD dwThreadId;
2845  DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
2846  GetCurrentProcess (), &hCurrentThread,
2847  0, FALSE, DUPLICATE_SAME_ACCESS);
2848  hThread = CreateThread (NULL, 0, dump_thread_proc, (LPVOID)hCurrentThread,
2849  0, &dwThreadId);
2850  WaitForSingleObject (hThread, INFINITE);
2851  CloseHandle (hThread);
2852  CloseHandle (hCurrentThread);
2853 }
2854 #endif
2855 #endif /* asserts or tests enabled */
2856 
2857 #ifdef BACKTRACES
2859 {
2860  dump_backtrace ();
2861 }
2862 #else
2863 void _dbus_print_backtrace (void)
2864 {
2865  _dbus_verbose (" D-Bus not compiled with backtrace support\n");
2866 }
2867 #endif
2868 
2869 static dbus_uint32_t fromAscii(char ascii)
2870 {
2871  if(ascii >= '0' && ascii <= '9')
2872  return ascii - '0';
2873  if(ascii >= 'A' && ascii <= 'F')
2874  return ascii - 'A' + 10;
2875  if(ascii >= 'a' && ascii <= 'f')
2876  return ascii - 'a' + 10;
2877  return 0;
2878 }
2879 
2881  dbus_bool_t create_if_not_found,
2882  DBusError *error)
2883 {
2884 #ifdef DBUS_WINCE
2885  return TRUE;
2886  // TODO
2887 #else
2888  HW_PROFILE_INFOA info;
2889  char *lpc = &info.szHwProfileGuid[0];
2890  dbus_uint32_t u;
2891 
2892  // the hw-profile guid lives long enough
2893  if(!GetCurrentHwProfileA(&info))
2894  {
2895  dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); // FIXME
2896  return FALSE;
2897  }
2898 
2899  // Form: {12340001-4980-1920-6788-123456789012}
2900  lpc++;
2901  // 12340001
2902  u = ((fromAscii(lpc[0]) << 0) |
2903  (fromAscii(lpc[1]) << 4) |
2904  (fromAscii(lpc[2]) << 8) |
2905  (fromAscii(lpc[3]) << 12) |
2906  (fromAscii(lpc[4]) << 16) |
2907  (fromAscii(lpc[5]) << 20) |
2908  (fromAscii(lpc[6]) << 24) |
2909  (fromAscii(lpc[7]) << 28));
2910  machine_id->as_uint32s[0] = u;
2911 
2912  lpc += 9;
2913  // 4980-1920
2914  u = ((fromAscii(lpc[0]) << 0) |
2915  (fromAscii(lpc[1]) << 4) |
2916  (fromAscii(lpc[2]) << 8) |
2917  (fromAscii(lpc[3]) << 12) |
2918  (fromAscii(lpc[5]) << 16) |
2919  (fromAscii(lpc[6]) << 20) |
2920  (fromAscii(lpc[7]) << 24) |
2921  (fromAscii(lpc[8]) << 28));
2922  machine_id->as_uint32s[1] = u;
2923 
2924  lpc += 10;
2925  // 6788-1234
2926  u = ((fromAscii(lpc[0]) << 0) |
2927  (fromAscii(lpc[1]) << 4) |
2928  (fromAscii(lpc[2]) << 8) |
2929  (fromAscii(lpc[3]) << 12) |
2930  (fromAscii(lpc[5]) << 16) |
2931  (fromAscii(lpc[6]) << 20) |
2932  (fromAscii(lpc[7]) << 24) |
2933  (fromAscii(lpc[8]) << 28));
2934  machine_id->as_uint32s[2] = u;
2935 
2936  lpc += 9;
2937  // 56789012
2938  u = ((fromAscii(lpc[0]) << 0) |
2939  (fromAscii(lpc[1]) << 4) |
2940  (fromAscii(lpc[2]) << 8) |
2941  (fromAscii(lpc[3]) << 12) |
2942  (fromAscii(lpc[4]) << 16) |
2943  (fromAscii(lpc[5]) << 20) |
2944  (fromAscii(lpc[6]) << 24) |
2945  (fromAscii(lpc[7]) << 28));
2946  machine_id->as_uint32s[3] = u;
2947 #endif
2948  return TRUE;
2949 }
2950 
2951 // for proper cleanup in dbus-daemon
2952 static HANDLE hDBusDaemonMutex = NULL;
2953 static HANDLE hDBusSharedMem = NULL;
2954 // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
2955 static const char *cUniqueDBusInitMutex = "UniqueDBusInitMutex";
2956 // sync _dbus_get_autolaunch_address
2957 static const char *cDBusAutolaunchMutex = "DBusAutolaunchMutex";
2958 // mutex to determine if dbus-daemon is already started (per user)
2959 static const char *cDBusDaemonMutex = "DBusDaemonMutex";
2960 // named shm for dbus adress info (per user)
2961 static const char *cDBusDaemonAddressInfo = "DBusDaemonAddressInfo";
2962 
2963 /* custom command line parameter for autolaunching daemon */
2964 static const char *autolaunch_custom_command_line_parameter = "";
2965 
2978 void _dbus_test_win_autolaunch_set_command_line_parameter (const char *path)
2979 {
2980  autolaunch_custom_command_line_parameter = path;
2981 }
2982 
2983 static HANDLE *autolaunch_handle_location;
2984 
2995 void
2996 _dbus_test_win_set_autolaunch_handle_location (HANDLE *location)
2997 {
2998  autolaunch_handle_location = location;
2999 }
3000 
3011 static dbus_bool_t
3012 _dbus_get_install_root_as_hash (DBusString *out)
3013 {
3014  DBusString install_path;
3015  dbus_bool_t retval = FALSE;
3016  _dbus_assert (out != NULL);
3017 
3018  if (!_dbus_string_init (&install_path))
3019  return FALSE;
3020 
3021  if (!_dbus_get_install_root (&install_path))
3022  goto out;
3023 
3024  /* the install path can't be determined */
3025  if (_dbus_string_get_length (&install_path) == 0)
3026  {
3027  _dbus_string_set_length (out, 0);
3028  retval = TRUE;
3029  goto out;
3030  }
3031 
3032  _dbus_string_tolower_ascii (&install_path, 0, _dbus_string_get_length (&install_path));
3033 
3034  if (!_dbus_sha_compute (&install_path, out))
3035  goto out;
3036 
3037  retval = TRUE;
3038 
3039 out:
3040  _dbus_string_free (&install_path);
3041  return retval;
3042 }
3043 
3062 static dbus_bool_t
3063 _dbus_get_address_string (DBusString *out, const char *basestring, const char *scope)
3064 {
3065  _dbus_assert (out != NULL);
3066 
3067  if (!scope || strlen (scope) == 0)
3068  {
3069  return _dbus_string_append (out, basestring);
3070  }
3071  else if (strcmp (scope, "*install-path") == 0
3072  // for 1.3 compatibility
3073  || strcmp (scope, "install-path") == 0)
3074  {
3075  DBusString temp;
3076  dbus_bool_t retval = FALSE;
3077 
3078  if (!_dbus_string_init (&temp))
3079  return FALSE;
3080 
3081  if (!_dbus_get_install_root_as_hash (&temp))
3082  goto out;
3083 
3084  if (_dbus_string_get_length (&temp) == 0)
3085  {
3086  _dbus_string_set_length (out, 0);
3087  retval = TRUE;
3088  goto out;
3089  }
3090 
3091  if (!_dbus_string_append_printf (out, "%s-%s", basestring, _dbus_string_get_const_data (&temp)))
3092  goto out;
3093 
3094  retval = TRUE;
3095 out:
3096  _dbus_string_free (&temp);
3097  return retval;
3098  }
3099  else if (strcmp (scope, "*user") == 0)
3100  {
3101  char *sid = NULL;
3102  dbus_bool_t retval;
3103 
3104  if (!_dbus_getsid (&sid, _dbus_getpid()))
3105  return FALSE;
3106 
3107  retval = _dbus_string_append_printf (out, "%s-%s", basestring, sid);
3108 
3109  LocalFree(sid);
3110 
3111  return retval;
3112  }
3113  else /* strlen(scope) > 0 */
3114  {
3115  return _dbus_string_append_printf (out, "%s-%s", basestring, scope);
3116  }
3117 }
3118 
3127 static dbus_bool_t
3128 _dbus_get_shm_name (DBusString *out,const char *scope)
3129 {
3130  return _dbus_get_address_string (out, cDBusDaemonAddressInfo, scope);
3131 }
3132 
3142 static dbus_bool_t
3143 _dbus_get_mutex_name (DBusString *out, const char *scope)
3144 {
3145  return _dbus_get_address_string (out, cDBusDaemonMutex, scope);
3146 }
3147 
3149 _dbus_daemon_is_session_bus_address_published (const char *scope)
3150 {
3151  DBusRMutex *lock = NULL;
3152  DBusString mutex_name;
3153 
3154  if (!_dbus_string_init (&mutex_name))
3155  return FALSE;
3156 
3157  _dbus_verbose ("scope:%s\n", scope);
3158  if (!_dbus_get_mutex_name (&mutex_name, scope) ||
3159  /* not determinable */
3160  _dbus_string_get_length (&mutex_name) == 0)
3161  {
3162  _dbus_string_free (&mutex_name);
3163  return FALSE;
3164  }
3165 
3166  if (hDBusDaemonMutex)
3167  {
3168  _dbus_verbose ("(scope:%s) -> yes\n", scope);
3169  return TRUE;
3170  }
3171  lock = _dbus_win_rmutex_named_new (cUniqueDBusInitMutex);
3172  if (!lock)
3173  return FALSE;
3174 
3175  // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
3176  _dbus_platform_rmutex_lock (lock);
3177 
3178  // we use CreateMutex instead of OpenMutex because of possible race conditions,
3179  // see http://msdn.microsoft.com/en-us/library/ms684315%28VS.85%29.aspx
3180  hDBusDaemonMutex = CreateMutexA (NULL, FALSE, _dbus_string_get_const_data(&mutex_name));
3181 
3182  /* The client uses mutex ownership to detect a running server, so the server should do so too.
3183  Fortunally the client deletes the mutex in the lock protected area, so checking presence
3184  will work too. */
3185 
3186  _dbus_platform_rmutex_unlock (lock);
3187  _dbus_platform_rmutex_free (lock);
3188 
3189  _dbus_string_free (&mutex_name);
3190 
3191  if (hDBusDaemonMutex == NULL)
3192  {
3193  _dbus_verbose ("(scope:%s) -> no\n", scope);
3194  return FALSE;
3195  }
3196  if (GetLastError() == ERROR_ALREADY_EXISTS)
3197  {
3198  CloseHandle(hDBusDaemonMutex);
3199  hDBusDaemonMutex = NULL;
3200  _dbus_verbose ("(scope:%s) -> yes\n", scope);
3201  return TRUE;
3202  }
3203  // mutex wasn't created before, so return false.
3204  // We leave the mutex name allocated for later reusage
3205  // in _dbus_daemon_publish_session_bus_address.
3206  _dbus_verbose ("(scope:%s) -> no\n", scope);
3207  return FALSE;
3208 }
3209 
3211 _dbus_daemon_publish_session_bus_address (const char* address, const char *scope)
3212 {
3213  DBusRMutex *lock = NULL;
3214  char *shared_addr = NULL;
3215  DBusString shm_name = _DBUS_STRING_INIT_INVALID;
3216  DBusString mutex_name;
3217  dbus_uint64_t len;
3218  dbus_bool_t retval = FALSE;
3219 
3220  _dbus_assert (address);
3221 
3222  if (!_dbus_string_init (&mutex_name))
3223  return FALSE;
3224 
3225  _dbus_verbose ("address:%s scope:%s\n", address, scope);
3226  if (!_dbus_get_mutex_name (&mutex_name, scope) ||
3227  /* not determinable */
3228  _dbus_string_get_length (&mutex_name) == 0)
3229  {
3230  _dbus_string_free (&mutex_name);
3231  return FALSE;
3232  }
3233 
3234  // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
3235  lock = _dbus_win_rmutex_named_new (cUniqueDBusInitMutex);
3236  if (lock == NULL)
3237  {
3238  _dbus_string_free (&mutex_name);
3239  return FALSE;
3240  }
3241 
3242  _dbus_platform_rmutex_lock (lock);
3243 
3244  if (!hDBusDaemonMutex)
3245  {
3246  hDBusDaemonMutex = CreateMutexA (NULL, FALSE, _dbus_string_get_const_data(&mutex_name));
3247  }
3248  _dbus_string_free (&mutex_name);
3249 
3250  // acquire the mutex
3251  if (WaitForSingleObject (hDBusDaemonMutex, 10) != WAIT_OBJECT_0)
3252  {
3253  CloseHandle (hDBusDaemonMutex);
3254  goto out;
3255  }
3256 
3257  if (!_dbus_string_init (&shm_name))
3258  {
3259  goto out;
3260  }
3261 
3262  if (!_dbus_get_shm_name (&shm_name, scope) ||
3263  /* not determinable */
3264  _dbus_string_get_length (&shm_name) == 0)
3265  {
3266  goto out;
3267  }
3268 
3269  // create shm
3270  len = strlen (address) + 1;
3271 
3272  hDBusSharedMem = CreateFileMappingA ( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
3273  len >> 32, len & 0xffffffffu,
3274  _dbus_string_get_const_data (&shm_name) );
3275  _dbus_assert (hDBusSharedMem);
3276 
3277  shared_addr = MapViewOfFile (hDBusSharedMem, FILE_MAP_WRITE, 0, 0, 0);
3278 
3279  _dbus_assert (shared_addr);
3280 
3281  strcpy(shared_addr, address);
3282 
3283  // cleanup
3284  UnmapViewOfFile (shared_addr);
3285 
3286  _dbus_verbose ("published session bus address at %s\n",_dbus_string_get_const_data (&shm_name));
3287  retval = TRUE;
3288 
3289 out:
3290  _dbus_platform_rmutex_unlock (lock);
3291  _dbus_platform_rmutex_free (lock);
3292  _dbus_string_free (&shm_name);
3293  return retval;
3294 }
3295 
3315 {
3316  DBusRMutex *lock = NULL;
3317 
3318  _dbus_verbose ("\n");
3319  // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
3320  lock = _dbus_win_rmutex_named_new (cUniqueDBusInitMutex);
3321  if (lock == NULL)
3322  return FALSE;
3323 
3324  _dbus_platform_rmutex_lock (lock);
3325 
3326  CloseHandle (hDBusSharedMem);
3327 
3328  hDBusSharedMem = NULL;
3329 
3330  ReleaseMutex (hDBusDaemonMutex);
3331 
3332  CloseHandle (hDBusDaemonMutex);
3333 
3334  hDBusDaemonMutex = NULL;
3335 
3336  _dbus_platform_rmutex_unlock (lock);
3337  _dbus_platform_rmutex_free (lock);
3338  return TRUE;
3339 }
3340 
3350 static dbus_bool_t
3351 _dbus_get_autolaunch_shm (DBusString *address, DBusString *shm_name, dbus_bool_t wait)
3352 {
3353  HANDLE sharedMem = NULL;
3354  char *shared_addr;
3355  int i;
3356  int max = 20; /* max 2 seconds */
3357  dbus_bool_t retval = FALSE;
3358 
3359  if (!wait)
3360  max = 1;
3361 
3362  // read shm
3363  for (i = 0; i < max; ++i)
3364  {
3365  // we know that dbus-daemon is available, so we wait until shm is available
3366  sharedMem = OpenFileMappingA (FILE_MAP_READ, FALSE, _dbus_string_get_const_data (shm_name));
3367  if (sharedMem == 0)
3368  Sleep (100);
3369  if (sharedMem != 0)
3370  break;
3371  }
3372 
3373  if (sharedMem == 0)
3374  return FALSE;
3375 
3376  shared_addr = MapViewOfFile (sharedMem, FILE_MAP_READ, 0, 0, 0);
3377 
3378  if (!shared_addr)
3379  goto out;
3380 
3381  retval = _dbus_string_append (address, shared_addr);
3382 
3383  UnmapViewOfFile (shared_addr);
3384 
3385 out:
3386  CloseHandle (sharedMem);
3387  return retval;
3388 }
3389 
3390 static dbus_bool_t
3391 _dbus_daemon_already_runs (DBusString *address, DBusString *shm_name, const char *scope)
3392 {
3393  DBusRMutex *lock = NULL;
3394  HANDLE daemon;
3395  DBusString mutex_name;
3396  dbus_bool_t retval = FALSE;
3397 
3398  if (!_dbus_string_init (&mutex_name))
3399  return FALSE;
3400 
3401  if (!_dbus_get_mutex_name (&mutex_name, scope) ||
3402  /* not determinable */
3403  _dbus_string_get_length (&mutex_name) == 0)
3404  {
3405  _dbus_string_free (&mutex_name);
3406  return FALSE;
3407  }
3408 
3409  // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
3410  lock = _dbus_win_rmutex_named_new (cUniqueDBusInitMutex);
3411  if (lock == NULL)
3412  return FALSE;
3413 
3414  _dbus_platform_rmutex_lock (lock);
3415 
3416  // do checks
3417  daemon = CreateMutexA (NULL, FALSE, _dbus_string_get_const_data (&mutex_name));
3418  if (WaitForSingleObject (daemon, 10) != WAIT_TIMEOUT)
3419  {
3420  ReleaseMutex (daemon);
3421  CloseHandle (daemon);
3422  goto out;
3423  }
3424 
3425  // read shm, wait max 2 seconds
3426  retval = _dbus_get_autolaunch_shm (address, shm_name, TRUE);
3427 
3428  // cleanup
3429  CloseHandle (daemon);
3430 
3431 out:
3432  _dbus_platform_rmutex_unlock (lock);
3433  _dbus_platform_rmutex_free (lock);
3434  _dbus_string_free (&mutex_name);
3435 
3436  return retval;
3437 }
3438 
3440 _dbus_get_autolaunch_address (const char *scope,
3441  DBusString *address,
3442  DBusError *error)
3443 {
3444  DBusRMutex *lock = NULL;
3445  STARTUPINFOA si;
3446  PROCESS_INFORMATION pi;
3447  dbus_bool_t retval = FALSE;
3448  LPSTR lpFile;
3449  char dbus_exe_path[MAX_PATH];
3450  DBusString dbus_args = _DBUS_STRING_INIT_INVALID;
3451  const char *daemon_name = DBUS_DAEMON_NAME ".exe";
3452  DBusString shm_name;
3453  HANDLE ready_event_handle = NULL;
3454 
3455  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3456 
3457  if (!_dbus_string_init (&shm_name))
3458  {
3459  _DBUS_SET_OOM (error);
3460  return FALSE;
3461  }
3462 
3463  if (!_dbus_get_shm_name (&shm_name, scope) ||
3464  /* not determinable */
3465  _dbus_string_get_length (&shm_name) == 0)
3466  {
3467  dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not determine shm name");
3468  goto out;
3469  }
3470 
3471  lock = _dbus_win_rmutex_named_new (cDBusAutolaunchMutex);
3472  if (lock == NULL)
3473  {
3474  dbus_set_error (error, DBUS_ERROR_FAILED, "Could not lock '%s'", cDBusAutolaunchMutex);
3475  _dbus_string_free (&shm_name);
3476  return FALSE;
3477  }
3478 
3479  _dbus_platform_rmutex_lock (lock);
3480 
3481  if (_dbus_daemon_already_runs (address, &shm_name, scope))
3482  {
3483  _dbus_verbose ("found running dbus daemon for scope '%s' at %s\n",
3484  scope ? scope : "", _dbus_string_get_const_data (&shm_name));
3485  retval = TRUE;
3486  goto out;
3487  }
3488 
3489  if (!SearchPathA (NULL, daemon_name, NULL, sizeof (dbus_exe_path), dbus_exe_path, &lpFile))
3490  {
3491  // Look in directory containing dbus shared library
3492  HMODULE hmod;
3493  char dbus_module_path[MAX_PATH];
3494  DWORD rc;
3495 
3496  _dbus_verbose ("did not found dbus daemon executable on default search path, "
3497  "trying path where dbus shared library is located");
3498 
3499  hmod = _dbus_win_get_dll_hmodule ();
3500  rc = GetModuleFileNameA (hmod, dbus_module_path, sizeof (dbus_module_path));
3501  if (rc <= 0)
3502  {
3503  dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not retrieve dbus shared library file name");
3504  retval = FALSE;
3505  goto out;
3506  }
3507  else
3508  {
3509  char *ext_idx = strrchr (dbus_module_path, '\\');
3510  if (ext_idx)
3511  *ext_idx = '\0';
3512  if (!SearchPathA (dbus_module_path, daemon_name, NULL, sizeof (dbus_exe_path), dbus_exe_path, &lpFile))
3513  {
3515  "Could not find dbus-daemon executable. "
3516  "Please add the path to %s to your PATH "
3517  "environment variable or start the daemon manually",
3518  daemon_name);
3519  retval = FALSE;
3520  goto out;
3521  }
3522  _dbus_verbose ("found dbus daemon executable at %s", dbus_module_path);
3523  }
3524  }
3525 
3526  // Create process
3527  ZeroMemory (&si, sizeof (si));
3528  si.cb = sizeof (si);
3529  ZeroMemory (&pi, sizeof (pi));
3530 
3531  if (!_dbus_string_init (&dbus_args))
3532  {
3533  dbus_set_error_const (error, DBUS_ERROR_NO_MEMORY, "Failed to initialize argument buffer");
3534  retval = FALSE;
3535  goto out;
3536  }
3537 
3538  if (!_dbus_string_append_printf (&dbus_args, "\"%s\" %s", dbus_exe_path,
3539  autolaunch_custom_command_line_parameter ? autolaunch_custom_command_line_parameter : "--session"))
3540  {
3541  _DBUS_SET_OOM (error);
3542  retval = FALSE;
3543  goto out;
3544  }
3545 
3546  ready_event_handle = _dbus_win_event_create_inheritable (error);
3547  if (ready_event_handle == NULL)
3548  goto out;
3549 
3550  _dbus_verbose ("Creating connection readiness event: handle=%p\n", ready_event_handle);
3551  if (!_dbus_string_append_printf (&dbus_args, " \"--ready-event-handle=%p\"", ready_event_handle))
3552  {
3553  _DBUS_SET_OOM (error);
3554  goto out;
3555  }
3556 
3557  _dbus_verbose ("Starting dbus daemon with args: '%s'\n", _dbus_string_get_const_data (&dbus_args));
3558  if (CreateProcessA (dbus_exe_path, _dbus_string_get_data (&dbus_args), NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
3559  {
3560  DWORD status;
3561  HANDLE events[2];
3562 
3563  CloseHandle (pi.hThread);
3564 
3565  _dbus_verbose ("Wait until dbus-daemon is ready for connections (event handle %p)\n", ready_event_handle);
3566 
3567  events[0] = ready_event_handle;
3568  events[1] = pi.hProcess;
3569  status = WaitForMultipleObjects (2, events, FALSE, 30000);
3570 
3571  switch (status)
3572  {
3573  case WAIT_OBJECT_0:
3574  /* ready event signalled, everything is okay */
3575  retval = TRUE;
3576  break;
3577 
3578  case WAIT_OBJECT_0 + 1:
3579  /* dbus-daemon process has exited */
3580  dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED, "dbus-daemon exited before signalling ready");
3581  goto out;
3582 
3583  case WAIT_FAILED:
3584  _dbus_win_set_error_from_last_error (error, "Unable to wait for server readiness (handle %p)", ready_event_handle);
3585  goto out;
3586 
3587  case WAIT_TIMEOUT:
3588  /* GetLastError() is not set */
3589  dbus_set_error (error, DBUS_ERROR_TIMEOUT, "Timed out waiting for server readiness or exit (handle %p)", ready_event_handle);
3590  goto out;
3591 
3592  default:
3593  /* GetLastError() is probably not set? */
3594  dbus_set_error (error, DBUS_ERROR_FAILED, "Unknown result '%lu' while waiting for server readiness (handle %p)", status, ready_event_handle);
3595  goto out;
3596  }
3597  _dbus_verbose ("Got signal that dbus-daemon with process id '%ld' is ready for connections\n", GetProcessId (pi.hProcess));
3598 
3599  if (autolaunch_handle_location != NULL)
3600  {
3601  *autolaunch_handle_location = pi.hProcess;
3602  _dbus_verbose ("Returning process handle of started server (handle=%p)\n", pi.hProcess);
3603  }
3604  else
3605  {
3606  CloseHandle (pi.hProcess);
3607  }
3608 
3609  /* do not wait for the appearance of shm, we can assume that it is present */
3610  retval = _dbus_get_autolaunch_shm (address, &shm_name, FALSE);
3611  if (retval == FALSE)
3612  dbus_set_error_const (error, DBUS_ERROR_FAILED, "Failed to get autolaunch address from launched dbus-daemon");
3613  }
3614  else
3615  {
3616  dbus_set_error_const (error, DBUS_ERROR_FAILED, "Failed to launch dbus-daemon");
3617  retval = FALSE;
3618  }
3619 
3620 out:
3621  _DBUS_ASSERT_ERROR_XOR_BOOL (error, retval);
3622  _dbus_platform_rmutex_unlock (lock);
3623  _dbus_platform_rmutex_free (lock);
3624  _dbus_string_free (&shm_name);
3625  _dbus_string_free (&dbus_args);
3626  if (ready_event_handle)
3627  _dbus_win_event_free (ready_event_handle, NULL);
3628 
3629  _DBUS_ASSERT_ERROR_XOR_BOOL (error, retval);
3630  return retval;
3631 }
3632 
3641  DBusError *error)
3642 {
3643  // TODO
3644  return TRUE;
3645 }
3646 
3656 {
3657  // +/- 1 is needed here!
3658  // no volatile argument with mingw
3659  return InterlockedIncrement (&atomic->value) - 1;
3660 }
3661 
3671 {
3672  // +/- 1 is needed here!
3673  // no volatile argument with mingw
3674  return InterlockedDecrement (&atomic->value) + 1;
3675 }
3676 
3686 {
3687  /* In this situation, GLib issues a MemoryBarrier() and then returns
3688  * atomic->value. However, mingw from mingw.org (not to be confused with
3689  * mingw-w64 from mingw-w64.sf.net) does not have MemoryBarrier in its
3690  * headers, so we have to get a memory barrier some other way.
3691  *
3692  * InterlockedIncrement is older, and is documented on MSDN to be a full
3693  * memory barrier, so let's use that.
3694  */
3695  long dummy = 0;
3696 
3697  InterlockedExchange (&dummy, 1);
3698 
3699  return atomic->value;
3700 }
3701 
3707 void
3709 {
3710  InterlockedExchange (&atomic->value, 0);
3711 }
3712 
3718 void
3720 {
3721  InterlockedExchange (&atomic->value, 1);
3722 }
3723 
3731 void
3733 {
3734 }
3735 
3744 {
3745  return e == WSAEWOULDBLOCK;
3746 }
3747 
3756 _dbus_get_install_root (DBusString *str)
3757 {
3758  /* this is just an initial guess */
3759  DWORD pathLength = MAX_PATH;
3760  unsigned char *lastSlash;
3761  unsigned char *prefix;
3762 
3763  do
3764  {
3765  /* allocate enough space for our best guess at the length */
3766  if (!_dbus_string_set_length (str, pathLength))
3767  {
3768  _dbus_string_set_length (str, 0);
3769  return FALSE;
3770  }
3771 
3772  SetLastError (0);
3773  pathLength = GetModuleFileNameA (_dbus_win_get_dll_hmodule (),
3774  _dbus_string_get_data (str), _dbus_string_get_length (str));
3775 
3776  if (pathLength == 0 || GetLastError () != 0)
3777  {
3778  /* failed, but not OOM */
3779  _dbus_string_set_length (str, 0);
3780  return TRUE;
3781  }
3782 
3783  /* if the return is strictly less than the buffer size, it has
3784  * not been truncated, so we can continue */
3785  if (pathLength < (DWORD) _dbus_string_get_length (str))
3786  {
3787  /* reduce the length to match what Windows filled in */
3788  if (!_dbus_string_set_length (str, pathLength))
3789  {
3790  _dbus_string_set_length (str, 0);
3791  return FALSE;
3792  }
3793 
3794  break;
3795  }
3796 
3797  /* else it may have been truncated; try with a larger buffer */
3798  pathLength *= 2;
3799  }
3800  while (TRUE);
3801 
3802  /* the rest of this function works by direct byte manipulation of the
3803  * underlying buffer */
3804  prefix = _dbus_string_get_udata (str);
3805 
3806  lastSlash = _mbsrchr (prefix, '\\');
3807  if (lastSlash == NULL) {
3808  /* failed, but not OOM */
3809  _dbus_string_set_length (str, 0);
3810  return TRUE;
3811  }
3812  //cut off binary name
3813  lastSlash[1] = 0;
3814 
3815  //cut possible "\\bin"
3816  //this fails if we are in a double-byte system codepage and the
3817  //folder's name happens to end with the *bytes*
3818  //"\\bin"... (I.e. the second byte of some Han character and then
3819  //the Latin "bin", but that is not likely I think...
3820  if (lastSlash - prefix >= 4 && _mbsnicmp (lastSlash - 4, (const unsigned char *)"\\bin", 4) == 0)
3821  lastSlash[-3] = 0;
3822  else if (lastSlash - prefix >= 10 && _mbsnicmp (lastSlash - 10, (const unsigned char *)"\\bin\\debug", 10) == 0)
3823  lastSlash[-9] = 0;
3824  else if (lastSlash - prefix >= 12 && _mbsnicmp (lastSlash - 12, (const unsigned char *)"\\bin\\release", 12) == 0)
3825  lastSlash[-11] = 0;
3826 
3827  /* fix up the length to match the byte-manipulation */
3828  _dbus_string_set_length (str, strlen ((char *) prefix));
3829 
3830  return TRUE;
3831 }
3832 
3833 /* See comment in dbus-sysdeps-unix.c */
3836  DBusString *address,
3837  DBusError *error)
3838 {
3839  /* Probably fill this in with something based on COM? */
3840  *supported = FALSE;
3841  return TRUE;
3842 }
3843 
3859  DBusCredentials *credentials)
3860 {
3861  DBusString homedir;
3862  DBusString dotdir;
3863  const char *homepath;
3864  const char *homedrive;
3865 
3866  _dbus_assert (credentials != NULL);
3868 
3869  if (!_dbus_string_init (&homedir))
3870  return FALSE;
3871 
3872  homedrive = _dbus_getenv("HOMEDRIVE");
3873  if (homedrive != NULL && *homedrive != '\0')
3874  {
3875  _dbus_string_append(&homedir,homedrive);
3876  }
3877 
3878  homepath = _dbus_getenv("HOMEPATH");
3879  if (homepath != NULL && *homepath != '\0')
3880  {
3881  _dbus_string_append(&homedir,homepath);
3882  }
3883 
3884 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
3885  {
3886  const char *override;
3887 
3888  override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
3889  if (override != NULL && *override != '\0')
3890  {
3891  _dbus_string_set_length (&homedir, 0);
3892  if (!_dbus_string_append (&homedir, override))
3893  goto failed;
3894 
3895  _dbus_verbose ("Using fake homedir for testing: %s\n",
3896  _dbus_string_get_const_data (&homedir));
3897  }
3898  else
3899  {
3900  /* Not strictly thread-safe, but if we fail at thread-safety here,
3901  * the worst that will happen is some extra warnings. */
3902  static dbus_bool_t already_warned = FALSE;
3903  if (!already_warned)
3904  {
3905  _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid");
3906  already_warned = TRUE;
3907  }
3908  }
3909  }
3910 #endif
3911 
3912 #ifdef DBUS_WINCE
3913  /* It's not possible to create a .something directory in Windows CE
3914  using the file explorer. */
3915 #define KEYRING_DIR "dbus-keyrings"
3916 #else
3917 #define KEYRING_DIR ".dbus-keyrings"
3918 #endif
3919 
3920  _dbus_string_init_const (&dotdir, KEYRING_DIR);
3921  if (!_dbus_concat_dir_and_file (&homedir,
3922  &dotdir))
3923  goto failed;
3924 
3925  if (!_dbus_string_copy (&homedir, 0,
3926  directory, _dbus_string_get_length (directory))) {
3927  goto failed;
3928  }
3929 
3930  _dbus_string_free (&homedir);
3931  return TRUE;
3932 
3933  failed:
3934  _dbus_string_free (&homedir);
3935  return FALSE;
3936 }
3937 
3943 dbus_bool_t
3944 _dbus_file_exists (const char *file)
3945 {
3946  DWORD attributes = GetFileAttributesA (file);
3947 
3948  if (attributes != INVALID_FILE_ATTRIBUTES && GetLastError() != ERROR_PATH_NOT_FOUND)
3949  return TRUE;
3950  else
3951  return FALSE;
3952 }
3953 
3961 const char*
3962 _dbus_strerror (int error_number)
3963 {
3964 #ifdef DBUS_WINCE
3965  // TODO
3966  return "unknown";
3967 #else
3968  const char *msg;
3969 
3970  switch (error_number)
3971  {
3972  case WSAEINTR:
3973  return "Interrupted function call";
3974  case WSAEACCES:
3975  return "Permission denied";
3976  case WSAEFAULT:
3977  return "Bad address";
3978  case WSAEINVAL:
3979  return "Invalid argument";
3980  case WSAEMFILE:
3981  return "Too many open files";
3982  case WSAEWOULDBLOCK:
3983  return "Resource temporarily unavailable";
3984  case WSAEINPROGRESS:
3985  return "Operation now in progress";
3986  case WSAEALREADY:
3987  return "Operation already in progress";
3988  case WSAENOTSOCK:
3989  return "Socket operation on nonsocket";
3990  case WSAEDESTADDRREQ:
3991  return "Destination address required";
3992  case WSAEMSGSIZE:
3993  return "Message too long";
3994  case WSAEPROTOTYPE:
3995  return "Protocol wrong type for socket";
3996  case WSAENOPROTOOPT:
3997  return "Bad protocol option";
3998  case WSAEPROTONOSUPPORT:
3999  return "Protocol not supported";
4000  case WSAESOCKTNOSUPPORT:
4001  return "Socket type not supported";
4002  case WSAEOPNOTSUPP:
4003  return "Operation not supported";
4004  case WSAEPFNOSUPPORT:
4005  return "Protocol family not supported";
4006  case WSAEAFNOSUPPORT:
4007  return "Address family not supported by protocol family";
4008  case WSAEADDRINUSE:
4009  return "Address already in use";
4010  case WSAEADDRNOTAVAIL:
4011  return "Cannot assign requested address";
4012  case WSAENETDOWN:
4013  return "Network is down";
4014  case WSAENETUNREACH:
4015  return "Network is unreachable";
4016  case WSAENETRESET:
4017  return "Network dropped connection on reset";
4018  case WSAECONNABORTED:
4019  return "Software caused connection abort";
4020  case WSAECONNRESET:
4021  return "Connection reset by peer";
4022  case WSAENOBUFS:
4023  return "No buffer space available";
4024  case WSAEISCONN:
4025  return "Socket is already connected";
4026  case WSAENOTCONN:
4027  return "Socket is not connected";
4028  case WSAESHUTDOWN:
4029  return "Cannot send after socket shutdown";
4030  case WSAETIMEDOUT:
4031  return "Connection timed out";
4032  case WSAECONNREFUSED:
4033  return "Connection refused";
4034  case WSAEHOSTDOWN:
4035  return "Host is down";
4036  case WSAEHOSTUNREACH:
4037  return "No route to host";
4038  case WSAEPROCLIM:
4039  return "Too many processes";
4040  case WSAEDISCON:
4041  return "Graceful shutdown in progress";
4042  case WSATYPE_NOT_FOUND:
4043  return "Class type not found";
4044  case WSAHOST_NOT_FOUND:
4045  return "Host not found";
4046  case WSATRY_AGAIN:
4047  return "Nonauthoritative host not found";
4048  case WSANO_RECOVERY:
4049  return "This is a nonrecoverable error";
4050  case WSANO_DATA:
4051  return "Valid name, no data record of requested type";
4052  case WSA_INVALID_HANDLE:
4053  return "Specified event object handle is invalid";
4054  case WSA_INVALID_PARAMETER:
4055  return "One or more parameters are invalid";
4056  case WSA_IO_INCOMPLETE:
4057  return "Overlapped I/O event object not in signaled state";
4058  case WSA_IO_PENDING:
4059  return "Overlapped operations will complete later";
4060  case WSA_NOT_ENOUGH_MEMORY:
4061  return "Insufficient memory available";
4062  case WSA_OPERATION_ABORTED:
4063  return "Overlapped operation aborted";
4064 #ifdef WSAINVALIDPROCTABLE
4065 
4066  case WSAINVALIDPROCTABLE:
4067  return "Invalid procedure table from service provider";
4068 #endif
4069 #ifdef WSAINVALIDPROVIDER
4070 
4071  case WSAINVALIDPROVIDER:
4072  return "Invalid service provider version number";
4073 #endif
4074 #ifdef WSAPROVIDERFAILEDINIT
4075 
4076  case WSAPROVIDERFAILEDINIT:
4077  return "Unable to initialize a service provider";
4078 #endif
4079 
4080  case WSASYSCALLFAILURE:
4081  return "System call failure";
4082 
4083  default:
4084  msg = strerror (error_number);
4085 
4086  if (msg == NULL)
4087  msg = "unknown";
4088 
4089  return msg;
4090  }
4091 #endif //DBUS_WINCE
4092 }
4093 
4101 void
4102 _dbus_win_set_error_from_win_error (DBusError *error,
4103  int code)
4104 {
4105  char *msg;
4106 
4107  /* As we want the English message, use the A API */
4108  FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
4109  FORMAT_MESSAGE_IGNORE_INSERTS |
4110  FORMAT_MESSAGE_FROM_SYSTEM,
4111  NULL, code, MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US),
4112  (LPSTR) &msg, 0, NULL);
4113  if (msg)
4114  {
4115  dbus_set_error (error, "win32.error", "%s", msg);
4116  LocalFree (msg);
4117  }
4118  else
4119  dbus_set_error (error, "win32.error", "Unknown error code %d or FormatMessage failed", code);
4120 }
4121 
4122 void
4123 _dbus_win_warn_win_error (const char *message,
4124  unsigned long code)
4125 {
4126  DBusError error;
4127 
4128  dbus_error_init (&error);
4129  _dbus_win_set_error_from_win_error (&error, code);
4130  _dbus_warn ("%s: %s", message, error.message);
4131  dbus_error_free (&error);
4132 }
4133 
4143  DBusError *error)
4144 {
4145  const char *filename_c;
4146 
4147  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4148 
4149  filename_c = _dbus_string_get_const_data (filename);
4150 
4151  if (RemoveDirectoryA (filename_c) == 0)
4152  {
4153  char *emsg = _dbus_win_error_string (GetLastError ());
4154  dbus_set_error (error, _dbus_win_error_from_last_error (),
4155  "Failed to remove directory %s: %s",
4156  filename_c, emsg);
4157  _dbus_win_free_error_string (emsg);
4158  return FALSE;
4159  }
4160 
4161  return TRUE;
4162 }
4163 
4172 {
4173  if (_dbus_string_get_length (filename) > 0)
4174  return _dbus_string_get_byte (filename, 1) == ':'
4175  || _dbus_string_get_byte (filename, 0) == '\\'
4176  || _dbus_string_get_byte (filename, 0) == '/';
4177  else
4178  return FALSE;
4179 }
4180 
4183 {
4184  return FALSE;
4185 }
4186 
4187 int
4188 _dbus_save_socket_errno (void)
4189 {
4190  return errno;
4191 }
4192 
4193 void
4194 _dbus_restore_socket_errno (int saved_errno)
4195 {
4196  _dbus_win_set_errno (saved_errno);
4197 }
4198 
4199 static const char *log_tag = "dbus";
4200 static DBusLogFlags log_flags = DBUS_LOG_FLAGS_STDERR;
4201 
4212 void
4213 _dbus_init_system_log (const char *tag,
4214  DBusLogFlags flags)
4215 {
4216  /* We never want to turn off logging completely */
4217  _dbus_assert (
4218  (flags & (DBUS_LOG_FLAGS_STDERR | DBUS_LOG_FLAGS_SYSTEM_LOG)) != 0);
4219 
4220  log_tag = tag;
4221  log_flags = flags;
4222 }
4223 
4231 void
4232 _dbus_logv (DBusSystemLogSeverity severity,
4233  const char *msg,
4234  va_list args)
4235 {
4236  const char *s = "";
4237  va_list tmp;
4238 
4239  switch(severity)
4240  {
4241  case DBUS_SYSTEM_LOG_INFO: s = "info"; break;
4242  case DBUS_SYSTEM_LOG_WARNING: s = "warning"; break;
4243  case DBUS_SYSTEM_LOG_SECURITY: s = "security"; break;
4244  case DBUS_SYSTEM_LOG_ERROR: s = "error"; break;
4245  default: _dbus_assert_not_reached ("invalid log severity");
4246  }
4247 
4248  if (log_flags & DBUS_LOG_FLAGS_SYSTEM_LOG)
4249  {
4250  DBusString out = _DBUS_STRING_INIT_INVALID;
4251  const char *message = NULL;
4252  DBUS_VA_COPY (tmp, args);
4253 
4254  if (!_dbus_string_init (&out))
4255  goto out;
4256  if (!_dbus_string_append_printf (&out, "%s: ", s))
4257  goto out;
4258  if (!_dbus_string_append_printf_valist (&out, msg, tmp))
4259  goto out;
4260  message = _dbus_string_get_const_data (&out);
4261 out:
4262  if (message != NULL)
4263  {
4264  OutputDebugStringA (message);
4265  }
4266  else
4267  {
4268  OutputDebugStringA ("Out of memory while formatting message: '''");
4269  OutputDebugStringA (msg);
4270  OutputDebugStringA ("'''");
4271  }
4272 
4273  va_end (tmp);
4274  _dbus_string_free (&out);
4275  }
4276 
4277  if (log_flags & DBUS_LOG_FLAGS_STDERR)
4278  {
4279  DBUS_VA_COPY (tmp, args);
4280  fprintf (stderr, "%s[%lu]: %s: ", log_tag, _dbus_pid_for_log (), s);
4281  vfprintf (stderr, msg, tmp);
4282  fprintf (stderr, "\n");
4283  va_end (tmp);
4284  }
4285 }
4286 
4287 /*
4288  * Return the low-level representation of a socket error, as used by
4289  * cross-platform socket APIs like inet_ntop(), send() and recv(). This
4290  * is the standard errno on Unix, but is WSAGetLastError() on Windows.
4291  *
4292  * Some libdbus internal functions copy this into errno, but with
4293  * hindsight that was probably a design flaw.
4294  */
4295 int
4296 _dbus_get_low_level_socket_errno (void)
4297 {
4298  return WSAGetLastError ();
4299 }
4300 
4301 void
4302 _dbus_win_set_error_from_last_error (DBusError *error,
4303  const char *format,
4304  ...)
4305 {
4306  const char *name;
4307  char *message = NULL;
4308 
4309  if (error == NULL)
4310  return;
4311 
4312  /* make sure to do this first, in case subsequent library calls overwrite GetLastError() */
4313  name = _dbus_win_error_from_last_error ();
4314  message = _dbus_win_error_string (GetLastError ());
4315 
4316  if (format != NULL)
4317  {
4318  DBusString str;
4319  va_list args;
4320  dbus_bool_t retval;
4321 
4322  if (!_dbus_string_init (&str))
4323  {
4324  _DBUS_SET_OOM (error);
4325  goto out;
4326  }
4327 
4328  va_start (args, format);
4329  retval = _dbus_string_append_printf_valist (&str, format, args);
4330  va_end (args);
4331  if (!retval)
4332  {
4333  _DBUS_SET_OOM (error);
4334  _dbus_string_free (&str);
4335  goto out;
4336  }
4337 
4338  dbus_set_error (error, name, "%s: %s", _dbus_string_get_const_data (&str), message);
4339  _dbus_string_free (&str);
4340  }
4341  else
4342  {
4343  dbus_set_error (error, name, "%s", message);
4344  }
4345 
4346 out:
4347  if (message != NULL)
4348  _dbus_win_free_error_string (message);
4349 
4350  _DBUS_ASSERT_ERROR_IS_SET (error);
4351 }
4352 
4364 HANDLE
4365 _dbus_win_event_create_inheritable (DBusError *error)
4366 {
4367  HANDLE handle;
4368 
4369  handle = CreateEvent (NULL, TRUE, FALSE, NULL);
4370  if (handle == NULL)
4371  {
4372  _dbus_win_set_error_from_last_error (error, "Could not create event");
4373  return NULL;
4374  }
4375  else if (GetLastError () == ERROR_ALREADY_EXISTS)
4376  {
4377  _dbus_win_set_error_from_last_error (error, "Event already exists");
4378  return NULL;
4379  }
4380 
4381  if (!SetHandleInformation (handle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
4382  {
4383  _dbus_win_set_error_from_last_error (error, "Could not set inheritance for event %p", handle);
4384  CloseHandle (handle);
4385  return NULL;
4386  }
4387  return handle;
4388 }
4389 
4398 _dbus_win_event_set (HANDLE handle, DBusError *error)
4399 {
4400  _dbus_assert (handle != NULL);
4401 
4402  if (!SetEvent (handle))
4403  {
4404  _dbus_win_set_error_from_last_error (error, "Could not trigger event (handle %p)", handle);
4405  return FALSE;
4406  }
4407  return TRUE;
4408 }
4409 
4421 _dbus_win_event_wait (HANDLE handle, int timeout, DBusError *error)
4422 {
4423  DWORD status;
4424 
4425  _dbus_assert (handle != NULL);
4426 
4427  status = WaitForSingleObject (handle, timeout);
4428  switch (status)
4429  {
4430  case WAIT_OBJECT_0:
4431  return TRUE;
4432 
4433  case WAIT_FAILED:
4434  {
4435  _dbus_win_set_error_from_last_error (error, "Unable to wait for event (handle %p)", handle);
4436  return FALSE;
4437  }
4438 
4439  case WAIT_TIMEOUT:
4440  /* GetLastError() is not set */
4441  dbus_set_error (error, DBUS_ERROR_TIMEOUT, "Timed out waiting for event (handle %p)", handle);
4442  return FALSE;
4443 
4444  default:
4445  /* GetLastError() is probably not set? */
4446  dbus_set_error (error, DBUS_ERROR_FAILED, "Unknown result '%lu' while waiting for event (handle %p)", status, handle);
4447  return FALSE;
4448  }
4449 }
4450 
4460 _dbus_win_event_free (HANDLE handle, DBusError *error)
4461 {
4462  if (handle == NULL || handle == INVALID_HANDLE_VALUE)
4463  return TRUE;
4464 
4465  if (CloseHandle (handle))
4466  return TRUE;
4467 
4468  /* the handle may already be closed */
4469  if (GetLastError () == ERROR_INVALID_HANDLE)
4470  return TRUE;
4471 
4472  _dbus_win_set_error_from_last_error (error, "Could not close event (handle %p)", handle);
4473  return FALSE;
4474 }
4475 
4476 #ifdef HAVE_AFUNIX_H
4477 static dbus_bool_t
4478 _dbus_open_socket (SOCKET *socket_p,
4479  int domain,
4480  int type,
4481  int protocol,
4482  DBusError *error)
4483 {
4484  if (!_dbus_win_startup_winsock ())
4485  {
4486  _DBUS_SET_OOM (error);
4487  return FALSE;
4488  }
4489 
4490  *socket_p = socket (domain, type, protocol);
4491  if (*socket_p == INVALID_SOCKET)
4492  {
4493  DBUS_SOCKET_SET_ERRNO ();
4494  dbus_set_error (error, _dbus_error_from_errno (errno),
4495  "Failed to open socket: %s",
4497  return FALSE;
4498  }
4499 
4500  _dbus_win_handle_set_close_on_exec ((HANDLE) *socket_p);
4501  return TRUE;
4502 }
4503 
4514 static dbus_bool_t
4515 _dbus_open_unix_socket (SOCKET *socket,
4516  DBusError *error)
4517 {
4518  return _dbus_open_socket (socket, AF_UNIX, SOCK_STREAM, 0, error);
4519 }
4520 #endif /* HAVE_AFUNIX_H */
4521 
4536 DBusSocket
4537 _dbus_connect_unix_socket (const char *path,
4538  dbus_bool_t abstract,
4539  DBusError *error)
4540 {
4541  DBusSocket s = DBUS_SOCKET_INIT;
4542 
4543 #ifdef HAVE_AFUNIX_H
4544  struct sockaddr_un addr;
4545  size_t path_len;
4546 
4547  _DBUS_STATIC_ASSERT (sizeof (addr.sun_path) > _DBUS_MAX_SUN_PATH_LENGTH);
4548  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4549 
4550  _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
4551  path, abstract);
4552 
4553  if (abstract)
4554  {
4556  "Failed to connect: UNIX abstract socket is not supported on this system");
4557  return s;
4558  }
4559 
4560  path_len = strlen (path);
4561  if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
4562  {
4564  "Failed to connect: socket name too long");
4565  return s;
4566  }
4567 
4568  if (!_dbus_open_unix_socket (&s.sock, error))
4569  {
4570  _DBUS_ASSERT_ERROR_IS_SET (error);
4571  return s;
4572  }
4573  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4574 
4575  _DBUS_ZERO (addr);
4576  addr.sun_family = AF_UNIX;
4577  strncpy (addr.sun_path, path, sizeof (addr.sun_path) - 1);
4578 
4579  if (connect (s.sock, (struct sockaddr *) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
4580  {
4581  DBUS_SOCKET_SET_ERRNO ();
4582  dbus_set_error (error,
4583  _dbus_error_from_errno (errno),
4584  "Failed to connect to socket %s: %s",
4585  path, _dbus_strerror (errno));
4586 
4587  _dbus_close_socket (&s, NULL);
4588  return s;
4589  }
4590 
4591  if (!_dbus_set_socket_nonblocking (s, error))
4592  _dbus_close_socket (&s, NULL);
4593 
4594 #else
4596  "Failed to connect: UNIX socket is not supported with this build");
4597 #endif
4598 
4599  return s;
4600 }
4601 
4616 DBusSocket
4617 _dbus_listen_unix_socket (const char *path,
4618  dbus_bool_t abstract,
4619  DBusError *error)
4620 {
4621  DBusSocket s = DBUS_SOCKET_INIT;
4622 
4623 #ifdef HAVE_AFUNIX_H
4624  struct sockaddr_un addr;
4625  size_t path_len;
4626  _DBUS_STATIC_ASSERT (sizeof (addr.sun_path) > _DBUS_MAX_SUN_PATH_LENGTH);
4627 
4628  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4629 
4630  _dbus_verbose ("listening on unix socket %s abstract=%d\n",
4631  path, abstract);
4632 
4633  if (abstract)
4634  {
4636  "Failed to listen: UNIX abstract socket is not supported on this system");
4637  return s;
4638  }
4639 
4640  if (!_dbus_open_unix_socket (&s.sock, error))
4641  {
4642  _DBUS_ASSERT_ERROR_IS_SET (error);
4643  return s;
4644  }
4645  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4646 
4647  _DBUS_ZERO (addr);
4648  addr.sun_family = AF_UNIX;
4649  path_len = strlen (path);
4650 
4651  /* see related comment in dbus-sysdeps-unix.c */
4652  /* there is no S_ISSOCK on windows yet, so just unlink the path */
4653  unlink (path);
4654 
4655  if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
4656  {
4658  "Failed to listen: socket name too long");
4659  _dbus_close_socket (&s, NULL);
4660  return s;
4661  }
4662 
4663  strncpy (addr.sun_path, path, sizeof (addr.sun_path) - 1);
4664 
4665  if (bind (s.sock, (struct sockaddr *) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
4666  {
4667  DBUS_SOCKET_SET_ERRNO ();
4668  dbus_set_error (error, _dbus_error_from_errno (errno),
4669  "Failed to bind socket \"%s\": %s",
4670  path, _dbus_strerror (errno));
4671  _dbus_close_socket (&s, NULL);
4672  return s;
4673  }
4674 
4675  if (listen (s.sock, SOMAXCONN /* backlog */) < 0)
4676  {
4677  DBUS_SOCKET_SET_ERRNO ();
4678  dbus_set_error (error, _dbus_error_from_errno (errno),
4679  "Failed to listen on socket \"%s\": %s",
4680  path, _dbus_strerror (errno));
4681  _dbus_close_socket (&s, NULL);
4682  return s;
4683  }
4684 
4685  if (!_dbus_set_socket_nonblocking (s, error))
4686  {
4687  _DBUS_ASSERT_ERROR_IS_SET (error);
4688  _dbus_close_socket (&s, NULL);
4689  return s;
4690  }
4691 #else
4693  "Failed to listen: UNIX socket is not supported with this build");
4694 #endif
4695 
4696  return s;
4697 }
4698 
4700 /* tests in dbus-sysdeps-util.c */
dbus_bool_t _dbus_credentials_add_windows_sid(DBusCredentials *credentials, const char *windows_sid)
Add a Windows user SID to the credentials.
dbus_bool_t _dbus_credentials_add_pid(DBusCredentials *credentials, dbus_pid_t pid)
Add a UNIX process ID to the credentials.
dbus_bool_t _dbus_credentials_are_anonymous(DBusCredentials *credentials)
Checks whether a credentials object contains a user identity.
void dbus_set_error_const(DBusError *error, const char *name, const char *message)
Assigns an error name and message to a DBusError.
Definition: dbus-errors.c:243
void dbus_error_init(DBusError *error)
Initializes a DBusError structure.
Definition: dbus-errors.c:188
void dbus_set_error(DBusError *error, const char *name, const char *format,...)
Assigns an error name and message to a DBusError.
Definition: dbus-errors.c:354
void dbus_error_free(DBusError *error)
Frees an error that's been set (or just initialized), then reinitializes the error as in dbus_error_i...
Definition: dbus-errors.c:211
dbus_bool_t dbus_error_is_set(const DBusError *error)
Checks whether an error occurred (the error is set).
Definition: dbus-errors.c:329
dbus_bool_t _dbus_file_exists(const char *file)
Checks if a file exists.
dbus_bool_t _dbus_delete_file(const DBusString *filename, DBusError *error)
Deletes the given file.
dbus_bool_t _dbus_make_file_world_readable(const DBusString *filename, DBusError *error)
Makes the file readable by every user in the system.
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
#define _DBUS_UNLOCK(name)
Unlocks a global lock.
const char * _dbus_error_from_errno(int error_number)
Converts a UNIX errno, or Windows errno or WinSock error value into a DBusError name.
Definition: dbus-sysdeps.c:599
#define _DBUS_LOCK(name)
Locks a global lock, initializing it first if necessary.
const char * _dbus_strerror_from_errno(void)
Get error message from errno.
Definition: dbus-sysdeps.c:758
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
#define _DBUS_ZERO(object)
Sets all bits in an object to zero.
void * _dbus_list_pop_first(DBusList **list)
Removes the first value in the list and returns it.
Definition: dbus-list.c:677
dbus_bool_t _dbus_list_append(DBusList **list, void *data)
Appends a value to the list.
Definition: dbus-list.c:271
#define NULL
A null pointer, defined appropriately for C or C++.
#define TRUE
Expands to "1".
#define FALSE
Expands to "0".
DBUS_PRIVATE_EXPORT void _dbus_verbose_bytes_of_string(const DBusString *str, int start, int len)
Dump the given part of the string to verbose log.
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:692
void * dbus_realloc(void *memory, size_t bytes)
Resizes a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:592
#define dbus_new(type, count)
Safe macro for using dbus_malloc().
Definition: dbus-memory.h:57
#define dbus_new0(type, count)
Safe macro for using dbus_malloc0().
Definition: dbus-memory.h:58
void * dbus_malloc(size_t bytes)
Allocates the given number of bytes, as with standard malloc().
Definition: dbus-memory.c:452
#define DBUS_ERROR_TIMEOUT
Certain timeout errors, possibly ETIMEDOUT on a socket.
#define DBUS_ERROR_NOT_SUPPORTED
Requested operation isn't supported (like ENOSYS on UNIX).
#define DBUS_ERROR_BAD_ADDRESS
A D-Bus bus address was malformed.
#define DBUS_ERROR_IO_ERROR
Something went wrong reading or writing to a socket, for example.
#define DBUS_ERROR_SPAWN_CHILD_EXITED
While starting a new process, the child exited with a status code.
#define DBUS_ERROR_ACCESS_DENIED
Security restrictions don't allow doing what you're trying to do.
#define DBUS_ERROR_FILE_EXISTS
Existing file and the operation you're using does not silently overwrite.
#define DBUS_ERROR_LIMITS_EXCEEDED
Some limited resource is exhausted.
#define DBUS_ERROR_FAILED
A generic error; "something went wrong" - see the error message for more.
#define DBUS_ERROR_NO_MEMORY
There was not enough memory to complete an operation.
#define DBUS_ERROR_INVALID_ARGS
Invalid arguments passed to a method call.
#define DBUS_ERROR_FILE_NOT_FOUND
Missing file.
dbus_bool_t _dbus_sha_compute(const DBusString *data, DBusString *ascii_output)
Computes the ASCII hex-encoded shasum of the given data and appends it to the output string.
Definition: dbus-sha.c:483
dbus_bool_t _dbus_string_set_length(DBusString *str, int length)
Sets the length of a string.
Definition: dbus-string.c:847
dbus_bool_t _dbus_string_append(DBusString *str, const char *buffer)
Appends a nul-terminated C-style string to a DBusString.
Definition: dbus-string.c:980
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:182
void _dbus_string_init_const(DBusString *str, const char *value)
Initializes a constant string.
Definition: dbus-string.c:197
dbus_bool_t _dbus_string_copy(const DBusString *source, int start, DBusString *dest, int insert_at)
Like _dbus_string_move(), but does not delete the section of the source string that's copied to the d...
Definition: dbus-string.c:1345
dbus_bool_t _dbus_string_validate_utf8(const DBusString *str, int start, int len)
Checks that the given range of the string is valid UTF-8.
Definition: dbus-string.c:2678
void _dbus_string_init_const_len(DBusString *str, const char *value, int len)
Initializes a constant string with a length.
Definition: dbus-string.c:217
void _dbus_string_tolower_ascii(const DBusString *str, int start, int len)
Converts the given range of the string to lower case.
Definition: dbus-string.c:2608
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init(), and fills it with the same contents as #_DBUS_STRING_I...
Definition: dbus-string.c:278
char * _dbus_string_get_data_len(DBusString *str, int start, int len)
Gets a sub-portion of the raw character buffer from the string.
Definition: dbus-string.c:535
void _dbus_string_shorten(DBusString *str, int length_to_remove)
Makes a string shorter by the given number of bytes.
Definition: dbus-string.c:825
dbus_bool_t _dbus_string_append_printf_valist(DBusString *str, const char *format, va_list args)
Appends a printf-style formatted string to the DBusString.
Definition: dbus-string.c:1105
dbus_bool_t _dbus_string_lengthen(DBusString *str, int additional_length)
Makes a string longer by the given number of bytes.
Definition: dbus-string.c:805
dbus_bool_t _dbus_string_append_byte(DBusString *str, unsigned char byte)
Appends a single byte to the string, returning FALSE if not enough memory.
Definition: dbus-string.c:1190
dbus_bool_t _dbus_string_append_printf(DBusString *str, const char *format,...)
Appends a printf-style formatted string to the DBusString.
Definition: dbus-string.c:1147
void _dbus_logv(DBusSystemLogSeverity severity, const char *msg, va_list args)
Log a message to the system log file (e.g.
dbus_bool_t _dbus_read_local_machine_uuid(DBusGUID *machine_id, dbus_bool_t create_if_not_found, DBusError *error)
Reads the uuid of the machine we're running on from the dbus configuration.
#define _DBUS_POLLOUT
Writing now will not block.
Definition: dbus-sysdeps.h:429
unsigned long dbus_uid_t
A user ID.
Definition: dbus-sysdeps.h:137
dbus_bool_t _dbus_get_is_errno_eagain_or_ewouldblock(int e)
See if errno is EAGAIN or EWOULDBLOCK (this has to be done differently for Winsock so is abstracted)
unsigned long _dbus_pid_for_log(void)
The only reason this is separate from _dbus_getpid() is to allow it on Windows for logging but not fo...
unsigned long dbus_pid_t
A process ID.
Definition: dbus-sysdeps.h:135
int _dbus_read_socket(DBusSocket fd, DBusString *buffer, int count)
Socket interface.
void _dbus_exit(int code)
Exit the process, returning the given value.
#define _DBUS_POLLERR
Error condition.
Definition: dbus-sysdeps.h:431
int _dbus_write_socket(DBusSocket fd, const DBusString *buffer, int start, int len)
Thin wrapper around the write() system call that writes a part of a DBusString and handles EINTR for ...
void _dbus_atomic_set_nonzero(DBusAtomic *atomic)
Atomically set the value of an integer to something nonzero.
dbus_bool_t _dbus_socketpair(DBusSocket *fd1, DBusSocket *fd2, dbus_bool_t blocking, DBusError *error)
Creates pair of connect sockets (as in socketpair()).
dbus_bool_t _dbus_append_keyring_directory_for_credentials(DBusString *directory, DBusCredentials *credentials)
Appends the directory in which a keyring for the given credentials should be stored.
#define DBUS_UID_UNSET
an invalid UID used to represent an uninitialized dbus_uid_t field
Definition: dbus-sysdeps.h:144
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
dbus_bool_t _dbus_read_credentials_socket(DBusSocket handle, DBusCredentials *credentials, DBusError *error)
Reads a single byte which must be nul (an error occurs otherwise), and reads unix credentials if avai...
const char * _dbus_getenv(const char *varname)
Wrapper for getenv().
Definition: dbus-sysdeps.c:195
DBusSocket _dbus_listen_unix_socket(const char *path, dbus_bool_t abstract, DBusError *error)
Creates a socket and binds it to the given path, then listens on the socket.
dbus_pid_t _dbus_getpid(void)
Gets our process ID.
dbus_int32_t _dbus_atomic_get(DBusAtomic *atomic)
Atomically get the value of an integer.
dbus_bool_t _dbus_set_socket_nonblocking(DBusSocket handle, DBusError *error)
Sets a file descriptor to be nonblocking.
dbus_bool_t _dbus_lookup_session_address(dbus_bool_t *supported, DBusString *address, DBusError *error)
Determines the address of the session bus by querying a platform-specific method.
dbus_bool_t _dbus_credentials_add_from_user(DBusCredentials *credentials, const DBusString *username, DBusCredentialsAddFlags flags, DBusError *error)
Adds the credentials corresponding to the given username.
DBusSocket _dbus_connect_tcp_socket(const char *host, const char *port, const char *family, DBusError *error)
Creates a socket and connects to a socket at the given host and port.
void _dbus_disable_sigpipe(void)
signal (SIGPIPE, SIG_IGN);
dbus_bool_t _dbus_check_setuid(void)
NOTE: If you modify this function, please also consider making the corresponding change in GLib.
void _dbus_sleep_milliseconds(int milliseconds)
Sleeps the given number of milliseconds.
const char * _dbus_get_tmpdir(void)
Gets the temporary files directory, using GetTempPath()
dbus_bool_t _dbus_check_dir_is_private_to_user(DBusString *dir, DBusError *error)
Checks to make sure the given directory is private to the user.
dbus_bool_t _dbus_daemon_unpublish_session_bus_address(void)
Clear the platform-specific centralized location where the session bus address is published.
#define _DBUS_POLLIN
There is data to read.
Definition: dbus-sysdeps.h:425
int _dbus_listen_tcp_socket(const char *host, const char *port, const char *family, DBusString *retport, const char **retfamily, DBusSocket **fds_p, DBusError *error)
Creates a socket and binds it to the given path, then listens on the socket.
dbus_bool_t _dbus_send_credentials_socket(DBusSocket handle, DBusError *error)
Sends a single nul byte with our UNIX credentials as ancillary data.
dbus_uid_t _dbus_getuid(void)
Gets our Unix UID.
dbus_bool_t _dbus_credentials_add_from_current_process(DBusCredentials *credentials)
Adds the credentials of the current process to the passed-in credentials object.
dbus_bool_t _dbus_close_socket(DBusSocket *fd, DBusError *error)
Closes a socket and invalidates it.
DBusSocket _dbus_connect_unix_socket(const char *path, dbus_bool_t abstract, DBusError *error)
Creates a socket and connects it to the UNIX domain socket at the given path.
void _dbus_atomic_set_zero(DBusAtomic *atomic)
Atomically set the value of an integer to 0.
dbus_int32_t _dbus_atomic_inc(DBusAtomic *atomic)
Atomically increments an integer.
dbus_bool_t _dbus_generate_random_bytes(DBusString *str, int n_bytes, DBusError *error)
Generates the given number of random bytes, using the best mechanism we can come up with.
int _dbus_printf_string_upper_bound(const char *format, va_list args)
Measure the message length without terminating nul.
void _dbus_get_monotonic_time(long *tv_sec, long *tv_usec)
Get current time, as in gettimeofday().
dbus_bool_t _dbus_delete_directory(const DBusString *filename, DBusError *error)
Removes a directory; Directory must be empty.
void _dbus_get_real_time(long *tv_sec, long *tv_usec)
Get current time, as in gettimeofday().
void _dbus_abort(void)
Aborts the program with SIGABRT (dumping core).
Definition: dbus-sysdeps.c:87
int _dbus_poll(DBusPollFD *fds, int n_fds, int timeout_milliseconds)
Wrapper for poll().
dbus_bool_t _dbus_get_autolaunch_address(const char *scope, DBusString *address, DBusError *error)
Returns the address of a new session bus.
int _dbus_write_socket_two(DBusSocket fd, const DBusString *buffer1, int start1, int len1, const DBusString *buffer2, int start2, int len2)
Like _dbus_write() but will use writev() if possible to write both buffers in sequence.
dbus_bool_t _dbus_concat_dir_and_file(DBusString *dir, const DBusString *next_component)
Appends the given filename to the given directory.
void _dbus_print_backtrace(void)
On GNU libc systems, print a crude backtrace to stderr.
void _dbus_init_system_log(const char *tag, DBusLogFlags flags)
Initialize the system log.
DBusSocket _dbus_accept(DBusSocket listen_fd)
Accepts a connection on a listening socket.
#define _DBUS_MAX_SUN_PATH_LENGTH
Maximum length of the path to a UNIX domain socket, sockaddr_un::sun_path member.
Definition: dbus-sysdeps.h:745
dbus_bool_t _dbus_append_user_from_current_process(DBusString *str)
Append to the string the identity we would like to have when we authenticate, on UNIX this is the cur...
void _dbus_flush_caches(void)
Called when the bus daemon is signaled to reload its configuration; any caches should be nuked.
dbus_bool_t _dbus_ensure_directory(const DBusString *filename, DBusError *error)
Creates a directory; succeeds if the directory is created or already existed.
dbus_bool_t _dbus_path_is_absolute(const DBusString *filename)
Checks whether the filename is an absolute path.
dbus_bool_t _dbus_create_directory(const DBusString *filename, DBusError *error)
Creates a directory.
_DBUS_GNUC_EXTENSION typedef unsigned long dbus_uint64_t
A 64-bit unsigned integer.
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
#define DBUS_INT64_CONSTANT(val)
Declare a 64-bit signed integer constant.
int dbus_int32_t
A 32-bit signed integer on all platforms.
unsigned int dbus_uint32_t
A 32-bit unsigned integer on all platforms.
An atomic integer safe to increment or decrement from multiple threads.
Definition: dbus-sysdeps.h:323
volatile dbus_int32_t value
Value of the atomic integer.
Definition: dbus-sysdeps.h:327
Object representing an exception.
Definition: dbus-errors.h:49
const char * message
public error message field
Definition: dbus-errors.h:51
A node in a linked list.
Definition: dbus-list.h:35
short events
Events to poll for.
Definition: dbus-sysdeps.h:420
short revents
Events that occurred.
Definition: dbus-sysdeps.h:421
DBusPollable fd
File descriptor.
Definition: dbus-sysdeps.h:419
Socket interface.
Definition: dbus-sysdeps.h:181
A globally unique ID ; we have one for each DBusServer, and also one for each machine with libdbus in...
dbus_uint32_t as_uint32s[DBUS_UUID_LENGTH_WORDS]
guid as four uint32 values