include: Add IXMLHTTPRequest2/3 interfaces.
[wine.git] / dlls / advpack / advpack.c
blob25751af64bc207b103b431905e932ec20d505da4
1 /*
2 * Advpack main
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 #include <stdarg.h>
23 #include <stdlib.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "winreg.h"
29 #include "winternl.h"
30 #include "winnls.h"
31 #include "setupapi.h"
32 #include "advpub.h"
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
41 #define PREFIX_LEN 5
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]=='\'')
51 *size -= 2;
52 buffer[*size] = 0x00;
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)
64 INFCONTEXT context;
65 WCHAR key[MAX_PATH + 2], value[MAX_PATH + 2];
66 WCHAR prefix[PREFIX_LEN + 2];
67 HKEY root, subkey = 0;
68 DWORD size;
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;
83 else
84 root = NULL;
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];
105 INFCONTEXT context;
106 DWORD size;
107 int ldid;
109 if (!SetupGetLineTextW(NULL, hInf, pszInstallSection, L"CustomDestination",
110 field, MAX_FIELD_LENGTH, &size))
111 return;
113 if (!SetupFindFirstLineW(hInf, field, NULL, &context))
114 return;
118 LPWSTR value, ptr, key, key_copy = NULL;
119 DWORD flags = 0;
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));
131 key_copy = key;
132 SetupGetStringFieldW(&context, 0, key, size, &size);
133 value = line;
135 else
137 key = line;
138 *(value++) = '\0';
141 /* remove leading whitespace from the value */
142 while (*value == ' ')
143 value++;
145 /* Extract the flags */
146 ptr = wcschr(value, ',');
147 if (ptr) {
148 *ptr = '\0';
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);
155 else
156 get_dest_dir(hInf, value, dest, MAX_PATH);
158 /* If prompting required, provide dialog to request path */
159 if (flags & 0x04)
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.
177 * PARAMS
178 * hInf [I] Handle to the INF file to close.
180 * RETURNS
181 * Success: S_OK.
182 * Failure: E_FAIL.
184 HRESULT WINAPI CloseINFEngine(HINF hInf)
186 TRACE("(%p)\n", hInf);
188 if (!hInf)
189 return E_INVALIDARG;
191 SetupCloseInfFile(hInf);
192 return S_OK;
195 /***********************************************************************
196 * IsNTAdmin (ADVPACK.@)
198 * Checks if the user has admin privileges.
200 * PARAMS
201 * reserved [I] Reserved. Must be 0.
202 * pReserved [I] Reserved. Must be NULL.
204 * RETURNS
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;
212 DWORD dwSize, i;
213 HANDLE hToken;
214 PSID pSid;
216 TRACE("(%d, %p)\n", reserved, pReserved);
218 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
219 return FALSE;
221 if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwSize))
223 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
225 CloseHandle(hToken);
226 return FALSE;
230 pTokenGroups = HeapAlloc(GetProcessHeap(), 0, dwSize);
231 if (!pTokenGroups)
233 CloseHandle(hToken);
234 return FALSE;
237 if (!GetTokenInformation(hToken, TokenGroups, pTokenGroups, dwSize, &dwSize))
239 HeapFree(GetProcessHeap(), 0, pTokenGroups);
240 CloseHandle(hToken);
241 return FALSE;
244 CloseHandle(hToken);
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);
250 return FALSE;
253 for (i = 0; i < pTokenGroups->GroupCount; i++)
255 if (EqualSid(pSid, pTokenGroups->Groups[i].Sid))
257 bSidFound = TRUE;
258 break;
262 HeapFree(GetProcessHeap(), 0, pTokenGroups);
263 FreeSid(pSid);
265 return bSidFound;
268 /***********************************************************************
269 * NeedRebootInit (ADVPACK.@)
271 * Sets up conditions for reboot checking.
273 * RETURNS
274 * Value required by NeedReboot.
276 DWORD WINAPI NeedRebootInit(VOID)
278 FIXME("(VOID): stub\n");
279 return 0;
282 /***********************************************************************
283 * NeedReboot (ADVPACK.@)
285 * Determines whether a reboot is required.
287 * PARAMS
288 * dwRebootCheck [I] Value from NeedRebootInit.
290 * RETURNS
291 * TRUE if a reboot is needed, FALSE otherwise.
293 * BUGS
294 * Unimplemented.
296 BOOL WINAPI NeedReboot(DWORD dwRebootCheck)
298 FIXME("(%d): stub\n", dwRebootCheck);
299 return FALSE;
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;
311 HRESULT res;
313 TRACE("(%s, %s, %d, %p, %p)\n", debugstr_a(pszInfFilename),
314 debugstr_a(pszInstallSection), dwFlags, phInf, pvReserved);
316 if (!pszInfFilename || !phInf)
317 return E_INVALIDARG;
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);
328 return res;
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.
337 * PARAMS
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.
344 * RETURNS
345 * Success: S_OK.
346 * Failure: E_FAIL.
348 HRESULT WINAPI OpenINFEngineW(LPCWSTR pszInfFilename, LPCWSTR pszInstallSection,
349 DWORD dwFlags, HINF *phInf, PVOID pvReserved)
351 TRACE("(%s, %s, %d, %p, %p)\n", debugstr_w(pszInfFilename),
352 debugstr_w(pszInstallSection), dwFlags, phInf, pvReserved);
354 if (!pszInfFilename || !phInf)
355 return E_INVALIDARG;
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);
363 return S_OK;
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;
375 HRESULT res;
377 TRACE("(%p, %s, %s, %d)\n", hWnd, debugstr_a(pszINF),
378 debugstr_a(pszSec), dwReserved);
380 if (!pszINF || !pszSec)
381 return E_INVALIDARG;
383 RtlCreateUnicodeStringFromAsciiz(&infW, pszINF);
384 RtlCreateUnicodeStringFromAsciiz(&secW, pszSec);
386 res = RebootCheckOnInstallW(hWnd, infW.Buffer, secW.Buffer, dwReserved);
388 RtlFreeUnicodeString(&infW);
389 RtlFreeUnicodeString(&secW);
391 return res;
394 /***********************************************************************
395 * RebootCheckOnInstallW (ADVPACK.@)
397 * Checks if a reboot is required for an installed INF section.
399 * PARAMS
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.
405 * RETURNS
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().
410 * NOTES
411 * if pszSec is NULL, RebootCheckOnInstall checks the DefaultInstall
412 * or DefaultInstall.NT section.
414 * BUGS
415 * Unimplemented.
417 HRESULT WINAPI RebootCheckOnInstallW(HWND hWnd, LPCWSTR pszINF,
418 LPCWSTR pszSec, DWORD dwReserved)
420 FIXME("(%p, %s, %s, %d): stub\n", hWnd, debugstr_w(pszINF),
421 debugstr_w(pszSec), dwReserved);
423 return E_FAIL;
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;
431 if (do_reg)
432 reg_func = (DLLREGISTER)GetProcAddress(hocx, "DllRegisterServer");
433 else
434 reg_func = (DLLREGISTER)GetProcAddress(hocx, "DllUnregisterServer");
436 if (!reg_func)
437 return E_FAIL;
439 reg_func();
440 return S_OK;
443 /***********************************************************************
444 * RegisterOCX (ADVPACK.@)
446 * Registers an OCX.
448 * PARAMS
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.
454 * RETURNS
455 * Success: S_OK.
456 * Failure: E_FAIL.
458 * NOTES
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;
470 HRESULT hr = E_FAIL;
471 HMODULE hm = NULL;
472 DWORD size;
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)
485 goto done;
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);
491 if (!hm)
492 goto done;
494 hr = do_ocx_reg(hm, TRUE, str_flags, param);
496 done:
497 FreeLibrary(hm);
498 HeapFree(GetProcessHeap(), 0, cmdline_copy);
499 RtlFreeUnicodeString(&cmdlineW);
501 return hr;
504 /***********************************************************************
505 * SetPerUserSecValuesA (ADVPACK.@)
507 * See SetPerUserSecValuesW.
509 HRESULT WINAPI SetPerUserSecValuesA(PERUSERSECTIONA* pPerUser)
511 PERUSERSECTIONW perUserW;
513 TRACE("(%p)\n", pPerUser);
515 if (!pPerUser)
516 return E_INVALIDARG;
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.
536 * PARAMS
537 * pPerUser [I] Per-user stub values.
539 * RETURNS
540 * Success: S_OK.
541 * Failure: E_FAIL.
543 HRESULT WINAPI SetPerUserSecValuesW(PERUSERSECTIONW* pPerUser)
545 HKEY setup, guid;
547 TRACE("(%p)\n", pPerUser);
549 if (!pPerUser || !*pPerUser->szGUID)
550 return S_OK;
552 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, setup_key, 0, NULL, 0, KEY_WRITE,
553 NULL, &setup, NULL))
555 return E_FAIL;
558 if (RegCreateKeyExW(setup, pPerUser->szGUID, 0, NULL, 0, KEY_ALL_ACCESS,
559 NULL, &guid, NULL))
561 RegCloseKey(setup);
562 return E_FAIL;
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));
598 RegCloseKey(guid);
599 RegCloseKey(setup);
601 return S_OK;
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;
615 LPWSTR bufferW;
616 HRESULT res;
617 DWORD len = 0;
619 TRACE("(%s, %s, %s, %s, %p, %d, %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)
626 return E_INVALIDARG;
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);
637 if (res == S_OK)
639 bufferW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
641 res = TranslateInfStringW(filenameW.Buffer, installW.Buffer,
642 translateW.Buffer, keyW.Buffer, bufferW,
643 len, &len, NULL);
644 if (res == S_OK)
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);
654 else
655 res = E_NOT_SUFFICIENT_BUFFER;
658 HeapFree(GetProcessHeap(), 0, bufferW);
661 RtlFreeUnicodeString(&filenameW);
662 RtlFreeUnicodeString(&installW);
663 RtlFreeUnicodeString(&translateW);
664 RtlFreeUnicodeString(&keyW);
666 return res;
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.
675 * PARAMS
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.
685 * RETURNS
686 * Success: S_OK.
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)
693 HINF hInf;
694 HRESULT hret = S_OK;
696 TRACE("(%s, %s, %s, %s, %p, %d, %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)
703 return E_INVALIDARG;
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;
716 else
717 hret = SPAPI_E_LINE_NOT_FOUND;
720 SetupCloseInfFile(hInf);
721 return hret;
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;
735 LPWSTR bufferW;
736 HRESULT res;
737 DWORD len = 0;
739 TRACE("(%p, %s, %s, %s, %p, %d, %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)
745 return E_INVALIDARG;
747 RtlCreateUnicodeStringFromAsciiz(&filenameW, pszInfFilename);
748 RtlCreateUnicodeStringFromAsciiz(&sectionW, pszTranslateSection);
749 RtlCreateUnicodeStringFromAsciiz(&keyW, pszTranslateKey);
751 res = TranslateInfStringExW(hInf, filenameW.Buffer, sectionW.Buffer,
752 keyW.Buffer, NULL, 0, &len, NULL);
754 if (res == S_OK)
756 bufferW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
758 res = TranslateInfStringExW(hInf, filenameW.Buffer, sectionW.Buffer,
759 keyW.Buffer, bufferW, len, &len, NULL);
761 if (res == S_OK)
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);
771 else
772 res = E_NOT_SUFFICIENT_BUFFER;
775 HeapFree(GetProcessHeap(), 0, bufferW);
778 RtlFreeUnicodeString(&filenameW);
779 RtlFreeUnicodeString(&sectionW);
780 RtlFreeUnicodeString(&keyW);
782 return res;
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.
792 * PARAMS
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.
802 * RETURNS
803 * Success: S_OK.
804 * Failure: E_FAIL.
806 * NOTES
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
812 * opened once.
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, %d, %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)
824 return E_INVALIDARG;
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;
835 return S_OK;
838 /***********************************************************************
839 * UserInstStubWrapperA (ADVPACK.@)
841 * See UserInstStubWrapperW.
843 HRESULT WINAPI UserInstStubWrapperA(HWND hWnd, HINSTANCE hInstance,
844 LPSTR pszParms, INT nShow)
846 UNICODE_STRING parmsW;
847 HRESULT res;
849 TRACE("(%p, %p, %s, %i)\n", hWnd, hInstance, debugstr_a(pszParms), nShow);
851 if (!pszParms)
852 return E_INVALIDARG;
854 RtlCreateUnicodeStringFromAsciiz(&parmsW, pszParms);
856 res = UserInstStubWrapperW(hWnd, hInstance, parmsW.Buffer, nShow);
858 RtlFreeUnicodeString(&parmsW);
860 return res;
863 /***********************************************************************
864 * UserInstStubWrapperW (ADVPACK.@)
866 * Launches the user stub wrapper specified by the RealStubPath
867 * registry value under Installed Components\szParms.
869 * PARAMS
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.
875 * RETURNS
876 * Success: S_OK.
877 * Failure: E_FAIL.
879 * TODO
880 * If the type of the StubRealPath value is REG_EXPAND_SZ, then
881 * we should call ExpandEnvironmentStrings on the value and
882 * launch the result.
884 HRESULT WINAPI UserInstStubWrapperW(HWND hWnd, HINSTANCE hInstance,
885 LPWSTR pszParms, INT nShow)
887 HKEY setup, guid;
888 WCHAR stub[MAX_PATH];
889 DWORD size = sizeof(stub);
890 HRESULT hr = S_OK;
891 BOOL res;
893 TRACE("(%p, %p, %s, %i)\n", hWnd, hInstance, debugstr_w(pszParms), nShow);
895 if (!pszParms || !*pszParms)
896 return E_INVALIDARG;
898 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, setup_key, 0, KEY_READ, &setup))
900 return E_FAIL;
903 if (RegOpenKeyExW(setup, pszParms, 0, KEY_READ, &guid))
905 RegCloseKey(setup);
906 return E_FAIL;
909 res = RegQueryValueExW(guid, L"RealStubPath", NULL, NULL, (BYTE *)stub, &size);
910 if (res || !*stub)
911 goto done;
913 /* launch the user stub wrapper */
914 hr = launch_exe(stub, NULL, NULL);
916 done:
917 RegCloseKey(setup);
918 RegCloseKey(guid);
920 return hr;
923 /***********************************************************************
924 * UserUnInstStubWrapperA (ADVPACK.@)
926 * See UserUnInstStubWrapperW.
928 HRESULT WINAPI UserUnInstStubWrapperA(HWND hWnd, HINSTANCE hInstance,
929 LPSTR pszParms, INT nShow)
931 UNICODE_STRING parmsW;
932 HRESULT res;
934 TRACE("(%p, %p, %s, %i)\n", hWnd, hInstance, debugstr_a(pszParms), nShow);
936 if (!pszParms)
937 return E_INVALIDARG;
939 RtlCreateUnicodeStringFromAsciiz(&parmsW, pszParms);
941 res = UserUnInstStubWrapperW(hWnd, hInstance, parmsW.Buffer, nShow);
943 RtlFreeUnicodeString(&parmsW);
945 return res;
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);
956 return E_FAIL;