4 * Copyright 2004 Huw D M Davies
5 * Copyright 2005 Sami Aario
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 #include "wine/unicode.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(advpack);
38 typedef HRESULT (WINAPI *DLLREGISTER) (void);
40 #define MAX_FIELD_LENGTH 512
43 /* parses the destination directory parameters from pszSection
44 * the parameters are of the form: root,key,value,unknown,fallback
45 * we first read the reg value root\\key\\value and if that fails,
46 * use fallback as the destination directory
48 static void get_dest_dir(HINF hInf, PCWSTR pszSection, PWSTR pszBuffer, DWORD dwSize)
51 WCHAR key[MAX_PATH], value[MAX_PATH];
52 WCHAR prefix[PREFIX_LEN];
56 static const WCHAR hklm[] = {'H','K','L','M',0};
57 static const WCHAR hkcu[] = {'H','K','C','U',0};
59 /* load the destination parameters */
60 SetupFindFirstLineW(hInf, pszSection, NULL, &context);
61 SetupGetStringFieldW(&context, 1, prefix, PREFIX_LEN, &size);
62 SetupGetStringFieldW(&context, 2, key, MAX_PATH, &size);
63 SetupGetStringFieldW(&context, 3, value, MAX_PATH, &size);
65 if (!lstrcmpW(prefix, hklm))
66 root = HKEY_LOCAL_MACHINE;
67 else if (!lstrcmpW(prefix, hkcu))
68 root = HKEY_CURRENT_USER;
72 size = dwSize * sizeof(WCHAR);
74 /* fallback to the default destination dir if reg fails */
75 if (RegOpenKeyW(root, key, &subkey) ||
76 RegQueryValueExW(subkey, value, NULL, NULL, (LPBYTE)pszBuffer, &size))
78 SetupGetStringFieldW(&context, 6, pszBuffer, dwSize, NULL);
84 /* loads the LDIDs specified in the install section of an INF */
85 static void set_ldids(HINF hInf, LPCWSTR pszInstallSection)
87 WCHAR field[MAX_FIELD_LENGTH];
88 WCHAR key[MAX_FIELD_LENGTH];
94 static const WCHAR custDestW[] = {
95 'C','u','s','t','o','m','D','e','s','t','i','n','a','t','i','o','n',0
98 if (!SetupGetLineTextW(NULL, hInf, pszInstallSection, custDestW,
99 field, MAX_FIELD_LENGTH, &size))
102 if (!SetupFindFirstLineW(hInf, field, NULL, &context))
107 SetupGetIntField(&context, 0, &ldid);
108 SetupGetLineTextW(&context, NULL, NULL, NULL,
109 key, MAX_FIELD_LENGTH, &size);
111 get_dest_dir(hInf, key, dest, MAX_PATH);
113 SetupSetDirectoryIdW(hInf, ldid, dest);
114 } while (SetupFindNextLine(&context, &context));
117 /***********************************************************************
118 * CloseINFEngine (ADVPACK.@)
120 * Closes a handle to an INF file opened with OpenINFEngine.
123 * hInf [I] Handle to the INF file to close.
129 HRESULT WINAPI CloseINFEngine(HINF hInf)
131 TRACE("(%p)\n", hInf);
136 SetupCloseInfFile(hInf);
140 /***********************************************************************
141 * DllMain (ADVPACK.@)
143 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
145 TRACE("(%p, %ld, %p)\n",hinstDLL, fdwReason, lpvReserved);
147 if (fdwReason == DLL_PROCESS_ATTACH)
148 DisableThreadLibraryCalls(hinstDLL);
153 /***********************************************************************
154 * IsNTAdmin (ADVPACK.@)
156 * Checks if the user has admin privileges.
159 * reserved [I] Reserved. Must be 0.
160 * pReserved [I] Reserved. Must be NULL.
163 * TRUE if user has admin rights, FALSE otherwise.
165 BOOL WINAPI IsNTAdmin( DWORD reserved, LPDWORD pReserved )
167 SID_IDENTIFIER_AUTHORITY SidAuthority = {SECURITY_NT_AUTHORITY};
168 PTOKEN_GROUPS pTokenGroups;
169 BOOL bSidFound = FALSE;
174 TRACE("(0x%08lx, %p)\n", reserved, pReserved);
176 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
179 if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwSize))
181 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
188 pTokenGroups = HeapAlloc(GetProcessHeap(), 0, dwSize);
195 if (!GetTokenInformation(hToken, TokenGroups, pTokenGroups, dwSize, &dwSize))
197 HeapFree(GetProcessHeap(), 0, pTokenGroups);
204 if (!AllocateAndInitializeSid(&SidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
205 DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pSid))
207 HeapFree(GetProcessHeap(), 0, pTokenGroups);
211 for (i = 0; i < pTokenGroups->GroupCount; i++)
213 if (EqualSid(pSid, pTokenGroups->Groups[i].Sid))
220 HeapFree(GetProcessHeap(), 0, pTokenGroups);
226 /***********************************************************************
227 * NeedRebootInit (ADVPACK.@)
229 * Sets up conditions for reboot checking.
232 * Value required by NeedReboot.
234 DWORD WINAPI NeedRebootInit(VOID)
240 /***********************************************************************
241 * NeedReboot (ADVPACK.@)
243 * Determines whether a reboot is required.
246 * dwRebootCheck [I] Value from NeedRebootInit.
249 * TRUE if a reboot is needed, FALSE otherwise.
254 BOOL WINAPI NeedReboot(DWORD dwRebootCheck)
256 FIXME("(0x%08lx): stub\n", dwRebootCheck);
260 /***********************************************************************
261 * OpenINFEngineA (ADVPACK.@)
263 * See OpenINFEngineW.
265 HRESULT WINAPI OpenINFEngineA(LPCSTR pszInfFilename, LPCSTR pszInstallSection,
266 DWORD dwFlags, HINF *phInf, PVOID pvReserved)
268 UNICODE_STRING filenameW, installW;
271 TRACE("(%p, %p, %ld, %p, %p)\n", pszInfFilename, pszInstallSection,
272 dwFlags, phInf, pvReserved);
274 if (!pszInfFilename || !phInf)
277 RtlCreateUnicodeStringFromAsciiz(&filenameW, pszInfFilename);
278 RtlCreateUnicodeStringFromAsciiz(&installW, pszInstallSection);
280 res = OpenINFEngineW(filenameW.Buffer, installW.Buffer,
281 dwFlags, phInf, pvReserved);
283 RtlFreeUnicodeString(&filenameW);
284 RtlFreeUnicodeString(&installW);
289 /***********************************************************************
290 * OpenINFEngineW (ADVPACK.@)
292 * Opens and returns a handle to an INF file to be used by
293 * TranslateInfStringEx to continuously translate the INF file.
296 * pszInfFilename [I] Filename of the INF to open.
297 * pszInstallSection [I] Name of the Install section in the INF.
298 * dwFlags [I] See advpub.h.
299 * phInf [O] Handle to the loaded INF file.
300 * pvReserved [I] Reserved. Must be NULL.
306 HRESULT WINAPI OpenINFEngineW(LPCWSTR pszInfFilename, LPCWSTR pszInstallSection,
307 DWORD dwFlags, HINF *phInf, PVOID pvReserved)
309 TRACE("(%p, %p, %ld, %p, %p)\n", debugstr_w(pszInfFilename),
310 debugstr_w(pszInstallSection), dwFlags, phInf, pvReserved);
312 if (!pszInfFilename || !phInf)
315 *phInf = SetupOpenInfFileW(pszInfFilename, NULL, INF_STYLE_WIN4, NULL);
316 if (*phInf == INVALID_HANDLE_VALUE)
317 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
319 set_ldids(*phInf, pszInstallSection);
324 /***********************************************************************
325 * RebootCheckOnInstallA (ADVPACK.@)
327 * See RebootCheckOnInstallW.
329 HRESULT WINAPI RebootCheckOnInstallA(HWND hWnd, LPCSTR pszINF,
330 LPSTR pszSec, DWORD dwReserved)
332 UNICODE_STRING infW, secW;
335 TRACE("(%p, %s, %s, %ld)\n", hWnd, debugstr_a(pszINF),
336 debugstr_a(pszSec), dwReserved);
338 if (!pszINF || !pszSec)
341 RtlCreateUnicodeStringFromAsciiz(&infW, pszINF);
342 RtlCreateUnicodeStringFromAsciiz(&secW, pszSec);
344 res = RebootCheckOnInstallW(hWnd, infW.Buffer, secW.Buffer, dwReserved);
346 RtlFreeUnicodeString(&infW);
347 RtlFreeUnicodeString(&secW);
352 /***********************************************************************
353 * RebootCheckOnInstallW (ADVPACK.@)
355 * Checks if a reboot is required for an installed INF section.
358 * hWnd [I] Handle to the window used for messages.
359 * pszINF [I] Filename of the INF file.
360 * pszSec [I] INF section to check.
361 * dwReserved [I] Reserved. Must be 0.
364 * Success: S_OK - Reboot is needed if the INF section is installed.
365 * S_FALSE - Reboot is not needed.
366 * Failure: HRESULT of GetLastError().
369 * if pszSec is NULL, RebootCheckOnInstall checks the DefaultInstall
370 * or DefaultInstall.NT section.
375 HRESULT WINAPI RebootCheckOnInstallW(HWND hWnd, LPCWSTR pszINF,
376 LPWSTR pszSec, DWORD dwReserved)
378 FIXME("(%p, %s, %s, %ld) stub\n", hWnd, debugstr_w(pszINF),
379 debugstr_w(pszSec), dwReserved);
384 /***********************************************************************
385 * RegisterOCX (ADVPACK.@)
387 void WINAPI RegisterOCX( HWND hWnd, HINSTANCE hInst, LPCSTR cmdline, INT show )
389 WCHAR wszBuff[MAX_PATH];
392 DLLREGISTER pfnRegister;
395 TRACE("(%s)\n", cmdline);
397 MultiByteToWideChar(CP_ACP, 0, cmdline, strlen(cmdline), wszBuff, MAX_PATH);
398 if ((pwcComma = strchrW( wszBuff, ',' ))) *pwcComma = 0;
400 TRACE("Parsed DLL name (%s)\n", debugstr_w(wszBuff));
402 hm = LoadLibraryExW(wszBuff, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
405 ERR("Couldn't load DLL: %s\n", debugstr_w(wszBuff));
409 pfnRegister = (DLLREGISTER)GetProcAddress(hm, "DllRegisterServer");
410 if (pfnRegister == NULL)
412 ERR("DllRegisterServer entry point not found\n");
419 ERR("DllRegisterServer entry point returned %08lx\n", hr);
423 TRACE("Successfully registered OCX\n");
428 /***********************************************************************
429 * SetPerUserSecValuesA (ADVPACK.@)
431 * Prepares the per-user stub values under IsInstalled\{GUID} that
432 * control the per-user installation.
435 * pPerUser [I] Per-user stub values.
444 HRESULT WINAPI SetPerUserSecValuesA(PERUSERSECTIONA* pPerUser)
446 FIXME("(%p) stub\n", pPerUser);
451 /***********************************************************************
452 * TranslateInfStringA (ADVPACK.@)
454 * See TranslateInfStringW.
456 HRESULT WINAPI TranslateInfStringA(LPCSTR pszInfFilename, LPCSTR pszInstallSection,
457 LPCSTR pszTranslateSection, LPCSTR pszTranslateKey, LPSTR pszBuffer,
458 DWORD dwBufferSize, PDWORD pdwRequiredSize, PVOID pvReserved)
460 UNICODE_STRING filenameW, installW;
461 UNICODE_STRING translateW, keyW;
466 TRACE("(%s %s %s %s %p %ld %p %p)\n",
467 debugstr_a(pszInfFilename), debugstr_a(pszInstallSection),
468 debugstr_a(pszTranslateSection), debugstr_a(pszTranslateKey),
469 pszBuffer, dwBufferSize,pdwRequiredSize, pvReserved);
471 if (!pszInfFilename || !pszTranslateSection ||
472 !pszTranslateKey || !pdwRequiredSize)
475 RtlCreateUnicodeStringFromAsciiz(&filenameW, pszInfFilename);
476 RtlCreateUnicodeStringFromAsciiz(&installW, pszInstallSection);
477 RtlCreateUnicodeStringFromAsciiz(&translateW, pszTranslateSection);
478 RtlCreateUnicodeStringFromAsciiz(&keyW, pszTranslateKey);
480 res = TranslateInfStringW(filenameW.Buffer, installW.Buffer,
481 translateW.Buffer, keyW.Buffer, NULL,
482 dwBufferSize, &len, NULL);
486 bufferW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
488 res = TranslateInfStringW(filenameW.Buffer, installW.Buffer,
489 translateW.Buffer, keyW.Buffer, bufferW,
493 *pdwRequiredSize = WideCharToMultiByte(CP_ACP, 0, bufferW, -1,
494 NULL, 0, NULL, NULL);
496 if (dwBufferSize >= *pdwRequiredSize)
498 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, pszBuffer,
499 dwBufferSize, NULL, NULL);
502 res = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
505 HeapFree(GetProcessHeap(), 0, bufferW);
508 RtlFreeUnicodeString(&filenameW);
509 RtlFreeUnicodeString(&installW);
510 RtlFreeUnicodeString(&translateW);
511 RtlFreeUnicodeString(&keyW);
516 /***********************************************************************
517 * TranslateInfStringW (ADVPACK.@)
519 * Translates the value of a specified key in an inf file into the
520 * current locale by expanding string macros.
523 * pszInfFilename [I] Filename of the inf file.
524 * pszInstallSection [I]
525 * pszTranslateSection [I] Inf section where the key exists.
526 * pszTranslateKey [I] Key to translate.
527 * pszBuffer [O] Contains the translated string on exit.
528 * dwBufferSize [I] Size on input of pszBuffer.
529 * pdwRequiredSize [O] Length of the translated key.
530 * pvReserved [I] Reserved, must be NULL.
534 * Failure: An hresult error code.
536 HRESULT WINAPI TranslateInfStringW(LPCWSTR pszInfFilename, LPCWSTR pszInstallSection,
537 LPCWSTR pszTranslateSection, LPCWSTR pszTranslateKey, LPWSTR pszBuffer,
538 DWORD dwBufferSize, PDWORD pdwRequiredSize, PVOID pvReserved)
542 TRACE("(%s %s %s %s %p %ld %p %p)\n",
543 debugstr_w(pszInfFilename), debugstr_w(pszInstallSection),
544 debugstr_w(pszTranslateSection), debugstr_w(pszTranslateKey),
545 pszBuffer, dwBufferSize,pdwRequiredSize, pvReserved);
547 if (!pszInfFilename || !pszTranslateSection ||
548 !pszTranslateKey || !pdwRequiredSize)
551 hInf = SetupOpenInfFileW(pszInfFilename, NULL, INF_STYLE_WIN4, NULL);
552 if (hInf == INVALID_HANDLE_VALUE)
553 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
555 set_ldids(hInf, pszInstallSection);
557 if (!SetupGetLineTextW(NULL, hInf, pszTranslateSection, pszTranslateKey,
558 pszBuffer, dwBufferSize, pdwRequiredSize))
560 if (dwBufferSize < *pdwRequiredSize)
561 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
563 return SPAPI_E_LINE_NOT_FOUND;
566 SetupCloseInfFile(hInf);
570 /***********************************************************************
571 * TranslateInfStringExA (ADVPACK.@)
573 * See TranslateInfStringExW.
575 HRESULT WINAPI TranslateInfStringExA(HINF hInf, LPCSTR pszInfFilename,
576 LPCSTR pszTranslateSection, LPCSTR pszTranslateKey,
577 LPSTR pszBuffer, DWORD dwBufferSize,
578 PDWORD pdwRequiredSize, PVOID pvReserved)
580 UNICODE_STRING filenameW, sectionW, keyW;
585 TRACE("(%p, %p, %p, %p, %p, %ld, %p, %p)\n", hInf, debugstr_a(pszInfFilename),
586 debugstr_a(pszTranslateSection), debugstr_a(pszTranslateKey),
587 debugstr_a(pszBuffer), dwBufferSize, pdwRequiredSize, pvReserved);
589 if (!pszInfFilename || !pszTranslateSection ||
590 !pszTranslateKey || !pdwRequiredSize)
593 RtlCreateUnicodeStringFromAsciiz(&filenameW, pszInfFilename);
594 RtlCreateUnicodeStringFromAsciiz(§ionW, pszTranslateSection);
595 RtlCreateUnicodeStringFromAsciiz(&keyW, pszTranslateKey);
597 res = TranslateInfStringExW(hInf, filenameW.Buffer, sectionW.Buffer,
598 keyW.Buffer, NULL, 0, &len, NULL);
602 bufferW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
604 res = TranslateInfStringExW(hInf, filenameW.Buffer, sectionW.Buffer,
605 keyW.Buffer, bufferW, len, &len, NULL);
609 *pdwRequiredSize = WideCharToMultiByte(CP_ACP, 0, bufferW, -1,
610 NULL, 0, NULL, NULL);
612 if (dwBufferSize >= *pdwRequiredSize)
614 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, pszBuffer,
615 dwBufferSize, NULL, NULL);
618 res = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
621 HeapFree(GetProcessHeap(), 0, bufferW);
624 RtlFreeUnicodeString(&filenameW);
625 RtlFreeUnicodeString(§ionW);
626 RtlFreeUnicodeString(&keyW);
631 /***********************************************************************
632 * TranslateInfStringExW (ADVPACK.@)
634 * Using a handle to an INF file opened with OpenINFEngine, translates
635 * the value of a specified key in an inf file into the current locale
636 * by expanding string macros.
639 * hInf [I] Handle to the INF file.
640 * pszInfFilename [I] Filename of the INF file.
641 * pszTranslateSection [I] Inf section where the key exists.
642 * pszTranslateKey [I] Key to translate.
643 * pszBuffer [O] Contains the translated string on exit.
644 * dwBufferSize [I] Size on input of pszBuffer.
645 * pdwRequiredSize [O] Length of the translated key.
646 * pvReserved [I] Reserved. Must be NULL.
653 * To use TranslateInfStringEx to translate an INF file continuously,
654 * open the INF file with OpenINFEngine, call TranslateInfStringEx as
655 * many times as needed, then release the handle with CloseINFEngine.
656 * When translating more than one keys, this method is more efficient
657 * than calling TranslateInfString, because the INF file is only
660 HRESULT WINAPI TranslateInfStringExW(HINF hInf, LPCWSTR pszInfFilename,
661 LPCWSTR pszTranslateSection, LPCWSTR pszTranslateKey,
662 LPWSTR pszBuffer, DWORD dwBufferSize,
663 PDWORD pdwRequiredSize, PVOID pvReserved)
665 TRACE("(%p, %p, %p, %p, %p, %ld, %p, %p)\n", hInf, debugstr_w(pszInfFilename),
666 debugstr_w(pszTranslateSection), debugstr_w(pszTranslateKey),
667 debugstr_w(pszBuffer), dwBufferSize, pdwRequiredSize, pvReserved);
669 if (!hInf || !pszInfFilename || !pszTranslateSection || !pszTranslateKey)
672 if (!SetupGetLineTextW(NULL, hInf, pszTranslateSection, pszTranslateKey,
673 pszBuffer, dwBufferSize, pdwRequiredSize))
675 if (dwBufferSize < *pdwRequiredSize)
676 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
678 return SPAPI_E_LINE_NOT_FOUND;
684 /***********************************************************************
685 * UserInstStubWrapperA (ADVPACK.@)
687 * See UserInstStubWrapperW.
689 HRESULT WINAPI UserInstStubWrapperA(HWND hWnd, HINSTANCE hInstance,
690 LPSTR pszParms, INT nShow)
692 UNICODE_STRING parmsW;
695 TRACE("(%p, %p, %p, %i)\n", hWnd, hInstance, pszParms, nShow);
700 RtlCreateUnicodeStringFromAsciiz(&parmsW, pszParms);
702 res = UserInstStubWrapperW(hWnd, hInstance, parmsW.Buffer, nShow);
704 RtlFreeUnicodeString(&parmsW);
709 /***********************************************************************
710 * UserInstStubWrapperW (ADVPACK.@)
712 HRESULT WINAPI UserInstStubWrapperW(HWND hWnd, HINSTANCE hInstance,
713 LPWSTR pszParms, INT nShow)
715 FIXME("(%p, %p, %p, %i) stub\n", hWnd, hInstance, pszParms, nShow);
720 /***********************************************************************
721 * UserUnInstStubWrapperA (ADVPACK.@)
723 * See UserUnInstStubWrapperW.
725 HRESULT WINAPI UserUnInstStubWrapperA(HWND hWnd, HINSTANCE hInstance,
726 LPSTR pszParms, INT nShow)
728 UNICODE_STRING parmsW;
731 TRACE("(%p, %p, %p, %i)\n", hWnd, hInstance, pszParms, nShow);
736 RtlCreateUnicodeStringFromAsciiz(&parmsW, pszParms);
738 res = UserUnInstStubWrapperW(hWnd, hInstance, parmsW.Buffer, nShow);
740 RtlFreeUnicodeString(&parmsW);
745 /***********************************************************************
746 * UserUnInstStubWrapperW (ADVPACK.@)
748 HRESULT WINAPI UserUnInstStubWrapperW(HWND hWnd, HINSTANCE hInstance,
749 LPWSTR pszParms, INT nShow)
751 FIXME("(%p, %p, %p, %i) stub\n", hWnd, hInstance, pszParms, nShow);