X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dbus%2Fdbus-sysdeps-win.c;h=72ccb93d1e4fbccb53ab61675e79728a15554d2c;hb=757b80b9711d9733798c927495d74c7323e95400;hp=d0b208192f109ba9296b6ece0dfbd0103d500d6a;hpb=3404bb7238f2bb6dd5d678bc8f782810f3079241;p=platform%2Fupstream%2Fdbus.git diff --git a/dbus/dbus-sysdeps-win.c b/dbus/dbus-sysdeps-win.c index d0b2081..72ccb93 100644 --- a/dbus/dbus-sysdeps-win.c +++ b/dbus/dbus-sysdeps-win.c @@ -4,9 +4,9 @@ * Copyright (C) 2002, 2003 Red Hat, Inc. * Copyright (C) 2003 CodeFactory AB * Copyright (C) 2005 Novell, Inc. - * Copyright (C) 2006 Ralf Habacker * Copyright (C) 2006 Peter Kümmel * Copyright (C) 2006 Christian Ehrlicher + * Copyright (C) 2006-2013 Ralf Habacker * * Licensed under the Academic Free License version 2.1 * @@ -37,10 +37,12 @@ #endif #include "dbus-internals.h" +#include "dbus-sha.h" #include "dbus-sysdeps.h" #include "dbus-threads.h" #include "dbus-protocol.h" #include "dbus-string.h" +#include "dbus-sysdeps.h" #include "dbus-sysdeps-win.h" #include "dbus-protocol.h" #include "dbus-hash.h" @@ -52,8 +54,9 @@ #include #include #include +#include -/* Declarations missing in mingw's headers */ +/* Declarations missing in mingw's and windows sdk 7.0 headers */ extern BOOL WINAPI ConvertStringSidToSidA (LPCSTR StringSid, PSID *Sid); extern BOOL WINAPI ConvertSidToStringSidA (PSID Sid, LPSTR *StringSid); @@ -69,6 +72,11 @@ extern BOOL WINAPI ConvertSidToStringSidA (PSID Sid, LPSTR *StringSid); #include #endif +#ifdef HAVE_WS2TCPIP_H +/* getaddrinfo for Windows CE (and Windows). */ +#include +#endif + #ifdef HAVE_WSPIAPI_H // needed for w2k compatibility (getaddrinfo/freeaddrinfo/getnameinfo) #ifdef __GNUC__ @@ -96,6 +104,93 @@ _dbus_win_set_errno (int err) #endif } +/** + * @brief return peer process id from tcp handle for localhost connections + * @param handle tcp socket descriptor + * @return process id or 0 in case the process id could not be fetched + */ +static dbus_pid_t +_dbus_get_peer_pid_from_tcp_handle (int handle) +{ + struct sockaddr_storage addr; + socklen_t len = sizeof (addr); + int peer_port; + + dbus_pid_t result; + DWORD size; + MIB_TCPTABLE_OWNER_PID *tcp_table; + DWORD i; + dbus_bool_t is_localhost = FALSE; + + getpeername (handle, (struct sockaddr *) &addr, &len); + + if (addr.ss_family == AF_INET) + { + struct sockaddr_in *s = (struct sockaddr_in *) &addr; + peer_port = ntohs (s->sin_port); + is_localhost = (htonl (s->sin_addr.s_addr) == INADDR_LOOPBACK); + } + else if (addr.ss_family == AF_INET6) + { + _dbus_verbose ("FIXME [61922]: IPV6 support not working on windows\n"); + return 0; + /* + struct sockaddr_in6 *s = (struct sockaddr_in6 * )&addr; + peer_port = ntohs (s->sin6_port); + is_localhost = (memcmp(s->sin6_addr.s6_addr, in6addr_loopback.s6_addr, 16) == 0); + _dbus_verbose ("IPV6 %08x %08x\n", s->sin6_addr.s6_addr, in6addr_loopback.s6_addr); + */ + } + else + { + _dbus_verbose ("no idea what address family %d is\n", addr.ss_family); + return 0; + } + + if (!is_localhost) + { + _dbus_verbose ("could not fetch process id from remote process\n"); + return 0; + } + + if (peer_port == 0) + { + _dbus_verbose + ("Error not been able to fetch tcp peer port from connection\n"); + return 0; + } + + if ((result = + GetExtendedTcpTable (NULL, &size, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0)) == ERROR_INSUFFICIENT_BUFFER) + { + tcp_table = (MIB_TCPTABLE_OWNER_PID *) dbus_malloc (size); + if (tcp_table == NULL) + { + _dbus_verbose ("Error allocating memory\n"); + return 0; + } + } + + if ((result = GetExtendedTcpTable (tcp_table, &size, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0)) != NO_ERROR) + { + _dbus_verbose ("Error fetching tcp table %d\n", result); + dbus_free (tcp_table); + return 0; + } + + result = 0; + for (i = 0; i < tcp_table->dwNumEntries; i++) + { + MIB_TCPROW_OWNER_PID *p = &tcp_table->table[i]; + int local_port = ntohs (p->dwLocalPort); + if (p->dwState == MIB_TCP_STATE_ESTAB && local_port == peer_port) + result = p->dwOwningPid; + } + + _dbus_verbose ("got pid %d\n", result); + dbus_free (tcp_table); + return result; +} /* Convert GetLastError() to a dbus error. */ const char* @@ -320,7 +415,7 @@ _dbus_close_socket (int fd, * @param fd the file descriptor */ void -_dbus_fd_set_close_on_exec (int handle) +_dbus_fd_set_close_on_exec (intptr_t handle) { if ( !SetHandleInformation( (HANDLE) handle, HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE, @@ -347,9 +442,10 @@ _dbus_set_fd_nonblocking (int handle, if (ioctlsocket (handle, FIONBIO, &one) == SOCKET_ERROR) { - dbus_set_error (error, _dbus_error_from_errno (WSAGetLastError ()), + DBUS_SOCKET_SET_ERRNO (); + dbus_set_error (error, _dbus_error_from_errno (errno), "Failed to set socket %d:%d to nonblocking: %s", handle, - _dbus_strerror (WSAGetLastError ())); + _dbus_strerror_from_errno ()); return FALSE; } @@ -426,7 +522,7 @@ _dbus_write_socket_two (int fd, NULL, NULL); - if (rc < 0) + if (rc == SOCKET_ERROR) { DBUS_SOCKET_SET_ERRNO (); _dbus_verbose ("WSASend: failed: %s\n", _dbus_strerror_from_errno ()); @@ -530,9 +626,12 @@ int _dbus_printf_string_upper_bound (const char *format, char buf[1024]; int bufsize; int len; + va_list args_copy; bufsize = sizeof (buf); - len = _vsnprintf (buf, bufsize - 1, format, args); + DBUS_VA_COPY (args_copy, args); + len = _vsnprintf (buf, bufsize - 1, format, args_copy); + va_end (args_copy); while (len == -1) /* try again */ { @@ -541,7 +640,13 @@ int _dbus_printf_string_upper_bound (const char *format, bufsize *= 2; p = malloc (bufsize); - len = _vsnprintf (p, bufsize - 1, format, args); + + if (p == NULL) + return -1; + + DBUS_VA_COPY (args_copy, args); + len = _vsnprintf (p, bufsize - 1, format, args_copy); + va_end (args_copy); free (p); } @@ -726,22 +831,23 @@ _dbus_pid_for_log (void) return _dbus_getpid (); } - #ifndef DBUS_WINCE /** Gets our SID - * @param points to sid buffer, need to be freed with LocalFree() + * @param sid points to sid buffer, need to be freed with LocalFree() + * @param process_id the process id for which the sid should be returned * @returns process sid */ static dbus_bool_t -_dbus_getsid(char **sid) +_dbus_getsid(char **sid, dbus_pid_t process_id) { HANDLE process_token = INVALID_HANDLE_VALUE; TOKEN_USER *token_user = NULL; DWORD n; PSID psid; int retval = FALSE; - - if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &process_token)) + HANDLE process_handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, process_id); + + if (!OpenProcessToken (process_handle, TOKEN_QUERY, &process_token)) { _dbus_win_warn_win_error ("OpenProcessToken failed", GetLastError ()); goto failed; @@ -769,6 +875,7 @@ _dbus_getsid(char **sid) retval = TRUE; failed: + CloseHandle (process_handle); if (process_token != INVALID_HANDLE_VALUE) CloseHandle (process_token); @@ -787,11 +894,6 @@ failed: * Creates a full-duplex pipe (as in socketpair()). * Sets both ends of the pipe nonblocking. * - * @todo libdbus only uses this for the debug-pipe server, so in - * principle it could be in dbus-sysdeps-util.c, except that - * dbus-sysdeps-util.c isn't in libdbus when tests are enabled and the - * debug-pipe server is used. - * * @param fd1 return location for one end * @param fd2 return location for the other end * @param blocking #TRUE if pipe should be blocking @@ -808,9 +910,6 @@ _dbus_full_duplex_pipe (int *fd1, struct sockaddr_in saddr; int len; u_long arg; - fd_set read_set, write_set; - struct timeval tv; - int res; _dbus_win_startup_winsock (); @@ -826,7 +925,7 @@ _dbus_full_duplex_pipe (int *fd1, saddr.sin_port = 0; saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - if (bind (temp, (struct sockaddr *)&saddr, sizeof (saddr))) + if (bind (temp, (struct sockaddr *)&saddr, sizeof (saddr)) == SOCKET_ERROR) { DBUS_SOCKET_SET_ERRNO (); goto out0; @@ -839,7 +938,7 @@ _dbus_full_duplex_pipe (int *fd1, } len = sizeof (saddr); - if (getsockname (temp, (struct sockaddr *)&saddr, &len)) + if (getsockname (temp, (struct sockaddr *)&saddr, &len) == SOCKET_ERROR) { DBUS_SOCKET_SET_ERRNO (); goto out0; @@ -946,7 +1045,6 @@ _dbus_poll (DBusPollFD *fds, msgp += sprintf (msgp, "WSAEventSelect: to=%d\n\t", timeout_milliseconds); for (i = 0; i < n_fds; i++) { - static dbus_bool_t warned = FALSE; DBusPollFD *fdp = &fds[i]; @@ -1084,7 +1182,6 @@ _dbus_poll (DBusPollFD *fds, msgp += sprintf (msgp, "select: to=%d\n\t", timeout_milliseconds); for (i = 0; i < n_fds; i++) { - static dbus_bool_t warned = FALSE; DBusPollFD *fdp = &fds[i]; @@ -1122,12 +1219,11 @@ _dbus_poll (DBusPollFD *fds, max_fd = MAX (max_fd, fdp->fd); } + // Avoid random lockups with send(), for lack of a better solution so far + tv.tv_sec = timeout_milliseconds < 0 ? 1 : timeout_milliseconds / 1000; + tv.tv_usec = timeout_milliseconds < 0 ? 0 : (timeout_milliseconds % 1000) * 1000; - tv.tv_sec = timeout_milliseconds / 1000; - tv.tv_usec = (timeout_milliseconds % 1000) * 1000; - - ready = select (max_fd + 1, &read_set, &write_set, &err_set, - timeout_milliseconds < 0 ? NULL : &tv); + ready = select (max_fd + 1, &read_set, &write_set, &err_set, &tv); if (DBUS_SOCKET_API_RETURNS_ERROR (ready)) { @@ -1261,21 +1357,6 @@ _dbus_connect_tcp_socket_with_nonce (const char *host, _dbus_win_startup_winsock (); - fd = socket (AF_INET, SOCK_STREAM, 0); - - if (DBUS_SOCKET_IS_INVALID (fd)) - { - DBUS_SOCKET_SET_ERRNO (); - dbus_set_error (error, - _dbus_error_from_errno (errno), - "Failed to create socket: %s", - _dbus_strerror_from_errno ()); - - return -1; - } - - _DBUS_ASSERT_ERROR_IS_CLEAR(error); - _DBUS_ZERO (hints); if (!family) @@ -1287,7 +1368,7 @@ _dbus_connect_tcp_socket_with_nonce (const char *host, else { dbus_set_error (error, - _dbus_error_from_errno (errno), + DBUS_ERROR_INVALID_ARGS, "Unknown address family %s", family); return -1; } @@ -1299,34 +1380,35 @@ _dbus_connect_tcp_socket_with_nonce (const char *host, hints.ai_flags = 0; #endif - if ((res = getaddrinfo(host, port, &hints, &ai)) != 0) + if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai) { dbus_set_error (error, - _dbus_error_from_errno (errno), + _dbus_error_from_errno (res), "Failed to lookup host/port: \"%s:%s\": %s (%d)", - host, port, gai_strerror(res), res); - closesocket (fd); + host, port, _dbus_strerror(res), res); return -1; } tmp = ai; while (tmp) { - if ((fd = socket (tmp->ai_family, SOCK_STREAM, 0)) < 0) + if ((fd = socket (tmp->ai_family, SOCK_STREAM, 0)) == INVALID_SOCKET) { + DBUS_SOCKET_SET_ERRNO (); + dbus_set_error (error, + _dbus_error_from_errno (errno), + "Failed to open socket: %s", + _dbus_strerror_from_errno ()); freeaddrinfo(ai); - dbus_set_error (error, - _dbus_error_from_errno (errno), - "Failed to open socket: %s", - _dbus_strerror_from_errno ()); return -1; } _DBUS_ASSERT_ERROR_IS_CLEAR(error); - if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) != 0) + if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) == SOCKET_ERROR) { + DBUS_SOCKET_SET_ERRNO (); closesocket(fd); - fd = -1; + fd = -1; tmp = tmp->ai_next; continue; } @@ -1340,11 +1422,11 @@ _dbus_connect_tcp_socket_with_nonce (const char *host, dbus_set_error (error, _dbus_error_from_errno (errno), "Failed to connect to socket \"%s:%s\" %s", - host, port, _dbus_strerror(errno)); + host, port, _dbus_strerror_from_errno ()); return -1; } - if ( noncefile != NULL ) + if (noncefile != NULL) { DBusString noncefileStr; dbus_bool_t ret; @@ -1354,20 +1436,22 @@ _dbus_connect_tcp_socket_with_nonce (const char *host, closesocket (fd); dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return -1; - } + } ret = _dbus_send_nonce (fd, &noncefileStr, error); _dbus_string_free (&noncefileStr); if (!ret) - { - closesocket (fd); + { + closesocket (fd); return -1; } } - if (!_dbus_set_fd_nonblocking (fd, error) ) + _dbus_fd_set_close_on_exec (fd); + + if (!_dbus_set_fd_nonblocking (fd, error)) { closesocket (fd); return -1; @@ -1429,7 +1513,7 @@ _dbus_listen_tcp_socket (const char *host, else { dbus_set_error (error, - _dbus_error_from_errno (errno), + DBUS_ERROR_INVALID_ARGS, "Unknown address family %s", family); return -1; } @@ -1446,9 +1530,9 @@ _dbus_listen_tcp_socket (const char *host, if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai) { dbus_set_error (error, - _dbus_error_from_errno (errno), + _dbus_error_from_errno (res), "Failed to lookup host/port: \"%s:%s\": %s (%d)", - host ? host : "*", port, gai_strerror(res), res); + host ? host : "*", port, _dbus_strerror(res), res); return -1; } @@ -1456,8 +1540,9 @@ _dbus_listen_tcp_socket (const char *host, while (tmp) { int fd = -1, *newlisten_fd; - if ((fd = socket (tmp->ai_family, SOCK_STREAM, 0)) < 0) + if ((fd = socket (tmp->ai_family, SOCK_STREAM, 0)) == INVALID_SOCKET) { + DBUS_SOCKET_SET_ERRNO (); dbus_set_error (error, _dbus_error_from_errno (errno), "Failed to open socket: %s", @@ -1468,31 +1553,32 @@ _dbus_listen_tcp_socket (const char *host, if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) == SOCKET_ERROR) { - closesocket (fd); + DBUS_SOCKET_SET_ERRNO (); dbus_set_error (error, _dbus_error_from_errno (errno), "Failed to bind socket \"%s:%s\": %s", host ? host : "*", port, _dbus_strerror_from_errno ()); + closesocket (fd); goto failed; } if (listen (fd, 30 /* backlog */) == SOCKET_ERROR) { - closesocket (fd); + DBUS_SOCKET_SET_ERRNO (); dbus_set_error (error, _dbus_error_from_errno (errno), "Failed to listen on socket \"%s:%s\": %s", host ? host : "*", port, _dbus_strerror_from_errno ()); + closesocket (fd); goto failed; } newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1)); if (!newlisten_fd) - { + { closesocket (fd); - dbus_set_error (error, _dbus_error_from_errno (errno), - "Failed to allocate file handle array: %s", - _dbus_strerror_from_errno ()); + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, + "Failed to allocate file handle array"); goto failed; - } + } listen_fd = newlisten_fd; listen_fd[nlisten_fd] = fd; nlisten_fd++; @@ -1509,11 +1595,12 @@ _dbus_listen_tcp_socket (const char *host, socklen_t addrlen = sizeof(addr); char portbuf[10]; - if ((res = getsockname(fd, &addr.Address, &addrlen)) != 0) - { - dbus_set_error (error, _dbus_error_from_errno (errno), - "Failed to resolve port \"%s:%s\": %s (%d)", - host ? host : "*", port, gai_strerror(res), res); + if (getsockname(fd, &addr.Address, &addrlen) == SOCKET_ERROR) + { + DBUS_SOCKET_SET_ERRNO (); + dbus_set_error (error, _dbus_error_from_errno (errno), + "Failed to resolve port \"%s:%s\": %s", + host ? host : "*", port, _dbus_strerror_from_errno()); goto failed; } snprintf( portbuf, sizeof( portbuf ) - 1, "%d", addr.AddressIn.sin_port ); @@ -1521,7 +1608,7 @@ _dbus_listen_tcp_socket (const char *host, { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto failed; - } + } /* Release current address list & redo lookup */ port = _dbus_string_get_const_data(retport); @@ -1556,6 +1643,7 @@ _dbus_listen_tcp_socket (const char *host, for (i = 0 ; i < nlisten_fd ; i++) { + _dbus_fd_set_close_on_exec (listen_fd[i]); if (!_dbus_set_fd_nonblocking (listen_fd[i], error)) { goto failed; @@ -1672,7 +1760,7 @@ again: * a byte was read, not whether we got valid credentials. On some * systems, such as Linux, reading/writing the byte isn't actually * required, but we do it anyway just to avoid multiple codepaths. - * + * * Fails if no byte is available, so you must select() first. * * The point of the byte is that on some systems we have to @@ -1690,22 +1778,41 @@ _dbus_read_credentials_socket (int handle, { int bytes_read = 0; DBusString buf; - + + char *sid = NULL; + dbus_pid_t pid; + int retval = FALSE; + // could fail due too OOM - if (_dbus_string_init(&buf)) + if (_dbus_string_init (&buf)) { - bytes_read = _dbus_read_socket(handle, &buf, 1 ); + bytes_read = _dbus_read_socket (handle, &buf, 1 ); if (bytes_read > 0) - _dbus_verbose("got one zero byte from server"); + _dbus_verbose ("got one zero byte from server\n"); - _dbus_string_free(&buf); + _dbus_string_free (&buf); } - _dbus_credentials_add_from_current_process (credentials); - _dbus_verbose("FIXME: get faked credentials from current process"); + pid = _dbus_get_peer_pid_from_tcp_handle (handle); + if (pid == 0) + return TRUE; - return TRUE; + _dbus_credentials_add_pid (credentials, pid); + + if (_dbus_getsid (&sid, pid)) + { + if (!_dbus_credentials_add_windows_sid (credentials, sid)) + goto out; + } + + retval = TRUE; + +out: + if (sid) + LocalFree (sid); + + return retval; } /** @@ -1799,10 +1906,10 @@ _dbus_credentials_add_from_current_process (DBusCredentials *credentials) dbus_bool_t retval = FALSE; char *sid = NULL; - if (!_dbus_getsid(&sid)) + if (!_dbus_getsid(&sid, _dbus_getpid())) goto failed; - if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid())) + if (!_dbus_credentials_add_pid (credentials, _dbus_getpid())) goto failed; if (!_dbus_credentials_add_windows_sid (credentials,sid)) @@ -1837,7 +1944,7 @@ _dbus_append_user_from_current_process (DBusString *str) dbus_bool_t retval = FALSE; char *sid = NULL; - if (!_dbus_getsid(&sid)) + if (!_dbus_getsid(&sid, _dbus_getpid())) return FALSE; retval = _dbus_string_append (str,sid); @@ -1879,14 +1986,15 @@ _dbus_sleep_milliseconds (int milliseconds) /** - * Get current time, as in gettimeofday(). + * Get current time, as in gettimeofday(). Never uses the monotonic + * clock. * * @param tv_sec return location for number of seconds * @param tv_usec return location for number of microseconds */ void -_dbus_get_current_time (long *tv_sec, - long *tv_usec) +_dbus_get_real_time (long *tv_sec, + long *tv_usec) { FILETIME ft; dbus_uint64_t time64; @@ -1908,6 +2016,20 @@ _dbus_get_current_time (long *tv_sec, *tv_usec = time64 % 1000000; } +/** + * Get current time, as in gettimeofday(). Use the monotonic clock if + * available, to avoid problems when the system time changes. + * + * @param tv_sec return location for number of seconds + * @param tv_usec return location for number of microseconds + */ +void +_dbus_get_monotonic_time (long *tv_sec, + long *tv_usec) +{ + /* no implementation yet, fall back to wall-clock time */ + _dbus_get_real_time (tv_sec, tv_usec); +} /** * signal (SIGPIPE, SIG_IGN); @@ -2055,7 +2177,51 @@ _dbus_delete_file (const DBusString *filename, return TRUE; } -#if !defined (DBUS_DISABLE_ASSERT) || defined(DBUS_BUILD_TESTS) +/* + * replaces the term DBUS_PREFIX in configure_time_path by the + * current dbus installation directory. On unix this function is a noop + * + * @param configure_time_path + * @return real path + */ +const char * +_dbus_replace_install_prefix (const char *configure_time_path) +{ +#ifndef DBUS_PREFIX + return configure_time_path; +#else + static char retval[1000]; + static char runtime_prefix[1000]; + int len = 1000; + int i; + + if (!configure_time_path) + return NULL; + + if ((!_dbus_get_install_root(runtime_prefix, len) || + strncmp (configure_time_path, DBUS_PREFIX "/", + strlen (DBUS_PREFIX) + 1))) { + strcat (retval, configure_time_path); + return retval; + } + + strcpy (retval, runtime_prefix); + strcat (retval, configure_time_path + strlen (DBUS_PREFIX) + 1); + + /* Somehow, in some situations, backslashes get collapsed in the string. + * Since windows C library accepts both forward and backslashes as + * path separators, convert all backslashes to forward slashes. + */ + + for(i = 0; retval[i] != '\0'; i++) { + if(retval[i] == '\\') + retval[i] = '/'; + } + return retval; +#endif +} + +#if !defined (DBUS_DISABLE_ASSERTS) || defined(DBUS_BUILD_TESTS) #if defined(_MSC_VER) || defined(DBUS_WINCE) # ifdef BACKTRACES @@ -2118,6 +2284,16 @@ static BOOL (WINAPI *pStackWalk)( PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine, PTRANSLATE_ADDRESS_ROUTINE TranslateAddress ); +#ifdef _WIN64 +static DWORD64 (WINAPI *pSymGetModuleBase)( + HANDLE hProcess, + DWORD64 dwAddr +); +static PVOID (WINAPI *pSymFunctionTableAccess)( + HANDLE hProcess, + DWORD64 AddrBase +); +#else static DWORD (WINAPI *pSymGetModuleBase)( HANDLE hProcess, DWORD dwAddr @@ -2126,6 +2302,7 @@ static PVOID (WINAPI *pSymFunctionTableAccess)( HANDLE hProcess, DWORD AddrBase ); +#endif static BOOL (WINAPI *pSymInitialize)( HANDLE hProcess, PSTR UserSearchPath, @@ -2180,6 +2357,16 @@ PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine, PTRANSLATE_ADDRESS_ROUTINE TranslateAddress ))GetProcAddress (hmodDbgHelp, FUNC(StackWalk)); +#ifdef _WIN64 + pSymGetModuleBase=(DWORD64 (WINAPI *)( + HANDLE hProcess, + DWORD64 dwAddr +))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleBase)); + pSymFunctionTableAccess=(PVOID (WINAPI *)( + HANDLE hProcess, + DWORD64 AddrBase +))GetProcAddress (hmodDbgHelp, FUNC(SymFunctionTableAccess)); +#else pSymGetModuleBase=(DWORD (WINAPI *)( HANDLE hProcess, DWORD dwAddr @@ -2188,6 +2375,7 @@ PTRANSLATE_ADDRESS_ROUTINE TranslateAddress HANDLE hProcess, DWORD AddrBase ))GetProcAddress (hmodDbgHelp, FUNC(SymFunctionTableAccess)); +#endif pSymInitialize = (BOOL (WINAPI *)( HANDLE hProcess, PSTR UserSearchPath, @@ -2329,7 +2517,10 @@ static void dump_backtrace() CloseHandle(hThread); CloseHandle(hCurrentThread); } +#endif +#endif /* asserts or tests enabled */ +#ifdef BACKTRACES void _dbus_print_backtrace(void) { init_backtrace(); @@ -2468,35 +2659,172 @@ static const char *cDBusAutolaunchMutex = "DBusAutolaunchMutex"; // mutex to determine if dbus-daemon is already started (per user) static const char *cDBusDaemonMutex = "DBusDaemonMutex"; // named shm for dbus adress info (per user) -#ifdef _DEBUG -static const char *cDBusDaemonAddressInfo = "DBusDaemonAddressInfoDebug"; -#else static const char *cDBusDaemonAddressInfo = "DBusDaemonAddressInfo"; -#endif +static dbus_bool_t +_dbus_get_install_root_as_hash(DBusString *out) +{ + DBusString install_path; -void -_dbus_daemon_publish_session_bus_address (const char* address) + char path[MAX_PATH*2]; + int path_size = sizeof(path); + + if (!_dbus_get_install_root(path,path_size)) + return FALSE; + + _dbus_string_init(&install_path); + _dbus_string_append(&install_path,path); + + _dbus_string_init(out); + _dbus_string_tolower_ascii(&install_path,0,_dbus_string_get_length(&install_path)); + + if (!_dbus_sha_compute (&install_path, out)) + return FALSE; + + return TRUE; +} + +static dbus_bool_t +_dbus_get_address_string (DBusString *out, const char *basestring, const char *scope) +{ + _dbus_string_init(out); + _dbus_string_append(out,basestring); + + if (!scope) + { + return TRUE; + } + else if (strcmp(scope,"*install-path") == 0 + // for 1.3 compatibility + || strcmp(scope,"install-path") == 0) + { + DBusString temp; + if (!_dbus_get_install_root_as_hash(&temp)) + { + _dbus_string_free(out); + return FALSE; + } + _dbus_string_append(out,"-"); + _dbus_string_append(out,_dbus_string_get_const_data(&temp)); + _dbus_string_free(&temp); + } + else if (strcmp(scope,"*user") == 0) + { + _dbus_string_append(out,"-"); + if (!_dbus_append_user_from_current_process(out)) + { + _dbus_string_free(out); + return FALSE; + } + } + else if (strlen(scope) > 0) + { + _dbus_string_append(out,"-"); + _dbus_string_append(out,scope); + return TRUE; + } + return TRUE; +} + +static dbus_bool_t +_dbus_get_shm_name (DBusString *out,const char *scope) +{ + return _dbus_get_address_string (out,cDBusDaemonAddressInfo,scope); +} + +static dbus_bool_t +_dbus_get_mutex_name (DBusString *out,const char *scope) +{ + return _dbus_get_address_string (out,cDBusDaemonMutex,scope); +} + +dbus_bool_t +_dbus_daemon_is_session_bus_address_published (const char *scope) +{ + HANDLE lock; + DBusString mutex_name; + + if (!_dbus_get_mutex_name(&mutex_name,scope)) + { + _dbus_string_free( &mutex_name ); + return FALSE; + } + + if (hDBusDaemonMutex) + return TRUE; + + // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs + lock = _dbus_global_lock( cUniqueDBusInitMutex ); + + // we use CreateMutex instead of OpenMutex because of possible race conditions, + // see http://msdn.microsoft.com/en-us/library/ms684315%28VS.85%29.aspx + hDBusDaemonMutex = CreateMutexA( NULL, FALSE, _dbus_string_get_const_data(&mutex_name) ); + + /* The client uses mutex ownership to detect a running server, so the server should do so too. + Fortunally the client deletes the mutex in the lock protected area, so checking presence + will work too. */ + + _dbus_global_unlock( lock ); + + _dbus_string_free( &mutex_name ); + + if (hDBusDaemonMutex == NULL) + return FALSE; + if (GetLastError() == ERROR_ALREADY_EXISTS) + { + CloseHandle(hDBusDaemonMutex); + hDBusDaemonMutex = NULL; + return TRUE; + } + // mutex wasn't created before, so return false. + // We leave the mutex name allocated for later reusage + // in _dbus_daemon_publish_session_bus_address. + return FALSE; +} + +dbus_bool_t +_dbus_daemon_publish_session_bus_address (const char* address, const char *scope) { HANDLE lock; char *shared_addr = NULL; - DWORD ret; + DBusString shm_name; + DBusString mutex_name; _dbus_assert (address); - // before _dbus_global_lock to keep correct lock/release order - hDBusDaemonMutex = CreateMutexA( NULL, FALSE, cDBusDaemonMutex ); - ret = WaitForSingleObject( hDBusDaemonMutex, 1000 ); - if ( ret != WAIT_OBJECT_0 ) { - _dbus_warn("Could not lock mutex %s (return code %d). daemon already running? Bus address not published.\n", cDBusDaemonMutex, ret ); - return; - } + + if (!_dbus_get_mutex_name(&mutex_name,scope)) + { + _dbus_string_free( &mutex_name ); + return FALSE; + } // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs lock = _dbus_global_lock( cUniqueDBusInitMutex ); + if (!hDBusDaemonMutex) + { + hDBusDaemonMutex = CreateMutexA( NULL, FALSE, _dbus_string_get_const_data(&mutex_name) ); + } + _dbus_string_free( &mutex_name ); + + // acquire the mutex + if (WaitForSingleObject( hDBusDaemonMutex, 10 ) != WAIT_OBJECT_0) + { + _dbus_global_unlock( lock ); + CloseHandle( hDBusDaemonMutex ); + return FALSE; + } + + if (!_dbus_get_shm_name(&shm_name,scope)) + { + _dbus_string_free( &shm_name ); + _dbus_global_unlock( lock ); + return FALSE; + } + // create shm hDBusSharedMem = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, - 0, strlen( address ) + 1, cDBusDaemonAddressInfo ); + 0, strlen( address ) + 1, _dbus_string_get_const_data(&shm_name) ); _dbus_assert( hDBusSharedMem ); shared_addr = MapViewOfFile( hDBusSharedMem, FILE_MAP_WRITE, 0, 0, 0 ); @@ -2509,6 +2837,10 @@ _dbus_daemon_publish_session_bus_address (const char* address) UnmapViewOfFile( shared_addr ); _dbus_global_unlock( lock ); + _dbus_verbose( "published session bus address at %s\n",_dbus_string_get_const_data (&shm_name) ); + + _dbus_string_free( &shm_name ); + return TRUE; } void @@ -2533,7 +2865,7 @@ _dbus_daemon_unpublish_session_bus_address (void) } static dbus_bool_t -_dbus_get_autolaunch_shm (DBusString *address) +_dbus_get_autolaunch_shm (DBusString *address, DBusString *shm_name) { HANDLE sharedMem; char *shared_addr; @@ -2542,7 +2874,7 @@ _dbus_get_autolaunch_shm (DBusString *address) // read shm for(i=0;i<20;++i) { // we know that dbus-daemon is available, so we wait until shm is available - sharedMem = OpenFileMappingA( FILE_MAP_READ, FALSE, cDBusDaemonAddressInfo ); + sharedMem = OpenFileMappingA( FILE_MAP_READ, FALSE, _dbus_string_get_const_data(shm_name)); if( sharedMem == 0 ) Sleep( 100 ); if ( sharedMem != 0) @@ -2570,39 +2902,48 @@ _dbus_get_autolaunch_shm (DBusString *address) } static dbus_bool_t -_dbus_daemon_already_runs (DBusString *address) +_dbus_daemon_already_runs (DBusString *address, DBusString *shm_name, const char *scope) { HANDLE lock; HANDLE daemon; + DBusString mutex_name; dbus_bool_t bRet = TRUE; + if (!_dbus_get_mutex_name(&mutex_name,scope)) + { + _dbus_string_free( &mutex_name ); + return FALSE; + } + // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs lock = _dbus_global_lock( cUniqueDBusInitMutex ); // do checks - daemon = CreateMutexA( NULL, FALSE, cDBusDaemonMutex ); + daemon = CreateMutexA( NULL, FALSE, _dbus_string_get_const_data(&mutex_name) ); if(WaitForSingleObject( daemon, 10 ) != WAIT_TIMEOUT) { ReleaseMutex (daemon); CloseHandle (daemon); _dbus_global_unlock( lock ); + _dbus_string_free( &mutex_name ); return FALSE; } // read shm - bRet = _dbus_get_autolaunch_shm( address ); + bRet = _dbus_get_autolaunch_shm( address, shm_name ); // cleanup CloseHandle ( daemon ); _dbus_global_unlock( lock ); + _dbus_string_free( &mutex_name ); return bRet; } dbus_bool_t -_dbus_get_autolaunch_address (DBusString *address, +_dbus_get_autolaunch_address (const char *scope, DBusString *address, DBusError *error) { HANDLE mutex; @@ -2613,26 +2954,62 @@ _dbus_get_autolaunch_address (DBusString *address, char dbus_exe_path[MAX_PATH]; char dbus_args[MAX_PATH * 2]; const char * daemon_name = DBUS_DAEMON_NAME ".exe"; - - mutex = _dbus_global_lock ( cDBusAutolaunchMutex ); + DBusString shm_name; _DBUS_ASSERT_ERROR_IS_CLEAR (error); - if (_dbus_daemon_already_runs(address)) + if (!_dbus_get_shm_name(&shm_name,scope)) + { + dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not determine shm name"); + return FALSE; + } + + mutex = _dbus_global_lock ( cDBusAutolaunchMutex ); + + if (_dbus_daemon_already_runs(address,&shm_name,scope)) { - _dbus_verbose("found already running dbus daemon\n"); + _dbus_verbose( "found running dbus daemon at %s\n", + _dbus_string_get_const_data (&shm_name) ); retval = TRUE; goto out; } if (!SearchPathA(NULL, daemon_name, NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile)) { - printf ("please add the path to %s to your PATH environment variable\n", daemon_name); - printf ("or start the daemon manually\n\n"); - printf (""); - goto out; + // Look in directory containing dbus shared library + HMODULE hmod; + char dbus_module_path[MAX_PATH]; + DWORD rc; + + _dbus_verbose( "did not found dbus daemon executable on default search path, " + "trying path where dbus shared library is located"); + + hmod = _dbus_win_get_dll_hmodule(); + rc = GetModuleFileNameA(hmod, dbus_module_path, sizeof(dbus_module_path)); + if (rc <= 0) + { + dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not retrieve dbus shared library file name"); + retval = FALSE; + goto out; + } + else + { + char *ext_idx = strrchr(dbus_module_path, '\\'); + if (ext_idx) + *ext_idx = '\0'; + if (!SearchPathA(dbus_module_path, daemon_name, NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile)) + { + dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not find dbus-daemon executable"); + retval = FALSE; + printf ("please add the path to %s to your PATH environment variable\n", daemon_name); + printf ("or start the daemon manually\n\n"); + goto out; + } + _dbus_verbose( "found dbus daemon executable at %s",dbus_module_path); + } } + // Create process ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); @@ -2646,11 +3023,15 @@ _dbus_get_autolaunch_address (DBusString *address, { CloseHandle (pi.hThread); CloseHandle (pi.hProcess); - retval = _dbus_get_autolaunch_shm( address ); + retval = _dbus_get_autolaunch_shm( address, &shm_name ); + if (retval == FALSE) + dbus_set_error_const (error, DBUS_ERROR_FAILED, "Failed to get autolaunch address from launched dbus-daemon"); + } + else + { + dbus_set_error_const (error, DBUS_ERROR_FAILED, "Failed to launch dbus-daemon"); + retval = FALSE; } - - if (retval == FALSE) - dbus_set_error_const (error, DBUS_ERROR_FAILED, "Failed to launch dbus-daemon"); out: if (retval) @@ -2678,6 +3059,21 @@ _dbus_make_file_world_readable(const DBusString *filename, return TRUE; } +/** + * return the relocated DATADIR + * + * @returns relocated DATADIR static string + */ + +static const char * +_dbus_windows_get_datadir (void) +{ + return _dbus_replace_install_prefix(DBUS_DATADIR); +} + +#undef DBUS_DATADIR +#define DBUS_DATADIR _dbus_windows_get_datadir () + #define DBUS_STANDARD_SESSION_SERVICEDIR "/dbus-1/services" #define DBUS_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services" @@ -2692,7 +3088,7 @@ _dbus_make_file_world_readable(const DBusString *filename, * * and * - * DBUS_DATADIR + * relocated DBUS_DATADIR * * @param dirs the directory list we are returning * @returns #FALSE on OOM @@ -2722,8 +3118,30 @@ _dbus_get_standard_session_servicedirs (DBusList **dirs) } } #else - if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR _DBUS_PATH_SEPARATOR)) - goto oom; +/* + the code for accessing services requires absolute base pathes + in case DBUS_DATADIR is relative make it absolute +*/ +#ifdef DBUS_WIN + { + DBusString p; + + _dbus_string_init_const (&p, DBUS_DATADIR); + + if (!_dbus_path_is_absolute (&p)) + { + char install_root[1000]; + if (_dbus_get_install_root (install_root, sizeof(install_root))) + if (!_dbus_string_append (&servicedir_path, install_root)) + goto oom; + } + } +#endif + if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR)) + goto oom; + + if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR)) + goto oom; #endif common_progs = _dbus_getenv ("CommonProgramFiles"); @@ -2775,8 +3193,6 @@ _dbus_get_standard_system_servicedirs (DBusList **dirs) return TRUE; } -_DBUS_DEFINE_GLOBAL_LOCK (atomic); - /** * Atomically increments an integer * @@ -2807,7 +3223,30 @@ _dbus_atomic_dec (DBusAtomic *atomic) return InterlockedDecrement (&atomic->value) + 1; } -#endif /* asserts or tests enabled */ +/** + * Atomically get the value of an integer. It may change at any time + * thereafter, so this is mostly only useful for assertions. + * + * @param atomic pointer to the integer to get + * @returns the value at this moment + */ +dbus_int32_t +_dbus_atomic_get (DBusAtomic *atomic) +{ + /* In this situation, GLib issues a MemoryBarrier() and then returns + * atomic->value. However, mingw from mingw.org (not to be confused with + * mingw-w64 from mingw-w64.sf.net) does not have MemoryBarrier in its + * headers, so we have to get a memory barrier some other way. + * + * InterlockedIncrement is older, and is documented on MSDN to be a full + * memory barrier, so let's use that. + */ + long dummy = 0; + + InterlockedExchange (&dummy, 1); + + return atomic->value; +} /** * Called when the bus daemon is signaled to reload its configuration; any @@ -2840,12 +3279,10 @@ _dbus_get_is_errno_eagain_or_ewouldblock (void) * @param len length of buffer * @returns #FALSE on failure */ -static dbus_bool_t +dbus_bool_t _dbus_get_install_root(char *prefix, int len) { //To find the prefix, we cut the filename and also \bin\ if present - char* p = 0; - int i; DWORD pathLength; char *lastSlash; SetLastError( 0 ); @@ -2999,7 +3436,6 @@ _dbus_append_keyring_directory_for_credentials (DBusString *directory, { DBusString homedir; DBusString dotdir; - dbus_uid_t uid; const char *homepath; const char *homedrive; @@ -3301,6 +3737,29 @@ _dbus_delete_directory (const DBusString *filename, return TRUE; } +/** + * Checks whether the filename is an absolute path + * + * @param filename the filename + * @returns #TRUE if an absolute path + */ +dbus_bool_t +_dbus_path_is_absolute (const DBusString *filename) +{ + if (_dbus_string_get_length (filename) > 0) + return _dbus_string_get_byte (filename, 1) == ':' + || _dbus_string_get_byte (filename, 0) == '\\' + || _dbus_string_get_byte (filename, 0) == '/'; + else + return FALSE; +} + +dbus_bool_t +_dbus_check_setuid (void) +{ + return FALSE; +} + /** @} end of sysdeps-win */ /* tests in dbus-sysdeps-util.c */