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