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