*
*/
-#undef open
+#include <config.h>
#define STRSAFE_NO_DEPRECATE
#ifndef DBUS_WINCE
+#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif
+#endif
#include "dbus-internals.h"
#include "dbus-sysdeps.h"
#include "dbus-hash.h"
#include "dbus-sockets-win.h"
#include "dbus-list.h"
+#include "dbus-nonce.h"
#include "dbus-credentials.h"
#include <windows.h>
#include <ws2tcpip.h>
+#include <wincrypt.h>
+
+/* Declarations missing in mingw's headers */
+extern BOOL WINAPI ConvertStringSidToSidA (LPCSTR StringSid, PSID *Sid);
+extern BOOL WINAPI ConvertSidToStringSidA (PSID Sid, LPSTR *StringSid);
+
#include <fcntl.h>
#include <process.h>
+#include <stdio.h>
+#include <io.h>
+
+#include <string.h>
+#include <mbstring.h>
+#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#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
*
* 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,
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
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());
+ }
}
/**
const char *data2;
int rc;
DWORD bytes_written;
- int ret1;
_dbus_assert (buffer1 != NULL);
_dbus_assert (start1 >= 0);
return bytes_written;
}
+dbus_bool_t
+_dbus_socket_is_invalid (int fd)
+{
+ return fd == INVALID_SOCKET ? TRUE : FALSE;
+}
+
#if 0
/**
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;
}
/** @} 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.
* @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;
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
* @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;
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)
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;
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)
}
}
return ready;
+#endif /* USE_CHRIS_IMPL */
}
-#endif // USE_CHRIS_IMPL
-
/**
- * @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
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;
}
_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;
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
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);
to use the same port */
if (!port || !strcmp(port, "0"))
{
- sockaddr_gen addr;
+ mysockaddr_gen addr;
socklen_t addrlen = sizeof(addr);
char portbuf[10];
}
sscanf(_dbus_string_get_const_data(retport), "%d", &port_num);
- _dbus_daemon_init(host, port_num);
for (i = 0 ; i < nlisten_fd ; i++)
{
_dbus_string_get_length (dir));
}
-/*---------------- DBusCredentials ----------------------------------
+/*---------------- DBusCredentials ----------------------------------*/
/**
* Adds the credentials corresponding to the given username.
* Gets our process ID
* @returns process ID
*/
-unsigned long
+dbus_pid_t
_dbus_getpid (void)
{
return GetCurrentProcessId ();
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;
}
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;
}
_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);
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
// 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";
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];
-
- _dbus_assert(host);
- _dbus_assert(port);
-
- _snprintf(szAddress, sizeof(szAddress) - 1, "tcp:host=%s,port=%d", host, port);
-
- _dbus_assert( GetUserName(szUserName, &dwUserNameSize) != 0);
- _snprintf(szDBusDaemonMutex, sizeof(szDBusDaemonMutex) - 1, "%s:%s",
- cDBusDaemonMutex, szUserName);
- _snprintf(szDBusDaemonAddressInfo, sizeof(szDBusDaemonAddressInfo) - 1, "%s:%s",
- cDBusDaemonAddressInfo, szUserName);
+ char *shared_addr = NULL;
+ DWORD ret;
+ _dbus_assert (address);
// before _dbus_global_lock to keep correct lock/release order
- hDBusDaemonMutex = CreateMutex( NULL, FALSE, szDBusDaemonMutex );
-
- _dbus_assert(WaitForSingleObject( hDBusDaemonMutex, 1000 ) == WAIT_OBJECT_0);
+ hDBusDaemonMutex = CreateMutex( 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;
+ }
- // 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 );
}
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)
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 );
}
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);
}
// read shm
- bRet = _dbus_get_autolaunch_shm( adress );
+ bRet = _dbus_get_autolaunch_shm( address );
// cleanup
CloseHandle ( daemon );
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 );
// 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 );
}
void
_dbus_flush_caches (void)
{
-
-}
-
-dbus_bool_t _dbus_windows_user_is_process_owner (const char *windows_sid)
-{
- return TRUE;
}
/**
dbus_bool_t
_dbus_get_is_errno_eagain_or_ewouldblock (void)
{
- return errno == EAGAIN || errno == EWOULDBLOCK;
+ return errno == WSAEWOULDBLOCK;
}
/**
* @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;
}
/**
the following path layout
install-root/
bin/dbus-daemon[d].exe
- etc/<config-file>.conf
+ etc/<config-file>.conf *or* etc/dbus-1/<config-file>.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
{
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);
{
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))
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;
}
DBusString dotdir;
dbus_uid_t uid;
const char *homepath;
+ const char *homedrive;
_dbus_assert (credentials != NULL);
_dbus_assert (!_dbus_credentials_are_anonymous (credentials));
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')
{
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 */