D-Bus 1.15.0
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 */
56extern BOOL WINAPI ConvertStringSidToSidA (LPCSTR StringSid, PSID *Sid);
57extern 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
86typedef int socklen_t;
87
88/* uncomment to enable windows event based poll implementation */
89//#define USE_CHRIS_IMPL
90
91void
92_dbus_win_set_errno (int err)
93{
94#ifdef DBUS_WINCE
95 SetLastError (err);
96#else
97 errno = err;
98#endif
99}
100
101static 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 */
107typedef MIB_TCPROW_OWNER_PID _MIB_TCPROW_EX;
108typedef MIB_TCPTABLE_OWNER_PID MIB_TCPTABLE_EX;
109typedef PMIB_TCPTABLE_OWNER_PID PMIB_TCPTABLE_EX;
110typedef 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 */
115static ProcAllocateAndGetTcpExtTableFromStack lpfnAllocateAndGetTcpExTableFromStack = NULL;
116
122static BOOL
123load_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
147static dbus_pid_t
148get_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
200static dbus_pid_t
201get_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
246static 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. */
304const 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:
322
323 case 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
336char*
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
355void
356_dbus_win_free_error_string (char *string)
357{
358 LocalFree (string);
359}
360
381int
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
451int
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
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
529static 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 ();
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
588int
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
662int
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
715out:
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
737int _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 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 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
779wchar_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
828char *
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
922out2:
923 dbus_free (wdomain);
924out1:
925 if (!retval)
926 {
927 dbus_free (*ppsid);
928 *ppsid = NULL;
929 }
930
931 return retval;
932}
933
943unsigned long
945{
946 return _dbus_getpid ();
947}
948
949#ifndef DBUS_WINCE
950
951static BOOL
952is_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
1032failed:
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
1155out2:
1156 closesocket (socket2);
1157out1:
1158 closesocket (socket1);
1159out0:
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
1170static 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;
1200oom:
1201 _dbus_string_free (&msg);
1202 return result;
1203}
1204
1205#ifdef USE_CHRIS_IMPL
1206static 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;
1237oom:
1238 _dbus_string_free (&msg);
1239 return result;
1240}
1241#else
1242static 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;
1273oom:
1274 _dbus_string_free (&msg);
1275 return result;
1276}
1277#endif
1278#endif
1279
1280#ifdef USE_CHRIS_IMPL
1289static 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
1400oom:
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
1423static 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
1511int
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
1525Original 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
1559void
1560_dbus_exit (int code)
1561{
1562 _exit (code);
1563}
1564
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
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,
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
1720out:
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
1748int
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,
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
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);
2091again:
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 */
2126static 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
2151static 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
2236out:
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;
2353failed:
2354 retval = FALSE;
2355end:
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
2395{
2396 return GetCurrentProcessId ();
2397}
2398
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
2423void
2425{
2426 Sleep (milliseconds);
2427}
2428
2429
2437void
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
2468void
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
2479void
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
2597const 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
2710static 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
2831static 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 */
2839static void
2840dump_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
2863void _dbus_print_backtrace (void)
2864{
2865 _dbus_verbose (" D-Bus not compiled with backtrace support\n");
2866}
2867#endif
2868
2869static 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
2952static HANDLE hDBusDaemonMutex = NULL;
2953static HANDLE hDBusSharedMem = NULL;
2954// sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
2955static const char *cUniqueDBusInitMutex = "UniqueDBusInitMutex";
2956// sync _dbus_get_autolaunch_address
2957static const char *cDBusAutolaunchMutex = "DBusAutolaunchMutex";
2958// mutex to determine if dbus-daemon is already started (per user)
2959static const char *cDBusDaemonMutex = "DBusDaemonMutex";
2960// named shm for dbus adress info (per user)
2961static const char *cDBusDaemonAddressInfo = "DBusDaemonAddressInfo";
2962
2963/* custom command line parameter for autolaunching daemon */
2964static const char *autolaunch_custom_command_line_parameter = "";
2965
2978void _dbus_test_win_autolaunch_set_command_line_parameter (const char *path)
2979{
2980 autolaunch_custom_command_line_parameter = path;
2981}
2982
2983static HANDLE *autolaunch_handle_location;
2984
2995void
2996_dbus_test_win_set_autolaunch_handle_location (HANDLE *location)
2997{
2998 autolaunch_handle_location = location;
2999}
3000
3011static 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
3039out:
3040 _dbus_string_free (&install_path);
3041 return retval;
3042}
3043
3062static 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;
3095out:
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
3127static 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
3142static 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
3289out:
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
3350static 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
3385out:
3386 CloseHandle (sharedMem);
3387 return retval;
3388}
3389
3390static 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
3431out:
3432 _dbus_platform_rmutex_unlock (lock);
3433 _dbus_platform_rmutex_free (lock);
3434 _dbus_string_free (&mutex_name);
3435
3436 return retval;
3437}
3438
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
3620out:
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
3707void
3709{
3710 InterlockedExchange (&atomic->value, 0);
3711}
3712
3718void
3720{
3721 InterlockedExchange (&atomic->value, 1);
3722}
3723
3731void
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
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
3961const 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
4101void
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
4122void
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
4187int
4188_dbus_save_socket_errno (void)
4189{
4190 return errno;
4191}
4192
4193void
4194_dbus_restore_socket_errno (int saved_errno)
4195{
4196 _dbus_win_set_errno (saved_errno);
4197}
4198
4199static const char *log_tag = "dbus";
4200static DBusLogFlags log_flags = DBUS_LOG_FLAGS_STDERR;
4201
4212void
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
4231void
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 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);
4261out:
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 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 */
4295int
4296_dbus_get_low_level_socket_errno (void)
4297{
4298 return WSAGetLastError ();
4299}
4300
4301void
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
4346out:
4347 if (message != NULL)
4348 _dbus_win_free_error_string (message);
4349
4350 _DBUS_ASSERT_ERROR_IS_SET (error);
4351}
4352
4364HANDLE
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
4477static 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
4514static 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
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
4588 return s;
4589 }
4590
4591 if (!_dbus_set_socket_nonblocking (s, error))
4593
4594#else
4596 "Failed to connect: UNIX socket is not supported with this build");
4597#endif
4598
4599 return s;
4600}
4601
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");
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));
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));
4682 return s;
4683 }
4684
4685 if (!_dbus_set_socket_nonblocking (s, error))
4686 {
4687 _DBUS_ASSERT_ERROR_IS_SET (error);
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.
#define _DBUS_LOCK(name)
Locks a global lock, initializing it first if necessary.
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
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:845
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:978
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:180
void _dbus_string_init_const(DBusString *str, const char *value)
Initializes a constant string.
Definition: dbus-string.c:195
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:1343
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:533
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:2676
void _dbus_string_init_const_len(DBusString *str, const char *value, int len)
Initializes a constant string with a length.
Definition: dbus-string.c:215
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:2606
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:276
void _dbus_string_shorten(DBusString *str, int length_to_remove)
Makes a string shorter by the given number of bytes.
Definition: dbus-string.c:823
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:1103
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:803
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:1188
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:1145
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:427
unsigned long dbus_uid_t
A user ID.
Definition: dbus-sysdeps.h:135
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:133
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:429
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:142
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.
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:423
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:743
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.
const char * _dbus_get_tmpdir(void)
Gets the temporary files directory, using GetTempPath()
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:321
volatile dbus_int32_t value
Value of the atomic integer.
Definition: dbus-sysdeps.h:325
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:418
short revents
Events that occurred.
Definition: dbus-sysdeps.h:419
DBusPollable fd
File descriptor.
Definition: dbus-sysdeps.h:417
Socket interface.
Definition: dbus-sysdeps.h:179
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