4 * Copyright 2004 Huw D M Davies
5 * Copyright 2005 Sami Aario
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "wine/unicode.h"
33 #include "wine/debug.h"
34 #include "advpack_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(advpack);
38 typedef HRESULT (WINAPI *DLLREGISTER) (void);
40 #define MAX_FIELD_LENGTH 512
43 /* registry path of the Installed Components key for per-user stubs */
44 static const WCHAR setup_key[] = {
45 'S','O','F','T','W','A','R','E','\\',
46 'M','i','c','r','o','s','o','f','t','\\',
47 'A','c','t','i','v','e',' ','S','e','t','u','p','\\',
48 'I','n','s','t','a','l','l','e','d',' ',
49 'C','o','m','p','o','n','e','n','t','s',0
52 /* Strip single quotes from a token - note size includes NULL */
53 static void strip_quotes(WCHAR *buffer, DWORD *size)
55 if (buffer[0] == '\'' && (*size > 1) && buffer[*size-2]=='\'')
59 memmove(buffer, buffer + 1, *size * sizeof(WCHAR));
63 /* parses the destination directory parameters from pszSection
64 * the parameters are of the form: root,key,value,unknown,fallback
65 * we first read the reg value root\\key\\value and if that fails,
66 * use fallback as the destination directory
68 static void get_dest_dir(HINF hInf, PCWSTR pszSection, PWSTR pszBuffer, DWORD dwSize)
71 WCHAR key[MAX_PATH + 2], value[MAX_PATH + 2];
72 WCHAR prefix[PREFIX_LEN + 2];
73 HKEY root, subkey = 0;
76 static const WCHAR hklm[] = {'H','K','L','M',0};
77 static const WCHAR hkcu[] = {'H','K','C','U',0};
79 /* load the destination parameters */
80 SetupFindFirstLineW(hInf, pszSection, NULL, &context);
81 SetupGetStringFieldW(&context, 1, prefix, PREFIX_LEN + 2, &size);
82 strip_quotes(prefix, &size);
83 SetupGetStringFieldW(&context, 2, key, MAX_PATH + 2, &size);
84 strip_quotes(key, &size);
85 SetupGetStringFieldW(&context, 3, value, MAX_PATH + 2, &size);
86 strip_quotes(value, &size);
88 if (!lstrcmpW(prefix, hklm))
89 root = HKEY_LOCAL_MACHINE;
90 else if (!lstrcmpW(prefix, hkcu))
91 root = HKEY_CURRENT_USER;
95 size = dwSize * sizeof(WCHAR);
97 /* fallback to the default destination dir if reg fails */
98 if (RegOpenKeyW(root, key, &subkey) ||
99 RegQueryValueExW(subkey, value, NULL, NULL, (LPBYTE)pszBuffer, &size))
101 SetupGetStringFieldW(&context, 5, pszBuffer, dwSize, &size);
102 strip_quotes(pszBuffer, &size);
105 if (subkey) RegCloseKey(subkey);
108 /* loads the LDIDs specified in the install section of an INF */
109 void set_ldids(HINF hInf, LPCWSTR pszInstallSection, LPCWSTR pszWorkingDir)
111 WCHAR field[MAX_FIELD_LENGTH];
112 WCHAR line[MAX_FIELD_LENGTH];
113 WCHAR dest[MAX_PATH];
118 static const WCHAR source_dir[] = {'S','o','u','r','c','e','D','i','r',0};
120 static const WCHAR custDestW[] = {
121 'C','u','s','t','o','m','D','e','s','t','i','n','a','t','i','o','n',0
124 if (!SetupGetLineTextW(NULL, hInf, pszInstallSection, custDestW,
125 field, MAX_FIELD_LENGTH, &size))
128 if (!SetupFindFirstLineW(hInf, field, NULL, &context))
133 LPWSTR value, ptr, key, key_copy = NULL;
136 SetupGetLineTextW(&context, NULL, NULL, NULL,
137 line, MAX_FIELD_LENGTH, &size);
139 /* SetupGetLineTextW returns the value if there is only one key, but
140 * returns the whole line if there is more than one key
142 if (!(value = strchrW(line, '=')))
144 SetupGetStringFieldW(&context, 0, NULL, 0, &size);
145 key = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
147 SetupGetStringFieldW(&context, 0, key, size, &size);
156 /* remove leading whitespace from the value */
157 while (*value == ' ')
160 /* Extract the flags */
161 ptr = strchrW(value, ',');
164 flags = atolW(ptr+1);
167 /* set dest to pszWorkingDir if key is SourceDir */
168 if (pszWorkingDir && !lstrcmpiW(value, source_dir))
169 lstrcpynW(dest, pszWorkingDir, MAX_PATH);
171 get_dest_dir(hInf, value, dest, MAX_PATH);
173 /* If prompting required, provide dialog to request path */
175 FIXME("Need to support changing paths - default will be used\n");
177 /* set all ldids to dest */
178 while ((ptr = get_parameter(&key, ',')))
181 SetupSetDirectoryIdW(hInf, ldid, dest);
183 HeapFree(GetProcessHeap(), 0, key_copy);
184 } while (SetupFindNextLine(&context, &context));
187 /***********************************************************************
188 * CloseINFEngine (ADVPACK.@)
190 * Closes a handle to an INF file opened with OpenINFEngine.
193 * hInf [I] Handle to the INF file to close.
199 HRESULT WINAPI CloseINFEngine(HINF hInf)
201 TRACE("(%p)\n", hInf);
206 SetupCloseInfFile(hInf);
210 /***********************************************************************
211 * DllMain (ADVPACK.@)
213 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
215 TRACE("(%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
217 if (fdwReason == DLL_PROCESS_ATTACH)
218 DisableThreadLibraryCalls(hinstDLL);
223 /***********************************************************************
224 * IsNTAdmin (ADVPACK.@)
226 * Checks if the user has admin privileges.
229 * reserved [I] Reserved. Must be 0.
230 * pReserved [I] Reserved. Must be NULL.
233 * TRUE if user has admin rights, FALSE otherwise.
235 BOOL WINAPI IsNTAdmin(DWORD reserved, LPDWORD pReserved)
237 SID_IDENTIFIER_AUTHORITY SidAuthority = {SECURITY_NT_AUTHORITY};
238 PTOKEN_GROUPS pTokenGroups;
239 BOOL bSidFound = FALSE;
244 TRACE("(%d, %p)\n", reserved, pReserved);
246 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
249 if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwSize))
251 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
258 pTokenGroups = HeapAlloc(GetProcessHeap(), 0, dwSize);
265 if (!GetTokenInformation(hToken, TokenGroups, pTokenGroups, dwSize, &dwSize))
267 HeapFree(GetProcessHeap(), 0, pTokenGroups);
274 if (!AllocateAndInitializeSid(&SidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
275 DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pSid))
277 HeapFree(GetProcessHeap(), 0, pTokenGroups);
281 for (i = 0; i < pTokenGroups->GroupCount; i++)
283 if (EqualSid(pSid, pTokenGroups->Groups[i].Sid))
290 HeapFree(GetProcessHeap(), 0, pTokenGroups);
296 /***********************************************************************
297 * NeedRebootInit (ADVPACK.@)
299 * Sets up conditions for reboot checking.
302 * Value required by NeedReboot.
304 DWORD WINAPI NeedRebootInit(VOID)
306 FIXME("(VOID): stub\n");
310 /***********************************************************************
311 * NeedReboot (ADVPACK.@)
313 * Determines whether a reboot is required.
316 * dwRebootCheck [I] Value from NeedRebootInit.
319 * TRUE if a reboot is needed, FALSE otherwise.
324 BOOL WINAPI NeedReboot(DWORD dwRebootCheck)
326 FIXME("(%d): stub\n", dwRebootCheck);
330 /***********************************************************************
331 * OpenINFEngineA (ADVPACK.@)
333 * See OpenINFEngineW.
335 HRESULT WINAPI OpenINFEngineA(LPCSTR pszInfFilename, LPCSTR pszInstallSection,
336 DWORD dwFlags, HINF *phInf, PVOID pvReserved)
338 UNICODE_STRING filenameW, installW;
341 TRACE("(%s, %s, %d, %p, %p)\n", debugstr_a(pszInfFilename),
342 debugstr_a(pszInstallSection), dwFlags, phInf, pvReserved);
344 if (!pszInfFilename || !phInf)
347 RtlCreateUnicodeStringFromAsciiz(&filenameW, pszInfFilename);
348 RtlCreateUnicodeStringFromAsciiz(&installW, pszInstallSection);
350 res = OpenINFEngineW(filenameW.Buffer, installW.Buffer,
351 dwFlags, phInf, pvReserved);
353 RtlFreeUnicodeString(&filenameW);
354 RtlFreeUnicodeString(&installW);
359 /***********************************************************************
360 * OpenINFEngineW (ADVPACK.@)
362 * Opens and returns a handle to an INF file to be used by
363 * TranslateInfStringEx to continuously translate the INF file.
366 * pszInfFilename [I] Filename of the INF to open.
367 * pszInstallSection [I] Name of the Install section in the INF.
368 * dwFlags [I] See advpub.h.
369 * phInf [O] Handle to the loaded INF file.
370 * pvReserved [I] Reserved. Must be NULL.
376 HRESULT WINAPI OpenINFEngineW(LPCWSTR pszInfFilename, LPCWSTR pszInstallSection,
377 DWORD dwFlags, HINF *phInf, PVOID pvReserved)
379 TRACE("(%s, %s, %d, %p, %p)\n", debugstr_w(pszInfFilename),
380 debugstr_w(pszInstallSection), dwFlags, phInf, pvReserved);
382 if (!pszInfFilename || !phInf)
385 *phInf = SetupOpenInfFileW(pszInfFilename, NULL, INF_STYLE_WIN4, NULL);
386 if (*phInf == INVALID_HANDLE_VALUE)
387 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
389 set_ldids(*phInf, pszInstallSection, NULL);
394 /***********************************************************************
395 * RebootCheckOnInstallA (ADVPACK.@)
397 * See RebootCheckOnInstallW.
399 HRESULT WINAPI RebootCheckOnInstallA(HWND hWnd, LPCSTR pszINF,
400 LPCSTR pszSec, DWORD dwReserved)
402 UNICODE_STRING infW, secW;
405 TRACE("(%p, %s, %s, %d)\n", hWnd, debugstr_a(pszINF),
406 debugstr_a(pszSec), dwReserved);
408 if (!pszINF || !pszSec)
411 RtlCreateUnicodeStringFromAsciiz(&infW, pszINF);
412 RtlCreateUnicodeStringFromAsciiz(&secW, pszSec);
414 res = RebootCheckOnInstallW(hWnd, infW.Buffer, secW.Buffer, dwReserved);
416 RtlFreeUnicodeString(&infW);
417 RtlFreeUnicodeString(&secW);
422 /***********************************************************************
423 * RebootCheckOnInstallW (ADVPACK.@)
425 * Checks if a reboot is required for an installed INF section.
428 * hWnd [I] Handle to the window used for messages.
429 * pszINF [I] Filename of the INF file.
430 * pszSec [I] INF section to check.
431 * dwReserved [I] Reserved. Must be 0.
434 * Success: S_OK - Reboot is needed if the INF section is installed.
435 * S_FALSE - Reboot is not needed.
436 * Failure: HRESULT of GetLastError().
439 * if pszSec is NULL, RebootCheckOnInstall checks the DefaultInstall
440 * or DefaultInstall.NT section.
445 HRESULT WINAPI RebootCheckOnInstallW(HWND hWnd, LPCWSTR pszINF,
446 LPCWSTR pszSec, DWORD dwReserved)
448 FIXME("(%p, %s, %s, %d): stub\n", hWnd, debugstr_w(pszINF),
449 debugstr_w(pszSec), dwReserved);
454 /* registers the OCX if do_reg is TRUE, unregisters it otherwise */
455 HRESULT do_ocx_reg(HMODULE hocx, BOOL do_reg, const WCHAR *flags, const WCHAR *param)
457 DLLREGISTER reg_func;
460 reg_func = (DLLREGISTER)GetProcAddress(hocx, "DllRegisterServer");
462 reg_func = (DLLREGISTER)GetProcAddress(hocx, "DllUnregisterServer");
471 /***********************************************************************
472 * RegisterOCX (ADVPACK.@)
477 * hWnd [I] Handle to the window used for the display.
478 * hInst [I] Instance of the process.
479 * cmdline [I] Contains parameters in the order OCX,flags,param.
480 * show [I] How the window should be shown.
487 * OCX - Filename of the OCX to register.
488 * flags - Controls the operation of RegisterOCX.
489 * 'I' Call DllRegisterServer and DllInstall.
490 * 'N' Only call DllInstall.
491 * param - Command line passed to DllInstall.
493 HRESULT WINAPI RegisterOCX(HWND hWnd, HINSTANCE hInst, LPCSTR cmdline, INT show)
495 LPWSTR ocx_filename, str_flags, param;
496 LPWSTR cmdline_copy, cmdline_ptr;
497 UNICODE_STRING cmdlineW;
502 TRACE("(%s)\n", debugstr_a(cmdline));
504 RtlCreateUnicodeStringFromAsciiz(&cmdlineW, cmdline);
506 size = (lstrlenW(cmdlineW.Buffer) + 1) * sizeof(WCHAR);
507 cmdline_copy = HeapAlloc(GetProcessHeap(), 0, size);
508 cmdline_ptr = cmdline_copy;
509 lstrcpyW(cmdline_copy, cmdlineW.Buffer);
511 ocx_filename = get_parameter(&cmdline_ptr, ',');
512 if (!ocx_filename || !*ocx_filename)
515 str_flags = get_parameter(&cmdline_ptr, ',');
516 param = get_parameter(&cmdline_ptr, ',');
518 hm = LoadLibraryExW(ocx_filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
522 hr = do_ocx_reg(hm, TRUE, str_flags, param);
526 HeapFree(GetProcessHeap(), 0, cmdline_copy);
527 RtlFreeUnicodeString(&cmdlineW);
532 /***********************************************************************
533 * SetPerUserSecValuesA (ADVPACK.@)
535 * See SetPerUserSecValuesW.
537 HRESULT WINAPI SetPerUserSecValuesA(PERUSERSECTIONA* pPerUser)
539 PERUSERSECTIONW perUserW;
541 TRACE("(%p)\n", pPerUser);
546 MultiByteToWideChar(CP_ACP, 0, pPerUser->szGUID, -1, perUserW.szGUID,
547 sizeof(perUserW.szGUID) / sizeof(WCHAR));
548 MultiByteToWideChar(CP_ACP, 0, pPerUser->szDispName, -1, perUserW.szDispName,
549 sizeof(perUserW.szDispName) / sizeof(WCHAR));
550 MultiByteToWideChar(CP_ACP, 0, pPerUser->szLocale, -1, perUserW.szLocale,
551 sizeof(perUserW.szLocale) / sizeof(WCHAR));
552 MultiByteToWideChar(CP_ACP, 0, pPerUser->szStub, -1, perUserW.szStub,
553 sizeof(perUserW.szStub) / sizeof(WCHAR));
554 MultiByteToWideChar(CP_ACP, 0, pPerUser->szVersion, -1, perUserW.szVersion,
555 sizeof(perUserW.szVersion) / sizeof(WCHAR));
556 MultiByteToWideChar(CP_ACP, 0, pPerUser->szCompID, -1, perUserW.szCompID,
557 sizeof(perUserW.szCompID) / sizeof(WCHAR));
558 perUserW.dwIsInstalled = pPerUser->dwIsInstalled;
559 perUserW.bRollback = pPerUser->bRollback;
561 return SetPerUserSecValuesW(&perUserW);
564 /***********************************************************************
565 * SetPerUserSecValuesW (ADVPACK.@)
567 * Prepares the per-user stub values under IsInstalled\{GUID} that
568 * control the per-user installation.
571 * pPerUser [I] Per-user stub values.
577 HRESULT WINAPI SetPerUserSecValuesW(PERUSERSECTIONW* pPerUser)
581 static const WCHAR stub_path[] = {'S','t','u','b','P','a','t','h',0};
582 static const WCHAR version[] = {'V','e','r','s','i','o','n',0};
583 static const WCHAR locale[] = {'L','o','c','a','l','e',0};
584 static const WCHAR compid[] = {'C','o','m','p','o','n','e','n','t','I','D',0};
585 static const WCHAR isinstalled[] = {'I','s','I','n','s','t','a','l','l','e','d',0};
587 TRACE("(%p)\n", pPerUser);
589 if (!pPerUser || !*pPerUser->szGUID)
592 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, setup_key, 0, NULL, 0, KEY_WRITE,
598 if (RegCreateKeyExW(setup, pPerUser->szGUID, 0, NULL, 0, KEY_ALL_ACCESS,
605 if (*pPerUser->szStub)
607 RegSetValueExW(guid, stub_path, 0, REG_SZ, (LPBYTE)pPerUser->szStub,
608 (lstrlenW(pPerUser->szStub) + 1) * sizeof(WCHAR));
611 if (*pPerUser->szVersion)
613 RegSetValueExW(guid, version, 0, REG_SZ, (LPBYTE)pPerUser->szVersion,
614 (lstrlenW(pPerUser->szVersion) + 1) * sizeof(WCHAR));
617 if (*pPerUser->szLocale)
619 RegSetValueExW(guid, locale, 0, REG_SZ, (LPBYTE)pPerUser->szLocale,
620 (lstrlenW(pPerUser->szLocale) + 1) * sizeof(WCHAR));
623 if (*pPerUser->szCompID)
625 RegSetValueExW(guid, compid, 0, REG_SZ, (LPBYTE)pPerUser->szCompID,
626 (lstrlenW(pPerUser->szCompID) + 1) * sizeof(WCHAR));
629 if (*pPerUser->szDispName)
631 RegSetValueExW(guid, NULL, 0, REG_SZ, (LPBYTE)pPerUser->szDispName,
632 (lstrlenW(pPerUser->szDispName) + 1) * sizeof(WCHAR));
635 RegSetValueExW(guid, isinstalled, 0, REG_DWORD,
636 (LPBYTE)&pPerUser->dwIsInstalled, sizeof(DWORD));
644 /***********************************************************************
645 * TranslateInfStringA (ADVPACK.@)
647 * See TranslateInfStringW.
649 HRESULT WINAPI TranslateInfStringA(LPCSTR pszInfFilename, LPCSTR pszInstallSection,
650 LPCSTR pszTranslateSection, LPCSTR pszTranslateKey, LPSTR pszBuffer,
651 DWORD dwBufferSize, PDWORD pdwRequiredSize, PVOID pvReserved)
653 UNICODE_STRING filenameW, installW;
654 UNICODE_STRING translateW, keyW;
659 TRACE("(%s, %s, %s, %s, %p, %d, %p, %p)\n",
660 debugstr_a(pszInfFilename), debugstr_a(pszInstallSection),
661 debugstr_a(pszTranslateSection), debugstr_a(pszTranslateKey),
662 pszBuffer, dwBufferSize,pdwRequiredSize, pvReserved);
664 if (!pszInfFilename || !pszTranslateSection ||
665 !pszTranslateKey || !pdwRequiredSize)
668 RtlCreateUnicodeStringFromAsciiz(&filenameW, pszInfFilename);
669 RtlCreateUnicodeStringFromAsciiz(&installW, pszInstallSection);
670 RtlCreateUnicodeStringFromAsciiz(&translateW, pszTranslateSection);
671 RtlCreateUnicodeStringFromAsciiz(&keyW, pszTranslateKey);
673 res = TranslateInfStringW(filenameW.Buffer, installW.Buffer,
674 translateW.Buffer, keyW.Buffer, NULL,
675 dwBufferSize, &len, NULL);
679 bufferW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
681 res = TranslateInfStringW(filenameW.Buffer, installW.Buffer,
682 translateW.Buffer, keyW.Buffer, bufferW,
686 *pdwRequiredSize = WideCharToMultiByte(CP_ACP, 0, bufferW, -1,
687 NULL, 0, NULL, NULL);
689 if (dwBufferSize >= *pdwRequiredSize)
691 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, pszBuffer,
692 dwBufferSize, NULL, NULL);
695 res = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
698 HeapFree(GetProcessHeap(), 0, bufferW);
701 RtlFreeUnicodeString(&filenameW);
702 RtlFreeUnicodeString(&installW);
703 RtlFreeUnicodeString(&translateW);
704 RtlFreeUnicodeString(&keyW);
709 /***********************************************************************
710 * TranslateInfStringW (ADVPACK.@)
712 * Translates the value of a specified key in an inf file into the
713 * current locale by expanding string macros.
716 * pszInfFilename [I] Filename of the inf file.
717 * pszInstallSection [I]
718 * pszTranslateSection [I] Inf section where the key exists.
719 * pszTranslateKey [I] Key to translate.
720 * pszBuffer [O] Contains the translated string on exit.
721 * dwBufferSize [I] Size on input of pszBuffer.
722 * pdwRequiredSize [O] Length of the translated key.
723 * pvReserved [I] Reserved, must be NULL.
727 * Failure: An hresult error code.
729 HRESULT WINAPI TranslateInfStringW(LPCWSTR pszInfFilename, LPCWSTR pszInstallSection,
730 LPCWSTR pszTranslateSection, LPCWSTR pszTranslateKey, LPWSTR pszBuffer,
731 DWORD dwBufferSize, PDWORD pdwRequiredSize, PVOID pvReserved)
736 TRACE("(%s, %s, %s, %s, %p, %d, %p, %p)\n",
737 debugstr_w(pszInfFilename), debugstr_w(pszInstallSection),
738 debugstr_w(pszTranslateSection), debugstr_w(pszTranslateKey),
739 pszBuffer, dwBufferSize,pdwRequiredSize, pvReserved);
741 if (!pszInfFilename || !pszTranslateSection ||
742 !pszTranslateKey || !pdwRequiredSize)
745 hInf = SetupOpenInfFileW(pszInfFilename, NULL, INF_STYLE_WIN4, NULL);
746 if (hInf == INVALID_HANDLE_VALUE)
747 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
749 set_ldids(hInf, pszInstallSection, NULL);
751 if (!SetupGetLineTextW(NULL, hInf, pszTranslateSection, pszTranslateKey,
752 pszBuffer, dwBufferSize, pdwRequiredSize))
754 if (dwBufferSize < *pdwRequiredSize)
755 hret = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
757 hret = SPAPI_E_LINE_NOT_FOUND;
760 SetupCloseInfFile(hInf);
764 /***********************************************************************
765 * TranslateInfStringExA (ADVPACK.@)
767 * See TranslateInfStringExW.
769 HRESULT WINAPI TranslateInfStringExA(HINF hInf, LPCSTR pszInfFilename,
770 LPCSTR pszTranslateSection, LPCSTR pszTranslateKey,
771 LPSTR pszBuffer, DWORD dwBufferSize,
772 PDWORD pdwRequiredSize, PVOID pvReserved)
774 UNICODE_STRING filenameW, sectionW, keyW;
779 TRACE("(%p, %s, %s, %s, %s, %d, %p, %p)\n", hInf, debugstr_a(pszInfFilename),
780 debugstr_a(pszTranslateSection), debugstr_a(pszTranslateKey),
781 debugstr_a(pszBuffer), dwBufferSize, pdwRequiredSize, pvReserved);
783 if (!pszInfFilename || !pszTranslateSection ||
784 !pszTranslateKey || !pdwRequiredSize)
787 RtlCreateUnicodeStringFromAsciiz(&filenameW, pszInfFilename);
788 RtlCreateUnicodeStringFromAsciiz(§ionW, pszTranslateSection);
789 RtlCreateUnicodeStringFromAsciiz(&keyW, pszTranslateKey);
791 res = TranslateInfStringExW(hInf, filenameW.Buffer, sectionW.Buffer,
792 keyW.Buffer, NULL, 0, &len, NULL);
796 bufferW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
798 res = TranslateInfStringExW(hInf, filenameW.Buffer, sectionW.Buffer,
799 keyW.Buffer, bufferW, len, &len, NULL);
803 *pdwRequiredSize = WideCharToMultiByte(CP_ACP, 0, bufferW, -1,
804 NULL, 0, NULL, NULL);
806 if (dwBufferSize >= *pdwRequiredSize)
808 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, pszBuffer,
809 dwBufferSize, NULL, NULL);
812 res = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
815 HeapFree(GetProcessHeap(), 0, bufferW);
818 RtlFreeUnicodeString(&filenameW);
819 RtlFreeUnicodeString(§ionW);
820 RtlFreeUnicodeString(&keyW);
825 /***********************************************************************
826 * TranslateInfStringExW (ADVPACK.@)
828 * Using a handle to an INF file opened with OpenINFEngine, translates
829 * the value of a specified key in an inf file into the current locale
830 * by expanding string macros.
833 * hInf [I] Handle to the INF file.
834 * pszInfFilename [I] Filename of the INF file.
835 * pszTranslateSection [I] Inf section where the key exists.
836 * pszTranslateKey [I] Key to translate.
837 * pszBuffer [O] Contains the translated string on exit.
838 * dwBufferSize [I] Size on input of pszBuffer.
839 * pdwRequiredSize [O] Length of the translated key.
840 * pvReserved [I] Reserved. Must be NULL.
847 * To use TranslateInfStringEx to translate an INF file continuously,
848 * open the INF file with OpenINFEngine, call TranslateInfStringEx as
849 * many times as needed, then release the handle with CloseINFEngine.
850 * When translating more than one keys, this method is more efficient
851 * than calling TranslateInfString, because the INF file is only
854 HRESULT WINAPI TranslateInfStringExW(HINF hInf, LPCWSTR pszInfFilename,
855 LPCWSTR pszTranslateSection, LPCWSTR pszTranslateKey,
856 LPWSTR pszBuffer, DWORD dwBufferSize,
857 PDWORD pdwRequiredSize, PVOID pvReserved)
859 TRACE("(%p, %s, %s, %s, %s, %d, %p, %p)\n", hInf, debugstr_w(pszInfFilename),
860 debugstr_w(pszTranslateSection), debugstr_w(pszTranslateKey),
861 debugstr_w(pszBuffer), dwBufferSize, pdwRequiredSize, pvReserved);
863 if (!hInf || !pszInfFilename || !pszTranslateSection || !pszTranslateKey)
866 if (!SetupGetLineTextW(NULL, hInf, pszTranslateSection, pszTranslateKey,
867 pszBuffer, dwBufferSize, pdwRequiredSize))
869 if (dwBufferSize < *pdwRequiredSize)
870 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
872 return SPAPI_E_LINE_NOT_FOUND;
878 /***********************************************************************
879 * UserInstStubWrapperA (ADVPACK.@)
881 * See UserInstStubWrapperW.
883 HRESULT WINAPI UserInstStubWrapperA(HWND hWnd, HINSTANCE hInstance,
884 LPSTR pszParms, INT nShow)
886 UNICODE_STRING parmsW;
889 TRACE("(%p, %p, %s, %i)\n", hWnd, hInstance, debugstr_a(pszParms), nShow);
894 RtlCreateUnicodeStringFromAsciiz(&parmsW, pszParms);
896 res = UserInstStubWrapperW(hWnd, hInstance, parmsW.Buffer, nShow);
898 RtlFreeUnicodeString(&parmsW);
903 /***********************************************************************
904 * UserInstStubWrapperW (ADVPACK.@)
906 * Launches the user stub wrapper specified by the RealStubPath
907 * registry value under Installed Components\szParms.
910 * hWnd [I] Handle to the window used for the display.
911 * hInstance [I] Instance of the process.
912 * szParms [I] The GUID of the installation.
913 * show [I] How the window should be shown.
920 * If the type of the StubRealPath value is REG_EXPAND_SZ, then
921 * we should call ExpandEnvironmentStrings on the value and
924 HRESULT WINAPI UserInstStubWrapperW(HWND hWnd, HINSTANCE hInstance,
925 LPWSTR pszParms, INT nShow)
928 WCHAR stub[MAX_PATH];
929 DWORD size = MAX_PATH;
933 static const WCHAR real_stub_path[] = {
934 'R','e','a','l','S','t','u','b','P','a','t','h',0
937 TRACE("(%p, %p, %s, %i)\n", hWnd, hInstance, debugstr_w(pszParms), nShow);
939 if (!pszParms || !*pszParms)
942 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, setup_key, 0, KEY_READ, &setup))
947 if (RegOpenKeyExW(setup, pszParms, 0, KEY_READ, &guid))
953 res = RegQueryValueExW(guid, real_stub_path, NULL, NULL, (LPBYTE)stub, &size);
957 /* launch the user stub wrapper */
958 hr = launch_exe(stub, NULL, NULL);
967 /***********************************************************************
968 * UserUnInstStubWrapperA (ADVPACK.@)
970 * See UserUnInstStubWrapperW.
972 HRESULT WINAPI UserUnInstStubWrapperA(HWND hWnd, HINSTANCE hInstance,
973 LPSTR pszParms, INT nShow)
975 UNICODE_STRING parmsW;
978 TRACE("(%p, %p, %s, %i)\n", hWnd, hInstance, debugstr_a(pszParms), nShow);
983 RtlCreateUnicodeStringFromAsciiz(&parmsW, pszParms);
985 res = UserUnInstStubWrapperW(hWnd, hInstance, parmsW.Buffer, nShow);
987 RtlFreeUnicodeString(&parmsW);
992 /***********************************************************************
993 * UserUnInstStubWrapperW (ADVPACK.@)
995 HRESULT WINAPI UserUnInstStubWrapperW(HWND hWnd, HINSTANCE hInstance,
996 LPWSTR pszParms, INT nShow)
998 FIXME("(%p, %p, %s, %i): stub\n", hWnd, hInstance, debugstr_w(pszParms), nShow);