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
33 #include "wine/debug.h"
34 #include "advpack_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(advpack
);
38 typedef HRESULT (WINAPI
*DLLREGISTER
) (void);
40 #define MAX_FIELD_LENGTH 512
43 /* registry path of the Installed Components key for per-user stubs */
44 static const WCHAR setup_key
[] = L
"SOFTWARE\\Microsoft\\Active Setup\\Installed Components";
46 /* Strip single quotes from a token - note size includes NULL */
47 static void strip_quotes(WCHAR
*buffer
, DWORD
*size
)
49 if (buffer
[0] == '\'' && (*size
> 1) && buffer
[*size
-2]=='\'')
53 memmove(buffer
, buffer
+ 1, *size
* sizeof(WCHAR
));
57 /* parses the destination directory parameters from pszSection
58 * the parameters are of the form: root,key,value,unknown,fallback
59 * we first read the reg value root\\key\\value and if that fails,
60 * use fallback as the destination directory
62 static void get_dest_dir(HINF hInf
, PCWSTR pszSection
, PWSTR pszBuffer
, DWORD dwSize
)
65 WCHAR key
[MAX_PATH
+ 2], value
[MAX_PATH
+ 2];
66 WCHAR prefix
[PREFIX_LEN
+ 2];
67 HKEY root
, subkey
= 0;
70 /* load the destination parameters */
71 SetupFindFirstLineW(hInf
, pszSection
, NULL
, &context
);
72 SetupGetStringFieldW(&context
, 1, prefix
, PREFIX_LEN
+ 2, &size
);
73 strip_quotes(prefix
, &size
);
74 SetupGetStringFieldW(&context
, 2, key
, MAX_PATH
+ 2, &size
);
75 strip_quotes(key
, &size
);
76 SetupGetStringFieldW(&context
, 3, value
, MAX_PATH
+ 2, &size
);
77 strip_quotes(value
, &size
);
79 if (!lstrcmpW(prefix
, L
"HKLM"))
80 root
= HKEY_LOCAL_MACHINE
;
81 else if (!lstrcmpW(prefix
, L
"HKCU"))
82 root
= HKEY_CURRENT_USER
;
86 size
= dwSize
* sizeof(WCHAR
);
88 /* fallback to the default destination dir if reg fails */
89 if (RegOpenKeyW(root
, key
, &subkey
) ||
90 RegQueryValueExW(subkey
, value
, NULL
, NULL
, (LPBYTE
)pszBuffer
, &size
))
92 SetupGetStringFieldW(&context
, 5, pszBuffer
, dwSize
, &size
);
93 strip_quotes(pszBuffer
, &size
);
96 if (subkey
) RegCloseKey(subkey
);
99 /* loads the LDIDs specified in the install section of an INF */
100 void set_ldids(HINF hInf
, LPCWSTR pszInstallSection
, LPCWSTR pszWorkingDir
)
102 WCHAR field
[MAX_FIELD_LENGTH
];
103 WCHAR line
[MAX_FIELD_LENGTH
];
104 WCHAR dest
[MAX_PATH
];
109 if (!SetupGetLineTextW(NULL
, hInf
, pszInstallSection
, L
"CustomDestination",
110 field
, MAX_FIELD_LENGTH
, &size
))
113 if (!SetupFindFirstLineW(hInf
, field
, NULL
, &context
))
118 LPWSTR value
, ptr
, key
, key_copy
= NULL
;
121 SetupGetLineTextW(&context
, NULL
, NULL
, NULL
,
122 line
, MAX_FIELD_LENGTH
, &size
);
124 /* SetupGetLineTextW returns the value if there is only one key, but
125 * returns the whole line if there is more than one key
127 if (!(value
= wcschr(line
, '=')))
129 SetupGetStringFieldW(&context
, 0, NULL
, 0, &size
);
130 key
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
132 SetupGetStringFieldW(&context
, 0, key
, size
, &size
);
141 /* remove leading whitespace from the value */
142 while (*value
== ' ')
145 /* Extract the flags */
146 ptr
= wcschr(value
, ',');
149 flags
= wcstol(ptr
+1, NULL
, 10);
152 /* set dest to pszWorkingDir if key is SourceDir */
153 if (pszWorkingDir
&& !lstrcmpiW(value
, L
"SourceDir"))
154 lstrcpynW(dest
, pszWorkingDir
, MAX_PATH
);
156 get_dest_dir(hInf
, value
, dest
, MAX_PATH
);
158 /* If prompting required, provide dialog to request path */
160 FIXME("Need to support changing paths - default will be used\n");
162 /* set all ldids to dest */
163 while ((ptr
= get_parameter(&key
, ',', FALSE
)))
165 ldid
= wcstol(ptr
, NULL
, 10);
166 SetupSetDirectoryIdW(hInf
, ldid
, dest
);
168 HeapFree(GetProcessHeap(), 0, key_copy
);
169 } while (SetupFindNextLine(&context
, &context
));
172 /***********************************************************************
173 * CloseINFEngine (ADVPACK.@)
175 * Closes a handle to an INF file opened with OpenINFEngine.
178 * hInf [I] Handle to the INF file to close.
184 HRESULT WINAPI
CloseINFEngine(HINF hInf
)
186 TRACE("(%p)\n", hInf
);
191 SetupCloseInfFile(hInf
);
195 /***********************************************************************
196 * IsNTAdmin (ADVPACK.@)
198 * Checks if the user has admin privileges.
201 * reserved [I] Reserved. Must be 0.
202 * pReserved [I] Reserved. Must be NULL.
205 * TRUE if user has admin rights, FALSE otherwise.
207 BOOL WINAPI
IsNTAdmin(DWORD reserved
, LPDWORD pReserved
)
209 SID_IDENTIFIER_AUTHORITY SidAuthority
= {SECURITY_NT_AUTHORITY
};
210 PTOKEN_GROUPS pTokenGroups
;
211 BOOL bSidFound
= FALSE
;
216 TRACE("(%ld, %p)\n", reserved
, pReserved
);
218 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
))
221 if (!GetTokenInformation(hToken
, TokenGroups
, NULL
, 0, &dwSize
))
223 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
230 pTokenGroups
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
237 if (!GetTokenInformation(hToken
, TokenGroups
, pTokenGroups
, dwSize
, &dwSize
))
239 HeapFree(GetProcessHeap(), 0, pTokenGroups
);
246 if (!AllocateAndInitializeSid(&SidAuthority
, 2, SECURITY_BUILTIN_DOMAIN_RID
,
247 DOMAIN_ALIAS_RID_ADMINS
, 0, 0, 0, 0, 0, 0, &pSid
))
249 HeapFree(GetProcessHeap(), 0, pTokenGroups
);
253 for (i
= 0; i
< pTokenGroups
->GroupCount
; i
++)
255 if (EqualSid(pSid
, pTokenGroups
->Groups
[i
].Sid
))
262 HeapFree(GetProcessHeap(), 0, pTokenGroups
);
268 /***********************************************************************
269 * NeedRebootInit (ADVPACK.@)
271 * Sets up conditions for reboot checking.
274 * Value required by NeedReboot.
276 DWORD WINAPI
NeedRebootInit(VOID
)
278 FIXME("(VOID): stub\n");
282 /***********************************************************************
283 * NeedReboot (ADVPACK.@)
285 * Determines whether a reboot is required.
288 * dwRebootCheck [I] Value from NeedRebootInit.
291 * TRUE if a reboot is needed, FALSE otherwise.
296 BOOL WINAPI
NeedReboot(DWORD dwRebootCheck
)
298 FIXME("(%ld): stub\n", dwRebootCheck
);
302 /***********************************************************************
303 * OpenINFEngineA (ADVPACK.@)
305 * See OpenINFEngineW.
307 HRESULT WINAPI
OpenINFEngineA(LPCSTR pszInfFilename
, LPCSTR pszInstallSection
,
308 DWORD dwFlags
, HINF
*phInf
, PVOID pvReserved
)
310 UNICODE_STRING filenameW
, installW
;
313 TRACE("(%s, %s, %ld, %p, %p)\n", debugstr_a(pszInfFilename
),
314 debugstr_a(pszInstallSection
), dwFlags
, phInf
, pvReserved
);
316 if (!pszInfFilename
|| !phInf
)
319 RtlCreateUnicodeStringFromAsciiz(&filenameW
, pszInfFilename
);
320 RtlCreateUnicodeStringFromAsciiz(&installW
, pszInstallSection
);
322 res
= OpenINFEngineW(filenameW
.Buffer
, installW
.Buffer
,
323 dwFlags
, phInf
, pvReserved
);
325 RtlFreeUnicodeString(&filenameW
);
326 RtlFreeUnicodeString(&installW
);
331 /***********************************************************************
332 * OpenINFEngineW (ADVPACK.@)
334 * Opens and returns a handle to an INF file to be used by
335 * TranslateInfStringEx to continuously translate the INF file.
338 * pszInfFilename [I] Filename of the INF to open.
339 * pszInstallSection [I] Name of the Install section in the INF.
340 * dwFlags [I] See advpub.h.
341 * phInf [O] Handle to the loaded INF file.
342 * pvReserved [I] Reserved. Must be NULL.
348 HRESULT WINAPI
OpenINFEngineW(LPCWSTR pszInfFilename
, LPCWSTR pszInstallSection
,
349 DWORD dwFlags
, HINF
*phInf
, PVOID pvReserved
)
351 TRACE("(%s, %s, %ld, %p, %p)\n", debugstr_w(pszInfFilename
),
352 debugstr_w(pszInstallSection
), dwFlags
, phInf
, pvReserved
);
354 if (!pszInfFilename
|| !phInf
)
357 *phInf
= SetupOpenInfFileW(pszInfFilename
, NULL
, INF_STYLE_WIN4
, NULL
);
358 if (*phInf
== INVALID_HANDLE_VALUE
)
359 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
361 set_ldids(*phInf
, pszInstallSection
, NULL
);
366 /***********************************************************************
367 * RebootCheckOnInstallA (ADVPACK.@)
369 * See RebootCheckOnInstallW.
371 HRESULT WINAPI
RebootCheckOnInstallA(HWND hWnd
, LPCSTR pszINF
,
372 LPCSTR pszSec
, DWORD dwReserved
)
374 UNICODE_STRING infW
, secW
;
377 TRACE("(%p, %s, %s, %ld)\n", hWnd
, debugstr_a(pszINF
),
378 debugstr_a(pszSec
), dwReserved
);
380 if (!pszINF
|| !pszSec
)
383 RtlCreateUnicodeStringFromAsciiz(&infW
, pszINF
);
384 RtlCreateUnicodeStringFromAsciiz(&secW
, pszSec
);
386 res
= RebootCheckOnInstallW(hWnd
, infW
.Buffer
, secW
.Buffer
, dwReserved
);
388 RtlFreeUnicodeString(&infW
);
389 RtlFreeUnicodeString(&secW
);
394 /***********************************************************************
395 * RebootCheckOnInstallW (ADVPACK.@)
397 * Checks if a reboot is required for an installed INF section.
400 * hWnd [I] Handle to the window used for messages.
401 * pszINF [I] Filename of the INF file.
402 * pszSec [I] INF section to check.
403 * dwReserved [I] Reserved. Must be 0.
406 * Success: S_OK - Reboot is needed if the INF section is installed.
407 * S_FALSE - Reboot is not needed.
408 * Failure: HRESULT of GetLastError().
411 * if pszSec is NULL, RebootCheckOnInstall checks the DefaultInstall
412 * or DefaultInstall.NT section.
417 HRESULT WINAPI
RebootCheckOnInstallW(HWND hWnd
, LPCWSTR pszINF
,
418 LPCWSTR pszSec
, DWORD dwReserved
)
420 FIXME("(%p, %s, %s, %ld): stub\n", hWnd
, debugstr_w(pszINF
),
421 debugstr_w(pszSec
), dwReserved
);
426 /* registers the OCX if do_reg is TRUE, unregisters it otherwise */
427 HRESULT
do_ocx_reg(HMODULE hocx
, BOOL do_reg
, const WCHAR
*flags
, const WCHAR
*param
)
429 DLLREGISTER reg_func
;
432 reg_func
= (DLLREGISTER
)GetProcAddress(hocx
, "DllRegisterServer");
434 reg_func
= (DLLREGISTER
)GetProcAddress(hocx
, "DllUnregisterServer");
443 /***********************************************************************
444 * RegisterOCX (ADVPACK.@)
449 * hWnd [I] Handle to the window used for the display.
450 * hInst [I] Instance of the process.
451 * cmdline [I] Contains parameters in the order OCX,flags,param.
452 * show [I] How the window should be shown.
459 * OCX - Filename of the OCX to register.
460 * flags - Controls the operation of RegisterOCX.
461 * 'I' Call DllRegisterServer and DllInstall.
462 * 'N' Only call DllInstall.
463 * param - Command line passed to DllInstall.
465 HRESULT WINAPI
RegisterOCX(HWND hWnd
, HINSTANCE hInst
, LPCSTR cmdline
, INT show
)
467 LPWSTR ocx_filename
, str_flags
, param
;
468 LPWSTR cmdline_copy
, cmdline_ptr
;
469 UNICODE_STRING cmdlineW
;
474 TRACE("(%s)\n", debugstr_a(cmdline
));
476 RtlCreateUnicodeStringFromAsciiz(&cmdlineW
, cmdline
);
478 size
= (lstrlenW(cmdlineW
.Buffer
) + 1) * sizeof(WCHAR
);
479 cmdline_copy
= HeapAlloc(GetProcessHeap(), 0, size
);
480 cmdline_ptr
= cmdline_copy
;
481 lstrcpyW(cmdline_copy
, cmdlineW
.Buffer
);
483 ocx_filename
= get_parameter(&cmdline_ptr
, ',', TRUE
);
484 if (!ocx_filename
|| !*ocx_filename
)
487 str_flags
= get_parameter(&cmdline_ptr
, ',', TRUE
);
488 param
= get_parameter(&cmdline_ptr
, ',', TRUE
);
490 hm
= LoadLibraryExW(ocx_filename
, NULL
, LOAD_WITH_ALTERED_SEARCH_PATH
);
494 hr
= do_ocx_reg(hm
, TRUE
, str_flags
, param
);
498 HeapFree(GetProcessHeap(), 0, cmdline_copy
);
499 RtlFreeUnicodeString(&cmdlineW
);
504 /***********************************************************************
505 * SetPerUserSecValuesA (ADVPACK.@)
507 * See SetPerUserSecValuesW.
509 HRESULT WINAPI
SetPerUserSecValuesA(PERUSERSECTIONA
* pPerUser
)
511 PERUSERSECTIONW perUserW
;
513 TRACE("(%p)\n", pPerUser
);
518 MultiByteToWideChar(CP_ACP
, 0, pPerUser
->szGUID
, -1, perUserW
.szGUID
, ARRAY_SIZE(perUserW
.szGUID
));
519 MultiByteToWideChar(CP_ACP
, 0, pPerUser
->szDispName
, -1, perUserW
.szDispName
, ARRAY_SIZE(perUserW
.szDispName
));
520 MultiByteToWideChar(CP_ACP
, 0, pPerUser
->szLocale
, -1, perUserW
.szLocale
, ARRAY_SIZE(perUserW
.szLocale
));
521 MultiByteToWideChar(CP_ACP
, 0, pPerUser
->szStub
, -1, perUserW
.szStub
, ARRAY_SIZE(perUserW
.szStub
));
522 MultiByteToWideChar(CP_ACP
, 0, pPerUser
->szVersion
, -1, perUserW
.szVersion
, ARRAY_SIZE(perUserW
.szVersion
));
523 MultiByteToWideChar(CP_ACP
, 0, pPerUser
->szCompID
, -1, perUserW
.szCompID
, ARRAY_SIZE(perUserW
.szCompID
));
524 perUserW
.dwIsInstalled
= pPerUser
->dwIsInstalled
;
525 perUserW
.bRollback
= pPerUser
->bRollback
;
527 return SetPerUserSecValuesW(&perUserW
);
530 /***********************************************************************
531 * SetPerUserSecValuesW (ADVPACK.@)
533 * Prepares the per-user stub values under IsInstalled\{GUID} that
534 * control the per-user installation.
537 * pPerUser [I] Per-user stub values.
543 HRESULT WINAPI
SetPerUserSecValuesW(PERUSERSECTIONW
* pPerUser
)
547 TRACE("(%p)\n", pPerUser
);
549 if (!pPerUser
|| !*pPerUser
->szGUID
)
552 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
, setup_key
, 0, NULL
, 0, KEY_WRITE
,
558 if (RegCreateKeyExW(setup
, pPerUser
->szGUID
, 0, NULL
, 0, KEY_ALL_ACCESS
,
565 if (*pPerUser
->szStub
)
567 RegSetValueExW(guid
, L
"StubPath", 0, REG_SZ
, (BYTE
*)pPerUser
->szStub
,
568 (lstrlenW(pPerUser
->szStub
) + 1) * sizeof(WCHAR
));
571 if (*pPerUser
->szVersion
)
573 RegSetValueExW(guid
, L
"Version", 0, REG_SZ
, (BYTE
*)pPerUser
->szVersion
,
574 (lstrlenW(pPerUser
->szVersion
) + 1) * sizeof(WCHAR
));
577 if (*pPerUser
->szLocale
)
579 RegSetValueExW(guid
, L
"Locale", 0, REG_SZ
, (BYTE
*)pPerUser
->szLocale
,
580 (lstrlenW(pPerUser
->szLocale
) + 1) * sizeof(WCHAR
));
583 if (*pPerUser
->szCompID
)
585 RegSetValueExW(guid
, L
"ComponentID", 0, REG_SZ
, (BYTE
*)pPerUser
->szCompID
,
586 (lstrlenW(pPerUser
->szCompID
) + 1) * sizeof(WCHAR
));
589 if (*pPerUser
->szDispName
)
591 RegSetValueExW(guid
, NULL
, 0, REG_SZ
, (LPBYTE
)pPerUser
->szDispName
,
592 (lstrlenW(pPerUser
->szDispName
) + 1) * sizeof(WCHAR
));
595 RegSetValueExW(guid
, L
"IsInstalled", 0, REG_DWORD
,
596 (LPBYTE
)&pPerUser
->dwIsInstalled
, sizeof(DWORD
));
604 /***********************************************************************
605 * TranslateInfStringA (ADVPACK.@)
607 * See TranslateInfStringW.
609 HRESULT WINAPI
TranslateInfStringA(LPCSTR pszInfFilename
, LPCSTR pszInstallSection
,
610 LPCSTR pszTranslateSection
, LPCSTR pszTranslateKey
, LPSTR pszBuffer
,
611 DWORD dwBufferSize
, PDWORD pdwRequiredSize
, PVOID pvReserved
)
613 UNICODE_STRING filenameW
, installW
;
614 UNICODE_STRING translateW
, keyW
;
619 TRACE("(%s, %s, %s, %s, %p, %ld, %p, %p)\n",
620 debugstr_a(pszInfFilename
), debugstr_a(pszInstallSection
),
621 debugstr_a(pszTranslateSection
), debugstr_a(pszTranslateKey
),
622 pszBuffer
, dwBufferSize
,pdwRequiredSize
, pvReserved
);
624 if (!pszInfFilename
|| !pszTranslateSection
||
625 !pszTranslateKey
|| !pdwRequiredSize
)
628 RtlCreateUnicodeStringFromAsciiz(&filenameW
, pszInfFilename
);
629 RtlCreateUnicodeStringFromAsciiz(&installW
, pszInstallSection
);
630 RtlCreateUnicodeStringFromAsciiz(&translateW
, pszTranslateSection
);
631 RtlCreateUnicodeStringFromAsciiz(&keyW
, pszTranslateKey
);
633 res
= TranslateInfStringW(filenameW
.Buffer
, installW
.Buffer
,
634 translateW
.Buffer
, keyW
.Buffer
, NULL
,
635 dwBufferSize
, &len
, NULL
);
639 bufferW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
641 res
= TranslateInfStringW(filenameW
.Buffer
, installW
.Buffer
,
642 translateW
.Buffer
, keyW
.Buffer
, bufferW
,
646 *pdwRequiredSize
= WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1,
647 NULL
, 0, NULL
, NULL
);
649 if (dwBufferSize
>= *pdwRequiredSize
)
651 WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, pszBuffer
,
652 dwBufferSize
, NULL
, NULL
);
655 res
= E_NOT_SUFFICIENT_BUFFER
;
658 HeapFree(GetProcessHeap(), 0, bufferW
);
661 RtlFreeUnicodeString(&filenameW
);
662 RtlFreeUnicodeString(&installW
);
663 RtlFreeUnicodeString(&translateW
);
664 RtlFreeUnicodeString(&keyW
);
669 /***********************************************************************
670 * TranslateInfStringW (ADVPACK.@)
672 * Translates the value of a specified key in an inf file into the
673 * current locale by expanding string macros.
676 * pszInfFilename [I] Filename of the inf file.
677 * pszInstallSection [I]
678 * pszTranslateSection [I] Inf section where the key exists.
679 * pszTranslateKey [I] Key to translate.
680 * pszBuffer [O] Contains the translated string on exit.
681 * dwBufferSize [I] Size on input of pszBuffer.
682 * pdwRequiredSize [O] Length of the translated key.
683 * pvReserved [I] Reserved, must be NULL.
687 * Failure: An hresult error code.
689 HRESULT WINAPI
TranslateInfStringW(LPCWSTR pszInfFilename
, LPCWSTR pszInstallSection
,
690 LPCWSTR pszTranslateSection
, LPCWSTR pszTranslateKey
, LPWSTR pszBuffer
,
691 DWORD dwBufferSize
, PDWORD pdwRequiredSize
, PVOID pvReserved
)
696 TRACE("(%s, %s, %s, %s, %p, %ld, %p, %p)\n",
697 debugstr_w(pszInfFilename
), debugstr_w(pszInstallSection
),
698 debugstr_w(pszTranslateSection
), debugstr_w(pszTranslateKey
),
699 pszBuffer
, dwBufferSize
,pdwRequiredSize
, pvReserved
);
701 if (!pszInfFilename
|| !pszTranslateSection
||
702 !pszTranslateKey
|| !pdwRequiredSize
)
705 hInf
= SetupOpenInfFileW(pszInfFilename
, NULL
, INF_STYLE_WIN4
, NULL
);
706 if (hInf
== INVALID_HANDLE_VALUE
)
707 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
709 set_ldids(hInf
, pszInstallSection
, NULL
);
711 if (!SetupGetLineTextW(NULL
, hInf
, pszTranslateSection
, pszTranslateKey
,
712 pszBuffer
, dwBufferSize
, pdwRequiredSize
))
714 if (dwBufferSize
< *pdwRequiredSize
)
715 hret
= E_NOT_SUFFICIENT_BUFFER
;
717 hret
= SPAPI_E_LINE_NOT_FOUND
;
720 SetupCloseInfFile(hInf
);
724 /***********************************************************************
725 * TranslateInfStringExA (ADVPACK.@)
727 * See TranslateInfStringExW.
729 HRESULT WINAPI
TranslateInfStringExA(HINF hInf
, LPCSTR pszInfFilename
,
730 LPCSTR pszTranslateSection
, LPCSTR pszTranslateKey
,
731 LPSTR pszBuffer
, DWORD dwBufferSize
,
732 PDWORD pdwRequiredSize
, PVOID pvReserved
)
734 UNICODE_STRING filenameW
, sectionW
, keyW
;
739 TRACE("(%p, %s, %s, %s, %p, %ld, %p, %p)\n", hInf
, debugstr_a(pszInfFilename
),
740 debugstr_a(pszTranslateSection
), debugstr_a(pszTranslateKey
),
741 pszBuffer
, dwBufferSize
, pdwRequiredSize
, pvReserved
);
743 if (!pszInfFilename
|| !pszTranslateSection
||
744 !pszTranslateKey
|| !pdwRequiredSize
)
747 RtlCreateUnicodeStringFromAsciiz(&filenameW
, pszInfFilename
);
748 RtlCreateUnicodeStringFromAsciiz(§ionW
, pszTranslateSection
);
749 RtlCreateUnicodeStringFromAsciiz(&keyW
, pszTranslateKey
);
751 res
= TranslateInfStringExW(hInf
, filenameW
.Buffer
, sectionW
.Buffer
,
752 keyW
.Buffer
, NULL
, 0, &len
, NULL
);
756 bufferW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
758 res
= TranslateInfStringExW(hInf
, filenameW
.Buffer
, sectionW
.Buffer
,
759 keyW
.Buffer
, bufferW
, len
, &len
, NULL
);
763 *pdwRequiredSize
= WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1,
764 NULL
, 0, NULL
, NULL
);
766 if (dwBufferSize
>= *pdwRequiredSize
)
768 WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, pszBuffer
,
769 dwBufferSize
, NULL
, NULL
);
772 res
= E_NOT_SUFFICIENT_BUFFER
;
775 HeapFree(GetProcessHeap(), 0, bufferW
);
778 RtlFreeUnicodeString(&filenameW
);
779 RtlFreeUnicodeString(§ionW
);
780 RtlFreeUnicodeString(&keyW
);
785 /***********************************************************************
786 * TranslateInfStringExW (ADVPACK.@)
788 * Using a handle to an INF file opened with OpenINFEngine, translates
789 * the value of a specified key in an inf file into the current locale
790 * by expanding string macros.
793 * hInf [I] Handle to the INF file.
794 * pszInfFilename [I] Filename of the INF file.
795 * pszTranslateSection [I] Inf section where the key exists.
796 * pszTranslateKey [I] Key to translate.
797 * pszBuffer [O] Contains the translated string on exit.
798 * dwBufferSize [I] Size on input of pszBuffer.
799 * pdwRequiredSize [O] Length of the translated key.
800 * pvReserved [I] Reserved. Must be NULL.
807 * To use TranslateInfStringEx to translate an INF file continuously,
808 * open the INF file with OpenINFEngine, call TranslateInfStringEx as
809 * many times as needed, then release the handle with CloseINFEngine.
810 * When translating more than one keys, this method is more efficient
811 * than calling TranslateInfString, because the INF file is only
814 HRESULT WINAPI
TranslateInfStringExW(HINF hInf
, LPCWSTR pszInfFilename
,
815 LPCWSTR pszTranslateSection
, LPCWSTR pszTranslateKey
,
816 LPWSTR pszBuffer
, DWORD dwBufferSize
,
817 PDWORD pdwRequiredSize
, PVOID pvReserved
)
819 TRACE("(%p, %s, %s, %s, %p, %ld, %p, %p)\n", hInf
, debugstr_w(pszInfFilename
),
820 debugstr_w(pszTranslateSection
), debugstr_w(pszTranslateKey
),
821 pszBuffer
, dwBufferSize
, pdwRequiredSize
, pvReserved
);
823 if (!hInf
|| !pszInfFilename
|| !pszTranslateSection
|| !pszTranslateKey
)
826 if (!SetupGetLineTextW(NULL
, hInf
, pszTranslateSection
, pszTranslateKey
,
827 pszBuffer
, dwBufferSize
, pdwRequiredSize
))
829 if (dwBufferSize
< *pdwRequiredSize
)
830 return E_NOT_SUFFICIENT_BUFFER
;
832 return SPAPI_E_LINE_NOT_FOUND
;
838 /***********************************************************************
839 * UserInstStubWrapperA (ADVPACK.@)
841 * See UserInstStubWrapperW.
843 HRESULT WINAPI
UserInstStubWrapperA(HWND hWnd
, HINSTANCE hInstance
,
844 LPSTR pszParms
, INT nShow
)
846 UNICODE_STRING parmsW
;
849 TRACE("(%p, %p, %s, %i)\n", hWnd
, hInstance
, debugstr_a(pszParms
), nShow
);
854 RtlCreateUnicodeStringFromAsciiz(&parmsW
, pszParms
);
856 res
= UserInstStubWrapperW(hWnd
, hInstance
, parmsW
.Buffer
, nShow
);
858 RtlFreeUnicodeString(&parmsW
);
863 /***********************************************************************
864 * UserInstStubWrapperW (ADVPACK.@)
866 * Launches the user stub wrapper specified by the RealStubPath
867 * registry value under Installed Components\szParms.
870 * hWnd [I] Handle to the window used for the display.
871 * hInstance [I] Instance of the process.
872 * szParms [I] The GUID of the installation.
873 * show [I] How the window should be shown.
880 * If the type of the StubRealPath value is REG_EXPAND_SZ, then
881 * we should call ExpandEnvironmentStrings on the value and
884 HRESULT WINAPI
UserInstStubWrapperW(HWND hWnd
, HINSTANCE hInstance
,
885 LPWSTR pszParms
, INT nShow
)
888 WCHAR stub
[MAX_PATH
];
889 DWORD size
= sizeof(stub
);
893 TRACE("(%p, %p, %s, %i)\n", hWnd
, hInstance
, debugstr_w(pszParms
), nShow
);
895 if (!pszParms
|| !*pszParms
)
898 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, setup_key
, 0, KEY_READ
, &setup
))
903 if (RegOpenKeyExW(setup
, pszParms
, 0, KEY_READ
, &guid
))
909 res
= RegQueryValueExW(guid
, L
"RealStubPath", NULL
, NULL
, (BYTE
*)stub
, &size
);
913 /* launch the user stub wrapper */
914 hr
= launch_exe(stub
, NULL
, NULL
);
923 /***********************************************************************
924 * UserUnInstStubWrapperA (ADVPACK.@)
926 * See UserUnInstStubWrapperW.
928 HRESULT WINAPI
UserUnInstStubWrapperA(HWND hWnd
, HINSTANCE hInstance
,
929 LPSTR pszParms
, INT nShow
)
931 UNICODE_STRING parmsW
;
934 TRACE("(%p, %p, %s, %i)\n", hWnd
, hInstance
, debugstr_a(pszParms
), nShow
);
939 RtlCreateUnicodeStringFromAsciiz(&parmsW
, pszParms
);
941 res
= UserUnInstStubWrapperW(hWnd
, hInstance
, parmsW
.Buffer
, nShow
);
943 RtlFreeUnicodeString(&parmsW
);
948 /***********************************************************************
949 * UserUnInstStubWrapperW (ADVPACK.@)
951 HRESULT WINAPI
UserUnInstStubWrapperW(HWND hWnd
, HINSTANCE hInstance
,
952 LPWSTR pszParms
, INT nShow
)
954 FIXME("(%p, %p, %s, %i): stub\n", hWnd
, hInstance
, debugstr_w(pszParms
), nShow
);