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. */ 43static char * 44stpcpy (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! */ 60static char * 61get_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. */ 137static char * 138read_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 196static char * 197find_inst_dir () 198{ 199 return read_w32_registry_string ("HKEY_LOCAL_MACHINE", 200 "Software\\freedesktop\\DBus", 201 "Install Directory"); 202} 203 204 205static char * 206find_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 214static char * 215find_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 238static char * 239find_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 262static char * 263find_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 285char *environ[MAX_ENV + 1]; 286 287char * 288getenv (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 327int 328putenv (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 367clock_t 368clock (void) 369{ 370 return GetTickCount (); 371} 372 373 374void 375abort (void) 376{ 377 /* This is what windows does. */ 378 exit (3); 379} 380 381 382void 383GetSystemTimeAsFileTime (LPFILETIME ftp) 384{ 385 SYSTEMTIME st; 386 GetSystemTime (&st); 387 SystemTimeToFileTime (&st, ftp); 388} 389 390 391unsigned 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 399HANDLE 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 429BOOL 430MoveFileExA (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 444BOOL 445SetHandleInformation (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 456DWORD 457SearchPathA (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 */ 497dbus_bool_t 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 515BOOL 516LookupAccountNameW (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 524BOOL 525IsValidSid (PSID psid) 526{ 527 /* Currently not needed. */ 528 return FALSE; 529} 530 531 532HANDLE 533CreateFileA (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 557BOOL 558DeleteFileA (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 577BOOL 578MoveFileA (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 606DWORD 607GetFileAttributesA(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 626BOOL 627GetFileAttributesExA (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 647HANDLE 648CreateFileMappingA (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 676BOOL 677CreateDirectoryA (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 696BOOL 697RemoveDirectoryA (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 716static BOOL 717convert_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 741HANDLE 742FindFirstFileA (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 773BOOL 774FindNextFileA (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 788HANDLE 789CreateMutexA (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 814BOOL 815CreateProcessA (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 862LONG 863RegOpenKeyExA (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 888LONG 889RegQueryValueExA (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 975DWORD 976FormatMessageA (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 1028DWORD 1029GetModuleFileNameA (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 1070DWORD 1071GetTempPathA (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 1125BOOL 1126SHGetSpecialFolderPathA (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 1149void 1150OutputDebugStringA (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