D-Bus  1.13.7
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  * 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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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
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
368 clock (void)
369 {
370  return GetTickCount ();
371 }
372 
373 
374 void
375 abort (void)
376 {
377  /* This is what windows does. */
378  exit (3);
379 }
380 
381 
382 void
383 GetSystemTimeAsFileTime (LPFILETIME ftp)
384 {
385  SYSTEMTIME st;
386  GetSystemTime (&st);
387  SystemTimeToFileTime (&st, ftp);
388 }
389 
390 
391 unsigned char*
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 
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
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
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
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 
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
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
525 IsValidSid (PSID psid)
526 {
527  /* Currently not needed. */
528  return FALSE;
529 }
530 
531 
532 HANDLE
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }
#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:703
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
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:35
#define TRUE
Expands to "1".
#define FALSE
Expands to "0".