D-Bus 1.6.12

dbus-sysdeps-wince-glue.c

00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-sysdeps-wince-glue.c Wrappers for Windows CE around system/libc features (internal to D-BUS implementation)
00003  * 
00004  * Copyright (C) 2002, 2003  Red Hat, Inc.
00005  * Copyright (C) 2003 CodeFactory AB
00006  * Copyright (C) 2005 Novell, Inc.
00007  * Copyright (C) 2006 Ralf Habacker <ralf.habacker@freenet.de>
00008  * Copyright (C) 2006 Peter Kümmel  <syntheticpp@gmx.net>
00009  * Copyright (C) 2006 Christian Ehrlicher <ch.ehrlicher@gmx.de>
00010  *
00011  * Licensed under the Academic Free License version 2.1
00012  * 
00013  * This program is free software; you can redistribute it and/or modify
00014  * it under the terms of the GNU General Public License as published by
00015  * the Free Software Foundation; either version 2 of the License, or
00016  * (at your option) any later version.
00017  *
00018  * This program is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  * GNU General Public License for more details.
00022  * 
00023  * You should have received a copy of the GNU General Public License
00024  * along with this program; if not, write to the Free Software
00025  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00026  *
00027  */
00028 
00029 #include <config.h>
00030 #include "dbus-internals.h"
00031 #include "dbus-sysdeps.h"
00032 #include "dbus-sysdeps-win.h"
00033 
00034 #include <windows.h>
00035 /* Including shlobj.h creates trouble on some compilers.  Just chicken
00036    out here by defining just what we need.  */
00037 #ifndef CSIDL_PERSONAL
00038 #define CSIDL_PERSONAL 5
00039 #endif
00040 
00041 
00042 /* Copy SRC to DEST, returning the address of the terminating '\0' in DEST.  */
00043 static char *
00044 stpcpy (char *dest, const char *src)
00045 {
00046   char *d = dest;
00047   const char *s = src;
00048 
00049   do
00050     *d++ = *s;
00051   while (*s++ != '\0');
00052 
00053   return d - 1;
00054 }
00055 
00056 
00057 /* This is special cased, because we must avoid using many dbus
00058    functions (such as memory allocations): Those functions may in turn
00059    cause verbose output and check the flag!  */
00060 static char *
00061 get_verbose_setting()
00062 {
00063   const wchar_t dir[] = L"Software\\freedesktop\\DBus";
00064   const wchar_t name[] = L"Verbose";
00065   HKEY root_key;
00066   HKEY key_handle;
00067   DWORD nbytes;
00068   DWORD n1;
00069   DWORD type;
00070   wchar_t *result_w = NULL;
00071   char *result;
00072   int len;
00073 
00074   root_key = HKEY_LOCAL_MACHINE;
00075   if (RegOpenKeyExW (root_key, dir, 0, KEY_READ, &key_handle))
00076     return NULL;
00077 
00078   nbytes = 1;
00079   if (RegQueryValueExW (key_handle, name, 0, NULL, NULL, &nbytes))
00080     {
00081       RegCloseKey (key_handle);
00082       return NULL;
00083     }
00084   /* Round up to multiple of wchar_t, convert to number of wchar_t's, and add 1.  */
00085   n1 = ((nbytes + sizeof(wchar_t) - 1) / sizeof (wchar_t)) + 1;
00086   result_w = malloc (n1 * sizeof (wchar_t));
00087   if (!result_w)
00088     {
00089       RegCloseKey (key_handle);
00090       return NULL;
00091     }
00092   if (RegQueryValueExW (key_handle, name, 0, &type, (LPBYTE) result_w, &nbytes))
00093     {
00094       RegCloseKey (key_handle);
00095       free (result_w);
00096       return NULL;
00097     }
00098   RegCloseKey (key_handle);
00099   result_w[n1 - 1] = 0; /* Make sure it is really a string.  */
00100 
00101   /* NOTE: REG_MULTI_SZ and REG_EXPAND_SZ not supported, because they
00102      are not needed in this module.  */
00103   if (type != REG_SZ)
00104     {
00105       free (result_w);
00106       return NULL;
00107     }
00108 
00109   len = WideCharToMultiByte (CP_UTF8, 0, result_w, -1, NULL, 0, NULL, NULL);
00110   if (len < 0)
00111     {
00112       free (result_w);
00113       return NULL;
00114     }
00115 
00116   result = malloc (len + 1);
00117   if (!result)
00118     {
00119       free (result_w);
00120       return NULL;
00121     }
00122 
00123   len = WideCharToMultiByte (CP_UTF8, 0, result_w, -1, result, len, NULL, NULL);
00124   free (result_w);
00125   if (len < 0)
00126     {
00127       free (result);
00128       return NULL;
00129     }
00130   return result;
00131 }
00132 
00133 
00134 /* Return a string from the W32 Registry or NULL in case of error.
00135    Caller must release the return value.  A NULL for root is an alias
00136    for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn. */
00137 static char *
00138 read_w32_registry_string (const char *root, const char *dir, const char *name)
00139 {
00140   HKEY root_key, key_handle;
00141   DWORD n1, nbytes, type;
00142   char *result = NULL;
00143         
00144   if ( !root )
00145     root_key = HKEY_CURRENT_USER;
00146   else if ( !strcmp( root, "HKEY_CLASSES_ROOT" ) )
00147     root_key = HKEY_CLASSES_ROOT;
00148   else if ( !strcmp( root, "HKEY_CURRENT_USER" ) )
00149     root_key = HKEY_CURRENT_USER;
00150   else if ( !strcmp( root, "HKEY_LOCAL_MACHINE" ) )
00151     root_key = HKEY_LOCAL_MACHINE;
00152   else if ( !strcmp( root, "HKEY_USERS" ) )
00153     root_key = HKEY_USERS;
00154   else
00155     return NULL;
00156 
00157   if (RegOpenKeyExA (root_key, dir, 0, KEY_READ, &key_handle))
00158     {
00159       if (root)
00160         return NULL; /* no need for a RegClose, so return direct */
00161       /* It seems to be common practise to fall back to HKLM. */
00162       if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle))
00163         return NULL; /* still no need for a RegClose, so return direct */
00164     }
00165 
00166   nbytes = 1;
00167   if (RegQueryValueExA (key_handle, name, 0, NULL, NULL, &nbytes))
00168     {
00169       if (root)
00170         goto out;
00171       /* Try to fallback to HKLM also for a missing value.  */
00172       RegCloseKey (key_handle);
00173       if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle))
00174         return NULL; /* Nope.  */
00175       if (RegQueryValueExA (key_handle, name, 0, NULL, NULL, &nbytes))
00176         goto out;
00177     }
00178   n1 = nbytes + 1;
00179   result = malloc (n1);
00180   if (!result)
00181     goto out;
00182   if (RegQueryValueExA (key_handle, name, 0, &type, result, &n1))
00183     {
00184       free(result);
00185       result = NULL;
00186       goto out;
00187     }
00188   result[nbytes] = 0; /* Make sure it is really a string.  */
00189 
00190  out:
00191   RegCloseKey (key_handle);
00192   return result;
00193 }
00194 
00195 
00196 static char *
00197 find_inst_dir ()
00198 {
00199   return read_w32_registry_string ("HKEY_LOCAL_MACHINE",
00200                                   "Software\\freedesktop\\DBus",
00201                                   "Install Directory");
00202 }
00203 
00204 
00205 static char *
00206 find_env_in_registry (const char *name)
00207 {
00208   return read_w32_registry_string ("HKEY_LOCAL_MACHINE",
00209                                    "Software\\freedesktop\\DBus",
00210                                    name);
00211 }
00212 
00213 
00214 static char *
00215 find_program_in_inst_dir (const char *name)
00216 {
00217   char *result = NULL;
00218   char *tmp;
00219 
00220   tmp = find_inst_dir ();
00221   if (!tmp)
00222     return NULL;
00223 
00224   result = malloc (strlen (tmp) + 5 + strlen (name) + 1);
00225   if (!result)
00226     {
00227       free (tmp);
00228       return NULL;
00229     }
00230 
00231   strcpy (stpcpy (stpcpy (result, tmp), "\\bin\\"), name);
00232   free (tmp);
00233 
00234   return result;
00235 }
00236 
00237 
00238 static char *
00239 find_inst_subdir (const char *name)
00240 {
00241   char *result = NULL;
00242   char *tmp;
00243 
00244   tmp = find_inst_dir ();
00245   if (!tmp)
00246     return NULL;
00247 
00248   result = malloc (strlen (tmp) + 1 + strlen (name) + 1);
00249   if (!result)
00250     {
00251       free (tmp);
00252       return NULL;
00253     }
00254 
00255   strcpy (stpcpy (stpcpy (result, tmp), "\\"), name);
00256   free (tmp);
00257 
00258   return result;
00259 }
00260 
00261 
00262 static char *
00263 find_my_documents_folder ()
00264 {
00265   /* One for safety, just in case.  */
00266   char dir[MAX_PATH + 1];
00267   char *result;
00268 
00269   dir[0] = '\0';
00270   /* May return false even if successful.  */
00271   SHGetSpecialFolderPathA (0, dir, CSIDL_PERSONAL, 0);
00272   if (dir[0] == '\0')
00273     return NULL;
00274 
00275   result = malloc (strlen (dir) + 1);
00276   if (!result)
00277     return NULL;
00278   strcpy (result, dir);
00279   return result;
00280 }
00281 
00282 
00283 #define MAX_ENV 30
00284 
00285 char *environ[MAX_ENV + 1];
00286 
00287 char *
00288 getenv (const char *name)
00289 {
00290   static char *past_result;
00291   char **envp;
00292   int idx;
00293 
00294   if (past_result)
00295     {
00296       free (past_result);
00297       past_result = NULL;
00298     }
00299 
00300   if (! strcmp (name, "DBUS_VERBOSE"))
00301     return past_result = get_verbose_setting ();
00302   else if (! strcmp (name, "HOMEPATH"))
00303     return past_result = find_my_documents_folder ();
00304   else if (! strcmp (name, "DBUS_DATADIR"))
00305     return past_result = find_inst_subdir ("share");
00306 
00307   for (envp = environ; *envp != 0; envp++)
00308     {
00309       const char *varp = name;
00310       char *ep = *envp;
00311       int same_name = 0;
00312 
00313       while (*varp == *ep && *varp != '\0')
00314         {
00315           ++ep;
00316           ++varp;
00317         };
00318 
00319       if (*varp == '\0' && *ep == '=')
00320         return ep + 1;
00321     }
00322 
00323   return NULL;
00324 }
00325 
00326 
00327 int
00328 putenv (char *str)
00329 {
00330   char **envp;
00331   int idx;
00332   for (envp = environ; *envp != 0; envp++)
00333     {
00334       char *varp = str;
00335       char *ep = *envp;
00336       int same_name = 0;
00337 
00338       while (*varp == *ep && *varp != '\0')
00339         {
00340           if (*varp == '=')
00341             same_name = 1;
00342           ++ep;
00343           ++varp;
00344         };
00345 
00346       if (*varp == *ep && *varp == '\0')
00347         return 0;
00348       if (same_name)
00349         {
00350           *envp = str;
00351           return 0;
00352         }
00353     }
00354 
00355   idx = envp - environ;
00356   if (idx > MAX_ENV)
00357     {
00358       _dbus_win_set_errno (ENOMEM);
00359       return -1;
00360     }
00361 
00362   environ[idx] = str;
00363   return 0;
00364 }
00365 
00366 
00367 clock_t
00368 clock (void)
00369 {
00370   return GetTickCount ();
00371 }
00372 
00373 
00374 void
00375 abort (void)
00376 {
00377   /* This is what windows does.  */
00378   exit (3);
00379 }
00380 
00381 
00382 void
00383 GetSystemTimeAsFileTime (LPFILETIME ftp)
00384 {
00385   SYSTEMTIME st;
00386   GetSystemTime (&st);
00387   SystemTimeToFileTime (&st, ftp);
00388 }
00389 
00390 
00391 unsigned char*
00392 _mbsrchr (const unsigned char* str, unsigned int ch)
00393 {
00394   /* FIXME.  This is not multi-byte safe.  */
00395   return strrchr (str, ch);
00396 }
00397 
00398 
00399 HANDLE OpenFileMappingA(DWORD dwDesiredAccess,
00400                         BOOL bInheritHandle,
00401                         LPCSTR lpName)
00402 {
00403   DWORD flProtect = 0;
00404   HANDLE hMapping;
00405 
00406   if (dwDesiredAccess & FILE_MAP_READ)
00407     flProtect |= PAGE_READONLY;
00408 
00409   if (dwDesiredAccess & FILE_MAP_WRITE)
00410     flProtect |= PAGE_READWRITE;
00411 
00412   SetLastError (0);
00413   hMapping = CreateFileMappingA(INVALID_HANDLE_VALUE,
00414                                 NULL, flProtect, 0, 0, lpName);
00415   if (hMapping != INVALID_HANDLE_VALUE)
00416     {
00417       /* Just in case Windows CE changes its behaviour, we check for
00418          the right error value here.  */
00419       if (GetLastError () != ERROR_ALREADY_EXISTS)
00420         {
00421           CloseHandle(hMapping);
00422           hMapping = INVALID_HANDLE_VALUE;
00423         }
00424     }
00425   return hMapping;
00426 }
00427 
00428 
00429 BOOL
00430 MoveFileExA (LPCSTR lpExistingFileName, LPCSTR lpNewFileName, DWORD dwFlags)
00431 {
00432   _dbus_assert (dwFlags == MOVEFILE_REPLACE_EXISTING);
00433 
00434   if (_dbus_file_exists (lpNewFileName))
00435     {
00436       BOOL result = DeleteFileA (lpNewFileName);
00437       if (result == 0)
00438         return FALSE;
00439     }
00440   return MoveFileA (lpExistingFileName, lpNewFileName);
00441 }
00442 
00443 
00444 BOOL
00445 SetHandleInformation (HANDLE hObject, DWORD dwMask, DWORD dwFlags)
00446 {
00447   _dbus_assert (dwMask == (HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE));
00448   _dbus_assert (dwFlags == 0);
00449 
00450   /* Not supported on Windows CE, and actually the default.  So just
00451      return overwhelming success.  */
00452   return 1;
00453 }
00454 
00455 
00456 DWORD
00457 SearchPathA (LPCSTR lpPath, LPCSTR lpFileName, LPCSTR lpExtension,
00458              DWORD nBufferLength, LPSTR lpBuffer, LPSTR* lpFilePart)
00459 {
00460   char *filename;
00461   char *filepart;
00462   int filename_len;
00463   
00464   _dbus_assert (lpPath == NULL);
00465   _dbus_assert (lpExtension == NULL);
00466   
00467   filename = find_program_in_inst_dir (lpFileName);
00468   if (!filename)
00469     {
00470       SetLastError (ERROR_FILE_NOT_FOUND);
00471       return 0;
00472     }
00473 
00474   filename_len = strlen (filename) + 1;
00475   if (filename_len > nBufferLength)
00476     {
00477       free (filename);
00478       return filename_len;
00479     }
00480 
00481   strcpy (lpBuffer, filename);
00482   free (filename);
00483 
00484   filepart = _mbsrchr (lpBuffer, '\\');
00485   if (!filepart)
00486     filepart = lpBuffer;
00487   *lpFilePart = filepart;
00488 
00489   return filename_len - 1;
00490 }
00491 
00492 
00497 dbus_bool_t
00498 _dbus_getsid(char **sid)
00499 {
00500   /* There is nothing like this on Windows CE, so we fake it.  */
00501   static const char asid[] = "S-1-5-21-515967899-920026266-1708537768-1000";
00502   char *buf = LocalAlloc (LMEM_FIXED, sizeof (asid));
00503   if (!buf)
00504     {
00505       _dbus_win_warn_win_error ("LocalAlloc failed", GetLastError ());
00506       return FALSE;
00507     }
00508 
00509   memcpy (buf, asid, sizeof (asid));
00510   *sid = buf;
00511   return TRUE;
00512 }
00513 
00514 
00515 BOOL
00516 LookupAccountNameW (LPCWSTR lpSystemName, LPCWSTR lpAccountName, PSID Sid, PDWORD cbSid,
00517                     LPWSTR ReferencedDomainName, PDWORD cchReferencedDomainName, PSID_NAME_USE peUse)
00518 {
00519   /* Currently not needed.  */
00520   return FALSE;
00521 }
00522 
00523 
00524 BOOL
00525 IsValidSid (PSID psid)
00526 {
00527   /* Currently not needed.  */
00528   return FALSE;
00529 }
00530 
00531 
00532 HANDLE
00533 CreateFileA (LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwSharedMode,
00534              LPSECURITY_ATTRIBUTES lpSecurityAttributes,
00535              DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
00536              HANDLE hTemplateFile)
00537 {
00538   wchar_t *filename;
00539   HANDLE result;
00540   int err;
00541 
00542   filename = _dbus_win_utf8_to_utf16 (lpFileName, NULL);
00543   if (!filename)
00544     return INVALID_HANDLE_VALUE;
00545 
00546   result = CreateFileW (filename, dwDesiredAccess, dwSharedMode,
00547                         lpSecurityAttributes, dwCreationDisposition,
00548                         dwFlagsAndAttributes, hTemplateFile);
00549 
00550   err = GetLastError ();
00551   dbus_free (filename);
00552   SetLastError (err);
00553   return result;
00554 }
00555 
00556 
00557 BOOL
00558 DeleteFileA (LPCSTR lpFileName)
00559 {
00560   wchar_t *filename;
00561   BOOL result;
00562   int err;
00563 
00564   filename = _dbus_win_utf8_to_utf16 (lpFileName, NULL);
00565   if (!filename)
00566     return FALSE;
00567 
00568   result = DeleteFileW (filename);
00569 
00570   err = GetLastError ();
00571   dbus_free (filename);
00572   SetLastError (err);
00573   return result;
00574 }
00575 
00576 
00577 BOOL
00578 MoveFileA (LPCSTR lpExistingFileName, LPCSTR lpNewFileName)
00579 {
00580   wchar_t *existing_filename;
00581   wchar_t *new_filename;
00582   BOOL result;
00583   int err;
00584 
00585   existing_filename = _dbus_win_utf8_to_utf16 (lpExistingFileName, NULL);
00586   if (! existing_filename)
00587     return FALSE;
00588 
00589   new_filename = _dbus_win_utf8_to_utf16 (lpNewFileName, NULL);
00590   if (! new_filename)
00591     {
00592       dbus_free (existing_filename);
00593       return FALSE;
00594     }
00595 
00596   result = MoveFileW (existing_filename, new_filename);
00597 
00598   err = GetLastError ();
00599   dbus_free (existing_filename);
00600   dbus_free (new_filename);
00601   SetLastError (err);
00602   return result;
00603 }
00604 
00605 
00606 DWORD
00607 GetFileAttributesA(LPCSTR lpFileName)
00608 {
00609   wchar_t *filename;
00610   DWORD result;
00611   int err;
00612 
00613   filename = _dbus_win_utf8_to_utf16 (lpFileName, NULL);
00614   if (!filename)
00615     return INVALID_FILE_ATTRIBUTES;
00616 
00617   result = GetFileAttributesW (filename);
00618 
00619   err = GetLastError ();
00620   dbus_free (filename);
00621   SetLastError (err);
00622   return result;
00623 }
00624 
00625 
00626 BOOL
00627 GetFileAttributesExA (LPCSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
00628                       PVOID lpFileInformation)
00629 {
00630   wchar_t *filename;
00631   DWORD result;
00632   int err;
00633 
00634   filename = _dbus_win_utf8_to_utf16 (lpFileName, NULL);
00635   if (!filename)
00636     return INVALID_FILE_ATTRIBUTES;
00637 
00638   result = GetFileAttributesExW (filename, fInfoLevelId, lpFileInformation);
00639 
00640   err = GetLastError ();
00641   dbus_free (filename);
00642   SetLastError (err);
00643   return result;
00644 }
00645 
00646 
00647 HANDLE
00648 CreateFileMappingA (HANDLE hFile, LPSECURITY_ATTRIBUTES lpAttributes,
00649                     DWORD flProtect, DWORD dwMaximumSizeHigh,
00650                     DWORD dwMaximumSizeLow, LPCSTR lpName)
00651 {
00652   wchar_t *name;
00653   HANDLE result;
00654   int err;
00655 
00656   if (lpName)
00657     {
00658       name = _dbus_win_utf8_to_utf16 (lpName, NULL);
00659       if (!name)
00660         return INVALID_HANDLE_VALUE;
00661     }
00662   else
00663     name = NULL;
00664 
00665   result = CreateFileMappingW (hFile, lpAttributes, flProtect,
00666                                dwMaximumSizeHigh, dwMaximumSizeLow,
00667                                name);
00668 
00669   err = GetLastError ();
00670   dbus_free (name);
00671   SetLastError (err);
00672   return result;
00673 }
00674 
00675 
00676 BOOL
00677 CreateDirectoryA (LPCSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
00678 {
00679   wchar_t *pathname;
00680   BOOL result;
00681   int err;
00682 
00683   pathname = _dbus_win_utf8_to_utf16 (lpPathName, NULL);
00684   if (!pathname)
00685     return FALSE;
00686 
00687   result = CreateDirectoryW (pathname, lpSecurityAttributes);
00688 
00689   err = GetLastError ();
00690   dbus_free (pathname);
00691   SetLastError (err);
00692   return result;
00693 }
00694 
00695 
00696 BOOL
00697 RemoveDirectoryA (LPCSTR lpPathName)
00698 {
00699   wchar_t *pathname;
00700   BOOL result;
00701   int err;
00702 
00703   pathname = _dbus_win_utf8_to_utf16 (lpPathName, NULL);
00704   if (!pathname)
00705     return FALSE;
00706 
00707   result = RemoveDirectoryW (pathname);
00708 
00709   err = GetLastError ();
00710   dbus_free (pathname);
00711   SetLastError (err);
00712   return result;
00713 }
00714 
00715 
00716 static BOOL
00717 convert_find_data (LPWIN32_FIND_DATAW fdw, LPWIN32_FIND_DATAA fda)
00718 {
00719   char *filename;
00720   int len;
00721 
00722   fda->dwFileAttributes = fdw->dwFileAttributes;
00723   fda->ftCreationTime = fdw->ftCreationTime;
00724   fda->ftLastAccessTime = fdw->ftLastAccessTime;
00725   fda->ftLastWriteTime = fdw->ftLastWriteTime;
00726   fda->nFileSizeHigh = fdw->nFileSizeHigh;
00727   fda->nFileSizeLow = fdw->nFileSizeLow;
00728 
00729   filename = _dbus_win_utf16_to_utf8 (fdw->cFileName, NULL);
00730   if (!filename)
00731     return FALSE;
00732 
00733   len = sizeof (fda->cFileName);
00734   strncpy (fda->cFileName, filename, len);
00735   fda->cFileName[len - 1] = '\0';
00736   
00737   return TRUE;
00738 }
00739 
00740 
00741 HANDLE
00742 FindFirstFileA (LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData)
00743 {
00744   wchar_t *pathname;
00745   WIN32_FIND_DATAW find_file_data;
00746   HANDLE result;
00747   int err;
00748 
00749   pathname = _dbus_win_utf8_to_utf16 (lpFileName, NULL);
00750   if (!pathname)
00751     return INVALID_HANDLE_VALUE;
00752 
00753   result = FindFirstFileW (pathname, &find_file_data);
00754   if (result != INVALID_HANDLE_VALUE)
00755     {
00756       BOOL res = convert_find_data (&find_file_data, lpFindFileData);
00757       if (! res)
00758         {
00759           err = GetLastError ();
00760           FindClose (result);
00761           SetLastError (err);
00762           result = INVALID_HANDLE_VALUE;
00763         }
00764     }
00765 
00766   err = GetLastError ();
00767   dbus_free (pathname);
00768   SetLastError (err);
00769   return result;
00770 }
00771 
00772 
00773 BOOL
00774 FindNextFileA (HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData)
00775 {
00776   WIN32_FIND_DATAW find_file_data;
00777   BOOL result;
00778   int err;
00779 
00780   result = FindNextFileW (hFindFile, &find_file_data);
00781   if (result)
00782     result = convert_find_data (&find_file_data, lpFindFileData);
00783 
00784   return result;  
00785 }
00786 
00787 
00788 HANDLE
00789 CreateMutexA (LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner,
00790               LPCSTR lpName)
00791 {
00792   wchar_t *name;
00793   HANDLE result;
00794   int err;
00795 
00796   if (lpName)
00797     {
00798       name = _dbus_win_utf8_to_utf16 (lpName, NULL);
00799       if (!name)
00800         return INVALID_HANDLE_VALUE;
00801     }
00802   else
00803     name = NULL;
00804 
00805   result = CreateMutexW (lpMutexAttributes, bInitialOwner, name);
00806 
00807   err = GetLastError ();
00808   dbus_free (name);
00809   SetLastError (err);
00810   return result;
00811 }
00812 
00813 
00814 BOOL
00815 CreateProcessA (LPCSTR pszImageName, LPSTR pszCmdLine,
00816                 LPSECURITY_ATTRIBUTES psaProcess,
00817                 LPSECURITY_ATTRIBUTES psaThread, BOOL fInheritHandles,
00818                 DWORD fdwCreate, PVOID pvEnvironment, LPCSTR pszCurDir,
00819                 LPSTARTUPINFOA psiStartInfo,
00820                 LPPROCESS_INFORMATION pProcInfo)
00821 {
00822   wchar_t *image_name = NULL;
00823   wchar_t *cmd_line = NULL;
00824   BOOL result;
00825   int err;
00826 
00827   _dbus_assert (psaProcess == NULL);
00828   _dbus_assert (psaThread == NULL);
00829   _dbus_assert (fInheritHandles == FALSE);
00830   _dbus_assert (pvEnvironment == NULL);
00831   _dbus_assert (pszCurDir == NULL);
00832   /* psiStartInfo is generally not NULL.  */
00833 
00834   if (pszImageName)
00835     {
00836       image_name = _dbus_win_utf8_to_utf16 (pszImageName, NULL);
00837       if (!image_name)
00838         return 0;
00839     }
00840   if (pszCmdLine)
00841     {
00842       cmd_line = _dbus_win_utf8_to_utf16 (pszCmdLine, NULL);
00843       if (!cmd_line)
00844         {
00845           if (image_name)
00846             dbus_free (image_name);
00847           return 0;
00848         }
00849     }
00850 
00851   result = CreateProcessW (image_name, cmd_line, NULL, NULL, FALSE,
00852                            fdwCreate, NULL, NULL, NULL, pProcInfo);
00853 
00854   err = GetLastError ();
00855   dbus_free (image_name);
00856   dbus_free (cmd_line);
00857   SetLastError (err);
00858   return result;
00859 }
00860 
00861 
00862 LONG
00863 RegOpenKeyExA (HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions,
00864                REGSAM samDesired, PHKEY phkResult)
00865 {
00866   wchar_t *subkey;
00867   LONG result;
00868   int err;
00869 
00870   if (lpSubKey)
00871     {
00872       subkey = _dbus_win_utf8_to_utf16 (lpSubKey, NULL);
00873       if (!subkey)
00874         return 0;
00875     }
00876   else
00877     subkey = NULL;
00878 
00879   result = RegOpenKeyEx (hKey, subkey, ulOptions, samDesired, phkResult);
00880 
00881   err = GetLastError ();
00882   dbus_free (subkey);
00883   SetLastError (err);
00884   return result;
00885 }
00886 
00887 
00888 LONG
00889 RegQueryValueExA (HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved,
00890                   LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
00891 {
00892   wchar_t *name;
00893   LONG err;
00894   BYTE *data;
00895   DWORD data_len;
00896   DWORD type;
00897 
00898   if (lpValueName)
00899     {
00900       name = _dbus_win_utf8_to_utf16 (lpValueName, NULL);
00901       if (!name)
00902         return GetLastError ();
00903     }
00904   else
00905     name = NULL;
00906 
00907   data_len = 0;
00908   err = RegQueryValueExW (hKey, name, lpReserved, lpType, NULL, &data_len);
00909   if (err || !lpcbData)
00910     {
00911       dbus_free (name);
00912       return err;
00913     }
00914 
00915   data = malloc (data_len + sizeof (wchar_t));
00916   if (!data)
00917     {
00918       dbus_free (name);
00919       return ERROR_NOT_ENOUGH_MEMORY;
00920     }
00921   
00922   err = RegQueryValueExW (hKey, name, lpReserved, &type, data, &data_len);
00923   if (lpType)
00924     *lpType = type;
00925   dbus_free (name);
00926   /* If err is ERROR_MORE_DATA, there probably was a race condition.
00927      We can punt this to the caller just as well.  */
00928   if (err)
00929     {
00930       free (data);
00931       return err;
00932     }
00933 
00934   /* NOTE: REG_MULTI_SZ and REG_EXPAND_SZ not supported, because they
00935      are not needed in this module.  */
00936   if (type == REG_SZ)
00937     {
00938       char *data_c;
00939       int data_c_len;
00940 
00941       /* This is valid since we allocated one more above.  */
00942       data[data_len] = '\0';
00943       data[data_len + 1] = '\0';
00944 
00945       /* The cast is valid because malloc guarantees alignment of
00946          basic types.  */
00947       data_c = _dbus_win_utf16_to_utf8 ((wchar_t*) data, NULL);
00948       if (!data_c)
00949         {
00950           free (data);
00951           return GetLastError();
00952         }
00953 
00954       data_c_len = strlen (data_c) + 1;
00955       _dbus_assert (data_c_len <= data_len + sizeof (wchar_t));
00956       memcpy (data, data_c, data_c_len);
00957       data_len = data_c_len;
00958       dbus_free (data_c);
00959     }
00960 
00961   /* DATA and DATA_LEN now contain the result.  */
00962   if (lpData)
00963     {
00964       if (data_len > *lpcbData)
00965         err = ERROR_MORE_DATA;
00966       else
00967         memcpy (lpData, data, data_len);
00968     }
00969   free (data);
00970   *lpcbData = data_len;
00971   return err;
00972 }
00973 
00974 
00975 DWORD
00976 FormatMessageA (DWORD dwFlags, PCVOID lpSource, DWORD dwMessageId,
00977                 DWORD dwLanguageId, LPSTR lpBuffer, DWORD nSize,
00978                 va_list* Arguments)
00979 {
00980   LPWSTR buffer_w = NULL;
00981   LPSTR buffer_c;
00982   DWORD len;
00983   char *buffer_new;
00984   DWORD buffer_new_len;
00985   BOOL buffer_w_free;
00986 
00987   len = FormatMessageW (dwFlags | FORMAT_MESSAGE_ALLOCATE_BUFFER,
00988                         lpSource, dwMessageId, dwLanguageId,
00989                         (LPWSTR) &buffer_w, 0, Arguments);
00990   if (len == 0)
00991     return 0;
00992 
00993   buffer_c = _dbus_win_utf16_to_utf8 (buffer_w, NULL);
00994   if (! buffer_c)
00995     {
00996       LocalFree (buffer_w);
00997       return 0;
00998     }
00999 
01000   if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER)
01001     {
01002       /* We need to return a buffer that's freeable with LocalFree.  */
01003       buffer_new = (char *) buffer_w;
01004       buffer_new_len = sizeof (wchar_t) * (len + 1);
01005       buffer_w_free = FALSE;
01006       /* Avoid alignment issue by using memcpy.  */
01007       memcpy (lpBuffer, &buffer_new, sizeof (buffer_new));
01008     }
01009   else
01010     {
01011       buffer_new = lpBuffer;
01012       buffer_new_len = nSize;
01013       buffer_w_free = TRUE;
01014     }
01015 
01016   strncpy (buffer_new, buffer_c, buffer_new_len);
01017   dbus_free (buffer_c);
01018   buffer_new[buffer_new_len - 1] = '\0';
01019   if (buffer_w_free)
01020     LocalFree (buffer_w);
01021 
01022   /* strlen is correct (not _mbstrlen), because we want storage and
01023      not string length.  */
01024   return strlen (buffer_new);
01025 }
01026 
01027 
01028 DWORD
01029 GetModuleFileNameA (HINSTANCE hModule, LPSTR lpFilename, DWORD nSize)
01030 {
01031   wchar_t *filename_w;
01032   char *filename_c;
01033   DWORD len;
01034 
01035   if (nSize == 0)
01036     {
01037       /* Windows XP/2000.  */
01038       SetLastError (0);
01039       return 0;
01040     }
01041 
01042   filename_w = malloc (sizeof (wchar_t) * nSize);
01043   if (! filename_w)
01044     return 0;
01045 
01046   len = GetModuleFileNameW (hModule, filename_w, nSize);
01047   if (len == 0)
01048     {
01049       /* Note: If we fail with ERROR_INSUFFICIENT_BUFFER, this is still
01050        (approximately) correct.  */
01051       free (filename_w);
01052       return 0;
01053     }
01054 
01055   filename_w[nSize - 1] = '\0';
01056   filename_c = _dbus_win_utf16_to_utf8 (filename_w, NULL);
01057   free (filename_w);
01058   if (! filename_c)
01059     return 0;
01060 
01061   strncpy (lpFilename, filename_c, nSize);
01062   dbus_free (filename_c);
01063   lpFilename[nSize - 1] = '\0';
01064   /* strlen is correct (not _mbstrlen), because we want storage and
01065      not string length.  */
01066   return strlen (lpFilename);
01067 }
01068 
01069 
01070 DWORD
01071 GetTempPathA (DWORD nBufferLength, LPSTR lpBuffer)
01072 {
01073   wchar_t dummy[1];
01074   DWORD len;
01075 
01076   len = GetTempPathW (0, dummy);
01077   if (len == 0)
01078     return 0;
01079 
01080   _dbus_assert (len <= MAX_PATH);
01081 
01082   /* Better be safe than sorry.  MSDN doesn't say if len is with or
01083      without terminating 0.  */
01084   len++;
01085 
01086   {
01087     wchar_t *buffer_w;
01088     DWORD len_w;
01089     char *buffer_c;
01090     DWORD len_c;
01091 
01092     buffer_w = malloc (sizeof (wchar_t) * len);
01093     if (! buffer_w)
01094       return 0;
01095 
01096     len_w = GetTempPathW (len, buffer_w);
01097     /* Give up if we still can't get at it.  */
01098     if (len_w == 0 || len_w >= len)
01099       {
01100         free (buffer_w);
01101         return 0;
01102       }
01103 
01104     /* Better be really safe.  */
01105     buffer_w[len_w] = '\0';
01106 
01107     buffer_c = _dbus_win_utf16_to_utf8 (buffer_w, NULL);
01108     free (buffer_w);
01109     if (! buffer_c)
01110       return 0;
01111 
01112     /* strlen is correct (not _mbstrlen), because we want storage and
01113        not string length.  */
01114     len_c = strlen (buffer_c) + 1;
01115     if (len_c > nBufferLength)
01116       return len_c;
01117 
01118     strcpy (lpBuffer, buffer_c);
01119     dbus_free (buffer_c);
01120     return len_c - 1;
01121   }
01122 }
01123 
01124 
01125 BOOL
01126 SHGetSpecialFolderPathA (HWND hwndOwner, LPSTR lpszPath, int nFolder,
01127                          BOOL fCreate)
01128 {
01129   wchar_t path[MAX_PATH];
01130   char *path_c;
01131   BOOL result;
01132 
01133   path[0] = (wchar_t) 0;
01134   result = SHGetSpecialFolderPathW (hwndOwner, path, nFolder, fCreate);
01135   /* Note: May return false even if succeeds.  */
01136 
01137   path[MAX_PATH - 1] = (wchar_t) 0;
01138   path_c = _dbus_win_utf16_to_utf8 (path, NULL);
01139   if (! path_c)
01140     return 0;
01141   
01142   strncpy (lpszPath, path_c, MAX_PATH);
01143   dbus_free (path_c);
01144   lpszPath[MAX_PATH - 1] = '\0';
01145   return result;
01146 }
01147 
01148 
01149 void
01150 OutputDebugStringA (LPCSTR lpOutputString)
01151 {
01152   wchar_t *str;
01153   HANDLE result;
01154   int err;
01155 
01156   str = _dbus_win_utf8_to_utf16 (lpOutputString, NULL);
01157   if (!str)
01158     return;
01159 
01160   OutputDebugStringW (str);
01161 
01162   err = GetLastError ();
01163   dbus_free (str);
01164   SetLastError (err);
01165 }