1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-sysdeps-wince-glue.c Wrappers for Windows CE around system/libc features (internal to D-BUS implementation)
4 * Copyright (C) 2002, 2003 Red Hat, Inc.
5 * Copyright (C) 2003 CodeFactory AB
6 * Copyright (C) 2005 Novell, Inc.
7 * Copyright (C) 2006 Ralf Habacker <ralf.habacker@freenet.de>
8 * Copyright (C) 2006 Peter Kümmel <syntheticpp@gmx.net>
9 * Copyright (C) 2006 Christian Ehrlicher <ch.ehrlicher@gmx.de>
11 * Licensed under the Academic Free License version 2.1
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30 #include "dbus-internals.h"
31 #include "dbus-sysdeps.h"
32 #include "dbus-sysdeps-win.h"
35 /* Including shlobj.h creates trouble on some compilers. Just chicken
36 out here by defining just what we need. */
37 #ifndef CSIDL_PERSONAL
38 #define CSIDL_PERSONAL 5
42 /* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */
44 stpcpy (char *dest, const char *src)
56 /* Return a string from the W32 Registry or NULL in case of error.
57 Caller must release the return value. A NULL for root is an alias
58 for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn. */
60 read_w32_registry_string (const char *root, const char *dir, const char *name)
62 HKEY root_key, key_handle;
63 DWORD n1, nbytes, type;
67 root_key = HKEY_CURRENT_USER;
68 else if ( !strcmp( root, "HKEY_CLASSES_ROOT" ) )
69 root_key = HKEY_CLASSES_ROOT;
70 else if ( !strcmp( root, "HKEY_CURRENT_USER" ) )
71 root_key = HKEY_CURRENT_USER;
72 else if ( !strcmp( root, "HKEY_LOCAL_MACHINE" ) )
73 root_key = HKEY_LOCAL_MACHINE;
74 else if ( !strcmp( root, "HKEY_USERS" ) )
75 root_key = HKEY_USERS;
79 if (RegOpenKeyExA (root_key, dir, 0, KEY_READ, &key_handle))
82 return NULL; /* no need for a RegClose, so return direct */
83 /* It seems to be common practise to fall back to HKLM. */
84 if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle))
85 return NULL; /* still no need for a RegClose, so return direct */
89 if (RegQueryValueExA (key_handle, name, 0, NULL, NULL, &nbytes))
93 /* Try to fallback to HKLM also for a missing value. */
94 RegCloseKey (key_handle);
95 if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle))
96 return NULL; /* Nope. */
97 if (RegQueryValueExA (key_handle, name, 0, NULL, NULL, &nbytes))
101 result = malloc (n1);
104 if (RegQueryValueExA (key_handle, name, 0, &type, result, &n1))
110 result[nbytes] = 0; /* Make sure it is really a string. */
113 RegCloseKey (key_handle);
121 return read_w32_registry_string ("HKEY_LOCAL_MACHINE",
122 "Software\\freedesktop\\DBus",
123 "Install Directory");
128 find_env_in_registry (const char *name)
130 return read_w32_registry_string ("HKEY_LOCAL_MACHINE",
131 "Software\\freedesktop\\DBus",
137 find_program_in_inst_dir (const char *name)
142 tmp = find_inst_dir ();
146 result = malloc (strlen (tmp) + 5 + strlen (name) + 1);
153 strcpy (stpcpy (stpcpy (result, tmp), "\\bin\\"), name);
161 find_inst_subdir (const char *name)
166 tmp = find_inst_dir ();
170 result = malloc (strlen (tmp) + 1 + strlen (name) + 1);
177 strcpy (stpcpy (stpcpy (result, tmp), "\\"), name);
185 find_my_documents_folder ()
187 /* One for safety, just in case. */
188 char dir[MAX_PATH + 1];
192 /* May return false even if successful. */
193 SHGetSpecialFolderPathA (0, dir, CSIDL_PERSONAL, 0);
197 result = malloc (strlen (dir) + 1);
200 strcpy (result, dir);
207 char *environ[MAX_ENV + 1];
210 getenv (const char *name)
212 static char *past_result;
222 if (! strcmp (name, "DBUS_VERBOSE"))
223 return past_result = find_env_in_registry ("Verbose");
224 else if (! strcmp (name, "HOMEPATH"))
225 return past_result = find_my_documents_folder ();
226 else if (! strcmp (name, "DBUS_DATADIR"))
227 return past_result = find_inst_subdir ("share");
229 for (envp = environ; *envp != 0; envp++)
231 const char *varp = name;
235 while (*varp == *ep && *varp != '\0')
241 if (*varp == '\0' && *ep == '=')
254 for (envp = environ; *envp != 0; envp++)
260 while (*varp == *ep && *varp != '\0')
268 if (*varp == *ep && *varp == '\0')
277 idx = envp - environ;
280 _dbus_win_set_errno (ENOMEM);
292 return GetTickCount ();
299 /* This is what windows does. */
305 GetSystemTimeAsFileTime (LPFILETIME ftp)
309 SystemTimeToFileTime (&st, ftp);
314 _mbsrchr (const unsigned char* str, unsigned int ch)
316 /* FIXME. This is not multi-byte safe. */
317 return strrchr (str, ch);
321 HANDLE OpenFileMappingA(DWORD dwDesiredAccess,
328 if (dwDesiredAccess & FILE_MAP_READ)
329 flProtect |= PAGE_READONLY;
331 if (dwDesiredAccess & FILE_MAP_WRITE)
332 flProtect |= PAGE_READWRITE;
335 hMapping = CreateFileMappingA(INVALID_HANDLE_VALUE,
336 NULL, flProtect, 0, 0, lpName);
337 if (hMapping != INVALID_HANDLE_VALUE)
339 /* Just in case Windows CE changes its behaviour, we check for
340 the right error value here. */
341 if (GetLastError () != ERROR_ALREADY_EXISTS)
343 CloseHandle(hMapping);
344 hMapping = INVALID_HANDLE_VALUE;
352 MoveFileExA (LPCSTR lpExistingFileName, LPCSTR lpNewFileName, DWORD dwFlags)
354 _dbus_assert (dwFlags == MOVEFILE_REPLACE_EXISTING);
356 if (_dbus_file_exists (lpNewFileName))
358 BOOL result = DeleteFileA (lpNewFileName);
362 return MoveFileA (lpExistingFileName, lpNewFileName);
367 SetHandleInformation (HANDLE hObject, DWORD dwMask, DWORD dwFlags)
369 _dbus_assert (dwMask == (HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE));
370 _dbus_assert (dwFlags == 0);
372 /* Not supported on Windows CE, and actually the default. So just
373 return overwhelming success. */
379 SearchPathA (LPCSTR lpPath, LPCSTR lpFileName, LPCSTR lpExtension,
380 DWORD nBufferLength, LPSTR lpBuffer, LPSTR* lpFilePart)
386 _dbus_assert (lpPath == NULL);
387 _dbus_assert (lpExtension == NULL);
389 filename = find_program_in_inst_dir (lpFileName);
392 SetLastError (ERROR_FILE_NOT_FOUND);
396 filename_len = strlen (filename) + 1;
397 if (filename_len > nBufferLength)
403 strcpy (lpBuffer, filename);
406 filepart = _mbsrchr (lpBuffer, '\\');
409 *lpFilePart = filepart;
411 return filename_len - 1;
416 * @param points to sid buffer, need to be freed with LocalFree()
417 * @returns process sid
420 _dbus_getsid(char **sid)
422 /* There is nothing like this on Windows CE, so we fake it. */
423 static const char asid[] = "S-1-5-21-515967899-920026266-1708537768-1000";
424 char *buf = LocalAlloc (LMEM_FIXED, sizeof (asid));
427 _dbus_win_warn_win_error ("LocalAlloc failed", GetLastError ());
431 memcpy (buf, asid, sizeof (asid));
438 LookupAccountNameW (LPCWSTR lpSystemName, LPCWSTR lpAccountName, PSID Sid, PDWORD cbSid,
439 LPWSTR ReferencedDomainName, PDWORD cchReferencedDomainName, PSID_NAME_USE peUse)
441 /* Currently not needed. */
447 IsValidSid (PSID psid)
449 /* Currently not needed. */
455 CreateFileA (LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwSharedMode,
456 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
457 DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
458 HANDLE hTemplateFile)
464 filename = _dbus_win_utf8_to_utf16 (lpFileName, NULL);
466 return INVALID_HANDLE_VALUE;
468 result = CreateFileW (filename, dwDesiredAccess, dwSharedMode,
469 lpSecurityAttributes, dwCreationDisposition,
470 dwFlagsAndAttributes, hTemplateFile);
472 err = GetLastError ();
473 dbus_free (filename);
480 DeleteFileA (LPCSTR lpFileName)
486 filename = _dbus_win_utf8_to_utf16 (lpFileName, NULL);
490 result = DeleteFileW (filename);
492 err = GetLastError ();
493 dbus_free (filename);
500 MoveFileA (LPCSTR lpExistingFileName, LPCSTR lpNewFileName)
502 wchar_t *existing_filename;
503 wchar_t *new_filename;
507 existing_filename = _dbus_win_utf8_to_utf16 (lpExistingFileName, NULL);
508 if (! existing_filename)
511 new_filename = _dbus_win_utf8_to_utf16 (lpNewFileName, NULL);
514 dbus_free (existing_filename);
518 result = MoveFileW (existing_filename, new_filename);
520 err = GetLastError ();
521 dbus_free (existing_filename);
522 dbus_free (new_filename);
529 GetFileAttributesA(LPCSTR lpFileName)
535 filename = _dbus_win_utf8_to_utf16 (lpFileName, NULL);
537 return INVALID_FILE_ATTRIBUTES;
539 result = GetFileAttributesW (filename);
541 err = GetLastError ();
542 dbus_free (filename);
549 GetFileAttributesExA (LPCSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
550 PVOID lpFileInformation)
556 filename = _dbus_win_utf8_to_utf16 (lpFileName, NULL);
558 return INVALID_FILE_ATTRIBUTES;
560 result = GetFileAttributesExW (filename, fInfoLevelId, lpFileInformation);
562 err = GetLastError ();
563 dbus_free (filename);
570 CreateFileMappingA (HANDLE hFile, LPSECURITY_ATTRIBUTES lpAttributes,
571 DWORD flProtect, DWORD dwMaximumSizeHigh,
572 DWORD dwMaximumSizeLow, LPCSTR lpName)
580 name = _dbus_win_utf8_to_utf16 (lpName, NULL);
582 return INVALID_HANDLE_VALUE;
587 result = CreateFileMappingW (hFile, lpAttributes, flProtect,
588 dwMaximumSizeHigh, dwMaximumSizeLow,
591 err = GetLastError ();
599 CreateDirectoryA (LPCSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
605 pathname = _dbus_win_utf8_to_utf16 (lpPathName, NULL);
609 result = CreateDirectoryW (pathname, lpSecurityAttributes);
611 err = GetLastError ();
612 dbus_free (pathname);
619 RemoveDirectoryA (LPCSTR lpPathName)
625 pathname = _dbus_win_utf8_to_utf16 (lpPathName, NULL);
629 result = RemoveDirectoryW (pathname);
631 err = GetLastError ();
632 dbus_free (pathname);
639 convert_find_data (LPWIN32_FIND_DATAW fdw, LPWIN32_FIND_DATAA fda)
644 fda->dwFileAttributes = fdw->dwFileAttributes;
645 fda->ftCreationTime = fdw->ftCreationTime;
646 fda->ftLastAccessTime = fdw->ftLastAccessTime;
647 fda->ftLastWriteTime = fdw->ftLastWriteTime;
648 fda->nFileSizeHigh = fdw->nFileSizeHigh;
649 fda->nFileSizeLow = fdw->nFileSizeLow;
651 filename = _dbus_win_utf16_to_utf8 (fdw->cFileName, NULL);
655 len = sizeof (fda->cFileName);
656 strncpy (fda->cFileName, filename, len);
657 fda->cFileName[len - 1] = '\0';
664 FindFirstFileA (LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData)
667 WIN32_FIND_DATAW find_file_data;
671 pathname = _dbus_win_utf8_to_utf16 (lpFileName, NULL);
673 return INVALID_HANDLE_VALUE;
675 result = FindFirstFileW (pathname, &find_file_data);
676 if (result != INVALID_HANDLE_VALUE)
678 BOOL res = convert_find_data (&find_file_data, lpFindFileData);
681 err = GetLastError ();
684 result = INVALID_HANDLE_VALUE;
688 err = GetLastError ();
689 dbus_free (pathname);
696 FindNextFileA (HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData)
698 WIN32_FIND_DATAW find_file_data;
702 result = FindNextFileW (hFindFile, &find_file_data);
704 result = convert_find_data (&find_file_data, lpFindFileData);
711 CreateMutexA (LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner,
720 name = _dbus_win_utf8_to_utf16 (lpName, NULL);
722 return INVALID_HANDLE_VALUE;
727 result = CreateMutexW (lpMutexAttributes, bInitialOwner, name);
729 err = GetLastError ();
737 CreateProcessA (LPCSTR pszImageName, LPSTR pszCmdLine,
738 LPSECURITY_ATTRIBUTES psaProcess,
739 LPSECURITY_ATTRIBUTES psaThread, BOOL fInheritHandles,
740 DWORD fdwCreate, PVOID pvEnvironment, LPCSTR pszCurDir,
741 LPSTARTUPINFOA psiStartInfo,
742 LPPROCESS_INFORMATION pProcInfo)
744 wchar_t *image_name = NULL;
745 wchar_t *cmd_line = NULL;
749 _dbus_assert (psaProcess == NULL);
750 _dbus_assert (psaThread == NULL);
751 _dbus_assert (fInheritHandles == FALSE);
752 _dbus_assert (pvEnvironment == NULL);
753 _dbus_assert (pszCurDir == NULL);
754 /* psiStartInfo is generally not NULL. */
758 image_name = _dbus_win_utf8_to_utf16 (pszImageName, NULL);
764 cmd_line = _dbus_win_utf8_to_utf16 (pszCmdLine, NULL);
768 dbus_free (image_name);
773 result = CreateProcessW (image_name, cmd_line, NULL, NULL, FALSE,
774 fdwCreate, NULL, NULL, NULL, pProcInfo);
776 err = GetLastError ();
777 dbus_free (image_name);
778 dbus_free (cmd_line);
785 RegOpenKeyExA (HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions,
786 REGSAM samDesired, PHKEY phkResult)
794 subkey = _dbus_win_utf8_to_utf16 (lpSubKey, NULL);
801 result = RegOpenKeyEx (hKey, subkey, ulOptions, samDesired, phkResult);
803 err = GetLastError ();
811 RegQueryValueExA (HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved,
812 LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
822 name = _dbus_win_utf8_to_utf16 (lpValueName, NULL);
824 return GetLastError ();
830 err = RegQueryValueExW (hKey, name, lpReserved, lpType, NULL, &data_len);
831 if (err || !lpcbData)
837 data = malloc (data_len + sizeof (wchar_t));
841 return ERROR_NOT_ENOUGH_MEMORY;
844 err = RegQueryValueExW (hKey, name, lpReserved, &type, data, &data_len);
848 /* If err is ERROR_MORE_DATA, there probably was a race condition.
849 We can punt this to the caller just as well. */
853 /* NOTE: REG_MULTI_SZ and REG_EXPAND_SZ not supported, because they
854 are not needed in this module. */
860 /* This is valid since we allocated one more above. */
861 data[data_len] = '\0';
862 data[data_len + 1] = '\0';
864 data_c = _dbus_win_utf16_to_utf8 ((wchar_t*) data, NULL);
866 return GetLastError();
868 data_c_len = strlen (data_c) + 1;
869 _dbus_assert (data_c_len <= data_len + sizeof (wchar_t));
870 memcpy (data, data_c, data_c_len);
871 data_len = data_c_len;
875 /* DATA and DATA_LEN now contain the result. */
878 if (data_len > *lpcbData)
879 err = ERROR_MORE_DATA;
881 memcpy (lpData, data, data_len);
883 *lpcbData = data_len;
889 FormatMessageA (DWORD dwFlags, PCVOID lpSource, DWORD dwMessageId,
890 DWORD dwLanguageId, LPSTR lpBuffer, DWORD nSize,
893 LPWSTR buffer_w = NULL;
897 DWORD buffer_new_len;
900 len = FormatMessageW (dwFlags | FORMAT_MESSAGE_ALLOCATE_BUFFER,
901 lpSource, dwMessageId, dwLanguageId,
902 (LPWSTR) &buffer_w, 0, Arguments);
906 buffer_c = _dbus_win_utf16_to_utf8 (buffer_w, NULL);
909 LocalFree (buffer_w);
913 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER)
915 /* We need to return a buffer that's freeable with LocalFree. */
916 buffer_new = (char *) buffer_w;
917 buffer_new_len = sizeof (wchar_t) * (len + 1);
918 buffer_w_free = FALSE;
919 /* Avoid alignment issue by using memcpy. */
920 memcpy (lpBuffer, &buffer_new, sizeof (buffer_new));
924 buffer_new = lpBuffer;
925 buffer_new_len = nSize;
926 buffer_w_free = TRUE;
929 strncpy (buffer_new, buffer_c, buffer_new_len);
930 dbus_free (buffer_c);
931 buffer_new[buffer_new_len - 1] = '\0';
933 LocalFree (buffer_w);
935 /* strlen is correct (not _mbstrlen), because we want storage and
936 not string length. */
937 return strlen (buffer_new);
942 GetModuleFileNameA (HINSTANCE hModule, LPSTR lpFilename, DWORD nSize)
944 wchar_t filename_w[MAX_PATH];
948 _dbus_assert (MAX_PATH >= nSize);
950 len = GetModuleFileNameW (hModule, filename_w, nSize);
954 filename_w[nSize - 1] = '\0';
955 filename_c = _dbus_win_utf16_to_utf8 (filename_w, NULL);
959 strncpy (lpFilename, filename_c, nSize);
960 dbus_free (filename_c);
961 lpFilename[nSize - 1] = '\0';
962 /* strlen is correct (not _mbstrlen), because we want storage and
963 not string length. */
964 return strlen (lpFilename);
969 GetTempPathA (DWORD nBufferLength, LPSTR lpBuffer)
974 len = GetTempPathW (0, dummy);
978 _dbus_assert (len <= MAX_PATH);
980 /* Better be safe than sorry. MSDN doesn't say if len is with or
981 without terminating 0. */
990 buffer_w = malloc (sizeof (wchar_t) * len);
994 len_w = GetTempPathW (len, buffer_w);
995 /* Give up if we still can't get at it. */
996 if (len_w == 0 || len_w >= len)
1002 /* Better be really safe. */
1003 buffer_w[len_w] = '\0';
1005 buffer_c = _dbus_win_utf16_to_utf8 (buffer_w, NULL);
1010 /* strlen is correct (not _mbstrlen), because we want storage and
1011 not string length. */
1012 len_c = strlen (buffer_c) + 1;
1013 if (len_c > nBufferLength)
1016 strcpy (lpBuffer, buffer_c);
1017 dbus_free (buffer_c);
1024 SHGetSpecialFolderPathA (HWND hwndOwner, LPSTR lpszPath, int nFolder,
1027 wchar_t path[MAX_PATH];
1031 path[0] = (wchar_t) 0;
1032 result = SHGetSpecialFolderPathW (hwndOwner, path, nFolder, fCreate);
1033 /* Note: May return false even if succeeds. */
1035 path[MAX_PATH - 1] = (wchar_t) 0;
1036 path_c = _dbus_win_utf16_to_utf8 (path, NULL);
1040 strncpy (lpszPath, path_c, MAX_PATH);
1042 lpszPath[MAX_PATH - 1] = '\0';