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