• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)
3  *
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>
10  *
11  * Licensed under the Academic Free License version 2.1
12  *
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.
17  *
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.
22  *
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
26  *
27  */
28 
29 #include <config.h>
30 #include "dbus-internals.h"
31 #include "dbus-sysdeps.h"
32 #include "dbus-sysdeps-win.h"
33 
34 #include <windows.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
39 #endif
40 
41 
42 /* Copy SRC to DEST, returning the address of the terminating '\0' in DEST.  */
43 static char *
stpcpy(char * dest,const char * src)44 stpcpy (char *dest, const char *src)
45 {
46   char *d = dest;
47   const char *s = src;
48 
49   do
50     *d++ = *s;
51   while (*s++ != '\0');
52 
53   return d - 1;
54 }
55 
56 
57 /* This is special cased, because we must avoid using many dbus
58    functions (such as memory allocations): Those functions may in turn
59    cause verbose output and check the flag!  */
60 static char *
get_verbose_setting()61 get_verbose_setting()
62 {
63   const wchar_t dir[] = L"Software\\freedesktop\\DBus";
64   const wchar_t name[] = L"Verbose";
65   HKEY root_key;
66   HKEY key_handle;
67   DWORD nbytes;
68   DWORD n1;
69   DWORD type;
70   wchar_t *result_w = NULL;
71   char *result;
72   int len;
73 
74   root_key = HKEY_LOCAL_MACHINE;
75   if (RegOpenKeyExW (root_key, dir, 0, KEY_READ, &key_handle))
76     return NULL;
77 
78   nbytes = 1;
79   if (RegQueryValueExW (key_handle, name, 0, NULL, NULL, &nbytes))
80     {
81       RegCloseKey (key_handle);
82       return NULL;
83     }
84   /* Round up to multiple of wchar_t, convert to number of wchar_t's, and add 1.  */
85   n1 = ((nbytes + sizeof(wchar_t) - 1) / sizeof (wchar_t)) + 1;
86   result_w = malloc (n1 * sizeof (wchar_t));
87   if (!result_w)
88     {
89       RegCloseKey (key_handle);
90       return NULL;
91     }
92   if (RegQueryValueExW (key_handle, name, 0, &type, (LPBYTE) result_w, &nbytes))
93     {
94       RegCloseKey (key_handle);
95       free (result_w);
96       return NULL;
97     }
98   RegCloseKey (key_handle);
99   result_w[n1 - 1] = 0; /* Make sure it is really a string.  */
100 
101   /* NOTE: REG_MULTI_SZ and REG_EXPAND_SZ not supported, because they
102      are not needed in this module.  */
103   if (type != REG_SZ)
104     {
105       free (result_w);
106       return NULL;
107     }
108 
109   len = WideCharToMultiByte (CP_UTF8, 0, result_w, -1, NULL, 0, NULL, NULL);
110   if (len < 0)
111     {
112       free (result_w);
113       return NULL;
114     }
115 
116   result = malloc (len + 1);
117   if (!result)
118     {
119       free (result_w);
120       return NULL;
121     }
122 
123   len = WideCharToMultiByte (CP_UTF8, 0, result_w, -1, result, len, NULL, NULL);
124   free (result_w);
125   if (len < 0)
126     {
127       free (result);
128       return NULL;
129     }
130   return result;
131 }
132 
133 
134 /* Return a string from the W32 Registry or NULL in case of error.
135    Caller must release the return value.  A NULL for root is an alias
136    for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn. */
137 static char *
read_w32_registry_string(const char * root,const char * dir,const char * name)138 read_w32_registry_string (const char *root, const char *dir, const char *name)
139 {
140   HKEY root_key, key_handle;
141   DWORD n1, nbytes, type;
142   char *result = NULL;
143 
144   if ( !root )
145     root_key = HKEY_CURRENT_USER;
146   else if ( !strcmp( root, "HKEY_CLASSES_ROOT" ) )
147     root_key = HKEY_CLASSES_ROOT;
148   else if ( !strcmp( root, "HKEY_CURRENT_USER" ) )
149     root_key = HKEY_CURRENT_USER;
150   else if ( !strcmp( root, "HKEY_LOCAL_MACHINE" ) )
151     root_key = HKEY_LOCAL_MACHINE;
152   else if ( !strcmp( root, "HKEY_USERS" ) )
153     root_key = HKEY_USERS;
154   else
155     return NULL;
156 
157   if (RegOpenKeyExA (root_key, dir, 0, KEY_READ, &key_handle))
158     {
159       if (root)
160         return NULL; /* no need for a RegClose, so return direct */
161       /* It seems to be common practise to fall back to HKLM. */
162       if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle))
163         return NULL; /* still no need for a RegClose, so return direct */
164     }
165 
166   nbytes = 1;
167   if (RegQueryValueExA (key_handle, name, 0, NULL, NULL, &nbytes))
168     {
169       if (root)
170         goto out;
171       /* Try to fallback to HKLM also for a missing value.  */
172       RegCloseKey (key_handle);
173       if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle))
174         return NULL; /* Nope.  */
175       if (RegQueryValueExA (key_handle, name, 0, NULL, NULL, &nbytes))
176         goto out;
177     }
178   n1 = nbytes + 1;
179   result = malloc (n1);
180   if (!result)
181     goto out;
182   if (RegQueryValueExA (key_handle, name, 0, &type, result, &n1))
183     {
184       free(result);
185       result = NULL;
186       goto out;
187     }
188   result[nbytes] = 0; /* Make sure it is really a string.  */
189 
190  out:
191   RegCloseKey (key_handle);
192   return result;
193 }
194 
195 
196 static char *
find_inst_dir()197 find_inst_dir ()
198 {
199   return read_w32_registry_string ("HKEY_LOCAL_MACHINE",
200 				  "Software\\freedesktop\\DBus",
201 				  "Install Directory");
202 }
203 
204 
205 static char *
find_env_in_registry(const char * name)206 find_env_in_registry (const char *name)
207 {
208   return read_w32_registry_string ("HKEY_LOCAL_MACHINE",
209                                    "Software\\freedesktop\\DBus",
210                                    name);
211 }
212 
213 
214 static char *
find_program_in_inst_dir(const char * name)215 find_program_in_inst_dir (const char *name)
216 {
217   char *result = NULL;
218   char *tmp;
219 
220   tmp = find_inst_dir ();
221   if (!tmp)
222     return NULL;
223 
224   result = malloc (strlen (tmp) + 5 + strlen (name) + 1);
225   if (!result)
226     {
227       free (tmp);
228       return NULL;
229     }
230 
231   strcpy (stpcpy (stpcpy (result, tmp), "\\bin\\"), name);
232   free (tmp);
233 
234   return result;
235 }
236 
237 
238 static char *
find_inst_subdir(const char * name)239 find_inst_subdir (const char *name)
240 {
241   char *result = NULL;
242   char *tmp;
243 
244   tmp = find_inst_dir ();
245   if (!tmp)
246     return NULL;
247 
248   result = malloc (strlen (tmp) + 1 + strlen (name) + 1);
249   if (!result)
250     {
251       free (tmp);
252       return NULL;
253     }
254 
255   strcpy (stpcpy (stpcpy (result, tmp), "\\"), name);
256   free (tmp);
257 
258   return result;
259 }
260 
261 
262 static char *
find_my_documents_folder()263 find_my_documents_folder ()
264 {
265   /* One for safety, just in case.  */
266   char dir[MAX_PATH + 1];
267   char *result;
268 
269   dir[0] = '\0';
270   /* May return false even if successful.  */
271   SHGetSpecialFolderPathA (0, dir, CSIDL_PERSONAL, 0);
272   if (dir[0] == '\0')
273     return NULL;
274 
275   result = malloc (strlen (dir) + 1);
276   if (!result)
277     return NULL;
278   strcpy (result, dir);
279   return result;
280 }
281 
282 
283 #define MAX_ENV 30
284 
285 char *environ[MAX_ENV + 1];
286 
287 char *
getenv(const char * name)288 getenv (const char *name)
289 {
290   static char *past_result;
291   char **envp;
292   int idx;
293 
294   if (past_result)
295     {
296       free (past_result);
297       past_result = NULL;
298     }
299 
300   if (! strcmp (name, "DBUS_VERBOSE"))
301     return past_result = get_verbose_setting ();
302   else if (! strcmp (name, "HOMEPATH"))
303     return past_result = find_my_documents_folder ();
304   else if (! strcmp (name, "DBUS_DATADIR"))
305     return past_result = find_inst_subdir ("share");
306 
307   for (envp = environ; *envp != 0; envp++)
308     {
309       const char *varp = name;
310       char *ep = *envp;
311       int same_name = 0;
312 
313       while (*varp == *ep && *varp != '\0')
314 	{
315 	  ++ep;
316 	  ++varp;
317 	};
318 
319       if (*varp == '\0' && *ep == '=')
320 	return ep + 1;
321     }
322 
323   return NULL;
324 }
325 
326 
327 int
putenv(char * str)328 putenv (char *str)
329 {
330   char **envp;
331   int idx;
332   for (envp = environ; *envp != 0; envp++)
333     {
334       char *varp = str;
335       char *ep = *envp;
336       int same_name = 0;
337 
338       while (*varp == *ep && *varp != '\0')
339 	{
340 	  if (*varp == '=')
341 	    same_name = 1;
342 	  ++ep;
343 	  ++varp;
344 	};
345 
346       if (*varp == *ep && *varp == '\0')
347 	return 0;
348       if (same_name)
349 	{
350 	  *envp = str;
351 	  return 0;
352 	}
353     }
354 
355   idx = envp - environ;
356   if (idx > MAX_ENV)
357     {
358       _dbus_win_set_errno (ENOMEM);
359       return -1;
360     }
361 
362   environ[idx] = str;
363   return 0;
364 }
365 
366 
367 clock_t
clock(void)368 clock (void)
369 {
370   return GetTickCount ();
371 }
372 
373 
374 void
abort(void)375 abort (void)
376 {
377   /* This is what windows does.  */
378   exit (3);
379 }
380 
381 
382 void
GetSystemTimeAsFileTime(LPFILETIME ftp)383 GetSystemTimeAsFileTime (LPFILETIME ftp)
384 {
385   SYSTEMTIME st;
386   GetSystemTime (&st);
387   SystemTimeToFileTime (&st, ftp);
388 }
389 
390 
391 unsigned char*
_mbsrchr(const unsigned char * str,unsigned int ch)392 _mbsrchr (const unsigned char* str, unsigned int ch)
393 {
394   /* FIXME.  This is not multi-byte safe.  */
395   return strrchr (str, ch);
396 }
397 
398 
OpenFileMappingA(DWORD dwDesiredAccess,BOOL bInheritHandle,LPCSTR lpName)399 HANDLE OpenFileMappingA(DWORD dwDesiredAccess,
400 			BOOL bInheritHandle,
401 			LPCSTR lpName)
402 {
403   DWORD flProtect = 0;
404   HANDLE hMapping;
405 
406   if (dwDesiredAccess & FILE_MAP_READ)
407     flProtect |= PAGE_READONLY;
408 
409   if (dwDesiredAccess & FILE_MAP_WRITE)
410     flProtect |= PAGE_READWRITE;
411 
412   SetLastError (0);
413   hMapping = CreateFileMappingA(INVALID_HANDLE_VALUE,
414 				NULL, flProtect, 0, 0, lpName);
415   if (hMapping != INVALID_HANDLE_VALUE)
416     {
417       /* Just in case Windows CE changes its behaviour, we check for
418          the right error value here.  */
419       if (GetLastError () != ERROR_ALREADY_EXISTS)
420         {
421           CloseHandle(hMapping);
422           hMapping = INVALID_HANDLE_VALUE;
423         }
424     }
425   return hMapping;
426 }
427 
428 
429 BOOL
MoveFileExA(LPCSTR lpExistingFileName,LPCSTR lpNewFileName,DWORD dwFlags)430 MoveFileExA (LPCSTR lpExistingFileName, LPCSTR lpNewFileName, DWORD dwFlags)
431 {
432   _dbus_assert (dwFlags == MOVEFILE_REPLACE_EXISTING);
433 
434   if (_dbus_file_exists (lpNewFileName))
435     {
436       BOOL result = DeleteFileA (lpNewFileName);
437       if (result == 0)
438 	return FALSE;
439     }
440   return MoveFileA (lpExistingFileName, lpNewFileName);
441 }
442 
443 
444 BOOL
SetHandleInformation(HANDLE hObject,DWORD dwMask,DWORD dwFlags)445 SetHandleInformation (HANDLE hObject, DWORD dwMask, DWORD dwFlags)
446 {
447   _dbus_assert (dwMask == (HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE));
448   _dbus_assert (dwFlags == 0);
449 
450   /* Not supported on Windows CE, and actually the default.  So just
451      return overwhelming success.  */
452   return 1;
453 }
454 
455 
456 DWORD
SearchPathA(LPCSTR lpPath,LPCSTR lpFileName,LPCSTR lpExtension,DWORD nBufferLength,LPSTR lpBuffer,LPSTR * lpFilePart)457 SearchPathA (LPCSTR lpPath, LPCSTR lpFileName, LPCSTR lpExtension,
458              DWORD nBufferLength, LPSTR lpBuffer, LPSTR* lpFilePart)
459 {
460   char *filename;
461   char *filepart;
462   int filename_len;
463 
464   _dbus_assert (lpPath == NULL);
465   _dbus_assert (lpExtension == NULL);
466 
467   filename = find_program_in_inst_dir (lpFileName);
468   if (!filename)
469     {
470       SetLastError (ERROR_FILE_NOT_FOUND);
471       return 0;
472     }
473 
474   filename_len = strlen (filename) + 1;
475   if (filename_len > nBufferLength)
476     {
477       free (filename);
478       return filename_len;
479     }
480 
481   strcpy (lpBuffer, filename);
482   free (filename);
483 
484   filepart = _mbsrchr (lpBuffer, '\\');
485   if (!filepart)
486     filepart = lpBuffer;
487   *lpFilePart = filepart;
488 
489   return filename_len - 1;
490 }
491 
492 
493 /** Gets our SID
494  * @param points to sid buffer, need to be freed with LocalFree()
495  * @returns process sid
496  */
497 dbus_bool_t
_dbus_getsid(char ** sid)498 _dbus_getsid(char **sid)
499 {
500   /* There is nothing like this on Windows CE, so we fake it.  */
501   static const char asid[] = "S-1-5-21-515967899-920026266-1708537768-1000";
502   char *buf = LocalAlloc (LMEM_FIXED, sizeof (asid));
503   if (!buf)
504     {
505       _dbus_win_warn_win_error ("LocalAlloc failed", GetLastError ());
506       return FALSE;
507     }
508 
509   memcpy (buf, asid, sizeof (asid));
510   *sid = buf;
511   return TRUE;
512 }
513 
514 
515 BOOL
LookupAccountNameW(LPCWSTR lpSystemName,LPCWSTR lpAccountName,PSID Sid,PDWORD cbSid,LPWSTR ReferencedDomainName,PDWORD cchReferencedDomainName,PSID_NAME_USE peUse)516 LookupAccountNameW (LPCWSTR lpSystemName, LPCWSTR lpAccountName, PSID Sid, PDWORD cbSid,
517                     LPWSTR ReferencedDomainName, PDWORD cchReferencedDomainName, PSID_NAME_USE peUse)
518 {
519   /* Currently not needed.  */
520   return FALSE;
521 }
522 
523 
524 BOOL
IsValidSid(PSID psid)525 IsValidSid (PSID psid)
526 {
527   /* Currently not needed.  */
528   return FALSE;
529 }
530 
531 
532 HANDLE
CreateFileA(LPCSTR lpFileName,DWORD dwDesiredAccess,DWORD dwSharedMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile)533 CreateFileA (LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwSharedMode,
534 	     LPSECURITY_ATTRIBUTES lpSecurityAttributes,
535 	     DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
536 	     HANDLE hTemplateFile)
537 {
538   wchar_t *filename;
539   HANDLE result;
540   int err;
541 
542   filename = _dbus_win_utf8_to_utf16 (lpFileName, NULL);
543   if (!filename)
544     return INVALID_HANDLE_VALUE;
545 
546   result = CreateFileW (filename, dwDesiredAccess, dwSharedMode,
547 			lpSecurityAttributes, dwCreationDisposition,
548 			dwFlagsAndAttributes, hTemplateFile);
549 
550   err = GetLastError ();
551   dbus_free (filename);
552   SetLastError (err);
553   return result;
554 }
555 
556 
557 BOOL
DeleteFileA(LPCSTR lpFileName)558 DeleteFileA (LPCSTR lpFileName)
559 {
560   wchar_t *filename;
561   BOOL result;
562   int err;
563 
564   filename = _dbus_win_utf8_to_utf16 (lpFileName, NULL);
565   if (!filename)
566     return FALSE;
567 
568   result = DeleteFileW (filename);
569 
570   err = GetLastError ();
571   dbus_free (filename);
572   SetLastError (err);
573   return result;
574 }
575 
576 
577 BOOL
MoveFileA(LPCSTR lpExistingFileName,LPCSTR lpNewFileName)578 MoveFileA (LPCSTR lpExistingFileName, LPCSTR lpNewFileName)
579 {
580   wchar_t *existing_filename;
581   wchar_t *new_filename;
582   BOOL result;
583   int err;
584 
585   existing_filename = _dbus_win_utf8_to_utf16 (lpExistingFileName, NULL);
586   if (! existing_filename)
587     return FALSE;
588 
589   new_filename = _dbus_win_utf8_to_utf16 (lpNewFileName, NULL);
590   if (! new_filename)
591     {
592       dbus_free (existing_filename);
593       return FALSE;
594     }
595 
596   result = MoveFileW (existing_filename, new_filename);
597 
598   err = GetLastError ();
599   dbus_free (existing_filename);
600   dbus_free (new_filename);
601   SetLastError (err);
602   return result;
603 }
604 
605 
606 DWORD
GetFileAttributesA(LPCSTR lpFileName)607 GetFileAttributesA(LPCSTR lpFileName)
608 {
609   wchar_t *filename;
610   DWORD result;
611   int err;
612 
613   filename = _dbus_win_utf8_to_utf16 (lpFileName, NULL);
614   if (!filename)
615     return INVALID_FILE_ATTRIBUTES;
616 
617   result = GetFileAttributesW (filename);
618 
619   err = GetLastError ();
620   dbus_free (filename);
621   SetLastError (err);
622   return result;
623 }
624 
625 
626 BOOL
GetFileAttributesExA(LPCSTR lpFileName,GET_FILEEX_INFO_LEVELS fInfoLevelId,PVOID lpFileInformation)627 GetFileAttributesExA (LPCSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
628                       PVOID lpFileInformation)
629 {
630   wchar_t *filename;
631   DWORD result;
632   int err;
633 
634   filename = _dbus_win_utf8_to_utf16 (lpFileName, NULL);
635   if (!filename)
636     return INVALID_FILE_ATTRIBUTES;
637 
638   result = GetFileAttributesExW (filename, fInfoLevelId, lpFileInformation);
639 
640   err = GetLastError ();
641   dbus_free (filename);
642   SetLastError (err);
643   return result;
644 }
645 
646 
647 HANDLE
CreateFileMappingA(HANDLE hFile,LPSECURITY_ATTRIBUTES lpAttributes,DWORD flProtect,DWORD dwMaximumSizeHigh,DWORD dwMaximumSizeLow,LPCSTR lpName)648 CreateFileMappingA (HANDLE hFile, LPSECURITY_ATTRIBUTES lpAttributes,
649 		    DWORD flProtect, DWORD dwMaximumSizeHigh,
650 		    DWORD dwMaximumSizeLow, LPCSTR lpName)
651 {
652   wchar_t *name;
653   HANDLE result;
654   int err;
655 
656   if (lpName)
657     {
658       name = _dbus_win_utf8_to_utf16 (lpName, NULL);
659       if (!name)
660 	return INVALID_HANDLE_VALUE;
661     }
662   else
663     name = NULL;
664 
665   result = CreateFileMappingW (hFile, lpAttributes, flProtect,
666 			       dwMaximumSizeHigh, dwMaximumSizeLow,
667 			       name);
668 
669   err = GetLastError ();
670   dbus_free (name);
671   SetLastError (err);
672   return result;
673 }
674 
675 
676 BOOL
CreateDirectoryA(LPCSTR lpPathName,LPSECURITY_ATTRIBUTES lpSecurityAttributes)677 CreateDirectoryA (LPCSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
678 {
679   wchar_t *pathname;
680   BOOL result;
681   int err;
682 
683   pathname = _dbus_win_utf8_to_utf16 (lpPathName, NULL);
684   if (!pathname)
685     return FALSE;
686 
687   result = CreateDirectoryW (pathname, lpSecurityAttributes);
688 
689   err = GetLastError ();
690   dbus_free (pathname);
691   SetLastError (err);
692   return result;
693 }
694 
695 
696 BOOL
RemoveDirectoryA(LPCSTR lpPathName)697 RemoveDirectoryA (LPCSTR lpPathName)
698 {
699   wchar_t *pathname;
700   BOOL result;
701   int err;
702 
703   pathname = _dbus_win_utf8_to_utf16 (lpPathName, NULL);
704   if (!pathname)
705     return FALSE;
706 
707   result = RemoveDirectoryW (pathname);
708 
709   err = GetLastError ();
710   dbus_free (pathname);
711   SetLastError (err);
712   return result;
713 }
714 
715 
716 static BOOL
convert_find_data(LPWIN32_FIND_DATAW fdw,LPWIN32_FIND_DATAA fda)717 convert_find_data (LPWIN32_FIND_DATAW fdw, LPWIN32_FIND_DATAA fda)
718 {
719   char *filename;
720   int len;
721 
722   fda->dwFileAttributes = fdw->dwFileAttributes;
723   fda->ftCreationTime = fdw->ftCreationTime;
724   fda->ftLastAccessTime = fdw->ftLastAccessTime;
725   fda->ftLastWriteTime = fdw->ftLastWriteTime;
726   fda->nFileSizeHigh = fdw->nFileSizeHigh;
727   fda->nFileSizeLow = fdw->nFileSizeLow;
728 
729   filename = _dbus_win_utf16_to_utf8 (fdw->cFileName, NULL);
730   if (!filename)
731     return FALSE;
732 
733   len = sizeof (fda->cFileName);
734   strncpy (fda->cFileName, filename, len);
735   fda->cFileName[len - 1] = '\0';
736 
737   return TRUE;
738 }
739 
740 
741 HANDLE
FindFirstFileA(LPCSTR lpFileName,LPWIN32_FIND_DATAA lpFindFileData)742 FindFirstFileA (LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData)
743 {
744   wchar_t *pathname;
745   WIN32_FIND_DATAW find_file_data;
746   HANDLE result;
747   int err;
748 
749   pathname = _dbus_win_utf8_to_utf16 (lpFileName, NULL);
750   if (!pathname)
751     return INVALID_HANDLE_VALUE;
752 
753   result = FindFirstFileW (pathname, &find_file_data);
754   if (result != INVALID_HANDLE_VALUE)
755     {
756       BOOL res = convert_find_data (&find_file_data, lpFindFileData);
757       if (! res)
758         {
759           err = GetLastError ();
760           FindClose (result);
761           SetLastError (err);
762           result = INVALID_HANDLE_VALUE;
763         }
764     }
765 
766   err = GetLastError ();
767   dbus_free (pathname);
768   SetLastError (err);
769   return result;
770 }
771 
772 
773 BOOL
FindNextFileA(HANDLE hFindFile,LPWIN32_FIND_DATAA lpFindFileData)774 FindNextFileA (HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData)
775 {
776   WIN32_FIND_DATAW find_file_data;
777   BOOL result;
778   int err;
779 
780   result = FindNextFileW (hFindFile, &find_file_data);
781   if (result)
782     result = convert_find_data (&find_file_data, lpFindFileData);
783 
784   return result;
785 }
786 
787 
788 HANDLE
CreateMutexA(LPSECURITY_ATTRIBUTES lpMutexAttributes,BOOL bInitialOwner,LPCSTR lpName)789 CreateMutexA (LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner,
790 	      LPCSTR lpName)
791 {
792   wchar_t *name;
793   HANDLE result;
794   int err;
795 
796   if (lpName)
797     {
798       name = _dbus_win_utf8_to_utf16 (lpName, NULL);
799       if (!name)
800 	return INVALID_HANDLE_VALUE;
801     }
802   else
803     name = NULL;
804 
805   result = CreateMutexW (lpMutexAttributes, bInitialOwner, name);
806 
807   err = GetLastError ();
808   dbus_free (name);
809   SetLastError (err);
810   return result;
811 }
812 
813 
814 BOOL
CreateProcessA(LPCSTR pszImageName,LPSTR pszCmdLine,LPSECURITY_ATTRIBUTES psaProcess,LPSECURITY_ATTRIBUTES psaThread,BOOL fInheritHandles,DWORD fdwCreate,PVOID pvEnvironment,LPCSTR pszCurDir,LPSTARTUPINFOA psiStartInfo,LPPROCESS_INFORMATION pProcInfo)815 CreateProcessA (LPCSTR pszImageName, LPSTR pszCmdLine,
816                 LPSECURITY_ATTRIBUTES psaProcess,
817                 LPSECURITY_ATTRIBUTES psaThread, BOOL fInheritHandles,
818                 DWORD fdwCreate, PVOID pvEnvironment, LPCSTR pszCurDir,
819                 LPSTARTUPINFOA psiStartInfo,
820                 LPPROCESS_INFORMATION pProcInfo)
821 {
822   wchar_t *image_name = NULL;
823   wchar_t *cmd_line = NULL;
824   BOOL result;
825   int err;
826 
827   _dbus_assert (psaProcess == NULL);
828   _dbus_assert (psaThread == NULL);
829   _dbus_assert (fInheritHandles == FALSE);
830   _dbus_assert (pvEnvironment == NULL);
831   _dbus_assert (pszCurDir == NULL);
832   /* psiStartInfo is generally not NULL.  */
833 
834   if (pszImageName)
835     {
836       image_name = _dbus_win_utf8_to_utf16 (pszImageName, NULL);
837       if (!image_name)
838 	return 0;
839     }
840   if (pszCmdLine)
841     {
842       cmd_line = _dbus_win_utf8_to_utf16 (pszCmdLine, NULL);
843       if (!cmd_line)
844         {
845           if (image_name)
846             dbus_free (image_name);
847           return 0;
848         }
849     }
850 
851   result = CreateProcessW (image_name, cmd_line, NULL, NULL, FALSE,
852                            fdwCreate, NULL, NULL, NULL, pProcInfo);
853 
854   err = GetLastError ();
855   dbus_free (image_name);
856   dbus_free (cmd_line);
857   SetLastError (err);
858   return result;
859 }
860 
861 
862 LONG
RegOpenKeyExA(HKEY hKey,LPCSTR lpSubKey,DWORD ulOptions,REGSAM samDesired,PHKEY phkResult)863 RegOpenKeyExA (HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions,
864                REGSAM samDesired, PHKEY phkResult)
865 {
866   wchar_t *subkey;
867   LONG result;
868   int err;
869 
870   if (lpSubKey)
871     {
872       subkey = _dbus_win_utf8_to_utf16 (lpSubKey, NULL);
873       if (!subkey)
874 	return 0;
875     }
876   else
877     subkey = NULL;
878 
879   result = RegOpenKeyEx (hKey, subkey, ulOptions, samDesired, phkResult);
880 
881   err = GetLastError ();
882   dbus_free (subkey);
883   SetLastError (err);
884   return result;
885 }
886 
887 
888 LONG
RegQueryValueExA(HKEY hKey,LPCSTR lpValueName,LPDWORD lpReserved,LPDWORD lpType,LPBYTE lpData,LPDWORD lpcbData)889 RegQueryValueExA (HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved,
890                   LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
891 {
892   wchar_t *name;
893   LONG err;
894   BYTE *data;
895   DWORD data_len;
896   DWORD type;
897 
898   if (lpValueName)
899     {
900       name = _dbus_win_utf8_to_utf16 (lpValueName, NULL);
901       if (!name)
902 	return GetLastError ();
903     }
904   else
905     name = NULL;
906 
907   data_len = 0;
908   err = RegQueryValueExW (hKey, name, lpReserved, lpType, NULL, &data_len);
909   if (err || !lpcbData)
910     {
911       dbus_free (name);
912       return err;
913     }
914 
915   data = malloc (data_len + sizeof (wchar_t));
916   if (!data)
917     {
918       dbus_free (name);
919       return ERROR_NOT_ENOUGH_MEMORY;
920     }
921 
922   err = RegQueryValueExW (hKey, name, lpReserved, &type, data, &data_len);
923   if (lpType)
924     *lpType = type;
925   dbus_free (name);
926   /* If err is ERROR_MORE_DATA, there probably was a race condition.
927      We can punt this to the caller just as well.  */
928   if (err)
929     {
930       free (data);
931       return err;
932     }
933 
934   /* NOTE: REG_MULTI_SZ and REG_EXPAND_SZ not supported, because they
935      are not needed in this module.  */
936   if (type == REG_SZ)
937     {
938       char *data_c;
939       int data_c_len;
940 
941       /* This is valid since we allocated one more above.  */
942       data[data_len] = '\0';
943       data[data_len + 1] = '\0';
944 
945       /* The cast is valid because malloc guarantees alignment of
946          basic types.  */
947       data_c = _dbus_win_utf16_to_utf8 ((wchar_t*) data, NULL);
948       if (!data_c)
949         {
950           free (data);
951           return GetLastError();
952         }
953 
954       data_c_len = strlen (data_c) + 1;
955       _dbus_assert (data_c_len <= data_len + sizeof (wchar_t));
956       memcpy (data, data_c, data_c_len);
957       data_len = data_c_len;
958       dbus_free (data_c);
959     }
960 
961   /* DATA and DATA_LEN now contain the result.  */
962   if (lpData)
963     {
964       if (data_len > *lpcbData)
965         err = ERROR_MORE_DATA;
966       else
967         memcpy (lpData, data, data_len);
968     }
969   free (data);
970   *lpcbData = data_len;
971   return err;
972 }
973 
974 
975 DWORD
FormatMessageA(DWORD dwFlags,PCVOID lpSource,DWORD dwMessageId,DWORD dwLanguageId,LPSTR lpBuffer,DWORD nSize,va_list * Arguments)976 FormatMessageA (DWORD dwFlags, PCVOID lpSource, DWORD dwMessageId,
977 		DWORD dwLanguageId, LPSTR lpBuffer, DWORD nSize,
978 		va_list* Arguments)
979 {
980   LPWSTR buffer_w = NULL;
981   LPSTR buffer_c;
982   DWORD len;
983   char *buffer_new;
984   DWORD buffer_new_len;
985   BOOL buffer_w_free;
986 
987   len = FormatMessageW (dwFlags | FORMAT_MESSAGE_ALLOCATE_BUFFER,
988 			lpSource, dwMessageId, dwLanguageId,
989 			(LPWSTR) &buffer_w, 0, Arguments);
990   if (len == 0)
991     return 0;
992 
993   buffer_c = _dbus_win_utf16_to_utf8 (buffer_w, NULL);
994   if (! buffer_c)
995     {
996       LocalFree (buffer_w);
997       return 0;
998     }
999 
1000   if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER)
1001     {
1002       /* We need to return a buffer that's freeable with LocalFree.  */
1003       buffer_new = (char *) buffer_w;
1004       buffer_new_len = sizeof (wchar_t) * (len + 1);
1005       buffer_w_free = FALSE;
1006       /* Avoid alignment issue by using memcpy.  */
1007       memcpy (lpBuffer, &buffer_new, sizeof (buffer_new));
1008     }
1009   else
1010     {
1011       buffer_new = lpBuffer;
1012       buffer_new_len = nSize;
1013       buffer_w_free = TRUE;
1014     }
1015 
1016   strncpy (buffer_new, buffer_c, buffer_new_len);
1017   dbus_free (buffer_c);
1018   buffer_new[buffer_new_len - 1] = '\0';
1019   if (buffer_w_free)
1020     LocalFree (buffer_w);
1021 
1022   /* strlen is correct (not _mbstrlen), because we want storage and
1023      not string length.  */
1024   return strlen (buffer_new);
1025 }
1026 
1027 
1028 DWORD
GetModuleFileNameA(HINSTANCE hModule,LPSTR lpFilename,DWORD nSize)1029 GetModuleFileNameA (HINSTANCE hModule, LPSTR lpFilename, DWORD nSize)
1030 {
1031   wchar_t *filename_w;
1032   char *filename_c;
1033   DWORD len;
1034 
1035   if (nSize == 0)
1036     {
1037       /* Windows XP/2000.  */
1038       SetLastError (0);
1039       return 0;
1040     }
1041 
1042   filename_w = malloc (sizeof (wchar_t) * nSize);
1043   if (! filename_w)
1044     return 0;
1045 
1046   len = GetModuleFileNameW (hModule, filename_w, nSize);
1047   if (len == 0)
1048     {
1049       /* Note: If we fail with ERROR_INSUFFICIENT_BUFFER, this is still
1050        (approximately) correct.  */
1051       free (filename_w);
1052       return 0;
1053     }
1054 
1055   filename_w[nSize - 1] = '\0';
1056   filename_c = _dbus_win_utf16_to_utf8 (filename_w, NULL);
1057   free (filename_w);
1058   if (! filename_c)
1059     return 0;
1060 
1061   strncpy (lpFilename, filename_c, nSize);
1062   dbus_free (filename_c);
1063   lpFilename[nSize - 1] = '\0';
1064   /* strlen is correct (not _mbstrlen), because we want storage and
1065      not string length.  */
1066   return strlen (lpFilename);
1067 }
1068 
1069 
1070 DWORD
GetTempPathA(DWORD nBufferLength,LPSTR lpBuffer)1071 GetTempPathA (DWORD nBufferLength, LPSTR lpBuffer)
1072 {
1073   wchar_t dummy[1];
1074   DWORD len;
1075 
1076   len = GetTempPathW (0, dummy);
1077   if (len == 0)
1078     return 0;
1079 
1080   _dbus_assert (len <= MAX_PATH);
1081 
1082   /* Better be safe than sorry.  MSDN doesn't say if len is with or
1083      without terminating 0.  */
1084   len++;
1085 
1086   {
1087     wchar_t *buffer_w;
1088     DWORD len_w;
1089     char *buffer_c;
1090     DWORD len_c;
1091 
1092     buffer_w = malloc (sizeof (wchar_t) * len);
1093     if (! buffer_w)
1094       return 0;
1095 
1096     len_w = GetTempPathW (len, buffer_w);
1097     /* Give up if we still can't get at it.  */
1098     if (len_w == 0 || len_w >= len)
1099       {
1100         free (buffer_w);
1101         return 0;
1102       }
1103 
1104     /* Better be really safe.  */
1105     buffer_w[len_w] = '\0';
1106 
1107     buffer_c = _dbus_win_utf16_to_utf8 (buffer_w, NULL);
1108     free (buffer_w);
1109     if (! buffer_c)
1110       return 0;
1111 
1112     /* strlen is correct (not _mbstrlen), because we want storage and
1113        not string length.  */
1114     len_c = strlen (buffer_c) + 1;
1115     if (len_c > nBufferLength)
1116       return len_c;
1117 
1118     strcpy (lpBuffer, buffer_c);
1119     dbus_free (buffer_c);
1120     return len_c - 1;
1121   }
1122 }
1123 
1124 
1125 BOOL
SHGetSpecialFolderPathA(HWND hwndOwner,LPSTR lpszPath,int nFolder,BOOL fCreate)1126 SHGetSpecialFolderPathA (HWND hwndOwner, LPSTR lpszPath, int nFolder,
1127                          BOOL fCreate)
1128 {
1129   wchar_t path[MAX_PATH];
1130   char *path_c;
1131   BOOL result;
1132 
1133   path[0] = (wchar_t) 0;
1134   result = SHGetSpecialFolderPathW (hwndOwner, path, nFolder, fCreate);
1135   /* Note: May return false even if succeeds.  */
1136 
1137   path[MAX_PATH - 1] = (wchar_t) 0;
1138   path_c = _dbus_win_utf16_to_utf8 (path, NULL);
1139   if (! path_c)
1140     return 0;
1141 
1142   strncpy (lpszPath, path_c, MAX_PATH);
1143   dbus_free (path_c);
1144   lpszPath[MAX_PATH - 1] = '\0';
1145   return result;
1146 }
1147 
1148 
1149 void
OutputDebugStringA(LPCSTR lpOutputString)1150 OutputDebugStringA (LPCSTR lpOutputString)
1151 {
1152   wchar_t *str;
1153   HANDLE result;
1154   int err;
1155 
1156   str = _dbus_win_utf8_to_utf16 (lpOutputString, NULL);
1157   if (!str)
1158     return;
1159 
1160   OutputDebugStringW (str);
1161 
1162   err = GetLastError ();
1163   dbus_free (str);
1164   SetLastError (err);
1165 }
1166