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"
36 WINE_DEFAULT_DEBUG_CHANNEL(advpack);
38 typedef HRESULT (WINAPI *DLLREGISTER) (void);
40 #define MAX_FIELD_LENGTH 512
43 HRESULT launch_exe(LPCWSTR cmd, LPCWSTR dir, HANDLE *phEXE);
45 /* registry path of the Installed Components key for per-user stubs */
46 static const WCHAR setup_key[] = {
47 'S','O','F','T','W','A','R','E','\\',
48 'M','i','c','r','o','s','o','f','t','\\',
49 'A','c','t','i','v','e',' ','S','e','t','u','p','\\',
50 'I','n','s','t','a','l','l','e','d',' ',
51 'C','o','m','p','o','n','e','n','t','s',0
54 /* parses the destination directory parameters from pszSection
55 * the parameters are of the form: root,key,value,unknown,fallback
56 * we first read the reg value root\\key\\value and if that fails,
57 * use fallback as the destination directory
59 static void get_dest_dir(HINF hInf, PCWSTR pszSection, PWSTR pszBuffer, DWORD dwSize)
62 WCHAR key[MAX_PATH], value[MAX_PATH];
63 WCHAR prefix[PREFIX_LEN];
67 static const WCHAR hklm[] = {'H','K','L','M',0};
68 static const WCHAR hkcu[] = {'H','K','C','U',0};
70 /* load the destination parameters */
71 SetupFindFirstLineW(hInf, pszSection, NULL, &context);
72 SetupGetStringFieldW(&context, 1, prefix, PREFIX_LEN, &size);
73 SetupGetStringFieldW(&context, 2, key, MAX_PATH, &size);
74 SetupGetStringFieldW(&context, 3, value, MAX_PATH, &size);
76 if (!lstrcmpW(prefix, hklm))
77 root = HKEY_LOCAL_MACHINE;
78 else if (!lstrcmpW(prefix, hkcu))
79 root = HKEY_CURRENT_USER;
83 size = dwSize * sizeof(WCHAR);
85 /* fallback to the default destination dir if reg fails */
86 if (RegOpenKeyW(root, key, &subkey) ||
87 RegQueryValueExW(subkey, value, NULL, NULL, (LPBYTE)pszBuffer, &size))
89 SetupGetStringFieldW(&context, 6, pszBuffer, dwSize, NULL);
95 /* loads the LDIDs specified in the install section of an INF */
96 static void set_ldids(HINF hInf, LPCWSTR pszInstallSection)
98 WCHAR field[MAX_FIELD_LENGTH];
99 WCHAR key[MAX_FIELD_LENGTH];
100 WCHAR dest[MAX_PATH];
105 static const WCHAR custDestW[] = {
106 'C','u','s','t','o','m','D','e','s','t','i','n','a','t','i','o','n',0
109 if (!SetupGetLineTextW(NULL, hInf, pszInstallSection, custDestW,
110 field, MAX_FIELD_LENGTH, &size))
113 if (!SetupFindFirstLineW(hInf, field, NULL, &context))
118 SetupGetIntField(&context, 0, &ldid);
119 SetupGetLineTextW(&context, NULL, NULL, NULL,
120 key, MAX_FIELD_LENGTH, &size);
122 get_dest_dir(hInf, key, dest, MAX_PATH);
124 SetupSetDirectoryIdW(hInf, ldid, dest);
125 } while (SetupFindNextLine(&context, &context));
128 /***********************************************************************
129 * CloseINFEngine (ADVPACK.@)
131 * Closes a handle to an INF file opened with OpenINFEngine.
134 * hInf [I] Handle to the INF file to close.
140 HRESULT WINAPI CloseINFEngine(HINF hInf)
142 TRACE("(%p)\n", hInf);
147 SetupCloseInfFile(hInf);
151 /***********************************************************************
152 * DllMain (ADVPACK.@)
154 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
156 TRACE("(%p, %ld, %p)\n", hinstDLL, fdwReason, lpvReserved);
158 if (fdwReason == DLL_PROCESS_ATTACH)
159 DisableThreadLibraryCalls(hinstDLL);
164 /***********************************************************************
165 * IsNTAdmin (ADVPACK.@)
167 * Checks if the user has admin privileges.
170 * reserved [I] Reserved. Must be 0.
171 * pReserved [I] Reserved. Must be NULL.
174 * TRUE if user has admin rights, FALSE otherwise.
176 BOOL WINAPI IsNTAdmin(DWORD reserved, LPDWORD pReserved)
178 SID_IDENTIFIER_AUTHORITY SidAuthority = {SECURITY_NT_AUTHORITY};
179 PTOKEN_GROUPS pTokenGroups;
180 BOOL bSidFound = FALSE;
185 TRACE("(%ld, %p)\n", reserved, pReserved);
187 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
190 if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwSize))
192 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
199 pTokenGroups = HeapAlloc(GetProcessHeap(), 0, dwSize);
206 if (!GetTokenInformation(hToken, TokenGroups, pTokenGroups, dwSize, &dwSize))
208 HeapFree(GetProcessHeap(), 0, pTokenGroups);
215 if (!AllocateAndInitializeSid(&SidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
216 DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pSid))
218 HeapFree(GetProcessHeap(), 0, pTokenGroups);
222 for (i = 0; i < pTokenGroups->GroupCount; i++)
224 if (EqualSid(pSid, pTokenGroups->Groups[i].Sid))
231 HeapFree(GetProcessHeap(), 0, pTokenGroups);
237 /***********************************************************************
238 * NeedRebootInit (ADVPACK.@)
240 * Sets up conditions for reboot checking.
243 * Value required by NeedReboot.
245 DWORD WINAPI NeedRebootInit(VOID)
247 FIXME("(VOID): stub\n");
251 /***********************************************************************
252 * NeedReboot (ADVPACK.@)
254 * Determines whether a reboot is required.
257 * dwRebootCheck [I] Value from NeedRebootInit.
260 * TRUE if a reboot is needed, FALSE otherwise.
265 BOOL WINAPI NeedReboot(DWORD dwRebootCheck)
267 FIXME("(%ld): stub\n", dwRebootCheck);
271 /***********************************************************************
272 * OpenINFEngineA (ADVPACK.@)
274 * See OpenINFEngineW.
276 HRESULT WINAPI OpenINFEngineA(LPCSTR pszInfFilename, LPCSTR pszInstallSection,
277 DWORD dwFlags, HINF *phInf, PVOID pvReserved)
279 UNICODE_STRING filenameW, installW;
282 TRACE("(%s, %s, %ld, %p, %p)\n", debugstr_a(pszInfFilename),
283 debugstr_a(pszInstallSection), dwFlags, phInf, pvReserved);
285 if (!pszInfFilename || !phInf)
288 RtlCreateUnicodeStringFromAsciiz(&filenameW, pszInfFilename);
289 RtlCreateUnicodeStringFromAsciiz(&installW, pszInstallSection);
291 res = OpenINFEngineW(filenameW.Buffer, installW.Buffer,
292 dwFlags, phInf, pvReserved);
294 RtlFreeUnicodeString(&filenameW);
295 RtlFreeUnicodeString(&installW);
300 /***********************************************************************
301 * OpenINFEngineW (ADVPACK.@)
303 * Opens and returns a handle to an INF file to be used by
304 * TranslateInfStringEx to continuously translate the INF file.
307 * pszInfFilename [I] Filename of the INF to open.
308 * pszInstallSection [I] Name of the Install section in the INF.
309 * dwFlags [I] See advpub.h.
310 * phInf [O] Handle to the loaded INF file.
311 * pvReserved [I] Reserved. Must be NULL.
317 HRESULT WINAPI OpenINFEngineW(LPCWSTR pszInfFilename, LPCWSTR pszInstallSection,
318 DWORD dwFlags, HINF *phInf, PVOID pvReserved)
320 TRACE("(%s, %s, %ld, %p, %p)\n", debugstr_w(pszInfFilename),
321 debugstr_w(pszInstallSection), dwFlags, phInf, pvReserved);
323 if (!pszInfFilename || !phInf)
326 *phInf = SetupOpenInfFileW(pszInfFilename, NULL, INF_STYLE_WIN4, NULL);
327 if (*phInf == INVALID_HANDLE_VALUE)
328 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
330 set_ldids(*phInf, pszInstallSection);
335 /***********************************************************************
336 * RebootCheckOnInstallA (ADVPACK.@)
338 * See RebootCheckOnInstallW.
340 HRESULT WINAPI RebootCheckOnInstallA(HWND hWnd, LPCSTR pszINF,
341 LPSTR pszSec, DWORD dwReserved)
343 UNICODE_STRING infW, secW;
346 TRACE("(%p, %s, %s, %ld)\n", hWnd, debugstr_a(pszINF),
347 debugstr_a(pszSec), dwReserved);
349 if (!pszINF || !pszSec)
352 RtlCreateUnicodeStringFromAsciiz(&infW, pszINF);
353 RtlCreateUnicodeStringFromAsciiz(&secW, pszSec);
355 res = RebootCheckOnInstallW(hWnd, infW.Buffer, secW.Buffer, dwReserved);
357 RtlFreeUnicodeString(&infW);
358 RtlFreeUnicodeString(&secW);
363 /***********************************************************************
364 * RebootCheckOnInstallW (ADVPACK.@)
366 * Checks if a reboot is required for an installed INF section.
369 * hWnd [I] Handle to the window used for messages.
370 * pszINF [I] Filename of the INF file.
371 * pszSec [I] INF section to check.
372 * dwReserved [I] Reserved. Must be 0.
375 * Success: S_OK - Reboot is needed if the INF section is installed.
376 * S_FALSE - Reboot is not needed.
377 * Failure: HRESULT of GetLastError().
380 * if pszSec is NULL, RebootCheckOnInstall checks the DefaultInstall
381 * or DefaultInstall.NT section.
386 HRESULT WINAPI RebootCheckOnInstallW(HWND hWnd, LPCWSTR pszINF,
387 LPWSTR pszSec, DWORD dwReserved)
389 FIXME("(%p, %s, %s, %ld): stub\n", hWnd, debugstr_w(pszINF),
390 debugstr_w(pszSec), dwReserved);
395 /***********************************************************************
396 * RegisterOCX (ADVPACK.@)
398 void WINAPI RegisterOCX(HWND hWnd, HINSTANCE hInst, LPCSTR cmdline, INT show)
400 WCHAR wszBuff[MAX_PATH];
403 DLLREGISTER pfnRegister;
406 TRACE("(%s)\n", debugstr_a(cmdline));
408 MultiByteToWideChar(CP_ACP, 0, cmdline, strlen(cmdline), wszBuff, MAX_PATH);
409 if ((pwcComma = strchrW( wszBuff, ',' ))) *pwcComma = 0;
411 TRACE("Parsed DLL name (%s)\n", debugstr_w(wszBuff));
413 hm = LoadLibraryExW(wszBuff, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
416 ERR("Couldn't load DLL: %s\n", debugstr_w(wszBuff));
420 pfnRegister = (DLLREGISTER)GetProcAddress(hm, "DllRegisterServer");
421 if (pfnRegister == NULL)
423 ERR("DllRegisterServer entry point not found\n");
430 ERR("DllRegisterServer entry point returned %08lx\n", hr);
434 TRACE("Successfully registered OCX\n");
439 /***********************************************************************
440 * SetPerUserSecValuesA (ADVPACK.@)
442 * See SetPerUserSecValuesW.
444 HRESULT WINAPI SetPerUserSecValuesA(PERUSERSECTIONA* pPerUser)
446 PERUSERSECTIONW perUserW;
448 TRACE("(%p)\n", pPerUser);
453 MultiByteToWideChar(CP_ACP, 0, pPerUser->szGUID, -1, perUserW.szGUID,
454 sizeof(perUserW.szGUID) / sizeof(WCHAR));
455 MultiByteToWideChar(CP_ACP, 0, pPerUser->szDispName, -1, perUserW.szDispName,
456 sizeof(perUserW.szDispName) / sizeof(WCHAR));
457 MultiByteToWideChar(CP_ACP, 0, pPerUser->szLocale, -1, perUserW.szLocale,
458 sizeof(perUserW.szLocale) / sizeof(WCHAR));
459 MultiByteToWideChar(CP_ACP, 0, pPerUser->szStub, -1, perUserW.szStub,
460 sizeof(perUserW.szStub) / sizeof(WCHAR));
461 MultiByteToWideChar(CP_ACP, 0, pPerUser->szVersion, -1, perUserW.szVersion,
462 sizeof(perUserW.szVersion) / sizeof(WCHAR));
463 MultiByteToWideChar(CP_ACP, 0, pPerUser->szCompID, -1, perUserW.szCompID,
464 sizeof(perUserW.szCompID) / sizeof(WCHAR));
465 perUserW.dwIsInstalled = pPerUser->dwIsInstalled;
466 perUserW.bRollback = pPerUser->bRollback;
468 return SetPerUserSecValuesW(&perUserW);
471 /***********************************************************************
472 * SetPerUserSecValuesW (ADVPACK.@)
474 * Prepares the per-user stub values under IsInstalled\{GUID} that
475 * control the per-user installation.
478 * pPerUser [I] Per-user stub values.
484 HRESULT WINAPI SetPerUserSecValuesW(PERUSERSECTIONW* pPerUser)
488 static const WCHAR stub_path[] = {'S','t','u','b','P','a','t','h',0};
489 static const WCHAR version[] = {'V','e','r','s','i','o','n',0};
490 static const WCHAR locale[] = {'L','o','c','a','l','e',0};
491 static const WCHAR compid[] = {'C','o','m','p','o','n','e','n','t','I','D',0};
492 static const WCHAR isinstalled[] = {'I','s','I','n','s','t','a','l','l','e','d',0};
494 TRACE("(%p)\n", pPerUser);
496 if (!pPerUser || !*pPerUser->szGUID)
499 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, setup_key, 0, NULL, 0, KEY_WRITE,
505 if (RegCreateKeyExW(setup, pPerUser->szGUID, 0, NULL, 0, KEY_ALL_ACCESS,
512 if (*pPerUser->szStub)
514 RegSetValueExW(guid, stub_path, 0, REG_SZ, (LPBYTE)pPerUser->szStub,
515 (lstrlenW(pPerUser->szStub) + 1) * sizeof(WCHAR));
518 if (*pPerUser->szVersion)
520 RegSetValueExW(guid, version, 0, REG_SZ, (LPBYTE)pPerUser->szVersion,
521 (lstrlenW(pPerUser->szVersion) + 1) * sizeof(WCHAR));
524 if (*pPerUser->szLocale)
526 RegSetValueExW(guid, locale, 0, REG_SZ, (LPBYTE)pPerUser->szLocale,
527 (lstrlenW(pPerUser->szLocale) + 1) * sizeof(WCHAR));
530 if (*pPerUser->szCompID)
532 RegSetValueExW(guid, compid, 0, REG_SZ, (LPBYTE)pPerUser->szCompID,
533 (lstrlenW(pPerUser->szCompID) + 1) * sizeof(WCHAR));
536 if (*pPerUser->szDispName)
538 RegSetValueExW(guid, NULL, 0, REG_SZ, (LPBYTE)pPerUser->szDispName,
539 (lstrlenW(pPerUser->szDispName) + 1) * sizeof(WCHAR));
542 RegSetValueExW(guid, isinstalled, 0, REG_DWORD,
543 (LPBYTE)&pPerUser->dwIsInstalled, sizeof(DWORD));
551 /***********************************************************************
552 * TranslateInfStringA (ADVPACK.@)
554 * See TranslateInfStringW.
556 HRESULT WINAPI TranslateInfStringA(LPCSTR pszInfFilename, LPCSTR pszInstallSection,
557 LPCSTR pszTranslateSection, LPCSTR pszTranslateKey, LPSTR pszBuffer,
558 DWORD dwBufferSize, PDWORD pdwRequiredSize, PVOID pvReserved)
560 UNICODE_STRING filenameW, installW;
561 UNICODE_STRING translateW, keyW;
566 TRACE("(%s, %s, %s, %s, %p, %ld, %p, %p)\n",
567 debugstr_a(pszInfFilename), debugstr_a(pszInstallSection),
568 debugstr_a(pszTranslateSection), debugstr_a(pszTranslateKey),
569 pszBuffer, dwBufferSize,pdwRequiredSize, pvReserved);
571 if (!pszInfFilename || !pszTranslateSection ||
572 !pszTranslateKey || !pdwRequiredSize)
575 RtlCreateUnicodeStringFromAsciiz(&filenameW, pszInfFilename);
576 RtlCreateUnicodeStringFromAsciiz(&installW, pszInstallSection);
577 RtlCreateUnicodeStringFromAsciiz(&translateW, pszTranslateSection);
578 RtlCreateUnicodeStringFromAsciiz(&keyW, pszTranslateKey);
580 res = TranslateInfStringW(filenameW.Buffer, installW.Buffer,
581 translateW.Buffer, keyW.Buffer, NULL,
582 dwBufferSize, &len, NULL);
586 bufferW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
588 res = TranslateInfStringW(filenameW.Buffer, installW.Buffer,
589 translateW.Buffer, keyW.Buffer, bufferW,
593 *pdwRequiredSize = WideCharToMultiByte(CP_ACP, 0, bufferW, -1,
594 NULL, 0, NULL, NULL);
596 if (dwBufferSize >= *pdwRequiredSize)
598 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, pszBuffer,
599 dwBufferSize, NULL, NULL);
602 res = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
605 HeapFree(GetProcessHeap(), 0, bufferW);
608 RtlFreeUnicodeString(&filenameW);
609 RtlFreeUnicodeString(&installW);
610 RtlFreeUnicodeString(&translateW);
611 RtlFreeUnicodeString(&keyW);
616 /***********************************************************************
617 * TranslateInfStringW (ADVPACK.@)
619 * Translates the value of a specified key in an inf file into the
620 * current locale by expanding string macros.
623 * pszInfFilename [I] Filename of the inf file.
624 * pszInstallSection [I]
625 * pszTranslateSection [I] Inf section where the key exists.
626 * pszTranslateKey [I] Key to translate.
627 * pszBuffer [O] Contains the translated string on exit.
628 * dwBufferSize [I] Size on input of pszBuffer.
629 * pdwRequiredSize [O] Length of the translated key.
630 * pvReserved [I] Reserved, must be NULL.
634 * Failure: An hresult error code.
636 HRESULT WINAPI TranslateInfStringW(LPCWSTR pszInfFilename, LPCWSTR pszInstallSection,
637 LPCWSTR pszTranslateSection, LPCWSTR pszTranslateKey, LPWSTR pszBuffer,
638 DWORD dwBufferSize, PDWORD pdwRequiredSize, PVOID pvReserved)
642 TRACE("(%s, %s, %s, %s, %p, %ld, %p, %p)\n",
643 debugstr_w(pszInfFilename), debugstr_w(pszInstallSection),
644 debugstr_w(pszTranslateSection), debugstr_w(pszTranslateKey),
645 pszBuffer, dwBufferSize,pdwRequiredSize, pvReserved);
647 if (!pszInfFilename || !pszTranslateSection ||
648 !pszTranslateKey || !pdwRequiredSize)
651 hInf = SetupOpenInfFileW(pszInfFilename, NULL, INF_STYLE_WIN4, NULL);
652 if (hInf == INVALID_HANDLE_VALUE)
653 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
655 set_ldids(hInf, pszInstallSection);
657 if (!SetupGetLineTextW(NULL, hInf, pszTranslateSection, pszTranslateKey,
658 pszBuffer, dwBufferSize, pdwRequiredSize))
660 if (dwBufferSize < *pdwRequiredSize)
661 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
663 return SPAPI_E_LINE_NOT_FOUND;
666 SetupCloseInfFile(hInf);
670 /***********************************************************************
671 * TranslateInfStringExA (ADVPACK.@)
673 * See TranslateInfStringExW.
675 HRESULT WINAPI TranslateInfStringExA(HINF hInf, LPCSTR pszInfFilename,
676 LPCSTR pszTranslateSection, LPCSTR pszTranslateKey,
677 LPSTR pszBuffer, DWORD dwBufferSize,
678 PDWORD pdwRequiredSize, PVOID pvReserved)
680 UNICODE_STRING filenameW, sectionW, keyW;
685 TRACE("(%p, %s, %s, %s, %s, %ld, %p, %p)\n", hInf, debugstr_a(pszInfFilename),
686 debugstr_a(pszTranslateSection), debugstr_a(pszTranslateKey),
687 debugstr_a(pszBuffer), dwBufferSize, pdwRequiredSize, pvReserved);
689 if (!pszInfFilename || !pszTranslateSection ||
690 !pszTranslateKey || !pdwRequiredSize)
693 RtlCreateUnicodeStringFromAsciiz(&filenameW, pszInfFilename);
694 RtlCreateUnicodeStringFromAsciiz(§ionW, pszTranslateSection);
695 RtlCreateUnicodeStringFromAsciiz(&keyW, pszTranslateKey);
697 res = TranslateInfStringExW(hInf, filenameW.Buffer, sectionW.Buffer,
698 keyW.Buffer, NULL, 0, &len, NULL);
702 bufferW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
704 res = TranslateInfStringExW(hInf, filenameW.Buffer, sectionW.Buffer,
705 keyW.Buffer, bufferW, len, &len, NULL);
709 *pdwRequiredSize = WideCharToMultiByte(CP_ACP, 0, bufferW, -1,
710 NULL, 0, NULL, NULL);
712 if (dwBufferSize >= *pdwRequiredSize)
714 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, pszBuffer,
715 dwBufferSize, NULL, NULL);
718 res = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
721 HeapFree(GetProcessHeap(), 0, bufferW);
724 RtlFreeUnicodeString(&filenameW);
725 RtlFreeUnicodeString(§ionW);
726 RtlFreeUnicodeString(&keyW);
731 /***********************************************************************
732 * TranslateInfStringExW (ADVPACK.@)
734 * Using a handle to an INF file opened with OpenINFEngine, translates
735 * the value of a specified key in an inf file into the current locale
736 * by expanding string macros.
739 * hInf [I] Handle to the INF file.
740 * pszInfFilename [I] Filename of the INF file.
741 * pszTranslateSection [I] Inf section where the key exists.
742 * pszTranslateKey [I] Key to translate.
743 * pszBuffer [O] Contains the translated string on exit.
744 * dwBufferSize [I] Size on input of pszBuffer.
745 * pdwRequiredSize [O] Length of the translated key.
746 * pvReserved [I] Reserved. Must be NULL.
753 * To use TranslateInfStringEx to translate an INF file continuously,
754 * open the INF file with OpenINFEngine, call TranslateInfStringEx as
755 * many times as needed, then release the handle with CloseINFEngine.
756 * When translating more than one keys, this method is more efficient
757 * than calling TranslateInfString, because the INF file is only
760 HRESULT WINAPI TranslateInfStringExW(HINF hInf, LPCWSTR pszInfFilename,
761 LPCWSTR pszTranslateSection, LPCWSTR pszTranslateKey,
762 LPWSTR pszBuffer, DWORD dwBufferSize,
763 PDWORD pdwRequiredSize, PVOID pvReserved)
765 TRACE("(%p, %s, %s, %s, %s, %ld, %p, %p)\n", hInf, debugstr_w(pszInfFilename),
766 debugstr_w(pszTranslateSection), debugstr_w(pszTranslateKey),
767 debugstr_w(pszBuffer), dwBufferSize, pdwRequiredSize, pvReserved);
769 if (!hInf || !pszInfFilename || !pszTranslateSection || !pszTranslateKey)
772 if (!SetupGetLineTextW(NULL, hInf, pszTranslateSection, pszTranslateKey,
773 pszBuffer, dwBufferSize, pdwRequiredSize))
775 if (dwBufferSize < *pdwRequiredSize)
776 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
778 return SPAPI_E_LINE_NOT_FOUND;
784 /***********************************************************************
785 * UserInstStubWrapperA (ADVPACK.@)
787 * See UserInstStubWrapperW.
789 HRESULT WINAPI UserInstStubWrapperA(HWND hWnd, HINSTANCE hInstance,
790 LPSTR pszParms, INT nShow)
792 UNICODE_STRING parmsW;
795 TRACE("(%p, %p, %s, %i)\n", hWnd, hInstance, debugstr_a(pszParms), nShow);
800 RtlCreateUnicodeStringFromAsciiz(&parmsW, pszParms);
802 res = UserInstStubWrapperW(hWnd, hInstance, parmsW.Buffer, nShow);
804 RtlFreeUnicodeString(&parmsW);
809 /***********************************************************************
810 * UserInstStubWrapperW (ADVPACK.@)
812 * Launches the user stub wrapper specified by the RealStubPath
813 * registry value under Installed Components\szParms.
816 * hWnd [I] Handle to the window used for the display.
817 * hInstance [I] Instance of the process.
818 * szParms [I] The GUID of the installation.
819 * show [I] How the window should be shown.
826 * If the type of the StubRealPath value is REG_EXPAND_SZ, then
827 * we should call ExpandEnvironmentStrings on the value and
830 HRESULT WINAPI UserInstStubWrapperW(HWND hWnd, HINSTANCE hInstance,
831 LPWSTR pszParms, INT nShow)
834 WCHAR stub[MAX_PATH];
835 DWORD size = MAX_PATH;
839 static const WCHAR real_stub_path[] = {
840 'R','e','a','l','S','t','u','b','P','a','t','h',0
843 TRACE("(%p, %p, %s, %i)\n", hWnd, hInstance, debugstr_w(pszParms), nShow);
845 if (!pszParms || !*pszParms)
848 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, setup_key, 0, KEY_READ, &setup))
853 if (RegOpenKeyExW(setup, pszParms, 0, KEY_READ, &guid))
859 res = RegQueryValueExW(guid, real_stub_path, NULL, NULL, (LPBYTE)stub, &size);
863 /* launch the user stub wrapper */
864 hr = launch_exe(stub, NULL, NULL);
873 /***********************************************************************
874 * UserUnInstStubWrapperA (ADVPACK.@)
876 * See UserUnInstStubWrapperW.
878 HRESULT WINAPI UserUnInstStubWrapperA(HWND hWnd, HINSTANCE hInstance,
879 LPSTR pszParms, INT nShow)
881 UNICODE_STRING parmsW;
884 TRACE("(%p, %p, %s, %i)\n", hWnd, hInstance, debugstr_a(pszParms), nShow);
889 RtlCreateUnicodeStringFromAsciiz(&parmsW, pszParms);
891 res = UserUnInstStubWrapperW(hWnd, hInstance, parmsW.Buffer, nShow);
893 RtlFreeUnicodeString(&parmsW);
898 /***********************************************************************
899 * UserUnInstStubWrapperW (ADVPACK.@)
901 HRESULT WINAPI UserUnInstStubWrapperW(HWND hWnd, HINSTANCE hInstance,
902 LPWSTR pszParms, INT nShow)
904 FIXME("(%p, %p, %s, %i): stub\n", hWnd, hInstance, debugstr_w(pszParms), nShow);