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
22 #define WIN32_NO_STATUS
32 //#include "setupapi.h"
34 #include <wine/unicode.h>
35 #include <wine/debug.h>
36 #include "advpack_private.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(advpack
);
40 typedef HRESULT (WINAPI
*DLLREGISTER
) (void);
42 #define MAX_FIELD_LENGTH 512
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 /* Strip single quotes from a token - note size includes NULL */
55 static void strip_quotes(WCHAR
*buffer
, DWORD
*size
)
57 if (buffer
[0] == '\'' && (*size
> 1) && buffer
[*size
-2]=='\'')
61 memmove(buffer
, buffer
+ 1, *size
* sizeof(WCHAR
));
65 /* parses the destination directory parameters from pszSection
66 * the parameters are of the form: root,key,value,unknown,fallback
67 * we first read the reg value root\\key\\value and if that fails,
68 * use fallback as the destination directory
70 static void get_dest_dir(HINF hInf
, PCWSTR pszSection
, PWSTR pszBuffer
, DWORD dwSize
)
73 WCHAR key
[MAX_PATH
+ 2], value
[MAX_PATH
+ 2];
74 WCHAR prefix
[PREFIX_LEN
+ 2];
75 HKEY root
, subkey
= 0;
78 static const WCHAR hklm
[] = {'H','K','L','M',0};
79 static const WCHAR hkcu
[] = {'H','K','C','U',0};
81 /* load the destination parameters */
82 SetupFindFirstLineW(hInf
, pszSection
, NULL
, &context
);
83 SetupGetStringFieldW(&context
, 1, prefix
, PREFIX_LEN
+ 2, &size
);
84 strip_quotes(prefix
, &size
);
85 SetupGetStringFieldW(&context
, 2, key
, MAX_PATH
+ 2, &size
);
86 strip_quotes(key
, &size
);
87 SetupGetStringFieldW(&context
, 3, value
, MAX_PATH
+ 2, &size
);
88 strip_quotes(value
, &size
);
90 if (!lstrcmpW(prefix
, hklm
))
91 root
= HKEY_LOCAL_MACHINE
;
92 else if (!lstrcmpW(prefix
, hkcu
))
93 root
= HKEY_CURRENT_USER
;
97 size
= dwSize
* sizeof(WCHAR
);
99 /* fallback to the default destination dir if reg fails */
100 if (RegOpenKeyW(root
, key
, &subkey
) ||
101 RegQueryValueExW(subkey
, value
, NULL
, NULL
, (LPBYTE
)pszBuffer
, &size
))
103 SetupGetStringFieldW(&context
, 5, pszBuffer
, dwSize
, &size
);
104 strip_quotes(pszBuffer
, &size
);
107 if (subkey
) RegCloseKey(subkey
);
110 /* loads the LDIDs specified in the install section of an INF */
111 void set_ldids(HINF hInf
, LPCWSTR pszInstallSection
, LPCWSTR pszWorkingDir
)
113 WCHAR field
[MAX_FIELD_LENGTH
];
114 WCHAR line
[MAX_FIELD_LENGTH
];
115 WCHAR dest
[MAX_PATH
];
120 static const WCHAR source_dir
[] = {'S','o','u','r','c','e','D','i','r',0};
122 static const WCHAR custDestW
[] = {
123 'C','u','s','t','o','m','D','e','s','t','i','n','a','t','i','o','n',0
126 if (!SetupGetLineTextW(NULL
, hInf
, pszInstallSection
, custDestW
,
127 field
, MAX_FIELD_LENGTH
, &size
))
130 if (!SetupFindFirstLineW(hInf
, field
, NULL
, &context
))
135 LPWSTR value
, ptr
, key
, key_copy
= NULL
;
138 SetupGetLineTextW(&context
, NULL
, NULL
, NULL
,
139 line
, MAX_FIELD_LENGTH
, &size
);
141 /* SetupGetLineTextW returns the value if there is only one key, but
142 * returns the whole line if there is more than one key
144 if (!(value
= strchrW(line
, '=')))
146 SetupGetStringFieldW(&context
, 0, NULL
, 0, &size
);
147 key
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
149 SetupGetStringFieldW(&context
, 0, key
, size
, &size
);
158 /* remove leading whitespace from the value */
159 while (*value
== ' ')
162 /* Extract the flags */
163 ptr
= strchrW(value
, ',');
166 flags
= atolW(ptr
+1);
169 /* set dest to pszWorkingDir if key is SourceDir */
170 if (pszWorkingDir
&& !lstrcmpiW(value
, source_dir
))
171 lstrcpynW(dest
, pszWorkingDir
, MAX_PATH
);
173 get_dest_dir(hInf
, value
, dest
, MAX_PATH
);
175 /* If prompting required, provide dialog to request path */
177 FIXME("Need to support changing paths - default will be used\n");
179 /* set all ldids to dest */
180 while ((ptr
= get_parameter(&key
, ',')))
183 SetupSetDirectoryIdW(hInf
, ldid
, dest
);
185 HeapFree(GetProcessHeap(), 0, key_copy
);
186 } while (SetupFindNextLine(&context
, &context
));
189 /***********************************************************************
190 * CloseINFEngine (ADVPACK.@)
192 * Closes a handle to an INF file opened with OpenINFEngine.
195 * hInf [I] Handle to the INF file to close.
201 HRESULT WINAPI
CloseINFEngine(HINF hInf
)
203 TRACE("(%p)\n", hInf
);
208 SetupCloseInfFile(hInf
);
212 /***********************************************************************
213 * DllMain (ADVPACK.@)
215 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
217 TRACE("(%p, %d, %p)\n", hinstDLL
, fdwReason
, lpvReserved
);
219 if (fdwReason
== DLL_PROCESS_ATTACH
)
220 DisableThreadLibraryCalls(hinstDLL
);
225 /***********************************************************************
226 * IsNTAdmin (ADVPACK.@)
228 * Checks if the user has admin privileges.
231 * reserved [I] Reserved. Must be 0.
232 * pReserved [I] Reserved. Must be NULL.
235 * TRUE if user has admin rights, FALSE otherwise.
237 BOOL WINAPI
IsNTAdmin(DWORD reserved
, LPDWORD pReserved
)
239 SID_IDENTIFIER_AUTHORITY SidAuthority
= {SECURITY_NT_AUTHORITY
};
240 PTOKEN_GROUPS pTokenGroups
;
241 BOOL bSidFound
= FALSE
;
246 TRACE("(%d, %p)\n", reserved
, pReserved
);
248 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
))
251 if (!GetTokenInformation(hToken
, TokenGroups
, NULL
, 0, &dwSize
))
253 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
260 pTokenGroups
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
267 if (!GetTokenInformation(hToken
, TokenGroups
, pTokenGroups
, dwSize
, &dwSize
))
269 HeapFree(GetProcessHeap(), 0, pTokenGroups
);
276 if (!AllocateAndInitializeSid(&SidAuthority
, 2, SECURITY_BUILTIN_DOMAIN_RID
,
277 DOMAIN_ALIAS_RID_ADMINS
, 0, 0, 0, 0, 0, 0, &pSid
))
279 HeapFree(GetProcessHeap(), 0, pTokenGroups
);
283 for (i
= 0; i
< pTokenGroups
->GroupCount
; i
++)
285 if (EqualSid(pSid
, pTokenGroups
->Groups
[i
].Sid
))
292 HeapFree(GetProcessHeap(), 0, pTokenGroups
);
298 /***********************************************************************
299 * NeedRebootInit (ADVPACK.@)
301 * Sets up conditions for reboot checking.
304 * Value required by NeedReboot.
306 DWORD WINAPI
NeedRebootInit(VOID
)
308 FIXME("(VOID): stub\n");
312 /***********************************************************************
313 * NeedReboot (ADVPACK.@)
315 * Determines whether a reboot is required.
318 * dwRebootCheck [I] Value from NeedRebootInit.
321 * TRUE if a reboot is needed, FALSE otherwise.
326 BOOL WINAPI
NeedReboot(DWORD dwRebootCheck
)
328 FIXME("(%d): stub\n", dwRebootCheck
);
332 /***********************************************************************
333 * OpenINFEngineA (ADVPACK.@)
335 * See OpenINFEngineW.
337 HRESULT WINAPI
OpenINFEngineA(LPCSTR pszInfFilename
, LPCSTR pszInstallSection
,
338 DWORD dwFlags
, HINF
*phInf
, PVOID pvReserved
)
340 UNICODE_STRING filenameW
, installW
;
343 TRACE("(%s, %s, %d, %p, %p)\n", debugstr_a(pszInfFilename
),
344 debugstr_a(pszInstallSection
), dwFlags
, phInf
, pvReserved
);
346 if (!pszInfFilename
|| !phInf
)
349 RtlCreateUnicodeStringFromAsciiz(&filenameW
, pszInfFilename
);
350 RtlCreateUnicodeStringFromAsciiz(&installW
, pszInstallSection
);
352 res
= OpenINFEngineW(filenameW
.Buffer
, installW
.Buffer
,
353 dwFlags
, phInf
, pvReserved
);
355 RtlFreeUnicodeString(&filenameW
);
356 RtlFreeUnicodeString(&installW
);
361 /***********************************************************************
362 * OpenINFEngineW (ADVPACK.@)
364 * Opens and returns a handle to an INF file to be used by
365 * TranslateInfStringEx to continuously translate the INF file.
368 * pszInfFilename [I] Filename of the INF to open.
369 * pszInstallSection [I] Name of the Install section in the INF.
370 * dwFlags [I] See advpub.h.
371 * phInf [O] Handle to the loaded INF file.
372 * pvReserved [I] Reserved. Must be NULL.
378 HRESULT WINAPI
OpenINFEngineW(LPCWSTR pszInfFilename
, LPCWSTR pszInstallSection
,
379 DWORD dwFlags
, HINF
*phInf
, PVOID pvReserved
)
381 TRACE("(%s, %s, %d, %p, %p)\n", debugstr_w(pszInfFilename
),
382 debugstr_w(pszInstallSection
), dwFlags
, phInf
, pvReserved
);
384 if (!pszInfFilename
|| !phInf
)
387 *phInf
= SetupOpenInfFileW(pszInfFilename
, NULL
, INF_STYLE_WIN4
, NULL
);
388 if (*phInf
== INVALID_HANDLE_VALUE
)
389 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
391 set_ldids(*phInf
, pszInstallSection
, NULL
);
396 /***********************************************************************
397 * RebootCheckOnInstallA (ADVPACK.@)
399 * See RebootCheckOnInstallW.
401 HRESULT WINAPI
RebootCheckOnInstallA(HWND hWnd
, LPCSTR pszINF
,
402 LPCSTR pszSec
, DWORD dwReserved
)
404 UNICODE_STRING infW
, secW
;
407 TRACE("(%p, %s, %s, %d)\n", hWnd
, debugstr_a(pszINF
),
408 debugstr_a(pszSec
), dwReserved
);
410 if (!pszINF
|| !pszSec
)
413 RtlCreateUnicodeStringFromAsciiz(&infW
, pszINF
);
414 RtlCreateUnicodeStringFromAsciiz(&secW
, pszSec
);
416 res
= RebootCheckOnInstallW(hWnd
, infW
.Buffer
, secW
.Buffer
, dwReserved
);
418 RtlFreeUnicodeString(&infW
);
419 RtlFreeUnicodeString(&secW
);
424 /***********************************************************************
425 * RebootCheckOnInstallW (ADVPACK.@)
427 * Checks if a reboot is required for an installed INF section.
430 * hWnd [I] Handle to the window used for messages.
431 * pszINF [I] Filename of the INF file.
432 * pszSec [I] INF section to check.
433 * dwReserved [I] Reserved. Must be 0.
436 * Success: S_OK - Reboot is needed if the INF section is installed.
437 * S_FALSE - Reboot is not needed.
438 * Failure: HRESULT of GetLastError().
441 * if pszSec is NULL, RebootCheckOnInstall checks the DefaultInstall
442 * or DefaultInstall.NT section.
447 HRESULT WINAPI
RebootCheckOnInstallW(HWND hWnd
, LPCWSTR pszINF
,
448 LPCWSTR pszSec
, DWORD dwReserved
)
450 FIXME("(%p, %s, %s, %d): stub\n", hWnd
, debugstr_w(pszINF
),
451 debugstr_w(pszSec
), dwReserved
);
456 /* registers the OCX if do_reg is TRUE, unregisters it otherwise */
457 HRESULT
do_ocx_reg(HMODULE hocx
, BOOL do_reg
, const WCHAR
*flags
, const WCHAR
*param
)
459 DLLREGISTER reg_func
;
462 reg_func
= (DLLREGISTER
)GetProcAddress(hocx
, "DllRegisterServer");
464 reg_func
= (DLLREGISTER
)GetProcAddress(hocx
, "DllUnregisterServer");
473 /***********************************************************************
474 * RegisterOCX (ADVPACK.@)
479 * hWnd [I] Handle to the window used for the display.
480 * hInst [I] Instance of the process.
481 * cmdline [I] Contains parameters in the order OCX,flags,param.
482 * show [I] How the window should be shown.
489 * OCX - Filename of the OCX to register.
490 * flags - Controls the operation of RegisterOCX.
491 * 'I' Call DllRegisterServer and DllInstall.
492 * 'N' Only call DllInstall.
493 * param - Command line passed to DllInstall.
495 HRESULT WINAPI
RegisterOCX(HWND hWnd
, HINSTANCE hInst
, LPCSTR cmdline
, INT show
)
497 LPWSTR ocx_filename
, str_flags
, param
;
498 LPWSTR cmdline_copy
, cmdline_ptr
;
499 UNICODE_STRING cmdlineW
;
504 TRACE("(%s)\n", debugstr_a(cmdline
));
506 RtlCreateUnicodeStringFromAsciiz(&cmdlineW
, cmdline
);
508 size
= (lstrlenW(cmdlineW
.Buffer
) + 1) * sizeof(WCHAR
);
509 cmdline_copy
= HeapAlloc(GetProcessHeap(), 0, size
);
510 cmdline_ptr
= cmdline_copy
;
511 lstrcpyW(cmdline_copy
, cmdlineW
.Buffer
);
513 ocx_filename
= get_parameter(&cmdline_ptr
, ',');
514 if (!ocx_filename
|| !*ocx_filename
)
517 str_flags
= get_parameter(&cmdline_ptr
, ',');
518 param
= get_parameter(&cmdline_ptr
, ',');
520 hm
= LoadLibraryExW(ocx_filename
, NULL
, LOAD_WITH_ALTERED_SEARCH_PATH
);
524 hr
= do_ocx_reg(hm
, TRUE
, str_flags
, param
);
528 HeapFree(GetProcessHeap(), 0, cmdline_copy
);
529 RtlFreeUnicodeString(&cmdlineW
);
534 /***********************************************************************
535 * SetPerUserSecValuesA (ADVPACK.@)
537 * See SetPerUserSecValuesW.
539 HRESULT WINAPI
SetPerUserSecValuesA(PERUSERSECTIONA
* pPerUser
)
541 PERUSERSECTIONW perUserW
;
543 TRACE("(%p)\n", pPerUser
);
548 MultiByteToWideChar(CP_ACP
, 0, pPerUser
->szGUID
, -1, perUserW
.szGUID
,
549 sizeof(perUserW
.szGUID
) / sizeof(WCHAR
));
550 MultiByteToWideChar(CP_ACP
, 0, pPerUser
->szDispName
, -1, perUserW
.szDispName
,
551 sizeof(perUserW
.szDispName
) / sizeof(WCHAR
));
552 MultiByteToWideChar(CP_ACP
, 0, pPerUser
->szLocale
, -1, perUserW
.szLocale
,
553 sizeof(perUserW
.szLocale
) / sizeof(WCHAR
));
554 MultiByteToWideChar(CP_ACP
, 0, pPerUser
->szStub
, -1, perUserW
.szStub
,
555 sizeof(perUserW
.szStub
) / sizeof(WCHAR
));
556 MultiByteToWideChar(CP_ACP
, 0, pPerUser
->szVersion
, -1, perUserW
.szVersion
,
557 sizeof(perUserW
.szVersion
) / sizeof(WCHAR
));
558 MultiByteToWideChar(CP_ACP
, 0, pPerUser
->szCompID
, -1, perUserW
.szCompID
,
559 sizeof(perUserW
.szCompID
) / sizeof(WCHAR
));
560 perUserW
.dwIsInstalled
= pPerUser
->dwIsInstalled
;
561 perUserW
.bRollback
= pPerUser
->bRollback
;
563 return SetPerUserSecValuesW(&perUserW
);
566 /***********************************************************************
567 * SetPerUserSecValuesW (ADVPACK.@)
569 * Prepares the per-user stub values under IsInstalled\{GUID} that
570 * control the per-user installation.
573 * pPerUser [I] Per-user stub values.
579 HRESULT WINAPI
SetPerUserSecValuesW(PERUSERSECTIONW
* pPerUser
)
583 static const WCHAR stub_path
[] = {'S','t','u','b','P','a','t','h',0};
584 static const WCHAR version
[] = {'V','e','r','s','i','o','n',0};
585 static const WCHAR locale
[] = {'L','o','c','a','l','e',0};
586 static const WCHAR compid
[] = {'C','o','m','p','o','n','e','n','t','I','D',0};
587 static const WCHAR isinstalled
[] = {'I','s','I','n','s','t','a','l','l','e','d',0};
589 TRACE("(%p)\n", pPerUser
);
591 if (!pPerUser
|| !*pPerUser
->szGUID
)
594 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
, setup_key
, 0, NULL
, 0, KEY_WRITE
,
600 if (RegCreateKeyExW(setup
, pPerUser
->szGUID
, 0, NULL
, 0, KEY_ALL_ACCESS
,
607 if (*pPerUser
->szStub
)
609 RegSetValueExW(guid
, stub_path
, 0, REG_SZ
, (LPBYTE
)pPerUser
->szStub
,
610 (lstrlenW(pPerUser
->szStub
) + 1) * sizeof(WCHAR
));
613 if (*pPerUser
->szVersion
)
615 RegSetValueExW(guid
, version
, 0, REG_SZ
, (LPBYTE
)pPerUser
->szVersion
,
616 (lstrlenW(pPerUser
->szVersion
) + 1) * sizeof(WCHAR
));
619 if (*pPerUser
->szLocale
)
621 RegSetValueExW(guid
, locale
, 0, REG_SZ
, (LPBYTE
)pPerUser
->szLocale
,
622 (lstrlenW(pPerUser
->szLocale
) + 1) * sizeof(WCHAR
));
625 if (*pPerUser
->szCompID
)
627 RegSetValueExW(guid
, compid
, 0, REG_SZ
, (LPBYTE
)pPerUser
->szCompID
,
628 (lstrlenW(pPerUser
->szCompID
) + 1) * sizeof(WCHAR
));
631 if (*pPerUser
->szDispName
)
633 RegSetValueExW(guid
, NULL
, 0, REG_SZ
, (LPBYTE
)pPerUser
->szDispName
,
634 (lstrlenW(pPerUser
->szDispName
) + 1) * sizeof(WCHAR
));
637 RegSetValueExW(guid
, isinstalled
, 0, REG_DWORD
,
638 (LPBYTE
)&pPerUser
->dwIsInstalled
, sizeof(DWORD
));
646 /***********************************************************************
647 * TranslateInfStringA (ADVPACK.@)
649 * See TranslateInfStringW.
651 HRESULT WINAPI
TranslateInfStringA(LPCSTR pszInfFilename
, LPCSTR pszInstallSection
,
652 LPCSTR pszTranslateSection
, LPCSTR pszTranslateKey
, LPSTR pszBuffer
,
653 DWORD dwBufferSize
, PDWORD pdwRequiredSize
, PVOID pvReserved
)
655 UNICODE_STRING filenameW
, installW
;
656 UNICODE_STRING translateW
, keyW
;
661 TRACE("(%s, %s, %s, %s, %p, %d, %p, %p)\n",
662 debugstr_a(pszInfFilename
), debugstr_a(pszInstallSection
),
663 debugstr_a(pszTranslateSection
), debugstr_a(pszTranslateKey
),
664 pszBuffer
, dwBufferSize
,pdwRequiredSize
, pvReserved
);
666 if (!pszInfFilename
|| !pszTranslateSection
||
667 !pszTranslateKey
|| !pdwRequiredSize
)
670 RtlCreateUnicodeStringFromAsciiz(&filenameW
, pszInfFilename
);
671 RtlCreateUnicodeStringFromAsciiz(&installW
, pszInstallSection
);
672 RtlCreateUnicodeStringFromAsciiz(&translateW
, pszTranslateSection
);
673 RtlCreateUnicodeStringFromAsciiz(&keyW
, pszTranslateKey
);
675 res
= TranslateInfStringW(filenameW
.Buffer
, installW
.Buffer
,
676 translateW
.Buffer
, keyW
.Buffer
, NULL
,
677 dwBufferSize
, &len
, NULL
);
681 bufferW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
683 res
= TranslateInfStringW(filenameW
.Buffer
, installW
.Buffer
,
684 translateW
.Buffer
, keyW
.Buffer
, bufferW
,
688 *pdwRequiredSize
= WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1,
689 NULL
, 0, NULL
, NULL
);
691 if (dwBufferSize
>= *pdwRequiredSize
)
693 WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, pszBuffer
,
694 dwBufferSize
, NULL
, NULL
);
697 res
= HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
700 HeapFree(GetProcessHeap(), 0, bufferW
);
703 RtlFreeUnicodeString(&filenameW
);
704 RtlFreeUnicodeString(&installW
);
705 RtlFreeUnicodeString(&translateW
);
706 RtlFreeUnicodeString(&keyW
);
711 /***********************************************************************
712 * TranslateInfStringW (ADVPACK.@)
714 * Translates the value of a specified key in an inf file into the
715 * current locale by expanding string macros.
718 * pszInfFilename [I] Filename of the inf file.
719 * pszInstallSection [I]
720 * pszTranslateSection [I] Inf section where the key exists.
721 * pszTranslateKey [I] Key to translate.
722 * pszBuffer [O] Contains the translated string on exit.
723 * dwBufferSize [I] Size on input of pszBuffer.
724 * pdwRequiredSize [O] Length of the translated key.
725 * pvReserved [I] Reserved, must be NULL.
729 * Failure: An hresult error code.
731 HRESULT WINAPI
TranslateInfStringW(LPCWSTR pszInfFilename
, LPCWSTR pszInstallSection
,
732 LPCWSTR pszTranslateSection
, LPCWSTR pszTranslateKey
, LPWSTR pszBuffer
,
733 DWORD dwBufferSize
, PDWORD pdwRequiredSize
, PVOID pvReserved
)
738 TRACE("(%s, %s, %s, %s, %p, %d, %p, %p)\n",
739 debugstr_w(pszInfFilename
), debugstr_w(pszInstallSection
),
740 debugstr_w(pszTranslateSection
), debugstr_w(pszTranslateKey
),
741 pszBuffer
, dwBufferSize
,pdwRequiredSize
, pvReserved
);
743 if (!pszInfFilename
|| !pszTranslateSection
||
744 !pszTranslateKey
|| !pdwRequiredSize
)
747 hInf
= SetupOpenInfFileW(pszInfFilename
, NULL
, INF_STYLE_WIN4
, NULL
);
748 if (hInf
== INVALID_HANDLE_VALUE
)
749 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
751 set_ldids(hInf
, pszInstallSection
, NULL
);
753 if (!SetupGetLineTextW(NULL
, hInf
, pszTranslateSection
, pszTranslateKey
,
754 pszBuffer
, dwBufferSize
, pdwRequiredSize
))
756 if (dwBufferSize
< *pdwRequiredSize
)
757 hret
= HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
759 hret
= SPAPI_E_LINE_NOT_FOUND
;
762 SetupCloseInfFile(hInf
);
766 /***********************************************************************
767 * TranslateInfStringExA (ADVPACK.@)
769 * See TranslateInfStringExW.
771 HRESULT WINAPI
TranslateInfStringExA(HINF hInf
, LPCSTR pszInfFilename
,
772 LPCSTR pszTranslateSection
, LPCSTR pszTranslateKey
,
773 LPSTR pszBuffer
, DWORD dwBufferSize
,
774 PDWORD pdwRequiredSize
, PVOID pvReserved
)
776 UNICODE_STRING filenameW
, sectionW
, keyW
;
781 TRACE("(%p, %s, %s, %s, %s, %d, %p, %p)\n", hInf
, debugstr_a(pszInfFilename
),
782 debugstr_a(pszTranslateSection
), debugstr_a(pszTranslateKey
),
783 debugstr_a(pszBuffer
), dwBufferSize
, pdwRequiredSize
, pvReserved
);
785 if (!pszInfFilename
|| !pszTranslateSection
||
786 !pszTranslateKey
|| !pdwRequiredSize
)
789 RtlCreateUnicodeStringFromAsciiz(&filenameW
, pszInfFilename
);
790 RtlCreateUnicodeStringFromAsciiz(§ionW
, pszTranslateSection
);
791 RtlCreateUnicodeStringFromAsciiz(&keyW
, pszTranslateKey
);
793 res
= TranslateInfStringExW(hInf
, filenameW
.Buffer
, sectionW
.Buffer
,
794 keyW
.Buffer
, NULL
, 0, &len
, NULL
);
798 bufferW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
800 res
= TranslateInfStringExW(hInf
, filenameW
.Buffer
, sectionW
.Buffer
,
801 keyW
.Buffer
, bufferW
, len
, &len
, NULL
);
805 *pdwRequiredSize
= WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1,
806 NULL
, 0, NULL
, NULL
);
808 if (dwBufferSize
>= *pdwRequiredSize
)
810 WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, pszBuffer
,
811 dwBufferSize
, NULL
, NULL
);
814 res
= HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
817 HeapFree(GetProcessHeap(), 0, bufferW
);
820 RtlFreeUnicodeString(&filenameW
);
821 RtlFreeUnicodeString(§ionW
);
822 RtlFreeUnicodeString(&keyW
);
827 /***********************************************************************
828 * TranslateInfStringExW (ADVPACK.@)
830 * Using a handle to an INF file opened with OpenINFEngine, translates
831 * the value of a specified key in an inf file into the current locale
832 * by expanding string macros.
835 * hInf [I] Handle to the INF file.
836 * pszInfFilename [I] Filename of the INF file.
837 * pszTranslateSection [I] Inf section where the key exists.
838 * pszTranslateKey [I] Key to translate.
839 * pszBuffer [O] Contains the translated string on exit.
840 * dwBufferSize [I] Size on input of pszBuffer.
841 * pdwRequiredSize [O] Length of the translated key.
842 * pvReserved [I] Reserved. Must be NULL.
849 * To use TranslateInfStringEx to translate an INF file continuously,
850 * open the INF file with OpenINFEngine, call TranslateInfStringEx as
851 * many times as needed, then release the handle with CloseINFEngine.
852 * When translating more than one keys, this method is more efficient
853 * than calling TranslateInfString, because the INF file is only
856 HRESULT WINAPI
TranslateInfStringExW(HINF hInf
, LPCWSTR pszInfFilename
,
857 LPCWSTR pszTranslateSection
, LPCWSTR pszTranslateKey
,
858 LPWSTR pszBuffer
, DWORD dwBufferSize
,
859 PDWORD pdwRequiredSize
, PVOID pvReserved
)
861 TRACE("(%p, %s, %s, %s, %s, %d, %p, %p)\n", hInf
, debugstr_w(pszInfFilename
),
862 debugstr_w(pszTranslateSection
), debugstr_w(pszTranslateKey
),
863 debugstr_w(pszBuffer
), dwBufferSize
, pdwRequiredSize
, pvReserved
);
865 if (!hInf
|| !pszInfFilename
|| !pszTranslateSection
|| !pszTranslateKey
)
868 if (!SetupGetLineTextW(NULL
, hInf
, pszTranslateSection
, pszTranslateKey
,
869 pszBuffer
, dwBufferSize
, pdwRequiredSize
))
871 if (dwBufferSize
< *pdwRequiredSize
)
872 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
874 return SPAPI_E_LINE_NOT_FOUND
;
880 /***********************************************************************
881 * UserInstStubWrapperA (ADVPACK.@)
883 * See UserInstStubWrapperW.
885 HRESULT WINAPI
UserInstStubWrapperA(HWND hWnd
, HINSTANCE hInstance
,
886 LPSTR pszParms
, INT nShow
)
888 UNICODE_STRING parmsW
;
891 TRACE("(%p, %p, %s, %i)\n", hWnd
, hInstance
, debugstr_a(pszParms
), nShow
);
896 RtlCreateUnicodeStringFromAsciiz(&parmsW
, pszParms
);
898 res
= UserInstStubWrapperW(hWnd
, hInstance
, parmsW
.Buffer
, nShow
);
900 RtlFreeUnicodeString(&parmsW
);
905 /***********************************************************************
906 * UserInstStubWrapperW (ADVPACK.@)
908 * Launches the user stub wrapper specified by the RealStubPath
909 * registry value under Installed Components\szParms.
912 * hWnd [I] Handle to the window used for the display.
913 * hInstance [I] Instance of the process.
914 * szParms [I] The GUID of the installation.
915 * show [I] How the window should be shown.
922 * If the type of the StubRealPath value is REG_EXPAND_SZ, then
923 * we should call ExpandEnvironmentStrings on the value and
926 HRESULT WINAPI
UserInstStubWrapperW(HWND hWnd
, HINSTANCE hInstance
,
927 LPWSTR pszParms
, INT nShow
)
930 WCHAR stub
[MAX_PATH
];
931 DWORD size
= MAX_PATH
;
935 static const WCHAR real_stub_path
[] = {
936 'R','e','a','l','S','t','u','b','P','a','t','h',0
939 TRACE("(%p, %p, %s, %i)\n", hWnd
, hInstance
, debugstr_w(pszParms
), nShow
);
941 if (!pszParms
|| !*pszParms
)
944 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, setup_key
, 0, KEY_READ
, &setup
))
949 if (RegOpenKeyExW(setup
, pszParms
, 0, KEY_READ
, &guid
))
955 res
= RegQueryValueExW(guid
, real_stub_path
, NULL
, NULL
, (LPBYTE
)stub
, &size
);
959 /* launch the user stub wrapper */
960 hr
= launch_exe(stub
, NULL
, NULL
);
969 /***********************************************************************
970 * UserUnInstStubWrapperA (ADVPACK.@)
972 * See UserUnInstStubWrapperW.
974 HRESULT WINAPI
UserUnInstStubWrapperA(HWND hWnd
, HINSTANCE hInstance
,
975 LPSTR pszParms
, INT nShow
)
977 UNICODE_STRING parmsW
;
980 TRACE("(%p, %p, %s, %i)\n", hWnd
, hInstance
, debugstr_a(pszParms
), nShow
);
985 RtlCreateUnicodeStringFromAsciiz(&parmsW
, pszParms
);
987 res
= UserUnInstStubWrapperW(hWnd
, hInstance
, parmsW
.Buffer
, nShow
);
989 RtlFreeUnicodeString(&parmsW
);
994 /***********************************************************************
995 * UserUnInstStubWrapperW (ADVPACK.@)
997 HRESULT WINAPI
UserUnInstStubWrapperW(HWND hWnd
, HINSTANCE hInstance
,
998 LPWSTR pszParms
, INT nShow
)
1000 FIXME("(%p, %p, %s, %i): stub\n", hWnd
, hInstance
, debugstr_w(pszParms
), nShow
);