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.@)
401 * hWnd [I] Handle to the window used for the display.
402 * hInst [I] Instance of the process.
403 * cmdline [I] Contains parameters in the order OCX,reboot,install_cmd
404 * show [I] How the window should be shown.
407 * This function does not return anything.
410 * OCX - Filename of the OCX to register.
411 * reboot - smart reboot behavior
412 * 'I' Reboot if needed.
414 * install_cmd - Command line to pass to the OCX's DllInstall.
416 void WINAPI
RegisterOCX(HWND hWnd
, HINSTANCE hInst
, LPCSTR cmdline
, INT show
)
418 WCHAR wszBuff
[MAX_PATH
];
421 DLLREGISTER pfnRegister
;
424 TRACE("(%s)\n", debugstr_a(cmdline
));
426 MultiByteToWideChar(CP_ACP
, 0, cmdline
, strlen(cmdline
), wszBuff
, MAX_PATH
);
427 if ((pwcComma
= strchrW( wszBuff
, ',' ))) *pwcComma
= 0;
429 TRACE("Parsed DLL name (%s)\n", debugstr_w(wszBuff
));
431 hm
= LoadLibraryExW(wszBuff
, 0, LOAD_WITH_ALTERED_SEARCH_PATH
);
434 ERR("Couldn't load DLL: %s\n", debugstr_w(wszBuff
));
438 pfnRegister
= (DLLREGISTER
)GetProcAddress(hm
, "DllRegisterServer");
439 if (pfnRegister
== NULL
)
441 ERR("DllRegisterServer entry point not found\n");
448 ERR("DllRegisterServer entry point returned %08lx\n", hr
);
452 TRACE("Successfully registered OCX\n");
457 /***********************************************************************
458 * SetPerUserSecValuesA (ADVPACK.@)
460 * See SetPerUserSecValuesW.
462 HRESULT WINAPI
SetPerUserSecValuesA(PERUSERSECTIONA
* pPerUser
)
464 PERUSERSECTIONW perUserW
;
466 TRACE("(%p)\n", pPerUser
);
471 MultiByteToWideChar(CP_ACP
, 0, pPerUser
->szGUID
, -1, perUserW
.szGUID
,
472 sizeof(perUserW
.szGUID
) / sizeof(WCHAR
));
473 MultiByteToWideChar(CP_ACP
, 0, pPerUser
->szDispName
, -1, perUserW
.szDispName
,
474 sizeof(perUserW
.szDispName
) / sizeof(WCHAR
));
475 MultiByteToWideChar(CP_ACP
, 0, pPerUser
->szLocale
, -1, perUserW
.szLocale
,
476 sizeof(perUserW
.szLocale
) / sizeof(WCHAR
));
477 MultiByteToWideChar(CP_ACP
, 0, pPerUser
->szStub
, -1, perUserW
.szStub
,
478 sizeof(perUserW
.szStub
) / sizeof(WCHAR
));
479 MultiByteToWideChar(CP_ACP
, 0, pPerUser
->szVersion
, -1, perUserW
.szVersion
,
480 sizeof(perUserW
.szVersion
) / sizeof(WCHAR
));
481 MultiByteToWideChar(CP_ACP
, 0, pPerUser
->szCompID
, -1, perUserW
.szCompID
,
482 sizeof(perUserW
.szCompID
) / sizeof(WCHAR
));
483 perUserW
.dwIsInstalled
= pPerUser
->dwIsInstalled
;
484 perUserW
.bRollback
= pPerUser
->bRollback
;
486 return SetPerUserSecValuesW(&perUserW
);
489 /***********************************************************************
490 * SetPerUserSecValuesW (ADVPACK.@)
492 * Prepares the per-user stub values under IsInstalled\{GUID} that
493 * control the per-user installation.
496 * pPerUser [I] Per-user stub values.
502 HRESULT WINAPI
SetPerUserSecValuesW(PERUSERSECTIONW
* pPerUser
)
506 static const WCHAR stub_path
[] = {'S','t','u','b','P','a','t','h',0};
507 static const WCHAR version
[] = {'V','e','r','s','i','o','n',0};
508 static const WCHAR locale
[] = {'L','o','c','a','l','e',0};
509 static const WCHAR compid
[] = {'C','o','m','p','o','n','e','n','t','I','D',0};
510 static const WCHAR isinstalled
[] = {'I','s','I','n','s','t','a','l','l','e','d',0};
512 TRACE("(%p)\n", pPerUser
);
514 if (!pPerUser
|| !*pPerUser
->szGUID
)
517 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
, setup_key
, 0, NULL
, 0, KEY_WRITE
,
523 if (RegCreateKeyExW(setup
, pPerUser
->szGUID
, 0, NULL
, 0, KEY_ALL_ACCESS
,
530 if (*pPerUser
->szStub
)
532 RegSetValueExW(guid
, stub_path
, 0, REG_SZ
, (LPBYTE
)pPerUser
->szStub
,
533 (lstrlenW(pPerUser
->szStub
) + 1) * sizeof(WCHAR
));
536 if (*pPerUser
->szVersion
)
538 RegSetValueExW(guid
, version
, 0, REG_SZ
, (LPBYTE
)pPerUser
->szVersion
,
539 (lstrlenW(pPerUser
->szVersion
) + 1) * sizeof(WCHAR
));
542 if (*pPerUser
->szLocale
)
544 RegSetValueExW(guid
, locale
, 0, REG_SZ
, (LPBYTE
)pPerUser
->szLocale
,
545 (lstrlenW(pPerUser
->szLocale
) + 1) * sizeof(WCHAR
));
548 if (*pPerUser
->szCompID
)
550 RegSetValueExW(guid
, compid
, 0, REG_SZ
, (LPBYTE
)pPerUser
->szCompID
,
551 (lstrlenW(pPerUser
->szCompID
) + 1) * sizeof(WCHAR
));
554 if (*pPerUser
->szDispName
)
556 RegSetValueExW(guid
, NULL
, 0, REG_SZ
, (LPBYTE
)pPerUser
->szDispName
,
557 (lstrlenW(pPerUser
->szDispName
) + 1) * sizeof(WCHAR
));
560 RegSetValueExW(guid
, isinstalled
, 0, REG_DWORD
,
561 (LPBYTE
)&pPerUser
->dwIsInstalled
, sizeof(DWORD
));
569 /***********************************************************************
570 * TranslateInfStringA (ADVPACK.@)
572 * See TranslateInfStringW.
574 HRESULT WINAPI
TranslateInfStringA(LPCSTR pszInfFilename
, LPCSTR pszInstallSection
,
575 LPCSTR pszTranslateSection
, LPCSTR pszTranslateKey
, LPSTR pszBuffer
,
576 DWORD dwBufferSize
, PDWORD pdwRequiredSize
, PVOID pvReserved
)
578 UNICODE_STRING filenameW
, installW
;
579 UNICODE_STRING translateW
, keyW
;
584 TRACE("(%s, %s, %s, %s, %p, %ld, %p, %p)\n",
585 debugstr_a(pszInfFilename
), debugstr_a(pszInstallSection
),
586 debugstr_a(pszTranslateSection
), debugstr_a(pszTranslateKey
),
587 pszBuffer
, dwBufferSize
,pdwRequiredSize
, pvReserved
);
589 if (!pszInfFilename
|| !pszTranslateSection
||
590 !pszTranslateKey
|| !pdwRequiredSize
)
593 RtlCreateUnicodeStringFromAsciiz(&filenameW
, pszInfFilename
);
594 RtlCreateUnicodeStringFromAsciiz(&installW
, pszInstallSection
);
595 RtlCreateUnicodeStringFromAsciiz(&translateW
, pszTranslateSection
);
596 RtlCreateUnicodeStringFromAsciiz(&keyW
, pszTranslateKey
);
598 res
= TranslateInfStringW(filenameW
.Buffer
, installW
.Buffer
,
599 translateW
.Buffer
, keyW
.Buffer
, NULL
,
600 dwBufferSize
, &len
, NULL
);
604 bufferW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
606 res
= TranslateInfStringW(filenameW
.Buffer
, installW
.Buffer
,
607 translateW
.Buffer
, keyW
.Buffer
, bufferW
,
611 *pdwRequiredSize
= WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1,
612 NULL
, 0, NULL
, NULL
);
614 if (dwBufferSize
>= *pdwRequiredSize
)
616 WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, pszBuffer
,
617 dwBufferSize
, NULL
, NULL
);
620 res
= HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
623 HeapFree(GetProcessHeap(), 0, bufferW
);
626 RtlFreeUnicodeString(&filenameW
);
627 RtlFreeUnicodeString(&installW
);
628 RtlFreeUnicodeString(&translateW
);
629 RtlFreeUnicodeString(&keyW
);
634 /***********************************************************************
635 * TranslateInfStringW (ADVPACK.@)
637 * Translates the value of a specified key in an inf file into the
638 * current locale by expanding string macros.
641 * pszInfFilename [I] Filename of the inf file.
642 * pszInstallSection [I]
643 * pszTranslateSection [I] Inf section where the key exists.
644 * pszTranslateKey [I] Key to translate.
645 * pszBuffer [O] Contains the translated string on exit.
646 * dwBufferSize [I] Size on input of pszBuffer.
647 * pdwRequiredSize [O] Length of the translated key.
648 * pvReserved [I] Reserved, must be NULL.
652 * Failure: An hresult error code.
654 HRESULT WINAPI
TranslateInfStringW(LPCWSTR pszInfFilename
, LPCWSTR pszInstallSection
,
655 LPCWSTR pszTranslateSection
, LPCWSTR pszTranslateKey
, LPWSTR pszBuffer
,
656 DWORD dwBufferSize
, PDWORD pdwRequiredSize
, PVOID pvReserved
)
660 TRACE("(%s, %s, %s, %s, %p, %ld, %p, %p)\n",
661 debugstr_w(pszInfFilename
), debugstr_w(pszInstallSection
),
662 debugstr_w(pszTranslateSection
), debugstr_w(pszTranslateKey
),
663 pszBuffer
, dwBufferSize
,pdwRequiredSize
, pvReserved
);
665 if (!pszInfFilename
|| !pszTranslateSection
||
666 !pszTranslateKey
|| !pdwRequiredSize
)
669 hInf
= SetupOpenInfFileW(pszInfFilename
, NULL
, INF_STYLE_WIN4
, NULL
);
670 if (hInf
== INVALID_HANDLE_VALUE
)
671 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
673 set_ldids(hInf
, pszInstallSection
);
675 if (!SetupGetLineTextW(NULL
, hInf
, pszTranslateSection
, pszTranslateKey
,
676 pszBuffer
, dwBufferSize
, pdwRequiredSize
))
678 if (dwBufferSize
< *pdwRequiredSize
)
679 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
681 return SPAPI_E_LINE_NOT_FOUND
;
684 SetupCloseInfFile(hInf
);
688 /***********************************************************************
689 * TranslateInfStringExA (ADVPACK.@)
691 * See TranslateInfStringExW.
693 HRESULT WINAPI
TranslateInfStringExA(HINF hInf
, LPCSTR pszInfFilename
,
694 LPCSTR pszTranslateSection
, LPCSTR pszTranslateKey
,
695 LPSTR pszBuffer
, DWORD dwBufferSize
,
696 PDWORD pdwRequiredSize
, PVOID pvReserved
)
698 UNICODE_STRING filenameW
, sectionW
, keyW
;
703 TRACE("(%p, %s, %s, %s, %s, %ld, %p, %p)\n", hInf
, debugstr_a(pszInfFilename
),
704 debugstr_a(pszTranslateSection
), debugstr_a(pszTranslateKey
),
705 debugstr_a(pszBuffer
), dwBufferSize
, pdwRequiredSize
, pvReserved
);
707 if (!pszInfFilename
|| !pszTranslateSection
||
708 !pszTranslateKey
|| !pdwRequiredSize
)
711 RtlCreateUnicodeStringFromAsciiz(&filenameW
, pszInfFilename
);
712 RtlCreateUnicodeStringFromAsciiz(§ionW
, pszTranslateSection
);
713 RtlCreateUnicodeStringFromAsciiz(&keyW
, pszTranslateKey
);
715 res
= TranslateInfStringExW(hInf
, filenameW
.Buffer
, sectionW
.Buffer
,
716 keyW
.Buffer
, NULL
, 0, &len
, NULL
);
720 bufferW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
722 res
= TranslateInfStringExW(hInf
, filenameW
.Buffer
, sectionW
.Buffer
,
723 keyW
.Buffer
, bufferW
, len
, &len
, NULL
);
727 *pdwRequiredSize
= WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1,
728 NULL
, 0, NULL
, NULL
);
730 if (dwBufferSize
>= *pdwRequiredSize
)
732 WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, pszBuffer
,
733 dwBufferSize
, NULL
, NULL
);
736 res
= HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
739 HeapFree(GetProcessHeap(), 0, bufferW
);
742 RtlFreeUnicodeString(&filenameW
);
743 RtlFreeUnicodeString(§ionW
);
744 RtlFreeUnicodeString(&keyW
);
749 /***********************************************************************
750 * TranslateInfStringExW (ADVPACK.@)
752 * Using a handle to an INF file opened with OpenINFEngine, translates
753 * the value of a specified key in an inf file into the current locale
754 * by expanding string macros.
757 * hInf [I] Handle to the INF file.
758 * pszInfFilename [I] Filename of the INF file.
759 * pszTranslateSection [I] Inf section where the key exists.
760 * pszTranslateKey [I] Key to translate.
761 * pszBuffer [O] Contains the translated string on exit.
762 * dwBufferSize [I] Size on input of pszBuffer.
763 * pdwRequiredSize [O] Length of the translated key.
764 * pvReserved [I] Reserved. Must be NULL.
771 * To use TranslateInfStringEx to translate an INF file continuously,
772 * open the INF file with OpenINFEngine, call TranslateInfStringEx as
773 * many times as needed, then release the handle with CloseINFEngine.
774 * When translating more than one keys, this method is more efficient
775 * than calling TranslateInfString, because the INF file is only
778 HRESULT WINAPI
TranslateInfStringExW(HINF hInf
, LPCWSTR pszInfFilename
,
779 LPCWSTR pszTranslateSection
, LPCWSTR pszTranslateKey
,
780 LPWSTR pszBuffer
, DWORD dwBufferSize
,
781 PDWORD pdwRequiredSize
, PVOID pvReserved
)
783 TRACE("(%p, %s, %s, %s, %s, %ld, %p, %p)\n", hInf
, debugstr_w(pszInfFilename
),
784 debugstr_w(pszTranslateSection
), debugstr_w(pszTranslateKey
),
785 debugstr_w(pszBuffer
), dwBufferSize
, pdwRequiredSize
, pvReserved
);
787 if (!hInf
|| !pszInfFilename
|| !pszTranslateSection
|| !pszTranslateKey
)
790 if (!SetupGetLineTextW(NULL
, hInf
, pszTranslateSection
, pszTranslateKey
,
791 pszBuffer
, dwBufferSize
, pdwRequiredSize
))
793 if (dwBufferSize
< *pdwRequiredSize
)
794 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
796 return SPAPI_E_LINE_NOT_FOUND
;
802 /***********************************************************************
803 * UserInstStubWrapperA (ADVPACK.@)
805 * See UserInstStubWrapperW.
807 HRESULT WINAPI
UserInstStubWrapperA(HWND hWnd
, HINSTANCE hInstance
,
808 LPSTR pszParms
, INT nShow
)
810 UNICODE_STRING parmsW
;
813 TRACE("(%p, %p, %s, %i)\n", hWnd
, hInstance
, debugstr_a(pszParms
), nShow
);
818 RtlCreateUnicodeStringFromAsciiz(&parmsW
, pszParms
);
820 res
= UserInstStubWrapperW(hWnd
, hInstance
, parmsW
.Buffer
, nShow
);
822 RtlFreeUnicodeString(&parmsW
);
827 /***********************************************************************
828 * UserInstStubWrapperW (ADVPACK.@)
830 * Launches the user stub wrapper specified by the RealStubPath
831 * registry value under Installed Components\szParms.
834 * hWnd [I] Handle to the window used for the display.
835 * hInstance [I] Instance of the process.
836 * szParms [I] The GUID of the installation.
837 * show [I] How the window should be shown.
844 * If the type of the StubRealPath value is REG_EXPAND_SZ, then
845 * we should call ExpandEnvironmentStrings on the value and
848 HRESULT WINAPI
UserInstStubWrapperW(HWND hWnd
, HINSTANCE hInstance
,
849 LPWSTR pszParms
, INT nShow
)
852 WCHAR stub
[MAX_PATH
];
853 DWORD size
= MAX_PATH
;
857 static const WCHAR real_stub_path
[] = {
858 'R','e','a','l','S','t','u','b','P','a','t','h',0
861 TRACE("(%p, %p, %s, %i)\n", hWnd
, hInstance
, debugstr_w(pszParms
), nShow
);
863 if (!pszParms
|| !*pszParms
)
866 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, setup_key
, 0, KEY_READ
, &setup
))
871 if (RegOpenKeyExW(setup
, pszParms
, 0, KEY_READ
, &guid
))
877 res
= RegQueryValueExW(guid
, real_stub_path
, NULL
, NULL
, (LPBYTE
)stub
, &size
);
881 /* launch the user stub wrapper */
882 hr
= launch_exe(stub
, NULL
, NULL
);
891 /***********************************************************************
892 * UserUnInstStubWrapperA (ADVPACK.@)
894 * See UserUnInstStubWrapperW.
896 HRESULT WINAPI
UserUnInstStubWrapperA(HWND hWnd
, HINSTANCE hInstance
,
897 LPSTR pszParms
, INT nShow
)
899 UNICODE_STRING parmsW
;
902 TRACE("(%p, %p, %s, %i)\n", hWnd
, hInstance
, debugstr_a(pszParms
), nShow
);
907 RtlCreateUnicodeStringFromAsciiz(&parmsW
, pszParms
);
909 res
= UserUnInstStubWrapperW(hWnd
, hInstance
, parmsW
.Buffer
, nShow
);
911 RtlFreeUnicodeString(&parmsW
);
916 /***********************************************************************
917 * UserUnInstStubWrapperW (ADVPACK.@)
919 HRESULT WINAPI
UserUnInstStubWrapperW(HWND hWnd
, HINSTANCE hInstance
,
920 LPWSTR pszParms
, INT nShow
)
922 FIXME("(%p, %p, %s, %i): stub\n", hWnd
, hInstance
, debugstr_w(pszParms
), nShow
);