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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 #include "wine/unicode.h"
34 #include "wine/debug.h"
35 #include "advpack_private.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(advpack);
39 typedef HRESULT (WINAPI *DLLREGISTER) (void);
41 #define MAX_FIELD_LENGTH 512
44 /* registry path of the Installed Components key for per-user stubs */
45 static const WCHAR setup_key[] = {
46 'S','O','F','T','W','A','R','E','\\',
47 'M','i','c','r','o','s','o','f','t','\\',
48 'A','c','t','i','v','e',' ','S','e','t','u','p','\\',
49 'I','n','s','t','a','l','l','e','d',' ',
50 'C','o','m','p','o','n','e','n','t','s',0
53 /* parses the destination directory parameters from pszSection
54 * the parameters are of the form: root,key,value,unknown,fallback
55 * we first read the reg value root\\key\\value and if that fails,
56 * use fallback as the destination directory
58 static void get_dest_dir(HINF hInf, PCWSTR pszSection, PWSTR pszBuffer, DWORD dwSize)
61 WCHAR key[MAX_PATH], value[MAX_PATH];
62 WCHAR prefix[PREFIX_LEN];
66 static const WCHAR hklm[] = {'H','K','L','M',0};
67 static const WCHAR hkcu[] = {'H','K','C','U',0};
69 /* load the destination parameters */
70 SetupFindFirstLineW(hInf, pszSection, NULL, &context);
71 SetupGetStringFieldW(&context, 1, prefix, PREFIX_LEN, &size);
72 SetupGetStringFieldW(&context, 2, key, MAX_PATH, &size);
73 SetupGetStringFieldW(&context, 3, value, MAX_PATH, &size);
75 if (!lstrcmpW(prefix, hklm))
76 root = HKEY_LOCAL_MACHINE;
77 else if (!lstrcmpW(prefix, hkcu))
78 root = HKEY_CURRENT_USER;
82 size = dwSize * sizeof(WCHAR);
84 /* fallback to the default destination dir if reg fails */
85 if (RegOpenKeyW(root, key, &subkey) ||
86 RegQueryValueExW(subkey, value, NULL, NULL, (LPBYTE)pszBuffer, &size))
88 SetupGetStringFieldW(&context, 5, pszBuffer, dwSize, NULL);
94 /* loads the LDIDs specified in the install section of an INF */
95 static void set_ldids(HINF hInf, LPCWSTR pszInstallSection, LPCWSTR pszWorkingDir)
97 WCHAR field[MAX_FIELD_LENGTH];
98 WCHAR line[MAX_FIELD_LENGTH];
104 static const WCHAR source_dir[] = {'S','o','u','r','c','e','D','i','r',0};
106 static const WCHAR custDestW[] = {
107 'C','u','s','t','o','m','D','e','s','t','i','n','a','t','i','o','n',0
110 if (!SetupGetLineTextW(NULL, hInf, pszInstallSection, custDestW,
111 field, MAX_FIELD_LENGTH, &size))
114 if (!SetupFindFirstLineW(hInf, field, NULL, &context))
119 LPWSTR value, ptr, key, key_copy = NULL;
121 SetupGetLineTextW(&context, NULL, NULL, NULL,
122 line, MAX_FIELD_LENGTH, &size);
124 /* SetupGetLineTextW returns the value if there is only one key, but
125 * returns the whole line if there is more than one key
127 if (!(value = strchrW(line, '=')))
129 SetupGetStringFieldW(&context, 0, NULL, 0, &size);
130 key = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
132 SetupGetStringFieldW(&context, 0, key, size, &size);
141 /* remove leading whitespace from the value */
142 while (*value == ' ')
145 /* FIXME: need to check the query option */
146 ptr = strchrW(value, ',');
150 /* set dest to pszWorkingDir if key is SourceDir */
151 if (pszWorkingDir && !lstrcmpiW(value, source_dir))
152 lstrcpynW(dest, pszWorkingDir, MAX_PATH);
154 get_dest_dir(hInf, value, dest, MAX_PATH);
156 /* set all ldids to dest */
157 while ((ptr = get_parameter(&key, ',')))
160 SetupSetDirectoryIdW(hInf, ldid, dest);
162 HeapFree(GetProcessHeap(), 0, key_copy);
163 } while (SetupFindNextLine(&context, &context));
166 /***********************************************************************
167 * CloseINFEngine (ADVPACK.@)
169 * Closes a handle to an INF file opened with OpenINFEngine.
172 * hInf [I] Handle to the INF file to close.
178 HRESULT WINAPI CloseINFEngine(HINF hInf)
180 TRACE("(%p)\n", hInf);
185 SetupCloseInfFile(hInf);
189 /***********************************************************************
190 * DllMain (ADVPACK.@)
192 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
194 TRACE("(%p, %ld, %p)\n", hinstDLL, fdwReason, lpvReserved);
196 if (fdwReason == DLL_PROCESS_ATTACH)
197 DisableThreadLibraryCalls(hinstDLL);
202 /***********************************************************************
203 * IsNTAdmin (ADVPACK.@)
205 * Checks if the user has admin privileges.
208 * reserved [I] Reserved. Must be 0.
209 * pReserved [I] Reserved. Must be NULL.
212 * TRUE if user has admin rights, FALSE otherwise.
214 BOOL WINAPI IsNTAdmin(DWORD reserved, LPDWORD pReserved)
216 SID_IDENTIFIER_AUTHORITY SidAuthority = {SECURITY_NT_AUTHORITY};
217 PTOKEN_GROUPS pTokenGroups;
218 BOOL bSidFound = FALSE;
223 TRACE("(%ld, %p)\n", reserved, pReserved);
225 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
228 if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwSize))
230 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
237 pTokenGroups = HeapAlloc(GetProcessHeap(), 0, dwSize);
244 if (!GetTokenInformation(hToken, TokenGroups, pTokenGroups, dwSize, &dwSize))
246 HeapFree(GetProcessHeap(), 0, pTokenGroups);
253 if (!AllocateAndInitializeSid(&SidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
254 DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pSid))
256 HeapFree(GetProcessHeap(), 0, pTokenGroups);
260 for (i = 0; i < pTokenGroups->GroupCount; i++)
262 if (EqualSid(pSid, pTokenGroups->Groups[i].Sid))
269 HeapFree(GetProcessHeap(), 0, pTokenGroups);
275 /***********************************************************************
276 * NeedRebootInit (ADVPACK.@)
278 * Sets up conditions for reboot checking.
281 * Value required by NeedReboot.
283 DWORD WINAPI NeedRebootInit(VOID)
285 FIXME("(VOID): stub\n");
289 /***********************************************************************
290 * NeedReboot (ADVPACK.@)
292 * Determines whether a reboot is required.
295 * dwRebootCheck [I] Value from NeedRebootInit.
298 * TRUE if a reboot is needed, FALSE otherwise.
303 BOOL WINAPI NeedReboot(DWORD dwRebootCheck)
305 FIXME("(%ld): stub\n", dwRebootCheck);
309 /***********************************************************************
310 * OpenINFEngineA (ADVPACK.@)
312 * See OpenINFEngineW.
314 HRESULT WINAPI OpenINFEngineA(LPCSTR pszInfFilename, LPCSTR pszInstallSection,
315 DWORD dwFlags, HINF *phInf, PVOID pvReserved)
317 UNICODE_STRING filenameW, installW;
320 TRACE("(%s, %s, %ld, %p, %p)\n", debugstr_a(pszInfFilename),
321 debugstr_a(pszInstallSection), dwFlags, phInf, pvReserved);
323 if (!pszInfFilename || !phInf)
326 RtlCreateUnicodeStringFromAsciiz(&filenameW, pszInfFilename);
327 RtlCreateUnicodeStringFromAsciiz(&installW, pszInstallSection);
329 res = OpenINFEngineW(filenameW.Buffer, installW.Buffer,
330 dwFlags, phInf, pvReserved);
332 RtlFreeUnicodeString(&filenameW);
333 RtlFreeUnicodeString(&installW);
338 /***********************************************************************
339 * OpenINFEngineW (ADVPACK.@)
341 * Opens and returns a handle to an INF file to be used by
342 * TranslateInfStringEx to continuously translate the INF file.
345 * pszInfFilename [I] Filename of the INF to open.
346 * pszInstallSection [I] Name of the Install section in the INF.
347 * dwFlags [I] See advpub.h.
348 * phInf [O] Handle to the loaded INF file.
349 * pvReserved [I] Reserved. Must be NULL.
355 HRESULT WINAPI OpenINFEngineW(LPCWSTR pszInfFilename, LPCWSTR pszInstallSection,
356 DWORD dwFlags, HINF *phInf, PVOID pvReserved)
358 TRACE("(%s, %s, %ld, %p, %p)\n", debugstr_w(pszInfFilename),
359 debugstr_w(pszInstallSection), dwFlags, phInf, pvReserved);
361 if (!pszInfFilename || !phInf)
364 *phInf = SetupOpenInfFileW(pszInfFilename, NULL, INF_STYLE_WIN4, NULL);
365 if (*phInf == INVALID_HANDLE_VALUE)
366 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
368 set_ldids(*phInf, pszInstallSection, NULL);
373 /***********************************************************************
374 * RebootCheckOnInstallA (ADVPACK.@)
376 * See RebootCheckOnInstallW.
378 HRESULT WINAPI RebootCheckOnInstallA(HWND hWnd, LPCSTR pszINF,
379 LPSTR pszSec, DWORD dwReserved)
381 UNICODE_STRING infW, secW;
384 TRACE("(%p, %s, %s, %ld)\n", hWnd, debugstr_a(pszINF),
385 debugstr_a(pszSec), dwReserved);
387 if (!pszINF || !pszSec)
390 RtlCreateUnicodeStringFromAsciiz(&infW, pszINF);
391 RtlCreateUnicodeStringFromAsciiz(&secW, pszSec);
393 res = RebootCheckOnInstallW(hWnd, infW.Buffer, secW.Buffer, dwReserved);
395 RtlFreeUnicodeString(&infW);
396 RtlFreeUnicodeString(&secW);
401 /***********************************************************************
402 * RebootCheckOnInstallW (ADVPACK.@)
404 * Checks if a reboot is required for an installed INF section.
407 * hWnd [I] Handle to the window used for messages.
408 * pszINF [I] Filename of the INF file.
409 * pszSec [I] INF section to check.
410 * dwReserved [I] Reserved. Must be 0.
413 * Success: S_OK - Reboot is needed if the INF section is installed.
414 * S_FALSE - Reboot is not needed.
415 * Failure: HRESULT of GetLastError().
418 * if pszSec is NULL, RebootCheckOnInstall checks the DefaultInstall
419 * or DefaultInstall.NT section.
424 HRESULT WINAPI RebootCheckOnInstallW(HWND hWnd, LPCWSTR pszINF,
425 LPWSTR pszSec, DWORD dwReserved)
427 FIXME("(%p, %s, %s, %ld): stub\n", hWnd, debugstr_w(pszINF),
428 debugstr_w(pszSec), dwReserved);
433 /* registers the OCX if do_reg is TRUE, unregisters it otherwise */
434 HRESULT do_ocx_reg(HMODULE hocx, BOOL do_reg)
436 DLLREGISTER reg_func;
439 reg_func = (DLLREGISTER)GetProcAddress(hocx, "DllRegisterServer");
441 reg_func = (DLLREGISTER)GetProcAddress(hocx, "DllUnregisterServer");
449 /***********************************************************************
450 * RegisterOCX (ADVPACK.@)
455 * hWnd [I] Handle to the window used for the display.
456 * hInst [I] Instance of the process.
457 * cmdline [I] Contains parameters in the order OCX,flags,param.
458 * show [I] How the window should be shown.
465 * OCX - Filename of the OCX to register.
466 * flags - Controls the operation of RegisterOCX.
467 * 'I' Call DllRegisterServer and DllInstall.
468 * 'N' Only call DllInstall.
469 * param - Command line passed to DllInstall.
471 HRESULT WINAPI RegisterOCX(HWND hWnd, HINSTANCE hInst, LPCSTR cmdline, INT show)
473 LPWSTR ocx_filename, str_flags, param;
474 LPWSTR cmdline_copy, cmdline_ptr;
475 UNICODE_STRING cmdlineW;
480 TRACE("(%s)\n", debugstr_a(cmdline));
482 RtlCreateUnicodeStringFromAsciiz(&cmdlineW, cmdline);
484 size = (lstrlenW(cmdlineW.Buffer) + 1) * sizeof(WCHAR);
485 cmdline_copy = HeapAlloc(GetProcessHeap(), 0, size);
486 cmdline_ptr = cmdline_copy;
487 lstrcpyW(cmdline_copy, cmdlineW.Buffer);
489 ocx_filename = get_parameter(&cmdline_ptr, ',');
490 if (!ocx_filename || !*ocx_filename)
493 str_flags = get_parameter(&cmdline_ptr, ',');
494 param = get_parameter(&cmdline_ptr, ',');
496 hm = LoadLibraryExW(ocx_filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
500 hr = do_ocx_reg(hm, TRUE);
504 HeapFree(GetProcessHeap(), 0, cmdline_copy);
505 RtlFreeUnicodeString(&cmdlineW);
510 /***********************************************************************
511 * SetPerUserSecValuesA (ADVPACK.@)
513 * See SetPerUserSecValuesW.
515 HRESULT WINAPI SetPerUserSecValuesA(PERUSERSECTIONA* pPerUser)
517 PERUSERSECTIONW perUserW;
519 TRACE("(%p)\n", pPerUser);
524 MultiByteToWideChar(CP_ACP, 0, pPerUser->szGUID, -1, perUserW.szGUID,
525 sizeof(perUserW.szGUID) / sizeof(WCHAR));
526 MultiByteToWideChar(CP_ACP, 0, pPerUser->szDispName, -1, perUserW.szDispName,
527 sizeof(perUserW.szDispName) / sizeof(WCHAR));
528 MultiByteToWideChar(CP_ACP, 0, pPerUser->szLocale, -1, perUserW.szLocale,
529 sizeof(perUserW.szLocale) / sizeof(WCHAR));
530 MultiByteToWideChar(CP_ACP, 0, pPerUser->szStub, -1, perUserW.szStub,
531 sizeof(perUserW.szStub) / sizeof(WCHAR));
532 MultiByteToWideChar(CP_ACP, 0, pPerUser->szVersion, -1, perUserW.szVersion,
533 sizeof(perUserW.szVersion) / sizeof(WCHAR));
534 MultiByteToWideChar(CP_ACP, 0, pPerUser->szCompID, -1, perUserW.szCompID,
535 sizeof(perUserW.szCompID) / sizeof(WCHAR));
536 perUserW.dwIsInstalled = pPerUser->dwIsInstalled;
537 perUserW.bRollback = pPerUser->bRollback;
539 return SetPerUserSecValuesW(&perUserW);
542 /***********************************************************************
543 * SetPerUserSecValuesW (ADVPACK.@)
545 * Prepares the per-user stub values under IsInstalled\{GUID} that
546 * control the per-user installation.
549 * pPerUser [I] Per-user stub values.
555 HRESULT WINAPI SetPerUserSecValuesW(PERUSERSECTIONW* pPerUser)
559 static const WCHAR stub_path[] = {'S','t','u','b','P','a','t','h',0};
560 static const WCHAR version[] = {'V','e','r','s','i','o','n',0};
561 static const WCHAR locale[] = {'L','o','c','a','l','e',0};
562 static const WCHAR compid[] = {'C','o','m','p','o','n','e','n','t','I','D',0};
563 static const WCHAR isinstalled[] = {'I','s','I','n','s','t','a','l','l','e','d',0};
565 TRACE("(%p)\n", pPerUser);
567 if (!pPerUser || !*pPerUser->szGUID)
570 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, setup_key, 0, NULL, 0, KEY_WRITE,
576 if (RegCreateKeyExW(setup, pPerUser->szGUID, 0, NULL, 0, KEY_ALL_ACCESS,
583 if (*pPerUser->szStub)
585 RegSetValueExW(guid, stub_path, 0, REG_SZ, (LPBYTE)pPerUser->szStub,
586 (lstrlenW(pPerUser->szStub) + 1) * sizeof(WCHAR));
589 if (*pPerUser->szVersion)
591 RegSetValueExW(guid, version, 0, REG_SZ, (LPBYTE)pPerUser->szVersion,
592 (lstrlenW(pPerUser->szVersion) + 1) * sizeof(WCHAR));
595 if (*pPerUser->szLocale)
597 RegSetValueExW(guid, locale, 0, REG_SZ, (LPBYTE)pPerUser->szLocale,
598 (lstrlenW(pPerUser->szLocale) + 1) * sizeof(WCHAR));
601 if (*pPerUser->szCompID)
603 RegSetValueExW(guid, compid, 0, REG_SZ, (LPBYTE)pPerUser->szCompID,
604 (lstrlenW(pPerUser->szCompID) + 1) * sizeof(WCHAR));
607 if (*pPerUser->szDispName)
609 RegSetValueExW(guid, NULL, 0, REG_SZ, (LPBYTE)pPerUser->szDispName,
610 (lstrlenW(pPerUser->szDispName) + 1) * sizeof(WCHAR));
613 RegSetValueExW(guid, isinstalled, 0, REG_DWORD,
614 (LPBYTE)&pPerUser->dwIsInstalled, sizeof(DWORD));
622 /***********************************************************************
623 * TranslateInfStringA (ADVPACK.@)
625 * See TranslateInfStringW.
627 HRESULT WINAPI TranslateInfStringA(LPCSTR pszInfFilename, LPCSTR pszInstallSection,
628 LPCSTR pszTranslateSection, LPCSTR pszTranslateKey, LPSTR pszBuffer,
629 DWORD dwBufferSize, PDWORD pdwRequiredSize, PVOID pvReserved)
631 UNICODE_STRING filenameW, installW;
632 UNICODE_STRING translateW, keyW;
637 TRACE("(%s, %s, %s, %s, %p, %ld, %p, %p)\n",
638 debugstr_a(pszInfFilename), debugstr_a(pszInstallSection),
639 debugstr_a(pszTranslateSection), debugstr_a(pszTranslateKey),
640 pszBuffer, dwBufferSize,pdwRequiredSize, pvReserved);
642 if (!pszInfFilename || !pszTranslateSection ||
643 !pszTranslateKey || !pdwRequiredSize)
646 RtlCreateUnicodeStringFromAsciiz(&filenameW, pszInfFilename);
647 RtlCreateUnicodeStringFromAsciiz(&installW, pszInstallSection);
648 RtlCreateUnicodeStringFromAsciiz(&translateW, pszTranslateSection);
649 RtlCreateUnicodeStringFromAsciiz(&keyW, pszTranslateKey);
651 res = TranslateInfStringW(filenameW.Buffer, installW.Buffer,
652 translateW.Buffer, keyW.Buffer, NULL,
653 dwBufferSize, &len, NULL);
657 bufferW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
659 res = TranslateInfStringW(filenameW.Buffer, installW.Buffer,
660 translateW.Buffer, keyW.Buffer, bufferW,
664 *pdwRequiredSize = WideCharToMultiByte(CP_ACP, 0, bufferW, -1,
665 NULL, 0, NULL, NULL);
667 if (dwBufferSize >= *pdwRequiredSize)
669 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, pszBuffer,
670 dwBufferSize, NULL, NULL);
673 res = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
676 HeapFree(GetProcessHeap(), 0, bufferW);
679 RtlFreeUnicodeString(&filenameW);
680 RtlFreeUnicodeString(&installW);
681 RtlFreeUnicodeString(&translateW);
682 RtlFreeUnicodeString(&keyW);
687 /***********************************************************************
688 * TranslateInfStringW (ADVPACK.@)
690 * Translates the value of a specified key in an inf file into the
691 * current locale by expanding string macros.
694 * pszInfFilename [I] Filename of the inf file.
695 * pszInstallSection [I]
696 * pszTranslateSection [I] Inf section where the key exists.
697 * pszTranslateKey [I] Key to translate.
698 * pszBuffer [O] Contains the translated string on exit.
699 * dwBufferSize [I] Size on input of pszBuffer.
700 * pdwRequiredSize [O] Length of the translated key.
701 * pvReserved [I] Reserved, must be NULL.
705 * Failure: An hresult error code.
707 HRESULT WINAPI TranslateInfStringW(LPCWSTR pszInfFilename, LPCWSTR pszInstallSection,
708 LPCWSTR pszTranslateSection, LPCWSTR pszTranslateKey, LPWSTR pszBuffer,
709 DWORD dwBufferSize, PDWORD pdwRequiredSize, PVOID pvReserved)
713 TRACE("(%s, %s, %s, %s, %p, %ld, %p, %p)\n",
714 debugstr_w(pszInfFilename), debugstr_w(pszInstallSection),
715 debugstr_w(pszTranslateSection), debugstr_w(pszTranslateKey),
716 pszBuffer, dwBufferSize,pdwRequiredSize, pvReserved);
718 if (!pszInfFilename || !pszTranslateSection ||
719 !pszTranslateKey || !pdwRequiredSize)
722 hInf = SetupOpenInfFileW(pszInfFilename, NULL, INF_STYLE_WIN4, NULL);
723 if (hInf == INVALID_HANDLE_VALUE)
724 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
726 set_ldids(hInf, pszInstallSection, NULL);
728 if (!SetupGetLineTextW(NULL, hInf, pszTranslateSection, pszTranslateKey,
729 pszBuffer, dwBufferSize, pdwRequiredSize))
731 if (dwBufferSize < *pdwRequiredSize)
732 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
734 return SPAPI_E_LINE_NOT_FOUND;
737 SetupCloseInfFile(hInf);
741 /***********************************************************************
742 * TranslateInfStringExA (ADVPACK.@)
744 * See TranslateInfStringExW.
746 HRESULT WINAPI TranslateInfStringExA(HINF hInf, LPCSTR pszInfFilename,
747 LPCSTR pszTranslateSection, LPCSTR pszTranslateKey,
748 LPSTR pszBuffer, DWORD dwBufferSize,
749 PDWORD pdwRequiredSize, PVOID pvReserved)
751 UNICODE_STRING filenameW, sectionW, keyW;
756 TRACE("(%p, %s, %s, %s, %s, %ld, %p, %p)\n", hInf, debugstr_a(pszInfFilename),
757 debugstr_a(pszTranslateSection), debugstr_a(pszTranslateKey),
758 debugstr_a(pszBuffer), dwBufferSize, pdwRequiredSize, pvReserved);
760 if (!pszInfFilename || !pszTranslateSection ||
761 !pszTranslateKey || !pdwRequiredSize)
764 RtlCreateUnicodeStringFromAsciiz(&filenameW, pszInfFilename);
765 RtlCreateUnicodeStringFromAsciiz(§ionW, pszTranslateSection);
766 RtlCreateUnicodeStringFromAsciiz(&keyW, pszTranslateKey);
768 res = TranslateInfStringExW(hInf, filenameW.Buffer, sectionW.Buffer,
769 keyW.Buffer, NULL, 0, &len, NULL);
773 bufferW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
775 res = TranslateInfStringExW(hInf, filenameW.Buffer, sectionW.Buffer,
776 keyW.Buffer, bufferW, len, &len, NULL);
780 *pdwRequiredSize = WideCharToMultiByte(CP_ACP, 0, bufferW, -1,
781 NULL, 0, NULL, NULL);
783 if (dwBufferSize >= *pdwRequiredSize)
785 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, pszBuffer,
786 dwBufferSize, NULL, NULL);
789 res = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
792 HeapFree(GetProcessHeap(), 0, bufferW);
795 RtlFreeUnicodeString(&filenameW);
796 RtlFreeUnicodeString(§ionW);
797 RtlFreeUnicodeString(&keyW);
802 /***********************************************************************
803 * TranslateInfStringExW (ADVPACK.@)
805 * Using a handle to an INF file opened with OpenINFEngine, translates
806 * the value of a specified key in an inf file into the current locale
807 * by expanding string macros.
810 * hInf [I] Handle to the INF file.
811 * pszInfFilename [I] Filename of the INF file.
812 * pszTranslateSection [I] Inf section where the key exists.
813 * pszTranslateKey [I] Key to translate.
814 * pszBuffer [O] Contains the translated string on exit.
815 * dwBufferSize [I] Size on input of pszBuffer.
816 * pdwRequiredSize [O] Length of the translated key.
817 * pvReserved [I] Reserved. Must be NULL.
824 * To use TranslateInfStringEx to translate an INF file continuously,
825 * open the INF file with OpenINFEngine, call TranslateInfStringEx as
826 * many times as needed, then release the handle with CloseINFEngine.
827 * When translating more than one keys, this method is more efficient
828 * than calling TranslateInfString, because the INF file is only
831 HRESULT WINAPI TranslateInfStringExW(HINF hInf, LPCWSTR pszInfFilename,
832 LPCWSTR pszTranslateSection, LPCWSTR pszTranslateKey,
833 LPWSTR pszBuffer, DWORD dwBufferSize,
834 PDWORD pdwRequiredSize, PVOID pvReserved)
836 TRACE("(%p, %s, %s, %s, %s, %ld, %p, %p)\n", hInf, debugstr_w(pszInfFilename),
837 debugstr_w(pszTranslateSection), debugstr_w(pszTranslateKey),
838 debugstr_w(pszBuffer), dwBufferSize, pdwRequiredSize, pvReserved);
840 if (!hInf || !pszInfFilename || !pszTranslateSection || !pszTranslateKey)
843 if (!SetupGetLineTextW(NULL, hInf, pszTranslateSection, pszTranslateKey,
844 pszBuffer, dwBufferSize, pdwRequiredSize))
846 if (dwBufferSize < *pdwRequiredSize)
847 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
849 return SPAPI_E_LINE_NOT_FOUND;
855 /***********************************************************************
856 * UserInstStubWrapperA (ADVPACK.@)
858 * See UserInstStubWrapperW.
860 HRESULT WINAPI UserInstStubWrapperA(HWND hWnd, HINSTANCE hInstance,
861 LPSTR pszParms, INT nShow)
863 UNICODE_STRING parmsW;
866 TRACE("(%p, %p, %s, %i)\n", hWnd, hInstance, debugstr_a(pszParms), nShow);
871 RtlCreateUnicodeStringFromAsciiz(&parmsW, pszParms);
873 res = UserInstStubWrapperW(hWnd, hInstance, parmsW.Buffer, nShow);
875 RtlFreeUnicodeString(&parmsW);
880 /***********************************************************************
881 * UserInstStubWrapperW (ADVPACK.@)
883 * Launches the user stub wrapper specified by the RealStubPath
884 * registry value under Installed Components\szParms.
887 * hWnd [I] Handle to the window used for the display.
888 * hInstance [I] Instance of the process.
889 * szParms [I] The GUID of the installation.
890 * show [I] How the window should be shown.
897 * If the type of the StubRealPath value is REG_EXPAND_SZ, then
898 * we should call ExpandEnvironmentStrings on the value and
901 HRESULT WINAPI UserInstStubWrapperW(HWND hWnd, HINSTANCE hInstance,
902 LPWSTR pszParms, INT nShow)
905 WCHAR stub[MAX_PATH];
906 DWORD size = MAX_PATH;
910 static const WCHAR real_stub_path[] = {
911 'R','e','a','l','S','t','u','b','P','a','t','h',0
914 TRACE("(%p, %p, %s, %i)\n", hWnd, hInstance, debugstr_w(pszParms), nShow);
916 if (!pszParms || !*pszParms)
919 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, setup_key, 0, KEY_READ, &setup))
924 if (RegOpenKeyExW(setup, pszParms, 0, KEY_READ, &guid))
930 res = RegQueryValueExW(guid, real_stub_path, NULL, NULL, (LPBYTE)stub, &size);
934 /* launch the user stub wrapper */
935 hr = launch_exe(stub, NULL, NULL);
944 /***********************************************************************
945 * UserUnInstStubWrapperA (ADVPACK.@)
947 * See UserUnInstStubWrapperW.
949 HRESULT WINAPI UserUnInstStubWrapperA(HWND hWnd, HINSTANCE hInstance,
950 LPSTR pszParms, INT nShow)
952 UNICODE_STRING parmsW;
955 TRACE("(%p, %p, %s, %i)\n", hWnd, hInstance, debugstr_a(pszParms), nShow);
960 RtlCreateUnicodeStringFromAsciiz(&parmsW, pszParms);
962 res = UserUnInstStubWrapperW(hWnd, hInstance, parmsW.Buffer, nShow);
964 RtlFreeUnicodeString(&parmsW);
969 /***********************************************************************
970 * UserUnInstStubWrapperW (ADVPACK.@)
972 HRESULT WINAPI UserUnInstStubWrapperW(HWND hWnd, HINSTANCE hInstance,
973 LPWSTR pszParms, INT nShow)
975 FIXME("(%p, %p, %s, %i): stub\n", hWnd, hInstance, debugstr_w(pszParms), nShow);