X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dbus%2Fdbus-sysdeps-win.c;h=bba8915f192ade2099257cb9ad80a834afd5facf;hb=dbecdeabb20e0ce11121819c63373f0afba57c58;hp=2163da7eec4c66fcf5a8ec53532c3ccc6b782014;hpb=09078aa1340ddce47c823a942792d60b253243f4;p=platform%2Fupstream%2Fdbus.git diff --git a/dbus/dbus-sysdeps-win.c b/dbus/dbus-sysdeps-win.c index 2163da7..bba8915 100644 --- a/dbus/dbus-sysdeps-win.c +++ b/dbus/dbus-sysdeps-win.c @@ -26,13 +26,15 @@ * */ -#undef open +#include #define STRSAFE_NO_DEPRECATE #ifndef DBUS_WINCE +#ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0501 #endif +#endif #include "dbus-internals.h" #include "dbus-sysdeps.h" @@ -44,13 +46,26 @@ #include "dbus-hash.h" #include "dbus-sockets-win.h" #include "dbus-list.h" +#include "dbus-nonce.h" #include "dbus-credentials.h" #include #include +#include + +/* Declarations missing in mingw's headers */ +extern BOOL WINAPI ConvertStringSidToSidA (LPCSTR StringSid, PSID *Sid); +extern BOOL WINAPI ConvertSidToStringSidA (PSID Sid, LPSTR *StringSid); + #include #include +#include +#include + +#include +#include +#include #include #include @@ -68,208 +83,33 @@ #define O_BINARY 0 #endif -#ifndef HAVE_SOCKLEN_T -#define socklen_t int -#endif - -/** - * File interface - * - */ -dbus_bool_t -_dbus_file_open (DBusFile *file, - const char *filename, - int oflag, - int pmode) -{ - if (pmode!=-1) - file->FDATA = _open (filename, oflag, pmode); - else - file->FDATA = _open (filename, oflag); - if (file->FDATA >= 0) - return TRUE; - else - { - file->FDATA = -1; - return FALSE; - } -} - -dbus_bool_t -_dbus_file_close (DBusFile *file, - DBusError *error) -{ - const int fd = file->FDATA; - - _DBUS_ASSERT_ERROR_IS_CLEAR (error); - - _dbus_assert (fd >= 0); - - if (_close (fd) == -1) - { - dbus_set_error (error, _dbus_error_from_errno (errno), - "Could not close fd %d: %s", fd, - _dbus_strerror (errno)); - return FALSE; - } - - file->FDATA = -1; - _dbus_verbose ("closed C file descriptor %d:\n",fd); - - return TRUE; -} - -int -_dbus_file_read(DBusFile *file, - DBusString *buffer, - int count) -{ - const int fd = file->FDATA; - int bytes_read; - int start; - char *data; - _dbus_assert (count >= 0); - - start = _dbus_string_get_length (buffer); - - if (!_dbus_string_lengthen (buffer, count)) - { - errno = ENOMEM; - return -1; - } - - data = _dbus_string_get_data_len (buffer, start, count); - - _dbus_assert (fd >= 0); - - _dbus_verbose ("read: count=%d fd=%d\n", count, fd); - bytes_read = read (fd, data, count); - - if (bytes_read == -1) - _dbus_verbose ("read: failed: %s\n", _dbus_strerror (errno)); - else - _dbus_verbose ("read: = %d\n", bytes_read); - - if (bytes_read < 0) - { - /* put length back (note that this doesn't actually realloc anything) */ - _dbus_string_set_length (buffer, start); - return -1; - } - else - { - /* put length back (doesn't actually realloc) */ - _dbus_string_set_length (buffer, start + bytes_read); - -#if 0 - - if (bytes_read > 0) - _dbus_verbose_bytes_of_string (buffer, start, bytes_read); -#endif - - return bytes_read; - } -} +typedef int socklen_t; -int -_dbus_file_write (DBusFile *file, - const DBusString *buffer, - int start, - int len) +char* +_dbus_win_error_string (int error_number) { - const int fd = file->FDATA; - const char *data; - int bytes_written; - - data = _dbus_string_get_const_data_len (buffer, start, len); + char *msg; - _dbus_assert (fd >= 0); - - _dbus_verbose ("write: len=%d fd=%d\n", len, fd); - bytes_written = write (fd, data, len); - - if (bytes_written == -1) - _dbus_verbose ("write: failed: %s\n", _dbus_strerror (errno)); - else - _dbus_verbose ("write: = %d\n", bytes_written); - -#if 0 - - if (bytes_written > 0) - _dbus_verbose_bytes_of_string (buffer, start, bytes_written); -#endif - - return bytes_written; -} - -dbus_bool_t -_dbus_is_valid_file (DBusFile* file) -{ - return file->FDATA >= 0; -} + FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, error_number, 0, + (LPSTR) &msg, 0, NULL); -dbus_bool_t _dbus_fstat (DBusFile *file, - struct stat *sb) -{ - return fstat(file->FDATA, sb) >= 0; -} + if (msg[strlen (msg) - 1] == '\n') + msg[strlen (msg) - 1] = '\0'; + if (msg[strlen (msg) - 1] == '\r') + msg[strlen (msg) - 1] = '\0'; -/** - * write data to a pipe. - * - * @param pipe the pipe instance - * @param buffer the buffer to write data from - * @param start the first byte in the buffer to write - * @param len the number of bytes to try to write - * @param error error return - * @returns the number of bytes written or -1 on error - */ -int -_dbus_pipe_write (DBusPipe *pipe, - const DBusString *buffer, - int start, - int len, - DBusError *error) -{ - int written; - DBusFile file; - file.FDATA = pipe->fd_or_handle; - written = _dbus_file_write (&file, buffer, start, len); - if (written < 0) - { - dbus_set_error (error, DBUS_ERROR_FAILED, - "Writing to pipe: %s\n", - _dbus_strerror (errno)); - } - return written; + return msg; } -/** - * close a pipe. - * - * @param pipe the pipe instance - * @param error return location for an error - * @returns #FALSE if error is set - */ -int -_dbus_pipe_close (DBusPipe *pipe, - DBusError *error) +void +_dbus_win_free_error_string (char *string) { - DBusFile file; - file.FDATA = pipe->fd_or_handle; - if (_dbus_file_close (&file, error) < 0) - { - return -1; - } - else - { - _dbus_pipe_invalidate (pipe); - return 0; - } + LocalFree (string); } -#undef FDATA - /** * Socket interface * @@ -280,14 +120,16 @@ _dbus_pipe_close (DBusPipe *pipe, * the data it reads to the DBusString buffer. It appends * up to the given count, and returns the same value * and same errno as read(). The only exception is that - * _dbus_read() handles EINTR for you. _dbus_read() can - * return ENOMEM, even though regular UNIX read doesn't. + * _dbus_read_socket() handles EINTR for you. + * _dbus_read_socket() can return ENOMEM, even though + * regular UNIX read doesn't. * * @param fd the file descriptor to read from * @param buffer the buffer to append data to * @param count the amount of data to read * @returns the number of bytes read or -1 */ + int _dbus_read_socket (int fd, DBusString *buffer, @@ -317,7 +159,7 @@ _dbus_read_socket (int fd, if (bytes_read == SOCKET_ERROR) { DBUS_SOCKET_SET_ERRNO(); - _dbus_verbose ("recv: failed: %s\n", _dbus_strerror (errno)); + _dbus_verbose ("recv: failed: %s (%d)\n", _dbus_strerror (errno), errno); bytes_read = -1; } else @@ -436,31 +278,12 @@ _dbus_close_socket (int fd, void _dbus_fd_set_close_on_exec (int handle) { -#ifdef ENABLE_DBUSSOCKET - DBusSocket *s; - if (handle < 0) - return; - - _dbus_lock_sockets(); - - _dbus_handle_to_socket_unlocked (handle, &s); - s->close_on_exec = TRUE; - - _dbus_unlock_sockets(); -#else - /* TODO unic code. - int val; - - val = fcntl (fd, F_GETFD, 0); - - if (val < 0) - return; - - val |= FD_CLOEXEC; - - fcntl (fd, F_SETFD, val); - */ -#endif + if ( !SetHandleInformation( (HANDLE) handle, + HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE, + 0 /*disable both flags*/ ) ) + { + _dbus_win_warn_win_error ("Disabling socket handle inheritance failed:", GetLastError()); + } } /** @@ -524,7 +347,6 @@ _dbus_write_socket_two (int fd, const char *data2; int rc; DWORD bytes_written; - int ret1; _dbus_assert (buffer1 != NULL); _dbus_assert (start1 >= 0); @@ -575,6 +397,12 @@ _dbus_write_socket_two (int fd, return bytes_written; } +dbus_bool_t +_dbus_socket_is_invalid (int fd) +{ + return fd == INVALID_SOCKET ? TRUE : FALSE; +} + #if 0 /** @@ -655,23 +483,24 @@ int _dbus_printf_string_upper_bound (const char *format, va_list args) { /* MSVCRT's vsnprintf semantics are a bit different */ - /* The C library source in the Platform SDK indicates that this - * would work, but alas, it doesn't. At least not on Windows - * 2000. Presumably those sources correspond to the C library on - * some newer or even future Windows version. - * - len = _vsnprintf (NULL, _DBUS_INT_MAX, format, args); - */ - char p[1024]; + char buf[1024]; + int bufsize; int len; - len = _vsnprintf (p, sizeof(p)-1, format, args); - if (len == -1) // try again + + bufsize = sizeof (buf); + len = _vsnprintf (buf, bufsize - 1, format, args); + + while (len == -1) /* try again */ { char *p; - p = malloc (strlen(format)*3); - len = _vsnprintf (p, sizeof(p)-1, format, args); - free(p); + + bufsize *= 2; + + p = malloc (bufsize); + len = _vsnprintf (p, bufsize - 1, format, args); + free (p); } + return len; } @@ -841,15 +670,6 @@ out1: /** @} end of sysdeps-win */ -/** Gets our UID - * @returns process UID - */ -dbus_uid_t -_dbus_getuid (void) -{ - return DBUS_UID_UNSET; -} - /** * The only reason this is separate from _dbus_getpid() is to allow it * on Windows for logging but not for other purposes. @@ -866,10 +686,10 @@ _dbus_pid_for_log (void) * @param points to sid buffer, need to be freed with LocalFree() * @returns process sid */ -dbus_bool_t +static dbus_bool_t _dbus_getsid(char **sid) { - HANDLE process_token = NULL; + HANDLE process_token = INVALID_HANDLE_VALUE; TOKEN_USER *token_user = NULL; DWORD n; PSID psid; @@ -903,38 +723,13 @@ _dbus_getsid(char **sid) retval = TRUE; failed: - if (process_token != NULL) + if (process_token != INVALID_HANDLE_VALUE) CloseHandle (process_token); _dbus_verbose("_dbus_getsid() returns %d\n",retval); return retval; } - -#ifdef DBUS_BUILD_TESTS -/** Gets our GID - * @returns process GID - */ -dbus_gid_t -_dbus_getgid (void) -{ - return DBUS_GID_UNSET; -} - -#if 0 -dbus_bool_t -_dbus_domain_test (const char *test_data_dir) -{ - if (!_dbus_test_oom_handling ("spawn_nonexistent", - check_spawn_nonexistent, - NULL)) - return FALSE; -} - -#endif - -#endif //DBUS_BUILD_TESTS - /************************************************************************ pipes @@ -1123,13 +918,15 @@ out0: * @param timeout_milliseconds timeout or -1 for infinite * @returns numbers of fds with revents, or <0 on error */ -#define USE_CHRIS_IMPL 0 -#if USE_CHRIS_IMPL int _dbus_poll (DBusPollFD *fds, int n_fds, int timeout_milliseconds) { +#define USE_CHRIS_IMPL 0 + +#if USE_CHRIS_IMPL + #define DBUS_POLL_CHAR_BUFFER_SIZE 2000 char msg[DBUS_POLL_CHAR_BUFFER_SIZE]; char *msgp; @@ -1201,8 +998,8 @@ _dbus_poll (DBusPollFD *fds, if (DBUS_SOCKET_API_RETURNS_ERROR (ready)) { DBUS_SOCKET_SET_ERRNO (); - if (errno != EWOULDBLOCK) - _dbus_verbose ("WSAWaitForMultipleEvents: failed: %s\n", _dbus_strerror (errno)); + if (errno != WSAEWOULDBLOCK) + _dbus_verbose ("WSAWaitForMultipleEvents: failed: %s\n", strerror (errno)); ret = -1; } else if (ready == WSA_WAIT_TIMEOUT) @@ -1268,15 +1065,9 @@ _dbus_poll (DBusPollFD *fds, free(pEvents); return ret; -} -#else // USE_CHRIS_IMPL +#else /* USE_CHRIS_IMPL */ -int -_dbus_poll (DBusPollFD *fds, - int n_fds, - int timeout_milliseconds) -{ #define DBUS_POLL_CHAR_BUFFER_SIZE 2000 char msg[DBUS_POLL_CHAR_BUFFER_SIZE]; char *msgp; @@ -1345,7 +1136,7 @@ _dbus_poll (DBusPollFD *fds, if (DBUS_SOCKET_API_RETURNS_ERROR (ready)) { DBUS_SOCKET_SET_ERRNO (); - if (errno != EWOULDBLOCK) + if (errno != WSAEWOULDBLOCK) _dbus_verbose ("select: failed: %s\n", _dbus_strerror (errno)); } else if (ready == 0) @@ -1391,10 +1182,9 @@ _dbus_poll (DBusPollFD *fds, } } return ready; +#endif /* USE_CHRIS_IMPL */ } -#endif // USE_CHRIS_IMPL - @@ -1430,17 +1220,6 @@ Original CVS version of dbus-sysdeps.c /** - * @addtogroup DBusInternalsUtils - * @{ - */ - -int _dbus_mkdir (const char *path, - mode_t mode) -{ - return _mkdir(path); -} - -/** * Exit the process, returning the given value. * * @param code the exit code @@ -1468,6 +1247,16 @@ _dbus_connect_tcp_socket (const char *host, const char *family, DBusError *error) { + return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error); +} + +int +_dbus_connect_tcp_socket_with_nonce (const char *host, + const char *port, + const char *family, + const char *noncefile, + DBusError *error) +{ int fd = -1, res; struct addrinfo hints; struct addrinfo *ai, *tmp; @@ -1538,7 +1327,7 @@ _dbus_connect_tcp_socket (const char *host, } _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) != 0) { closesocket(fd); fd = -1; @@ -1559,22 +1348,38 @@ _dbus_connect_tcp_socket (const char *host, return -1; } + if ( noncefile != NULL ) + { + DBusString noncefileStr; + dbus_bool_t ret; + if (!_dbus_string_init (&noncefileStr) || + !_dbus_string_append(&noncefileStr, noncefile)) + { + closesocket (fd); + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); + return -1; + } + + ret = _dbus_send_nonce (fd, &noncefileStr, error); - if (!_dbus_set_fd_nonblocking (fd, error)) + _dbus_string_free (&noncefileStr); + + if (!ret) { closesocket (fd); - fd = -1; + return -1; + } + } + if (!_dbus_set_fd_nonblocking (fd, error) ) + { + closesocket (fd); return -1; } return fd; } - -void -_dbus_daemon_init(const char *host, dbus_uint32_t port); - /** * Creates a socket and binds it to the given path, then listens on * the socket. The socket is set to be nonblocking. In case of port=0 @@ -1602,6 +1407,16 @@ _dbus_listen_tcp_socket (const char *host, struct addrinfo hints; struct addrinfo *ai, *tmp; + // On Vista, sockaddr_gen must be a sockaddr_in6, and not a sockaddr_in6_old + //That's required for family == IPv6(which is the default on Vista if family is not given) + //So we use our own union instead of sockaddr_gen: + + typedef union { + struct sockaddr Address; + struct sockaddr_in AddressIn; + struct sockaddr_in6 AddressIn6; + } mysockaddr_gen; + *fds_p = NULL; _DBUS_ASSERT_ERROR_IS_CLEAR (error); @@ -1694,7 +1509,7 @@ _dbus_listen_tcp_socket (const char *host, to use the same port */ if (!port || !strcmp(port, "0")) { - sockaddr_gen addr; + mysockaddr_gen addr; socklen_t addrlen = sizeof(addr); char portbuf[10]; @@ -1742,7 +1557,6 @@ _dbus_listen_tcp_socket (const char *host, } sscanf(_dbus_string_get_const_data(retport), "%d", &port_num); - _dbus_daemon_init(host, port_num); for (i = 0 ; i < nlisten_fd ; i++) { @@ -1961,7 +1775,7 @@ _dbus_concat_dir_and_file (DBusString *dir, _dbus_string_get_length (dir)); } -/*---------------- DBusCredentials ---------------------------------- +/*---------------- DBusCredentials ----------------------------------*/ /** * Adds the credentials corresponding to the given username. @@ -2043,7 +1857,7 @@ _dbus_append_user_from_current_process (DBusString *str) * Gets our process ID * @returns process ID */ -unsigned long +dbus_pid_t _dbus_getpid (void) { return GetCurrentProcessId (); @@ -2082,21 +1896,23 @@ _dbus_get_current_time (long *tv_sec, long *tv_usec) { FILETIME ft; - dbus_uint64_t *time64 = (dbus_uint64_t *) &ft; + dbus_uint64_t time64; GetSystemTimeAsFileTime (&ft); + memcpy (&time64, &ft, sizeof (time64)); + /* Convert from 100s of nanoseconds since 1601-01-01 * to Unix epoch. Yes, this is Y2038 unsafe. */ - *time64 -= DBUS_INT64_CONSTANT (116444736000000000); - *time64 /= 10; + time64 -= DBUS_INT64_CONSTANT (116444736000000000); + time64 /= 10; if (tv_sec) - *tv_sec = *time64 / 1000000; + *tv_sec = time64 / 1000000; if (tv_usec) - *tv_usec = *time64 % 1000000; + *tv_usec = time64 % 1000000; } @@ -2106,373 +1922,74 @@ _dbus_get_current_time (long *tv_sec, void _dbus_disable_sigpipe (void) { - _dbus_verbose("FIXME: implement _dbus_disable_sigpipe (void)\n"); } - /** - * Appends the contents of the given file to the string, - * returning error code. At the moment, won't open a file - * more than a megabyte in size. + * Creates a directory; succeeds if the directory + * is created or already existed. * - * @param str the string to append to - * @param filename filename to load - * @param error place to set an error - * @returns #FALSE if error was set + * @param filename directory filename + * @param error initialized error object + * @returns #TRUE on success */ dbus_bool_t -_dbus_file_get_contents (DBusString *str, - const DBusString *filename, - DBusError *error) +_dbus_create_directory (const DBusString *filename, + DBusError *error) { - DBusFile file; - struct stat sb; - int orig_len; - int total; const char *filename_c; _DBUS_ASSERT_ERROR_IS_CLEAR (error); filename_c = _dbus_string_get_const_data (filename); - /* O_BINARY useful on Cygwin and Win32 */ - if (!_dbus_file_open (&file, filename_c, O_RDONLY | O_BINARY, -1)) + if (!CreateDirectory (filename_c, NULL)) { - dbus_set_error (error, _dbus_error_from_errno (errno), - "Failed to open \"%s\": %s", - filename_c, - _dbus_strerror (errno)); + if (GetLastError () == ERROR_ALREADY_EXISTS) + return TRUE; + + dbus_set_error (error, DBUS_ERROR_FAILED, + "Failed to create directory %s: %s\n", + filename_c, strerror (errno)); return FALSE; } + else + return TRUE; +} - if (!_dbus_fstat (&file, &sb)) - { - dbus_set_error (error, _dbus_error_from_errno (errno), - "Failed to stat \"%s\": %s", - filename_c, - _dbus_strerror (errno)); - _dbus_verbose ("fstat() failed: %s", - _dbus_strerror (errno)); +/** + * Generates the given number of random bytes, + * using the best mechanism we can come up with. + * + * @param str the string + * @param n_bytes the number of random bytes to append to string + * @returns #TRUE on success, #FALSE if no memory + */ +dbus_bool_t +_dbus_generate_random_bytes (DBusString *str, + int n_bytes) +{ + int old_len; + char *p; + HCRYPTPROV hprov; - _dbus_file_close (&file, NULL); + old_len = _dbus_string_get_length (str); - return FALSE; - } + if (!_dbus_string_lengthen (str, n_bytes)) + return FALSE; - if (sb.st_size > _DBUS_ONE_MEGABYTE) - { - dbus_set_error (error, DBUS_ERROR_FAILED, - "File size %lu of \"%s\" is too large.", - (unsigned long) sb.st_size, filename_c); - _dbus_file_close (&file, NULL); - return FALSE; - } - - total = 0; - orig_len = _dbus_string_get_length (str); - if (sb.st_size > 0 && S_ISREG (sb.st_mode)) - { - int bytes_read; - - while (total < (int) sb.st_size) - { - bytes_read = _dbus_file_read (&file, str, - sb.st_size - total); - if (bytes_read <= 0) - { - dbus_set_error (error, _dbus_error_from_errno (errno), - "Error reading \"%s\": %s", - filename_c, - _dbus_strerror (errno)); - - _dbus_verbose ("read() failed: %s", - _dbus_strerror (errno)); - - _dbus_file_close (&file, NULL); - _dbus_string_set_length (str, orig_len); - return FALSE; - } - else - total += bytes_read; - } - - _dbus_file_close (&file, NULL); - return TRUE; - } - else if (sb.st_size != 0) - { - _dbus_verbose ("Can only open regular files at the moment.\n"); - dbus_set_error (error, DBUS_ERROR_FAILED, - "\"%s\" is not a regular file", - filename_c); - _dbus_file_close (&file, NULL); - return FALSE; - } - else - { - _dbus_file_close (&file, NULL); - return TRUE; - } -} - -/** - * Writes a string out to a file. If the file exists, - * it will be atomically overwritten by the new data. - * - * @param str the string to write out - * @param filename the file to save string to - * @param error error to be filled in on failure - * @returns #FALSE on failure - */ -dbus_bool_t -_dbus_string_save_to_file (const DBusString *str, - const DBusString *filename, - DBusError *error) -{ - DBusFile file; - int bytes_to_write; - const char *filename_c; - DBusString tmp_filename; - const char *tmp_filename_c; - int total; - dbus_bool_t need_unlink; - dbus_bool_t retval; - - _DBUS_ASSERT_ERROR_IS_CLEAR (error); - - retval = FALSE; - need_unlink = FALSE; - - if (!_dbus_string_init (&tmp_filename)) - { - dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); - return FALSE; - } - - if (!_dbus_string_copy (filename, 0, &tmp_filename, 0)) - { - dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); - _dbus_string_free (&tmp_filename); - return FALSE; - } - - if (!_dbus_string_append (&tmp_filename, ".")) - { - dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); - _dbus_string_free (&tmp_filename); - return FALSE; - } - -#define N_TMP_FILENAME_RANDOM_BYTES 8 - if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES)) - { - dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); - _dbus_string_free (&tmp_filename); - return FALSE; - } - - filename_c = _dbus_string_get_const_data (filename); - tmp_filename_c = _dbus_string_get_const_data (&tmp_filename); - - if (!_dbus_file_open (&file, tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT, - 0600)) - { - dbus_set_error (error, _dbus_error_from_errno (errno), - "Could not create %s: %s", tmp_filename_c, - _dbus_strerror (errno)); - goto out; - } - - need_unlink = TRUE; - - total = 0; - bytes_to_write = _dbus_string_get_length (str); - - while (total < bytes_to_write) - { - int bytes_written; - - bytes_written = _dbus_file_write (&file, str, total, - bytes_to_write - total); - - if (bytes_written <= 0) - { - dbus_set_error (error, _dbus_error_from_errno (errno), - "Could not write to %s: %s", tmp_filename_c, - _dbus_strerror (errno)); - - goto out; - } - - total += bytes_written; - } - - if (!_dbus_file_close (&file, NULL)) - { - dbus_set_error (error, _dbus_error_from_errno (errno), - "Could not close file %s: %s", - tmp_filename_c, _dbus_strerror (errno)); - - goto out; - } - - - if ((unlink (filename_c) == -1 && errno != ENOENT) || - rename (tmp_filename_c, filename_c) < 0) - { - dbus_set_error (error, _dbus_error_from_errno (errno), - "Could not rename %s to %s: %s", - tmp_filename_c, filename_c, - _dbus_strerror (errno)); - - goto out; - } - - need_unlink = FALSE; - - retval = TRUE; - -out: - /* close first, then unlink, to prevent ".nfs34234235" garbage - * files - */ - - if (_dbus_is_valid_file(&file)) - _dbus_file_close (&file, NULL); - - if (need_unlink && unlink (tmp_filename_c) < 0) - _dbus_verbose ("Failed to unlink temp file %s: %s\n", - tmp_filename_c, _dbus_strerror (errno)); - - _dbus_string_free (&tmp_filename); - - if (!retval) - _DBUS_ASSERT_ERROR_IS_SET (error); - - return retval; -} - - -/** Creates the given file, failing if the file already exists. - * - * @param filename the filename - * @param error error location - * @returns #TRUE if we created the file and it didn't exist - */ -dbus_bool_t -_dbus_create_file_exclusively (const DBusString *filename, - DBusError *error) -{ - DBusFile file; - const char *filename_c; - - _DBUS_ASSERT_ERROR_IS_CLEAR (error); + p = _dbus_string_get_data_len (str, old_len, n_bytes); - filename_c = _dbus_string_get_const_data (filename); + if (!CryptAcquireContext (&hprov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) + return FALSE; - if (!_dbus_file_open (&file, filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT, - 0600)) + if (!CryptGenRandom (hprov, n_bytes, p)) { - dbus_set_error (error, - DBUS_ERROR_FAILED, - "Could not create file %s: %s\n", - filename_c, - _dbus_strerror (errno)); + CryptReleaseContext (hprov, 0); return FALSE; } - if (!_dbus_file_close (&file, NULL)) - { - dbus_set_error (error, - DBUS_ERROR_FAILED, - "Could not close file %s: %s\n", - filename_c, - _dbus_strerror (errno)); - return FALSE; - } - - return TRUE; -} - - -/** - * Creates a directory; succeeds if the directory - * is created or already existed. - * - * @param filename directory filename - * @param error initialized error object - * @returns #TRUE on success - */ -dbus_bool_t -_dbus_create_directory (const DBusString *filename, - DBusError *error) -{ - const char *filename_c; - - _DBUS_ASSERT_ERROR_IS_CLEAR (error); - - filename_c = _dbus_string_get_const_data (filename); - - if (_dbus_mkdir (filename_c, 0700) < 0) - { - if (errno == EEXIST) - return TRUE; - - dbus_set_error (error, DBUS_ERROR_FAILED, - "Failed to create directory %s: %s\n", - filename_c, _dbus_strerror (errno)); - return FALSE; - } - else - return TRUE; -} - - -static void -pseudorandom_generate_random_bytes_buffer (char *buffer, - int n_bytes) -{ - long tv_usec; - int i; - - /* fall back to pseudorandom */ - _dbus_verbose ("Falling back to pseudorandom for %d bytes\n", - n_bytes); - - _dbus_get_current_time (NULL, &tv_usec); - srand (tv_usec); - - i = 0; - while (i < n_bytes) - { - double r; - unsigned int b; - - r = rand (); - b = (r / (double) RAND_MAX) * 255.0; - - buffer[i] = b; - - ++i; - } -} - -static dbus_bool_t -pseudorandom_generate_random_bytes (DBusString *str, - int n_bytes) -{ - int old_len; - char *p; - - old_len = _dbus_string_get_length (str); - - if (!_dbus_string_lengthen (str, n_bytes)) - return FALSE; - - p = _dbus_string_get_data_len (str, old_len, n_bytes); - - pseudorandom_generate_random_bytes_buffer (p, n_bytes); + CryptReleaseContext (hprov, 0); return TRUE; } @@ -2487,17 +2004,27 @@ const char* _dbus_get_tmpdir(void) { static const char* tmpdir = NULL; + static char buf[1000]; if (tmpdir == NULL) { - if (tmpdir == NULL) - tmpdir = getenv("TMP"); - if (tmpdir == NULL) - tmpdir = getenv("TEMP"); - if (tmpdir == NULL) - tmpdir = getenv("TMPDIR"); - if (tmpdir == NULL) - tmpdir = "C:\\Temp"; + char *last_slash; + + if (!GetTempPath (sizeof (buf), buf)) + { + _dbus_warn ("GetTempPath failed\n"); + _dbus_abort (); + } + + /* Drop terminating backslash or slash */ + last_slash = _mbsrchr (buf, '\\'); + if (last_slash > buf && last_slash[1] == '\0') + last_slash[0] = '\0'; + last_slash = _mbsrchr (buf, '/'); + if (last_slash > buf && last_slash[1] == '\0') + last_slash[0] = '\0'; + + tmpdir = buf; } _dbus_assert(tmpdir != NULL); @@ -2524,32 +2051,17 @@ _dbus_delete_file (const DBusString *filename, filename_c = _dbus_string_get_const_data (filename); - if (unlink (filename_c) < 0) + if (_unlink (filename_c) < 0) { dbus_set_error (error, DBUS_ERROR_FAILED, "Failed to delete file %s: %s\n", - filename_c, _dbus_strerror (errno)); + filename_c, strerror (errno)); return FALSE; } else return TRUE; } -/** - * Generates the given number of random bytes, - * using the best mechanism we can come up with. - * - * @param str the string - * @param n_bytes the number of random bytes to append to string - * @returns #TRUE on success, #FALSE if no memory - */ -dbus_bool_t -_dbus_generate_random_bytes (DBusString *str, - int n_bytes) -{ - return pseudorandom_generate_random_bytes (str, n_bytes); -} - #if !defined (DBUS_DISABLE_ASSERT) || defined(DBUS_BUILD_TESTS) #ifdef _MSC_VER @@ -2938,7 +2450,7 @@ void _dbus_global_unlock (HANDLE mutex) // for proper cleanup in dbus-daemon static HANDLE hDBusDaemonMutex = NULL; static HANDLE hDBusSharedMem = NULL; -// sync _dbus_daemon_init, _dbus_daemon_uninit and _dbus_daemon_already_runs +// sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs static const char *cUniqueDBusInitMutex = "UniqueDBusInitMutex"; // sync _dbus_get_autolaunch_address static const char *cDBusAutolaunchMutex = "DBusAutolaunchMutex"; @@ -2951,60 +2463,49 @@ static const char *cDBusDaemonAddressInfo = "DBusDaemonAddressInfoDebug"; static const char *cDBusDaemonAddressInfo = "DBusDaemonAddressInfo"; #endif + void -_dbus_daemon_init(const char *host, dbus_uint32_t port) +_dbus_daemon_publish_session_bus_address (const char* address) { HANDLE lock; - char *adr = NULL; - char szUserName[64]; - DWORD dwUserNameSize = sizeof(szUserName); - char szDBusDaemonMutex[128]; - char szDBusDaemonAddressInfo[128]; - char szAddress[128]; + char *shared_addr = NULL; DWORD ret; - _dbus_assert(host); - _dbus_assert(port); - - _snprintf(szAddress, sizeof(szAddress) - 1, "tcp:host=%s,port=%d", host, port); - ret = GetUserName(szUserName, &dwUserNameSize); - _dbus_assert(ret != 0); - _snprintf(szDBusDaemonMutex, sizeof(szDBusDaemonMutex) - 1, "%s:%s", - cDBusDaemonMutex, szUserName); - _snprintf(szDBusDaemonAddressInfo, sizeof(szDBusDaemonAddressInfo) - 1, "%s:%s", - cDBusDaemonAddressInfo, szUserName); - + _dbus_assert (address); // before _dbus_global_lock to keep correct lock/release order - hDBusDaemonMutex = CreateMutex( NULL, FALSE, szDBusDaemonMutex ); + hDBusDaemonMutex = CreateMutex( NULL, FALSE, cDBusDaemonMutex ); ret = WaitForSingleObject( hDBusDaemonMutex, 1000 ); - _dbus_assert(ret == WAIT_OBJECT_0); + 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; + } - // sync _dbus_daemon_init, _dbus_daemon_uninit and _dbus_daemon_already_runs + // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs lock = _dbus_global_lock( cUniqueDBusInitMutex ); // create shm hDBusSharedMem = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, - 0, strlen( szAddress ) + 1, szDBusDaemonAddressInfo ); + 0, strlen( address ) + 1, cDBusDaemonAddressInfo ); _dbus_assert( hDBusSharedMem ); - adr = MapViewOfFile( hDBusSharedMem, FILE_MAP_WRITE, 0, 0, 0 ); + shared_addr = MapViewOfFile( hDBusSharedMem, FILE_MAP_WRITE, 0, 0, 0 ); - _dbus_assert( adr ); + _dbus_assert (shared_addr); - strcpy( adr, szAddress); + strcpy( shared_addr, address); // cleanup - UnmapViewOfFile( adr ); + UnmapViewOfFile( shared_addr ); _dbus_global_unlock( lock ); } void -_dbus_daemon_release() +_dbus_daemon_unpublish_session_bus_address (void) { HANDLE lock; - // sync _dbus_daemon_init, _dbus_daemon_uninit and _dbus_daemon_already_runs + // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs lock = _dbus_global_lock( cUniqueDBusInitMutex ); CloseHandle( hDBusSharedMem ); @@ -3021,24 +2522,16 @@ _dbus_daemon_release() } static dbus_bool_t -_dbus_get_autolaunch_shm(DBusString *adress) +_dbus_get_autolaunch_shm (DBusString *address) { HANDLE sharedMem; - char *adr; - char szUserName[64]; - DWORD dwUserNameSize = sizeof(szUserName); - char szDBusDaemonAddressInfo[128]; + char *shared_addr; int i; - if( !GetUserName(szUserName, &dwUserNameSize) ) - return FALSE; - _snprintf(szDBusDaemonAddressInfo, sizeof(szDBusDaemonAddressInfo) - 1, "%s:%s", - cDBusDaemonAddressInfo, szUserName); - // read shm for(i=0;i<20;++i) { // we know that dbus-daemon is available, so we wait until shm is available - sharedMem = OpenFileMapping( FILE_MAP_READ, FALSE, szDBusDaemonAddressInfo ); + sharedMem = OpenFileMapping( FILE_MAP_READ, FALSE, cDBusDaemonAddressInfo ); if( sharedMem == 0 ) Sleep( 100 ); if ( sharedMem != 0) @@ -3048,17 +2541,17 @@ _dbus_get_autolaunch_shm(DBusString *adress) if( sharedMem == 0 ) return FALSE; - adr = MapViewOfFile( sharedMem, FILE_MAP_READ, 0, 0, 0 ); + shared_addr = MapViewOfFile( sharedMem, FILE_MAP_READ, 0, 0, 0 ); - if( adr == 0 ) + if( !shared_addr ) return FALSE; - _dbus_string_init( adress ); + _dbus_string_init( address ); - _dbus_string_append( adress, adr ); + _dbus_string_append( address, shared_addr ); // cleanup - UnmapViewOfFile( adr ); + UnmapViewOfFile( shared_addr ); CloseHandle( sharedMem ); @@ -3066,25 +2559,17 @@ _dbus_get_autolaunch_shm(DBusString *adress) } static dbus_bool_t -_dbus_daemon_already_runs (DBusString *adress) +_dbus_daemon_already_runs (DBusString *address) { HANDLE lock; HANDLE daemon; dbus_bool_t bRet = TRUE; - char szUserName[64]; - DWORD dwUserNameSize = sizeof(szUserName); - char szDBusDaemonMutex[128]; - // sync _dbus_daemon_init, _dbus_daemon_uninit and _dbus_daemon_already_runs + // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs lock = _dbus_global_lock( cUniqueDBusInitMutex ); - if( !GetUserName(szUserName, &dwUserNameSize) ) - return FALSE; - _snprintf(szDBusDaemonMutex, sizeof(szDBusDaemonMutex) - 1, "%s:%s", - cDBusDaemonMutex, szUserName); - // do checks - daemon = CreateMutex( NULL, FALSE, szDBusDaemonMutex ); + daemon = CreateMutex( NULL, FALSE, cDBusDaemonMutex ); if(WaitForSingleObject( daemon, 10 ) != WAIT_TIMEOUT) { ReleaseMutex (daemon); @@ -3095,7 +2580,7 @@ _dbus_daemon_already_runs (DBusString *adress) } // read shm - bRet = _dbus_get_autolaunch_shm( adress ); + bRet = _dbus_get_autolaunch_shm( address ); // cleanup CloseHandle ( daemon ); @@ -3116,11 +2601,7 @@ _dbus_get_autolaunch_address (DBusString *address, LPSTR lpFile; char dbus_exe_path[MAX_PATH]; char dbus_args[MAX_PATH * 2]; -#ifdef _DEBUG - const char * daemon_name = "dbus-daemond.exe"; -#else - const char * daemon_name = "dbus-daemon.exe"; -#endif + const char * daemon_name = DBUS_DAEMON_NAME ".exe"; mutex = _dbus_global_lock ( cDBusAutolaunchMutex ); @@ -3152,7 +2633,8 @@ _dbus_get_autolaunch_address (DBusString *address, // printf("create process \"%s\" %s\n", dbus_exe_path, dbus_args); if(CreateProcessA(dbus_exe_path, dbus_args, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) { - + CloseHandle (pi.hThread); + CloseHandle (pi.hProcess); retval = _dbus_get_autolaunch_shm( address ); } @@ -3310,12 +2792,6 @@ _dbus_atomic_dec (DBusAtomic *atomic) void _dbus_flush_caches (void) { - -} - -dbus_bool_t _dbus_windows_user_is_process_owner (const char *windows_sid) -{ - return TRUE; } /** @@ -3327,7 +2803,7 @@ dbus_bool_t _dbus_windows_user_is_process_owner (const char *windows_sid) dbus_bool_t _dbus_get_is_errno_eagain_or_ewouldblock (void) { - return errno == EAGAIN || errno == EWOULDBLOCK; + return errno == WSAEWOULDBLOCK; } /** @@ -3337,27 +2813,42 @@ _dbus_get_is_errno_eagain_or_ewouldblock (void) * @param len length of buffer * @returns #FALSE on failure */ -dbus_bool_t -_dbus_get_install_root(char *s, int len) -{ - char *p = NULL; - int ret = GetModuleFileName(NULL,s,len); - if ( ret == 0 - || ret == len && GetLastError() == ERROR_INSUFFICIENT_BUFFER) - { - *s = '\0'; - return FALSE; - } - else if ((p = strstr(s,"\\bin\\"))) - { - *(p+1)= '\0'; - return TRUE; +static 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 ); + pathLength = GetModuleFileName(_dbus_win_get_dll_hmodule(), prefix, len); + if ( pathLength == 0 || GetLastError() != 0 ) { + *prefix = '\0'; + return FALSE; } - else - { - *s = '\0'; - return FALSE; + lastSlash = _mbsrchr(prefix, '\\'); + if (lastSlash == NULL) { + *prefix = '\0'; + return FALSE; } + //cut off binary name + lastSlash[1] = 0; + + //cut possible "\\bin" + + //this fails if we are in a double-byte system codepage and the + //folder's name happens to end with the *bytes* + //"\\bin"... (I.e. the second byte of some Han character and then + //the Latin "bin", but that is not likely I think... + if (lastSlash - prefix >= 4 && strnicmp(lastSlash - 4, "\\bin", 4) == 0) + lastSlash[-3] = 0; + else if (lastSlash - prefix >= 10 && strnicmp(lastSlash - 10, "\\bin\\debug", 10) == 0) + lastSlash[-9] = 0; + else if (lastSlash - prefix >= 12 && strnicmp(lastSlash - 12, "\\bin\\release", 12) == 0) + lastSlash[-11] = 0; + + return TRUE; } /** @@ -3365,7 +2856,9 @@ _dbus_get_install_root(char *s, int len) the following path layout install-root/ bin/dbus-daemon[d].exe - etc/.conf + etc/.conf *or* etc/dbus-1/.conf + (the former above is what dbus4win uses, the latter above is + what a "normal" Unix-style "make install" uses) build-root/ bin/dbus-daemon[d].exe @@ -3376,12 +2869,11 @@ _dbus_get_config_file_name(DBusString *config_file, char *s) { char path[MAX_PATH*2]; int path_size = sizeof(path); - int len = 4 + strlen(s); if (!_dbus_get_install_root(path,path_size)) return FALSE; - if(len > sizeof(path)-2) + if(strlen(s) + 4 + strlen(path) > sizeof(path)-2) return FALSE; strcat(path,"etc\\"); strcat(path,s); @@ -3395,9 +2887,9 @@ _dbus_get_config_file_name(DBusString *config_file, char *s) { if (!_dbus_get_install_root(path,path_size)) return FALSE; - if(len + strlen(path) > sizeof(path)-2) + if(strlen(s) + 11 + strlen(path) > sizeof(path)-2) return FALSE; - strcat(path,"bus\\"); + strcat(path,"etc\\dbus-1\\"); strcat(path,s); if (_dbus_file_exists(path)) @@ -3405,6 +2897,21 @@ _dbus_get_config_file_name(DBusString *config_file, char *s) if (!_dbus_string_append (config_file, path)) return FALSE; } + else + { + if (!_dbus_get_install_root(path,path_size)) + return FALSE; + if(strlen(s) + 4 + strlen(path) > sizeof(path)-2) + return FALSE; + strcat(path,"bus\\"); + strcat(path,s); + + if (_dbus_file_exists(path)) + { + if (!_dbus_string_append (config_file, path)) + return FALSE; + } + } } return TRUE; } @@ -3467,6 +2974,7 @@ _dbus_append_keyring_directory_for_credentials (DBusString *directory, DBusString dotdir; dbus_uid_t uid; const char *homepath; + const char *homedrive; _dbus_assert (credentials != NULL); _dbus_assert (!_dbus_credentials_are_anonymous (credentials)); @@ -3474,6 +2982,12 @@ _dbus_append_keyring_directory_for_credentials (DBusString *directory, if (!_dbus_string_init (&homedir)) return FALSE; + homedrive = _dbus_getenv("HOMEDRIVE"); + if (homedrive != NULL && *homedrive != '\0') + { + _dbus_string_append(&homedir,homedrive); + } + homepath = _dbus_getenv("HOMEPATH"); if (homepath != NULL && *homepath != '\0') { @@ -3524,6 +3038,232 @@ _dbus_append_keyring_directory_for_credentials (DBusString *directory, return FALSE; } +/** Checks if a file exists +* +* @param file full path to the file +* @returns #TRUE if file exists +*/ +dbus_bool_t +_dbus_file_exists (const char *file) +{ + DWORD attributes = GetFileAttributes (file); + + if (attributes != INVALID_FILE_ATTRIBUTES && GetLastError() != ERROR_PATH_NOT_FOUND) + return TRUE; + else + return FALSE; +} + +/** + * A wrapper around strerror() because some platforms + * may be lame and not have strerror(). + * + * @param error_number errno. + * @returns error description. + */ +const char* +_dbus_strerror (int error_number) +{ +#ifdef DBUS_WINCE + // TODO + return "unknown"; +#else + const char *msg; + + switch (error_number) + { + case WSAEINTR: + return "Interrupted function call"; + case WSAEACCES: + return "Permission denied"; + case WSAEFAULT: + return "Bad address"; + case WSAEINVAL: + return "Invalid argument"; + case WSAEMFILE: + return "Too many open files"; + case WSAEWOULDBLOCK: + return "Resource temporarily unavailable"; + case WSAEINPROGRESS: + return "Operation now in progress"; + case WSAEALREADY: + return "Operation already in progress"; + case WSAENOTSOCK: + return "Socket operation on nonsocket"; + case WSAEDESTADDRREQ: + return "Destination address required"; + case WSAEMSGSIZE: + return "Message too long"; + case WSAEPROTOTYPE: + return "Protocol wrong type for socket"; + case WSAENOPROTOOPT: + return "Bad protocol option"; + case WSAEPROTONOSUPPORT: + return "Protocol not supported"; + case WSAESOCKTNOSUPPORT: + return "Socket type not supported"; + case WSAEOPNOTSUPP: + return "Operation not supported"; + case WSAEPFNOSUPPORT: + return "Protocol family not supported"; + case WSAEAFNOSUPPORT: + return "Address family not supported by protocol family"; + case WSAEADDRINUSE: + return "Address already in use"; + case WSAEADDRNOTAVAIL: + return "Cannot assign requested address"; + case WSAENETDOWN: + return "Network is down"; + case WSAENETUNREACH: + return "Network is unreachable"; + case WSAENETRESET: + return "Network dropped connection on reset"; + case WSAECONNABORTED: + return "Software caused connection abort"; + case WSAECONNRESET: + return "Connection reset by peer"; + case WSAENOBUFS: + return "No buffer space available"; + case WSAEISCONN: + return "Socket is already connected"; + case WSAENOTCONN: + return "Socket is not connected"; + case WSAESHUTDOWN: + return "Cannot send after socket shutdown"; + case WSAETIMEDOUT: + return "Connection timed out"; + case WSAECONNREFUSED: + return "Connection refused"; + case WSAEHOSTDOWN: + return "Host is down"; + case WSAEHOSTUNREACH: + return "No route to host"; + case WSAEPROCLIM: + return "Too many processes"; + case WSAEDISCON: + return "Graceful shutdown in progress"; + case WSATYPE_NOT_FOUND: + return "Class type not found"; + case WSAHOST_NOT_FOUND: + return "Host not found"; + case WSATRY_AGAIN: + return "Nonauthoritative host not found"; + case WSANO_RECOVERY: + return "This is a nonrecoverable error"; + case WSANO_DATA: + return "Valid name, no data record of requested type"; + case WSA_INVALID_HANDLE: + return "Specified event object handle is invalid"; + case WSA_INVALID_PARAMETER: + return "One or more parameters are invalid"; + case WSA_IO_INCOMPLETE: + return "Overlapped I/O event object not in signaled state"; + case WSA_IO_PENDING: + return "Overlapped operations will complete later"; + case WSA_NOT_ENOUGH_MEMORY: + return "Insufficient memory available"; + case WSA_OPERATION_ABORTED: + return "Overlapped operation aborted"; +#ifdef WSAINVALIDPROCTABLE + + case WSAINVALIDPROCTABLE: + return "Invalid procedure table from service provider"; +#endif +#ifdef WSAINVALIDPROVIDER + + case WSAINVALIDPROVIDER: + return "Invalid service provider version number"; +#endif +#ifdef WSAPROVIDERFAILEDINIT + + case WSAPROVIDERFAILEDINIT: + return "Unable to initialize a service provider"; +#endif + + case WSASYSCALLFAILURE: + return "System call failure"; + } + msg = strerror (error_number); + if (msg == NULL) + msg = "unknown"; + + return msg; +#endif //DBUS_WINCE +} + +/** + * Assigns an error name and message corresponding to a Win32 error + * code to a DBusError. Does nothing if error is #NULL. + * + * @param error the error. + * @param code the Win32 error code + */ +void +_dbus_win_set_error_from_win_error (DBusError *error, + int code) +{ + char *msg; + + /* As we want the English message, use the A API */ + FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, code, MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US), + (LPTSTR) &msg, 0, NULL); + if (msg) + { + char *msg_copy; + + msg_copy = dbus_malloc (strlen (msg)); + strcpy (msg_copy, msg); + LocalFree (msg); + + dbus_set_error (error, "win32.error", "%s", msg_copy); + } + else + dbus_set_error (error, "win32.error", "Unknown error code %d or FormatMessage failed", code); +} + +void +_dbus_win_warn_win_error (const char *message, + int code) +{ + DBusError error; + + dbus_error_init (&error); + _dbus_win_set_error_from_win_error (&error, code); + _dbus_warn ("%s: %s\n", message, error.message); + dbus_error_free (&error); +} + +/** + * Removes a directory; Directory must be empty + * + * @param filename directory filename + * @param error initialized error object + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_delete_directory (const DBusString *filename, + DBusError *error) +{ + const char *filename_c; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + filename_c = _dbus_string_get_const_data (filename); + + if (_rmdir (filename_c) != 0) + { + dbus_set_error (error, DBUS_ERROR_FAILED, + "Failed to remove directory %s: %s\n", + filename_c, strerror (errno)); + return FALSE; + } + + return TRUE; +} + /** @} end of sysdeps-win */ /* tests in dbus-sysdeps-util.c */