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 /* parses the destination directory parameters from pszSection
44 * the parameters are of the form: root,key,value,unknown,fallback
45 * we first read the reg value root\\key\\value and if that fails,
46 * use fallback as the destination directory
48 static void get_dest_dir(HINF hInf
, PCWSTR pszSection
, PWSTR pszBuffer
, DWORD dwSize
)
51 WCHAR key
[MAX_PATH
], value
[MAX_PATH
];
52 WCHAR prefix
[PREFIX_LEN
];
56 static const WCHAR hklm
[] = {'H','K','L','M',0};
57 static const WCHAR hkcu
[] = {'H','K','C','U',0};
59 /* load the destination parameters */
60 SetupFindFirstLineW(hInf
, pszSection
, NULL
, &context
);
61 SetupGetStringFieldW(&context
, 1, prefix
, PREFIX_LEN
, &size
);
62 SetupGetStringFieldW(&context
, 2, key
, MAX_PATH
, &size
);
63 SetupGetStringFieldW(&context
, 3, value
, MAX_PATH
, &size
);
65 if (!lstrcmpW(prefix
, hklm
))
66 root
= HKEY_LOCAL_MACHINE
;
67 else if (!lstrcmpW(prefix
, hkcu
))
68 root
= HKEY_CURRENT_USER
;
72 size
= dwSize
* sizeof(WCHAR
);
74 /* fallback to the default destination dir if reg fails */
75 if (RegOpenKeyW(root
, key
, &subkey
) ||
76 RegQueryValueExW(subkey
, value
, NULL
, NULL
, (LPBYTE
)pszBuffer
, &size
))
78 SetupGetStringFieldW(&context
, 6, pszBuffer
, dwSize
, NULL
);
84 /* loads the LDIDs specified in the install section of an INF */
85 static void set_ldids(HINF hInf
, LPCWSTR pszInstallSection
)
87 WCHAR field
[MAX_FIELD_LENGTH
];
88 WCHAR key
[MAX_FIELD_LENGTH
];
94 static const WCHAR custDestW
[] = {
95 'C','u','s','t','o','m','D','e','s','t','i','n','a','t','i','o','n',0
98 if (!SetupGetLineTextW(NULL
, hInf
, pszInstallSection
, custDestW
,
99 field
, MAX_FIELD_LENGTH
, &size
))
102 if (!SetupFindFirstLineW(hInf
, field
, NULL
, &context
))
107 SetupGetIntField(&context
, 0, &ldid
);
108 SetupGetLineTextW(&context
, NULL
, NULL
, NULL
,
109 key
, MAX_FIELD_LENGTH
, &size
);
111 get_dest_dir(hInf
, key
, dest
, MAX_PATH
);
113 SetupSetDirectoryIdW(hInf
, ldid
, dest
);
114 } while (SetupFindNextLine(&context
, &context
));
117 /***********************************************************************
118 * CloseINFEngine (ADVPACK.@)
120 * Closes a handle to an INF file opened with OpenINFEngine.
123 * hInf [I] Handle to the INF file to close.
129 HRESULT WINAPI
CloseINFEngine(HINF hInf
)
131 TRACE("(%p)\n", hInf
);
136 SetupCloseInfFile(hInf
);
140 /***********************************************************************
141 * DllMain (ADVPACK.@)
143 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
145 TRACE("(%p, %ld, %p)\n",hinstDLL
, fdwReason
, lpvReserved
);
147 if (fdwReason
== DLL_PROCESS_ATTACH
)
148 DisableThreadLibraryCalls(hinstDLL
);
153 /***********************************************************************
154 * IsNTAdmin (ADVPACK.@)
156 * Checks if the user has admin privileges.
159 * reserved [I] Reserved. Must be 0.
160 * pReserved [I] Reserved. Must be NULL.
163 * TRUE if user has admin rights, FALSE otherwise.
165 BOOL WINAPI
IsNTAdmin( DWORD reserved
, LPDWORD pReserved
)
167 SID_IDENTIFIER_AUTHORITY SidAuthority
= {SECURITY_NT_AUTHORITY
};
168 PTOKEN_GROUPS pTokenGroups
;
169 BOOL bSidFound
= FALSE
;
174 TRACE("(0x%08lx, %p)\n", reserved
, pReserved
);
176 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
))
179 if (!GetTokenInformation(hToken
, TokenGroups
, NULL
, 0, &dwSize
))
181 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
188 pTokenGroups
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
195 if (!GetTokenInformation(hToken
, TokenGroups
, pTokenGroups
, dwSize
, &dwSize
))
197 HeapFree(GetProcessHeap(), 0, pTokenGroups
);
204 if (!AllocateAndInitializeSid(&SidAuthority
, 2, SECURITY_BUILTIN_DOMAIN_RID
,
205 DOMAIN_ALIAS_RID_ADMINS
, 0, 0, 0, 0, 0, 0, &pSid
))
207 HeapFree(GetProcessHeap(), 0, pTokenGroups
);
211 for (i
= 0; i
< pTokenGroups
->GroupCount
; i
++)
213 if (EqualSid(pSid
, pTokenGroups
->Groups
[i
].Sid
))
220 HeapFree(GetProcessHeap(), 0, pTokenGroups
);
226 /***********************************************************************
227 * NeedRebootInit (ADVPACK.@)
229 * Sets up conditions for reboot checking.
232 * Value required by NeedReboot.
234 DWORD WINAPI
NeedRebootInit(VOID
)
240 /***********************************************************************
241 * NeedReboot (ADVPACK.@)
243 * Determines whether a reboot is required.
246 * dwRebootCheck [I] Value from NeedRebootInit.
249 * TRUE if a reboot is needed, FALSE otherwise.
254 BOOL WINAPI
NeedReboot(DWORD dwRebootCheck
)
256 FIXME("(0x%08lx): stub\n", dwRebootCheck
);
260 /***********************************************************************
261 * OpenINFEngineA (ADVPACK.@)
263 * See OpenINFEngineW.
265 HRESULT WINAPI
OpenINFEngineA(LPCSTR pszInfFilename
, LPCSTR pszInstallSection
,
266 DWORD dwFlags
, HINF
*phInf
, PVOID pvReserved
)
268 UNICODE_STRING filenameW
, installW
;
271 TRACE("(%p, %p, %ld, %p, %p)\n", pszInfFilename
, pszInstallSection
,
272 dwFlags
, phInf
, pvReserved
);
274 if (!pszInfFilename
|| !phInf
)
277 RtlCreateUnicodeStringFromAsciiz(&filenameW
, pszInfFilename
);
278 RtlCreateUnicodeStringFromAsciiz(&installW
, pszInstallSection
);
280 res
= OpenINFEngineW(filenameW
.Buffer
, installW
.Buffer
,
281 dwFlags
, phInf
, pvReserved
);
283 RtlFreeUnicodeString(&filenameW
);
284 RtlFreeUnicodeString(&installW
);
289 /***********************************************************************
290 * OpenINFEngineW (ADVPACK.@)
292 * Opens and returns a handle to an INF file to be used by
293 * TranslateInfStringEx to continuously translate the INF file.
296 * pszInfFilename [I] Filename of the INF to open.
297 * pszInstallSection [I] Name of the Install section in the INF.
298 * dwFlags [I] See advpub.h.
299 * phInf [O] Handle to the loaded INF file.
300 * pvReserved [I] Reserved. Must be NULL.
306 HRESULT WINAPI
OpenINFEngineW(LPCWSTR pszInfFilename
, LPCWSTR pszInstallSection
,
307 DWORD dwFlags
, HINF
*phInf
, PVOID pvReserved
)
309 TRACE("(%p, %p, %ld, %p, %p)\n", debugstr_w(pszInfFilename
),
310 debugstr_w(pszInstallSection
), dwFlags
, phInf
, pvReserved
);
312 if (!pszInfFilename
|| !phInf
)
315 *phInf
= SetupOpenInfFileW(pszInfFilename
, NULL
, INF_STYLE_WIN4
, NULL
);
316 if (*phInf
== INVALID_HANDLE_VALUE
)
317 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
319 set_ldids(*phInf
, pszInstallSection
);
324 /***********************************************************************
325 * RebootCheckOnInstallA (ADVPACK.@)
327 * See RebootCheckOnInstallW.
329 HRESULT WINAPI
RebootCheckOnInstallA(HWND hWnd
, LPCSTR pszINF
,
330 LPSTR pszSec
, DWORD dwReserved
)
332 UNICODE_STRING infW
, secW
;
335 TRACE("(%p, %s, %s, %ld)\n", hWnd
, debugstr_a(pszINF
),
336 debugstr_a(pszSec
), dwReserved
);
338 if (!pszINF
|| !pszSec
)
341 RtlCreateUnicodeStringFromAsciiz(&infW
, pszINF
);
342 RtlCreateUnicodeStringFromAsciiz(&secW
, pszSec
);
344 res
= RebootCheckOnInstallW(hWnd
, infW
.Buffer
, secW
.Buffer
, dwReserved
);
346 RtlFreeUnicodeString(&infW
);
347 RtlFreeUnicodeString(&secW
);
352 /***********************************************************************
353 * RebootCheckOnInstallW (ADVPACK.@)
355 * Checks if a reboot is required for an installed INF section.
358 * hWnd [I] Handle to the window used for messages.
359 * pszINF [I] Filename of the INF file.
360 * pszSec [I] INF section to check.
361 * dwReserved [I] Reserved. Must be 0.
364 * Success: S_OK - Reboot is needed if the INF section is installed.
365 * S_FALSE - Reboot is not needed.
366 * Failure: HRESULT of GetLastError().
369 * if pszSec is NULL, RebootCheckOnInstall checks the DefaultInstall
370 * or DefaultInstall.NT section.
375 HRESULT WINAPI
RebootCheckOnInstallW(HWND hWnd
, LPCWSTR pszINF
,
376 LPWSTR pszSec
, DWORD dwReserved
)
378 FIXME("(%p, %s, %s, %ld) stub\n", hWnd
, debugstr_w(pszINF
),
379 debugstr_w(pszSec
), dwReserved
);
384 /***********************************************************************
385 * RegisterOCX (ADVPACK.@)
387 void WINAPI
RegisterOCX( HWND hWnd
, HINSTANCE hInst
, LPCSTR cmdline
, INT show
)
389 WCHAR wszBuff
[MAX_PATH
];
392 DLLREGISTER pfnRegister
;
395 TRACE("(%s)\n", cmdline
);
397 MultiByteToWideChar(CP_ACP
, 0, cmdline
, strlen(cmdline
), wszBuff
, MAX_PATH
);
398 if ((pwcComma
= strchrW( wszBuff
, ',' ))) *pwcComma
= 0;
400 TRACE("Parsed DLL name (%s)\n", debugstr_w(wszBuff
));
402 hm
= LoadLibraryExW(wszBuff
, 0, LOAD_WITH_ALTERED_SEARCH_PATH
);
405 ERR("Couldn't load DLL: %s\n", debugstr_w(wszBuff
));
409 pfnRegister
= (DLLREGISTER
)GetProcAddress(hm
, "DllRegisterServer");
410 if (pfnRegister
== NULL
)
412 ERR("DllRegisterServer entry point not found\n");
419 ERR("DllRegisterServer entry point returned %08lx\n", hr
);
423 TRACE("Successfully registered OCX\n");
428 /***********************************************************************
429 * SetPerUserSecValuesA (ADVPACK.@)
431 * See SetPerUserSecValuesW.
433 HRESULT WINAPI
SetPerUserSecValuesA(PERUSERSECTIONA
* pPerUser
)
435 PERUSERSECTIONW perUserW
;
437 TRACE("(%p)\n", pPerUser
);
442 MultiByteToWideChar(CP_ACP
, 0, pPerUser
->szGUID
, -1, perUserW
.szGUID
,
443 sizeof(perUserW
.szGUID
) / sizeof(WCHAR
));
444 MultiByteToWideChar(CP_ACP
, 0, pPerUser
->szDispName
, -1, perUserW
.szDispName
,
445 sizeof(perUserW
.szDispName
) / sizeof(WCHAR
));
446 MultiByteToWideChar(CP_ACP
, 0, pPerUser
->szLocale
, -1, perUserW
.szLocale
,
447 sizeof(perUserW
.szLocale
) / sizeof(WCHAR
));
448 MultiByteToWideChar(CP_ACP
, 0, pPerUser
->szStub
, -1, perUserW
.szStub
,
449 sizeof(perUserW
.szStub
) / sizeof(WCHAR
));
450 MultiByteToWideChar(CP_ACP
, 0, pPerUser
->szVersion
, -1, perUserW
.szVersion
,
451 sizeof(perUserW
.szVersion
) / sizeof(WCHAR
));
452 MultiByteToWideChar(CP_ACP
, 0, pPerUser
->szCompID
, -1, perUserW
.szCompID
,
453 sizeof(perUserW
.szCompID
) / sizeof(WCHAR
));
454 perUserW
.dwIsInstalled
= pPerUser
->dwIsInstalled
;
455 perUserW
.bRollback
= pPerUser
->bRollback
;
457 return SetPerUserSecValuesW(&perUserW
);
460 /***********************************************************************
461 * SetPerUserSecValuesW (ADVPACK.@)
463 * Prepares the per-user stub values under IsInstalled\{GUID} that
464 * control the per-user installation.
467 * pPerUser [I] Per-user stub values.
473 HRESULT WINAPI
SetPerUserSecValuesW(PERUSERSECTIONW
* pPerUser
)
477 static const WCHAR setup_key
[] = {
478 'S','O','F','T','W','A','R','E','\\',
479 'M','i','c','r','o','s','o','f','t','\\',
480 'A','c','t','i','v','e',' ','S','e','t','u','p','\\',
481 'I','n','s','t','a','l','l','e','d',' ',
482 'C','o','m','p','o','n','e','n','t','s',0
485 static const WCHAR stub_path
[] = {'S','t','u','b','P','a','t','h',0};
486 static const WCHAR version
[] = {'V','e','r','s','i','o','n',0};
487 static const WCHAR locale
[] = {'L','o','c','a','l','e',0};
488 static const WCHAR compid
[] = {'C','o','m','p','o','n','e','n','t','I','D',0};
489 static const WCHAR isinstalled
[] = {'I','s','I','n','s','t','a','l','l','e','d',0};
491 TRACE("(%p)\n", pPerUser
);
493 if (!pPerUser
|| !*pPerUser
->szGUID
)
496 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
, setup_key
, 0, NULL
, 0, KEY_WRITE
,
502 if (RegCreateKeyExW(setup
, pPerUser
->szGUID
, 0, NULL
, 0, KEY_ALL_ACCESS
,
509 if (*pPerUser
->szStub
)
511 RegSetValueExW(guid
, stub_path
, 0, REG_SZ
, (LPBYTE
)pPerUser
->szStub
,
512 (lstrlenW(pPerUser
->szStub
) + 1) * sizeof(WCHAR
));
515 if (*pPerUser
->szVersion
)
517 RegSetValueExW(guid
, version
, 0, REG_SZ
, (LPBYTE
)pPerUser
->szVersion
,
518 (lstrlenW(pPerUser
->szVersion
) + 1) * sizeof(WCHAR
));
521 if (*pPerUser
->szLocale
)
523 RegSetValueExW(guid
, locale
, 0, REG_SZ
, (LPBYTE
)pPerUser
->szLocale
,
524 (lstrlenW(pPerUser
->szLocale
) + 1) * sizeof(WCHAR
));
527 if (*pPerUser
->szCompID
)
529 RegSetValueExW(guid
, compid
, 0, REG_SZ
, (LPBYTE
)pPerUser
->szCompID
,
530 (lstrlenW(pPerUser
->szCompID
) + 1) * sizeof(WCHAR
));
533 if (*pPerUser
->szDispName
)
535 RegSetValueExW(guid
, NULL
, 0, REG_SZ
, (LPBYTE
)pPerUser
->szDispName
,
536 (lstrlenW(pPerUser
->szDispName
) + 1) * sizeof(WCHAR
));
539 RegSetValueExW(guid
, isinstalled
, 0, REG_DWORD
,
540 (LPBYTE
)&pPerUser
->dwIsInstalled
, sizeof(DWORD
));
548 /***********************************************************************
549 * TranslateInfStringA (ADVPACK.@)
551 * See TranslateInfStringW.
553 HRESULT WINAPI
TranslateInfStringA(LPCSTR pszInfFilename
, LPCSTR pszInstallSection
,
554 LPCSTR pszTranslateSection
, LPCSTR pszTranslateKey
, LPSTR pszBuffer
,
555 DWORD dwBufferSize
, PDWORD pdwRequiredSize
, PVOID pvReserved
)
557 UNICODE_STRING filenameW
, installW
;
558 UNICODE_STRING translateW
, keyW
;
563 TRACE("(%s %s %s %s %p %ld %p %p)\n",
564 debugstr_a(pszInfFilename
), debugstr_a(pszInstallSection
),
565 debugstr_a(pszTranslateSection
), debugstr_a(pszTranslateKey
),
566 pszBuffer
, dwBufferSize
,pdwRequiredSize
, pvReserved
);
568 if (!pszInfFilename
|| !pszTranslateSection
||
569 !pszTranslateKey
|| !pdwRequiredSize
)
572 RtlCreateUnicodeStringFromAsciiz(&filenameW
, pszInfFilename
);
573 RtlCreateUnicodeStringFromAsciiz(&installW
, pszInstallSection
);
574 RtlCreateUnicodeStringFromAsciiz(&translateW
, pszTranslateSection
);
575 RtlCreateUnicodeStringFromAsciiz(&keyW
, pszTranslateKey
);
577 res
= TranslateInfStringW(filenameW
.Buffer
, installW
.Buffer
,
578 translateW
.Buffer
, keyW
.Buffer
, NULL
,
579 dwBufferSize
, &len
, NULL
);
583 bufferW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
585 res
= TranslateInfStringW(filenameW
.Buffer
, installW
.Buffer
,
586 translateW
.Buffer
, keyW
.Buffer
, bufferW
,
590 *pdwRequiredSize
= WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1,
591 NULL
, 0, NULL
, NULL
);
593 if (dwBufferSize
>= *pdwRequiredSize
)
595 WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, pszBuffer
,
596 dwBufferSize
, NULL
, NULL
);
599 res
= HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
602 HeapFree(GetProcessHeap(), 0, bufferW
);
605 RtlFreeUnicodeString(&filenameW
);
606 RtlFreeUnicodeString(&installW
);
607 RtlFreeUnicodeString(&translateW
);
608 RtlFreeUnicodeString(&keyW
);
613 /***********************************************************************
614 * TranslateInfStringW (ADVPACK.@)
616 * Translates the value of a specified key in an inf file into the
617 * current locale by expanding string macros.
620 * pszInfFilename [I] Filename of the inf file.
621 * pszInstallSection [I]
622 * pszTranslateSection [I] Inf section where the key exists.
623 * pszTranslateKey [I] Key to translate.
624 * pszBuffer [O] Contains the translated string on exit.
625 * dwBufferSize [I] Size on input of pszBuffer.
626 * pdwRequiredSize [O] Length of the translated key.
627 * pvReserved [I] Reserved, must be NULL.
631 * Failure: An hresult error code.
633 HRESULT WINAPI
TranslateInfStringW(LPCWSTR pszInfFilename
, LPCWSTR pszInstallSection
,
634 LPCWSTR pszTranslateSection
, LPCWSTR pszTranslateKey
, LPWSTR pszBuffer
,
635 DWORD dwBufferSize
, PDWORD pdwRequiredSize
, PVOID pvReserved
)
639 TRACE("(%s %s %s %s %p %ld %p %p)\n",
640 debugstr_w(pszInfFilename
), debugstr_w(pszInstallSection
),
641 debugstr_w(pszTranslateSection
), debugstr_w(pszTranslateKey
),
642 pszBuffer
, dwBufferSize
,pdwRequiredSize
, pvReserved
);
644 if (!pszInfFilename
|| !pszTranslateSection
||
645 !pszTranslateKey
|| !pdwRequiredSize
)
648 hInf
= SetupOpenInfFileW(pszInfFilename
, NULL
, INF_STYLE_WIN4
, NULL
);
649 if (hInf
== INVALID_HANDLE_VALUE
)
650 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
652 set_ldids(hInf
, pszInstallSection
);
654 if (!SetupGetLineTextW(NULL
, hInf
, pszTranslateSection
, pszTranslateKey
,
655 pszBuffer
, dwBufferSize
, pdwRequiredSize
))
657 if (dwBufferSize
< *pdwRequiredSize
)
658 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
660 return SPAPI_E_LINE_NOT_FOUND
;
663 SetupCloseInfFile(hInf
);
667 /***********************************************************************
668 * TranslateInfStringExA (ADVPACK.@)
670 * See TranslateInfStringExW.
672 HRESULT WINAPI
TranslateInfStringExA(HINF hInf
, LPCSTR pszInfFilename
,
673 LPCSTR pszTranslateSection
, LPCSTR pszTranslateKey
,
674 LPSTR pszBuffer
, DWORD dwBufferSize
,
675 PDWORD pdwRequiredSize
, PVOID pvReserved
)
677 UNICODE_STRING filenameW
, sectionW
, keyW
;
682 TRACE("(%p, %p, %p, %p, %p, %ld, %p, %p)\n", hInf
, debugstr_a(pszInfFilename
),
683 debugstr_a(pszTranslateSection
), debugstr_a(pszTranslateKey
),
684 debugstr_a(pszBuffer
), dwBufferSize
, pdwRequiredSize
, pvReserved
);
686 if (!pszInfFilename
|| !pszTranslateSection
||
687 !pszTranslateKey
|| !pdwRequiredSize
)
690 RtlCreateUnicodeStringFromAsciiz(&filenameW
, pszInfFilename
);
691 RtlCreateUnicodeStringFromAsciiz(§ionW
, pszTranslateSection
);
692 RtlCreateUnicodeStringFromAsciiz(&keyW
, pszTranslateKey
);
694 res
= TranslateInfStringExW(hInf
, filenameW
.Buffer
, sectionW
.Buffer
,
695 keyW
.Buffer
, NULL
, 0, &len
, NULL
);
699 bufferW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
701 res
= TranslateInfStringExW(hInf
, filenameW
.Buffer
, sectionW
.Buffer
,
702 keyW
.Buffer
, bufferW
, len
, &len
, NULL
);
706 *pdwRequiredSize
= WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1,
707 NULL
, 0, NULL
, NULL
);
709 if (dwBufferSize
>= *pdwRequiredSize
)
711 WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, pszBuffer
,
712 dwBufferSize
, NULL
, NULL
);
715 res
= HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
718 HeapFree(GetProcessHeap(), 0, bufferW
);
721 RtlFreeUnicodeString(&filenameW
);
722 RtlFreeUnicodeString(§ionW
);
723 RtlFreeUnicodeString(&keyW
);
728 /***********************************************************************
729 * TranslateInfStringExW (ADVPACK.@)
731 * Using a handle to an INF file opened with OpenINFEngine, translates
732 * the value of a specified key in an inf file into the current locale
733 * by expanding string macros.
736 * hInf [I] Handle to the INF file.
737 * pszInfFilename [I] Filename of the INF file.
738 * pszTranslateSection [I] Inf section where the key exists.
739 * pszTranslateKey [I] Key to translate.
740 * pszBuffer [O] Contains the translated string on exit.
741 * dwBufferSize [I] Size on input of pszBuffer.
742 * pdwRequiredSize [O] Length of the translated key.
743 * pvReserved [I] Reserved. Must be NULL.
750 * To use TranslateInfStringEx to translate an INF file continuously,
751 * open the INF file with OpenINFEngine, call TranslateInfStringEx as
752 * many times as needed, then release the handle with CloseINFEngine.
753 * When translating more than one keys, this method is more efficient
754 * than calling TranslateInfString, because the INF file is only
757 HRESULT WINAPI
TranslateInfStringExW(HINF hInf
, LPCWSTR pszInfFilename
,
758 LPCWSTR pszTranslateSection
, LPCWSTR pszTranslateKey
,
759 LPWSTR pszBuffer
, DWORD dwBufferSize
,
760 PDWORD pdwRequiredSize
, PVOID pvReserved
)
762 TRACE("(%p, %p, %p, %p, %p, %ld, %p, %p)\n", hInf
, debugstr_w(pszInfFilename
),
763 debugstr_w(pszTranslateSection
), debugstr_w(pszTranslateKey
),
764 debugstr_w(pszBuffer
), dwBufferSize
, pdwRequiredSize
, pvReserved
);
766 if (!hInf
|| !pszInfFilename
|| !pszTranslateSection
|| !pszTranslateKey
)
769 if (!SetupGetLineTextW(NULL
, hInf
, pszTranslateSection
, pszTranslateKey
,
770 pszBuffer
, dwBufferSize
, pdwRequiredSize
))
772 if (dwBufferSize
< *pdwRequiredSize
)
773 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
775 return SPAPI_E_LINE_NOT_FOUND
;
781 /***********************************************************************
782 * UserInstStubWrapperA (ADVPACK.@)
784 * See UserInstStubWrapperW.
786 HRESULT WINAPI
UserInstStubWrapperA(HWND hWnd
, HINSTANCE hInstance
,
787 LPSTR pszParms
, INT nShow
)
789 UNICODE_STRING parmsW
;
792 TRACE("(%p, %p, %p, %i)\n", hWnd
, hInstance
, pszParms
, nShow
);
797 RtlCreateUnicodeStringFromAsciiz(&parmsW
, pszParms
);
799 res
= UserInstStubWrapperW(hWnd
, hInstance
, parmsW
.Buffer
, nShow
);
801 RtlFreeUnicodeString(&parmsW
);
806 /***********************************************************************
807 * UserInstStubWrapperW (ADVPACK.@)
809 HRESULT WINAPI
UserInstStubWrapperW(HWND hWnd
, HINSTANCE hInstance
,
810 LPWSTR pszParms
, INT nShow
)
812 FIXME("(%p, %p, %p, %i) stub\n", hWnd
, hInstance
, pszParms
, nShow
);
817 /***********************************************************************
818 * UserUnInstStubWrapperA (ADVPACK.@)
820 * See UserUnInstStubWrapperW.
822 HRESULT WINAPI
UserUnInstStubWrapperA(HWND hWnd
, HINSTANCE hInstance
,
823 LPSTR pszParms
, INT nShow
)
825 UNICODE_STRING parmsW
;
828 TRACE("(%p, %p, %p, %i)\n", hWnd
, hInstance
, pszParms
, nShow
);
833 RtlCreateUnicodeStringFromAsciiz(&parmsW
, pszParms
);
835 res
= UserUnInstStubWrapperW(hWnd
, hInstance
, parmsW
.Buffer
, nShow
);
837 RtlFreeUnicodeString(&parmsW
);
842 /***********************************************************************
843 * UserUnInstStubWrapperW (ADVPACK.@)
845 HRESULT WINAPI
UserUnInstStubWrapperW(HWND hWnd
, HINSTANCE hInstance
,
846 LPWSTR pszParms
, INT nShow
)
848 FIXME("(%p, %p, %p, %i) stub\n", hWnd
, hInstance
, pszParms
, nShow
);