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 * Checks if a reboot is required for an installed INF section.
330 * hWnd [I] Handle to the window used for messages.
331 * pszINF [I] Filename of the INF file.
332 * pszSec [I] INF section to check.
333 * dwReserved [I] Reserved. Must be 0.
336 * Success: S_OK - Reboot is needed if the INF section is installed.
337 * S_FALSE - Reboot is not needed.
338 * Failure: HRESULT of GetLastError().
341 * if pszSec is NULL, RebootCheckOnInstall checks the DefaultInstall
342 * or DefaultInstall.NT section.
347 HRESULT WINAPI RebootCheckOnInstallA(HWND hWnd, LPCSTR pszINF,
348 LPSTR pszSec, DWORD dwReserved)
350 FIXME("(%p, %p, %p, %ld) stub\n", hWnd, pszINF, pszSec, dwReserved);
355 /***********************************************************************
356 * RegisterOCX (ADVPACK.@)
358 void WINAPI RegisterOCX( HWND hWnd, HINSTANCE hInst, LPCSTR cmdline, INT show )
360 WCHAR wszBuff[MAX_PATH];
363 DLLREGISTER pfnRegister;
366 TRACE("(%s)\n", cmdline);
368 MultiByteToWideChar(CP_ACP, 0, cmdline, strlen(cmdline), wszBuff, MAX_PATH);
369 if ((pwcComma = strchrW( wszBuff, ',' ))) *pwcComma = 0;
371 TRACE("Parsed DLL name (%s)\n", debugstr_w(wszBuff));
373 hm = LoadLibraryExW(wszBuff, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
376 ERR("Couldn't load DLL: %s\n", debugstr_w(wszBuff));
380 pfnRegister = (DLLREGISTER)GetProcAddress(hm, "DllRegisterServer");
381 if (pfnRegister == NULL)
383 ERR("DllRegisterServer entry point not found\n");
390 ERR("DllRegisterServer entry point returned %08lx\n", hr);
394 TRACE("Successfully registered OCX\n");
399 /***********************************************************************
400 * SetPerUserSecValuesA (ADVPACK.@)
402 * Prepares the per-user stub values under IsInstalled\{GUID} that
403 * control the per-user installation.
406 * pPerUser [I] Per-user stub values.
415 HRESULT WINAPI SetPerUserSecValuesA(PERUSERSECTIONA* pPerUser)
417 FIXME("(%p) stub\n", pPerUser);
422 /***********************************************************************
423 * TranslateInfStringA (ADVPACK.@)
425 * See TranslateInfStringW.
427 HRESULT WINAPI TranslateInfStringA(LPCSTR pszInfFilename, LPCSTR pszInstallSection,
428 LPCSTR pszTranslateSection, LPCSTR pszTranslateKey, LPSTR pszBuffer,
429 DWORD dwBufferSize, PDWORD pdwRequiredSize, PVOID pvReserved)
431 UNICODE_STRING filenameW, installW;
432 UNICODE_STRING translateW, keyW;
437 TRACE("(%s %s %s %s %p %ld %p %p)\n",
438 debugstr_a(pszInfFilename), debugstr_a(pszInstallSection),
439 debugstr_a(pszTranslateSection), debugstr_a(pszTranslateKey),
440 pszBuffer, dwBufferSize,pdwRequiredSize, pvReserved);
442 if (!pszInfFilename || !pszTranslateSection ||
443 !pszTranslateKey || !pdwRequiredSize)
446 RtlCreateUnicodeStringFromAsciiz(&filenameW, pszInfFilename);
447 RtlCreateUnicodeStringFromAsciiz(&installW, pszInstallSection);
448 RtlCreateUnicodeStringFromAsciiz(&translateW, pszTranslateSection);
449 RtlCreateUnicodeStringFromAsciiz(&keyW, pszTranslateKey);
451 res = TranslateInfStringW(filenameW.Buffer, installW.Buffer,
452 translateW.Buffer, keyW.Buffer, NULL,
453 dwBufferSize, &len, NULL);
457 bufferW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
459 res = TranslateInfStringW(filenameW.Buffer, installW.Buffer,
460 translateW.Buffer, keyW.Buffer, bufferW,
464 *pdwRequiredSize = WideCharToMultiByte(CP_ACP, 0, bufferW, -1,
465 NULL, 0, NULL, NULL);
467 if (dwBufferSize >= *pdwRequiredSize)
469 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, pszBuffer,
470 dwBufferSize, NULL, NULL);
473 res = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
476 HeapFree(GetProcessHeap(), 0, bufferW);
479 RtlFreeUnicodeString(&filenameW);
480 RtlFreeUnicodeString(&installW);
481 RtlFreeUnicodeString(&translateW);
482 RtlFreeUnicodeString(&keyW);
487 /***********************************************************************
488 * TranslateInfStringW (ADVPACK.@)
490 * Translates the value of a specified key in an inf file into the
491 * current locale by expanding string macros.
494 * pszInfFilename [I] Filename of the inf file.
495 * pszInstallSection [I]
496 * pszTranslateSection [I] Inf section where the key exists.
497 * pszTranslateKey [I] Key to translate.
498 * pszBuffer [O] Contains the translated string on exit.
499 * dwBufferSize [I] Size on input of pszBuffer.
500 * pdwRequiredSize [O] Length of the translated key.
501 * pvReserved [I] Reserved, must be NULL.
505 * Failure: An hresult error code.
507 HRESULT WINAPI TranslateInfStringW(LPCWSTR pszInfFilename, LPCWSTR pszInstallSection,
508 LPCWSTR pszTranslateSection, LPCWSTR pszTranslateKey, LPWSTR pszBuffer,
509 DWORD dwBufferSize, PDWORD pdwRequiredSize, PVOID pvReserved)
513 TRACE("(%s %s %s %s %p %ld %p %p)\n",
514 debugstr_w(pszInfFilename), debugstr_w(pszInstallSection),
515 debugstr_w(pszTranslateSection), debugstr_w(pszTranslateKey),
516 pszBuffer, dwBufferSize,pdwRequiredSize, pvReserved);
518 if (!pszInfFilename || !pszTranslateSection ||
519 !pszTranslateKey || !pdwRequiredSize)
522 hInf = SetupOpenInfFileW(pszInfFilename, NULL, INF_STYLE_WIN4, NULL);
523 if (hInf == INVALID_HANDLE_VALUE)
524 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
526 set_ldids(hInf, pszInstallSection);
528 if (!SetupGetLineTextW(NULL, hInf, pszTranslateSection, pszTranslateKey,
529 pszBuffer, dwBufferSize, pdwRequiredSize))
531 if (dwBufferSize < *pdwRequiredSize)
532 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
534 return SPAPI_E_LINE_NOT_FOUND;
537 SetupCloseInfFile(hInf);
541 /***********************************************************************
542 * TranslateInfStringExA (ADVPACK.@)
544 * Using a handle to an INF file opened with OpenINFEngine, translates
545 * the value of a specified key in an inf file into the current locale
546 * by expanding string macros.
549 * hInf [I] Handle to the INF file.
550 * pszInfFilename [I] Filename of the INF file.
551 * pszTranslateSection [I] Inf section where the key exists.
552 * pszTranslateKey [I] Key to translate.
553 * pszBuffer [O] Contains the translated string on exit.
554 * dwBufferSize [I] Size on input of pszBuffer.
555 * pdwRequiredSize [O] Length of the translated key.
556 * pvReserved [I] Reserved. Must be NULL.
563 * To use TranslateInfStringEx to translate an INF file continuously,
564 * open the INF file with OpenINFEngine, call TranslateInfStringEx as
565 * many times as needed, then release the handle with CloseINFEngine.
566 * When translating more than one keys, this method is more efficient
567 * than calling TranslateInfString, because the INF file is only
570 HRESULT WINAPI TranslateInfStringExA(HINF hInf, LPCSTR pszInfFilename,
571 LPCSTR pszTranslateSection, LPCSTR pszTranslateKey,
572 LPSTR pszBuffer, DWORD dwBufferSize,
573 PDWORD pdwRequiredSize, PVOID pvReserved)
575 TRACE("(%p, %p, %p, %p, %p, %ld, %p, %p)\n", hInf, pszInfFilename,
576 pszTranslateSection, pszTranslateKey, pszBuffer, dwBufferSize,
577 pdwRequiredSize, pvReserved);
579 if (!hInf || !pszInfFilename || !pszTranslateSection || !pszTranslateKey)
582 if (!SetupGetLineTextA(NULL, hInf, pszTranslateSection, pszTranslateKey,
583 pszBuffer, dwBufferSize, pdwRequiredSize))
585 if (dwBufferSize < *pdwRequiredSize)
586 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
588 return SPAPI_E_LINE_NOT_FOUND;
594 /***********************************************************************
595 * UserInstStubWrapperA (ADVPACK.@)
597 HRESULT WINAPI UserInstStubWrapperA(HWND hWnd, HINSTANCE hInstance,
598 LPSTR pszParms, INT nShow)
600 FIXME("(%p, %p, %p, %i) stub\n", hWnd, hInstance, pszParms, nShow);
605 /***********************************************************************
606 * UserUnInstStubWrapperA (ADVPACK.@)
608 HRESULT WINAPI UserUnInstStubWrapperA(HWND hWnd, HINSTANCE hInstance,
609 LPSTR pszParms, INT nShow)
611 FIXME("(%p, %p, %p, %i) stub\n", hWnd, hInstance, pszParms, nShow);