makefiles: Always use the global SOURCES variable for .l files.
[wine.git] / dlls / advpack / advpack.c
blobbbde2285ff3bf9e0bf1efb36a806eaa1235f32b2
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 = malloc(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 free(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("(%ld, %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 = malloc(dwSize);
231 if (!pTokenGroups)
233 CloseHandle(hToken);
234 return FALSE;
237 if (!GetTokenInformation(hToken, TokenGroups, pTokenGroups, dwSize, &dwSize))
239 free(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 free(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 free(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("(%ld): 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, %ld, %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, %ld, %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, %ld)\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, %ld): 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;
473 TRACE("(%s)\n", debugstr_a(cmdline));
475 RtlCreateUnicodeStringFromAsciiz(&cmdlineW, cmdline);
477 cmdline_copy = wcsdup(cmdlineW.Buffer);
478 cmdline_ptr = cmdline_copy;
480 ocx_filename = get_parameter(&cmdline_ptr, ',', TRUE);
481 if (!ocx_filename || !*ocx_filename)
482 goto done;
484 str_flags = get_parameter(&cmdline_ptr, ',', TRUE);
485 param = get_parameter(&cmdline_ptr, ',', TRUE);
487 hm = LoadLibraryExW(ocx_filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
488 if (!hm)
489 goto done;
491 hr = do_ocx_reg(hm, TRUE, str_flags, param);
493 done:
494 FreeLibrary(hm);
495 free(cmdline_copy);
496 RtlFreeUnicodeString(&cmdlineW);
498 return hr;
501 /***********************************************************************
502 * SetPerUserSecValuesA (ADVPACK.@)
504 * See SetPerUserSecValuesW.
506 HRESULT WINAPI SetPerUserSecValuesA(PERUSERSECTIONA* pPerUser)
508 PERUSERSECTIONW perUserW;
510 TRACE("(%p)\n", pPerUser);
512 if (!pPerUser)
513 return E_INVALIDARG;
515 MultiByteToWideChar(CP_ACP, 0, pPerUser->szGUID, -1, perUserW.szGUID, ARRAY_SIZE(perUserW.szGUID));
516 MultiByteToWideChar(CP_ACP, 0, pPerUser->szDispName, -1, perUserW.szDispName, ARRAY_SIZE(perUserW.szDispName));
517 MultiByteToWideChar(CP_ACP, 0, pPerUser->szLocale, -1, perUserW.szLocale, ARRAY_SIZE(perUserW.szLocale));
518 MultiByteToWideChar(CP_ACP, 0, pPerUser->szStub, -1, perUserW.szStub, ARRAY_SIZE(perUserW.szStub));
519 MultiByteToWideChar(CP_ACP, 0, pPerUser->szVersion, -1, perUserW.szVersion, ARRAY_SIZE(perUserW.szVersion));
520 MultiByteToWideChar(CP_ACP, 0, pPerUser->szCompID, -1, perUserW.szCompID, ARRAY_SIZE(perUserW.szCompID));
521 perUserW.dwIsInstalled = pPerUser->dwIsInstalled;
522 perUserW.bRollback = pPerUser->bRollback;
524 return SetPerUserSecValuesW(&perUserW);
527 /***********************************************************************
528 * SetPerUserSecValuesW (ADVPACK.@)
530 * Prepares the per-user stub values under IsInstalled\{GUID} that
531 * control the per-user installation.
533 * PARAMS
534 * pPerUser [I] Per-user stub values.
536 * RETURNS
537 * Success: S_OK.
538 * Failure: E_FAIL.
540 HRESULT WINAPI SetPerUserSecValuesW(PERUSERSECTIONW* pPerUser)
542 HKEY setup, guid;
544 TRACE("(%p)\n", pPerUser);
546 if (!pPerUser || !*pPerUser->szGUID)
547 return S_OK;
549 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, setup_key, 0, NULL, 0, KEY_WRITE,
550 NULL, &setup, NULL))
552 return E_FAIL;
555 if (RegCreateKeyExW(setup, pPerUser->szGUID, 0, NULL, 0, KEY_ALL_ACCESS,
556 NULL, &guid, NULL))
558 RegCloseKey(setup);
559 return E_FAIL;
562 if (*pPerUser->szStub)
564 RegSetValueExW(guid, L"StubPath", 0, REG_SZ, (BYTE *)pPerUser->szStub,
565 (lstrlenW(pPerUser->szStub) + 1) * sizeof(WCHAR));
568 if (*pPerUser->szVersion)
570 RegSetValueExW(guid, L"Version", 0, REG_SZ, (BYTE *)pPerUser->szVersion,
571 (lstrlenW(pPerUser->szVersion) + 1) * sizeof(WCHAR));
574 if (*pPerUser->szLocale)
576 RegSetValueExW(guid, L"Locale", 0, REG_SZ, (BYTE *)pPerUser->szLocale,
577 (lstrlenW(pPerUser->szLocale) + 1) * sizeof(WCHAR));
580 if (*pPerUser->szCompID)
582 RegSetValueExW(guid, L"ComponentID", 0, REG_SZ, (BYTE *)pPerUser->szCompID,
583 (lstrlenW(pPerUser->szCompID) + 1) * sizeof(WCHAR));
586 if (*pPerUser->szDispName)
588 RegSetValueExW(guid, NULL, 0, REG_SZ, (LPBYTE)pPerUser->szDispName,
589 (lstrlenW(pPerUser->szDispName) + 1) * sizeof(WCHAR));
592 RegSetValueExW(guid, L"IsInstalled", 0, REG_DWORD,
593 (LPBYTE)&pPerUser->dwIsInstalled, sizeof(DWORD));
595 RegCloseKey(guid);
596 RegCloseKey(setup);
598 return S_OK;
601 /***********************************************************************
602 * TranslateInfStringA (ADVPACK.@)
604 * See TranslateInfStringW.
606 HRESULT WINAPI TranslateInfStringA(LPCSTR pszInfFilename, LPCSTR pszInstallSection,
607 LPCSTR pszTranslateSection, LPCSTR pszTranslateKey, LPSTR pszBuffer,
608 DWORD dwBufferSize, PDWORD pdwRequiredSize, PVOID pvReserved)
610 UNICODE_STRING filenameW, installW;
611 UNICODE_STRING translateW, keyW;
612 LPWSTR bufferW;
613 HRESULT res;
614 DWORD len = 0;
616 TRACE("(%s, %s, %s, %s, %p, %ld, %p, %p)\n",
617 debugstr_a(pszInfFilename), debugstr_a(pszInstallSection),
618 debugstr_a(pszTranslateSection), debugstr_a(pszTranslateKey),
619 pszBuffer, dwBufferSize,pdwRequiredSize, pvReserved);
621 if (!pszInfFilename || !pszTranslateSection ||
622 !pszTranslateKey || !pdwRequiredSize)
623 return E_INVALIDARG;
625 RtlCreateUnicodeStringFromAsciiz(&filenameW, pszInfFilename);
626 RtlCreateUnicodeStringFromAsciiz(&installW, pszInstallSection);
627 RtlCreateUnicodeStringFromAsciiz(&translateW, pszTranslateSection);
628 RtlCreateUnicodeStringFromAsciiz(&keyW, pszTranslateKey);
630 res = TranslateInfStringW(filenameW.Buffer, installW.Buffer,
631 translateW.Buffer, keyW.Buffer, NULL,
632 dwBufferSize, &len, NULL);
634 if (res == S_OK)
636 bufferW = malloc(len * sizeof(WCHAR));
638 res = TranslateInfStringW(filenameW.Buffer, installW.Buffer,
639 translateW.Buffer, keyW.Buffer, bufferW,
640 len, &len, NULL);
641 if (res == S_OK)
643 *pdwRequiredSize = WideCharToMultiByte(CP_ACP, 0, bufferW, -1,
644 NULL, 0, NULL, NULL);
646 if (dwBufferSize >= *pdwRequiredSize)
648 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, pszBuffer,
649 dwBufferSize, NULL, NULL);
651 else
652 res = E_NOT_SUFFICIENT_BUFFER;
655 free(bufferW);
658 RtlFreeUnicodeString(&filenameW);
659 RtlFreeUnicodeString(&installW);
660 RtlFreeUnicodeString(&translateW);
661 RtlFreeUnicodeString(&keyW);
663 return res;
666 /***********************************************************************
667 * TranslateInfStringW (ADVPACK.@)
669 * Translates the value of a specified key in an inf file into the
670 * current locale by expanding string macros.
672 * PARAMS
673 * pszInfFilename [I] Filename of the inf file.
674 * pszInstallSection [I]
675 * pszTranslateSection [I] Inf section where the key exists.
676 * pszTranslateKey [I] Key to translate.
677 * pszBuffer [O] Contains the translated string on exit.
678 * dwBufferSize [I] Size on input of pszBuffer.
679 * pdwRequiredSize [O] Length of the translated key.
680 * pvReserved [I] Reserved, must be NULL.
682 * RETURNS
683 * Success: S_OK.
684 * Failure: An hresult error code.
686 HRESULT WINAPI TranslateInfStringW(LPCWSTR pszInfFilename, LPCWSTR pszInstallSection,
687 LPCWSTR pszTranslateSection, LPCWSTR pszTranslateKey, LPWSTR pszBuffer,
688 DWORD dwBufferSize, PDWORD pdwRequiredSize, PVOID pvReserved)
690 HINF hInf;
691 HRESULT hret = S_OK;
693 TRACE("(%s, %s, %s, %s, %p, %ld, %p, %p)\n",
694 debugstr_w(pszInfFilename), debugstr_w(pszInstallSection),
695 debugstr_w(pszTranslateSection), debugstr_w(pszTranslateKey),
696 pszBuffer, dwBufferSize,pdwRequiredSize, pvReserved);
698 if (!pszInfFilename || !pszTranslateSection ||
699 !pszTranslateKey || !pdwRequiredSize)
700 return E_INVALIDARG;
702 hInf = SetupOpenInfFileW(pszInfFilename, NULL, INF_STYLE_WIN4, NULL);
703 if (hInf == INVALID_HANDLE_VALUE)
704 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
706 set_ldids(hInf, pszInstallSection, NULL);
708 if (!SetupGetLineTextW(NULL, hInf, pszTranslateSection, pszTranslateKey,
709 pszBuffer, dwBufferSize, pdwRequiredSize))
711 if (dwBufferSize < *pdwRequiredSize)
712 hret = E_NOT_SUFFICIENT_BUFFER;
713 else
714 hret = SPAPI_E_LINE_NOT_FOUND;
717 SetupCloseInfFile(hInf);
718 return hret;
721 /***********************************************************************
722 * TranslateInfStringExA (ADVPACK.@)
724 * See TranslateInfStringExW.
726 HRESULT WINAPI TranslateInfStringExA(HINF hInf, LPCSTR pszInfFilename,
727 LPCSTR pszTranslateSection, LPCSTR pszTranslateKey,
728 LPSTR pszBuffer, DWORD dwBufferSize,
729 PDWORD pdwRequiredSize, PVOID pvReserved)
731 UNICODE_STRING filenameW, sectionW, keyW;
732 LPWSTR bufferW;
733 HRESULT res;
734 DWORD len = 0;
736 TRACE("(%p, %s, %s, %s, %p, %ld, %p, %p)\n", hInf, debugstr_a(pszInfFilename),
737 debugstr_a(pszTranslateSection), debugstr_a(pszTranslateKey),
738 pszBuffer, dwBufferSize, pdwRequiredSize, pvReserved);
740 if (!pszInfFilename || !pszTranslateSection ||
741 !pszTranslateKey || !pdwRequiredSize)
742 return E_INVALIDARG;
744 RtlCreateUnicodeStringFromAsciiz(&filenameW, pszInfFilename);
745 RtlCreateUnicodeStringFromAsciiz(&sectionW, pszTranslateSection);
746 RtlCreateUnicodeStringFromAsciiz(&keyW, pszTranslateKey);
748 res = TranslateInfStringExW(hInf, filenameW.Buffer, sectionW.Buffer,
749 keyW.Buffer, NULL, 0, &len, NULL);
751 if (res == S_OK)
753 bufferW = malloc(len * sizeof(WCHAR));
755 res = TranslateInfStringExW(hInf, filenameW.Buffer, sectionW.Buffer,
756 keyW.Buffer, bufferW, len, &len, NULL);
758 if (res == S_OK)
760 *pdwRequiredSize = WideCharToMultiByte(CP_ACP, 0, bufferW, -1,
761 NULL, 0, NULL, NULL);
763 if (dwBufferSize >= *pdwRequiredSize)
765 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, pszBuffer,
766 dwBufferSize, NULL, NULL);
768 else
769 res = E_NOT_SUFFICIENT_BUFFER;
772 free(bufferW);
775 RtlFreeUnicodeString(&filenameW);
776 RtlFreeUnicodeString(&sectionW);
777 RtlFreeUnicodeString(&keyW);
779 return res;
782 /***********************************************************************
783 * TranslateInfStringExW (ADVPACK.@)
785 * Using a handle to an INF file opened with OpenINFEngine, translates
786 * the value of a specified key in an inf file into the current locale
787 * by expanding string macros.
789 * PARAMS
790 * hInf [I] Handle to the INF file.
791 * pszInfFilename [I] Filename of the INF file.
792 * pszTranslateSection [I] Inf section where the key exists.
793 * pszTranslateKey [I] Key to translate.
794 * pszBuffer [O] Contains the translated string on exit.
795 * dwBufferSize [I] Size on input of pszBuffer.
796 * pdwRequiredSize [O] Length of the translated key.
797 * pvReserved [I] Reserved. Must be NULL.
799 * RETURNS
800 * Success: S_OK.
801 * Failure: E_FAIL.
803 * NOTES
804 * To use TranslateInfStringEx to translate an INF file continuously,
805 * open the INF file with OpenINFEngine, call TranslateInfStringEx as
806 * many times as needed, then release the handle with CloseINFEngine.
807 * When translating more than one keys, this method is more efficient
808 * than calling TranslateInfString, because the INF file is only
809 * opened once.
811 HRESULT WINAPI TranslateInfStringExW(HINF hInf, LPCWSTR pszInfFilename,
812 LPCWSTR pszTranslateSection, LPCWSTR pszTranslateKey,
813 LPWSTR pszBuffer, DWORD dwBufferSize,
814 PDWORD pdwRequiredSize, PVOID pvReserved)
816 TRACE("(%p, %s, %s, %s, %p, %ld, %p, %p)\n", hInf, debugstr_w(pszInfFilename),
817 debugstr_w(pszTranslateSection), debugstr_w(pszTranslateKey),
818 pszBuffer, dwBufferSize, pdwRequiredSize, pvReserved);
820 if (!hInf || !pszInfFilename || !pszTranslateSection || !pszTranslateKey)
821 return E_INVALIDARG;
823 if (!SetupGetLineTextW(NULL, hInf, pszTranslateSection, pszTranslateKey,
824 pszBuffer, dwBufferSize, pdwRequiredSize))
826 if (dwBufferSize < *pdwRequiredSize)
827 return E_NOT_SUFFICIENT_BUFFER;
829 return SPAPI_E_LINE_NOT_FOUND;
832 return S_OK;
835 /***********************************************************************
836 * UserInstStubWrapperA (ADVPACK.@)
838 * See UserInstStubWrapperW.
840 HRESULT WINAPI UserInstStubWrapperA(HWND hWnd, HINSTANCE hInstance,
841 LPSTR pszParms, INT nShow)
843 UNICODE_STRING parmsW;
844 HRESULT res;
846 TRACE("(%p, %p, %s, %i)\n", hWnd, hInstance, debugstr_a(pszParms), nShow);
848 if (!pszParms)
849 return E_INVALIDARG;
851 RtlCreateUnicodeStringFromAsciiz(&parmsW, pszParms);
853 res = UserInstStubWrapperW(hWnd, hInstance, parmsW.Buffer, nShow);
855 RtlFreeUnicodeString(&parmsW);
857 return res;
860 /***********************************************************************
861 * UserInstStubWrapperW (ADVPACK.@)
863 * Launches the user stub wrapper specified by the RealStubPath
864 * registry value under Installed Components\szParms.
866 * PARAMS
867 * hWnd [I] Handle to the window used for the display.
868 * hInstance [I] Instance of the process.
869 * szParms [I] The GUID of the installation.
870 * show [I] How the window should be shown.
872 * RETURNS
873 * Success: S_OK.
874 * Failure: E_FAIL.
876 * TODO
877 * If the type of the StubRealPath value is REG_EXPAND_SZ, then
878 * we should call ExpandEnvironmentStrings on the value and
879 * launch the result.
881 HRESULT WINAPI UserInstStubWrapperW(HWND hWnd, HINSTANCE hInstance,
882 LPWSTR pszParms, INT nShow)
884 HKEY setup, guid;
885 WCHAR stub[MAX_PATH];
886 DWORD size = sizeof(stub);
887 HRESULT hr = S_OK;
888 BOOL res;
890 TRACE("(%p, %p, %s, %i)\n", hWnd, hInstance, debugstr_w(pszParms), nShow);
892 if (!pszParms || !*pszParms)
893 return E_INVALIDARG;
895 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, setup_key, 0, KEY_READ, &setup))
897 return E_FAIL;
900 if (RegOpenKeyExW(setup, pszParms, 0, KEY_READ, &guid))
902 RegCloseKey(setup);
903 return E_FAIL;
906 res = RegQueryValueExW(guid, L"RealStubPath", NULL, NULL, (BYTE *)stub, &size);
907 if (res || !*stub)
908 goto done;
910 /* launch the user stub wrapper */
911 hr = launch_exe(stub, NULL, NULL);
913 done:
914 RegCloseKey(setup);
915 RegCloseKey(guid);
917 return hr;
920 /***********************************************************************
921 * UserUnInstStubWrapperA (ADVPACK.@)
923 * See UserUnInstStubWrapperW.
925 HRESULT WINAPI UserUnInstStubWrapperA(HWND hWnd, HINSTANCE hInstance,
926 LPSTR pszParms, INT nShow)
928 UNICODE_STRING parmsW;
929 HRESULT res;
931 TRACE("(%p, %p, %s, %i)\n", hWnd, hInstance, debugstr_a(pszParms), nShow);
933 if (!pszParms)
934 return E_INVALIDARG;
936 RtlCreateUnicodeStringFromAsciiz(&parmsW, pszParms);
938 res = UserUnInstStubWrapperW(hWnd, hInstance, parmsW.Buffer, nShow);
940 RtlFreeUnicodeString(&parmsW);
942 return res;
945 /***********************************************************************
946 * UserUnInstStubWrapperW (ADVPACK.@)
948 HRESULT WINAPI UserUnInstStubWrapperW(HWND hWnd, HINSTANCE hInstance,
949 LPWSTR pszParms, INT nShow)
951 FIXME("(%p, %p, %s, %i): stub\n", hWnd, hInstance, debugstr_w(pszParms), nShow);
953 return E_FAIL;