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
32 #include "wine/unicode.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(advpack);
37 typedef HRESULT (WINAPI *DLLREGISTER) (void);
39 #define MAX_FIELD_LENGTH 512
42 /* parses the destination directory parameters from pszSection
43 * the parameters are of the form: root,key,value,unknown,fallback
44 * we first read the reg value root\\key\\value and if that fails,
45 * use fallback as the destination directory
47 static void get_dest_dir(HINF hInf, PCSTR pszSection, PSTR pszBuffer, DWORD dwSize)
50 CHAR key[MAX_PATH], value[MAX_PATH];
51 CHAR prefix[PREFIX_LEN];
55 /* load the destination parameters */
56 SetupFindFirstLineA(hInf, pszSection, NULL, &context);
57 SetupGetStringFieldA(&context, 1, prefix, PREFIX_LEN, &size);
58 SetupGetStringFieldA(&context, 2, key, MAX_PATH, &size);
59 SetupGetStringFieldA(&context, 3, value, MAX_PATH, &size);
61 if (!lstrcmpA(prefix, "HKLM"))
62 root = HKEY_LOCAL_MACHINE;
63 else if (!lstrcmpA(prefix, "HKCU"))
64 root = HKEY_CURRENT_USER;
68 /* preserve the buffer size */
71 /* fallback to the default destination dir if reg fails */
72 if (RegOpenKeyA(root, key, &subkey) ||
73 RegQueryValueExA(subkey, value, NULL, NULL, (LPBYTE)pszBuffer, &size))
75 SetupGetStringFieldA(&context, 6, pszBuffer, dwSize, &size);
81 /* loads the LDIDs specified in the install section of an INF */
82 static void set_ldids(HINF hInf, PCSTR pszInstallSection)
84 CHAR field[MAX_FIELD_LENGTH];
85 CHAR key[MAX_FIELD_LENGTH];
91 if (!SetupGetLineTextA(NULL, hInf, pszInstallSection, "CustomDestination",
92 field, MAX_FIELD_LENGTH, &size))
95 if (!SetupFindFirstLineA(hInf, field, NULL, &context))
100 SetupGetIntField(&context, 0, &ldid);
101 SetupGetLineTextA(&context, NULL, NULL, NULL,
102 key, MAX_FIELD_LENGTH, &size);
104 get_dest_dir(hInf, key, dest, MAX_PATH);
106 SetupSetDirectoryIdA(hInf, ldid, dest);
107 } while (SetupFindNextLine(&context, &context));
110 /***********************************************************************
111 * CloseINFEngine (ADVPACK.@)
113 * Closes a handle to an INF file opened with OpenINFEngine.
116 * hInf [I] Handle to the INF file to close.
122 HRESULT WINAPI CloseINFEngine(HINF hInf)
124 TRACE("(%p)\n", hInf);
129 SetupCloseInfFile(hInf);
133 /***********************************************************************
134 * DllMain (ADVPACK.@)
136 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
138 TRACE("(%p, %ld, %p)\n",hinstDLL, fdwReason, lpvReserved);
140 if (fdwReason == DLL_PROCESS_ATTACH)
141 DisableThreadLibraryCalls(hinstDLL);
146 /***********************************************************************
147 * IsNTAdmin (ADVPACK.@)
149 * Checks if the user has admin privileges.
152 * reserved [I] Reserved. Must be 0.
153 * pReserved [I] Reserved. Must be NULL.
156 * TRUE if user has admin rights, FALSE otherwise.
158 BOOL WINAPI IsNTAdmin( DWORD reserved, LPDWORD pReserved )
160 SID_IDENTIFIER_AUTHORITY SidAuthority = {SECURITY_NT_AUTHORITY};
161 PTOKEN_GROUPS pTokenGroups;
162 BOOL bSidFound = FALSE;
167 TRACE("(0x%08lx, %p)\n", reserved, pReserved);
169 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
172 if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwSize))
174 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
181 pTokenGroups = HeapAlloc(GetProcessHeap(), 0, dwSize);
188 if (!GetTokenInformation(hToken, TokenGroups, pTokenGroups, dwSize, &dwSize))
190 HeapFree(GetProcessHeap(), 0, pTokenGroups);
197 if (!AllocateAndInitializeSid(&SidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
198 DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pSid))
200 HeapFree(GetProcessHeap(), 0, pTokenGroups);
204 for (i = 0; i < pTokenGroups->GroupCount; i++)
206 if (EqualSid(pSid, pTokenGroups->Groups[i].Sid))
213 HeapFree(GetProcessHeap(), 0, pTokenGroups);
219 /***********************************************************************
220 * NeedRebootInit (ADVPACK.@)
222 * Sets up conditions for reboot checking.
225 * Value required by NeedReboot.
227 DWORD WINAPI NeedRebootInit(VOID)
233 /***********************************************************************
234 * NeedReboot (ADVPACK.@)
236 * Determines whether a reboot is required.
239 * dwRebootCheck [I] Value from NeedRebootInit.
242 * TRUE if a reboot is needed, FALSE otherwise.
247 BOOL WINAPI NeedReboot(DWORD dwRebootCheck)
249 FIXME("(0x%08lx): stub\n", dwRebootCheck);
253 /***********************************************************************
254 * OpenINFEngineA (ADVPACK.@)
256 * Opens and returns a handle to an INF file to be used by
257 * TranslateInfStringEx to continuously translate the INF file.
260 * pszInfFilename [I] Filename of the INF to open.
261 * pszInstallSection [I] Name of the Install section in the INF.
262 * dwFlags [I] See advpub.h.
263 * phInf [O] Handle to the loaded INF file.
264 * pvReserved [I] Reserved. Must be NULL.
270 HRESULT WINAPI OpenINFEngineA(LPCSTR pszInfFilename, LPCSTR pszInstallSection,
271 DWORD dwFlags, HINF *phInf, PVOID pvReserved)
273 TRACE("(%p, %p, %ld, %p, %p)\n", pszInfFilename, pszInstallSection,
274 dwFlags, phInf, pvReserved);
276 if (!pszInfFilename || !phInf)
279 *phInf = SetupOpenInfFileA(pszInfFilename, NULL, INF_STYLE_WIN4, NULL);
280 if (*phInf == INVALID_HANDLE_VALUE)
281 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
283 set_ldids(*phInf, pszInstallSection);
288 /***********************************************************************
289 * RebootCheckOnInstallA (ADVPACK.@)
291 * Checks if a reboot is required for an installed INF section.
294 * hWnd [I] Handle to the window used for messages.
295 * pszINF [I] Filename of the INF file.
296 * pszSec [I] INF section to check.
297 * dwReserved [I] Reserved. Must be 0.
300 * Success: S_OK - Reboot is needed if the INF section is installed.
301 * S_FALSE - Reboot is not needed.
302 * Failure: HRESULT of GetLastError().
305 * if pszSec is NULL, RebootCheckOnInstall checks the DefaultInstall
306 * or DefaultInstall.NT section.
311 HRESULT WINAPI RebootCheckOnInstallA(HWND hWnd, LPCSTR pszINF,
312 LPSTR pszSec, DWORD dwReserved)
314 FIXME("(%p, %p, %p, %ld) stub\n", hWnd, pszINF, pszSec, dwReserved);
319 /***********************************************************************
320 * RegisterOCX (ADVPACK.@)
322 void WINAPI RegisterOCX( HWND hWnd, HINSTANCE hInst, LPCSTR cmdline, INT show )
324 WCHAR wszBuff[MAX_PATH];
327 DLLREGISTER pfnRegister;
330 TRACE("(%s)\n", cmdline);
332 MultiByteToWideChar(CP_ACP, 0, cmdline, strlen(cmdline), wszBuff, MAX_PATH);
333 if ((pwcComma = strchrW( wszBuff, ',' ))) *pwcComma = 0;
335 TRACE("Parsed DLL name (%s)\n", debugstr_w(wszBuff));
337 hm = LoadLibraryExW(wszBuff, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
340 ERR("Couldn't load DLL: %s\n", debugstr_w(wszBuff));
344 pfnRegister = (DLLREGISTER)GetProcAddress(hm, "DllRegisterServer");
345 if (pfnRegister == NULL)
347 ERR("DllRegisterServer entry point not found\n");
354 ERR("DllRegisterServer entry point returned %08lx\n", hr);
358 TRACE("Successfully registered OCX\n");
363 /***********************************************************************
364 * SetPerUserSecValuesA (ADVPACK.@)
366 * Prepares the per-user stub values under IsInstalled\{GUID} that
367 * control the per-user installation.
370 * pPerUser [I] Per-user stub values.
379 HRESULT WINAPI SetPerUserSecValuesA(PERUSERSECTIONA* pPerUser)
381 FIXME("(%p) stub\n", pPerUser);
386 /***********************************************************************
387 * TranslateInfStringA (ADVPACK.@)
389 * Translates the value of a specified key in an inf file into the
390 * current locale by expanding string macros.
393 * pszInfFilename [I] Filename of the inf file.
394 * pszInstallSection [I]
395 * pszTranslateSection [I] Inf section where the key exists.
396 * pszTranslateKey [I] Key to translate.
397 * pszBuffer [O] Contains the translated string on exit.
398 * dwBufferSize [I] Size on input of pszBuffer.
399 * pdwRequiredSize [O] Length of the translated key.
400 * pvReserved [I] Reserved, must be NULL.
404 * Failure: An hresult error code.
406 HRESULT WINAPI TranslateInfStringA(LPCSTR pszInfFilename, LPCSTR pszInstallSection,
407 LPCSTR pszTranslateSection, LPCSTR pszTranslateKey, LPSTR pszBuffer,
408 DWORD dwBufferSize, PDWORD pdwRequiredSize, PVOID pvReserved)
412 TRACE("(%s %s %s %s %p %ld %p %p)\n",
413 debugstr_a(pszInfFilename), debugstr_a(pszInstallSection),
414 debugstr_a(pszTranslateSection), debugstr_a(pszTranslateKey),
415 pszBuffer, dwBufferSize,pdwRequiredSize, pvReserved);
417 if (!pszInfFilename || !pszTranslateSection ||
418 !pszTranslateKey || !pdwRequiredSize)
421 hInf = SetupOpenInfFileA(pszInfFilename, NULL, INF_STYLE_WIN4, NULL);
422 if (hInf == INVALID_HANDLE_VALUE)
423 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
425 set_ldids(hInf, pszInstallSection);
427 if (!SetupGetLineTextA(NULL, hInf, pszTranslateSection, pszTranslateKey,
428 pszBuffer, dwBufferSize, pdwRequiredSize))
430 if (dwBufferSize < *pdwRequiredSize)
431 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
433 return SPAPI_E_LINE_NOT_FOUND;
436 SetupCloseInfFile(hInf);
440 /***********************************************************************
441 * TranslateInfStringExA (ADVPACK.@)
443 * Using a handle to an INF file opened with OpenINFEngine, translates
444 * the value of a specified key in an inf file into the current locale
445 * by expanding string macros.
448 * hInf [I] Handle to the INF file.
449 * pszInfFilename [I] Filename of the INF file.
450 * pszTranslateSection [I] Inf section where the key exists.
451 * pszTranslateKey [I] Key to translate.
452 * pszBuffer [O] Contains the translated string on exit.
453 * dwBufferSize [I] Size on input of pszBuffer.
454 * pdwRequiredSize [O] Length of the translated key.
455 * pvReserved [I] Reserved. Must be NULL.
462 * To use TranslateInfStringEx to translate an INF file continuously,
463 * open the INF file with OpenINFEngine, call TranslateInfStringEx as
464 * many times as needed, then release the handle with CloseINFEngine.
465 * When translating more than one keys, this method is more efficient
466 * than calling TranslateInfString, because the INF file is only
469 HRESULT WINAPI TranslateInfStringExA(HINF hInf, LPCSTR pszInfFilename,
470 LPCSTR pszTranslateSection, LPCSTR pszTranslateKey,
471 LPSTR pszBuffer, DWORD dwBufferSize,
472 PDWORD pdwRequiredSize, PVOID pvReserved)
474 TRACE("(%p, %p, %p, %p, %p, %ld, %p, %p)\n", hInf, pszInfFilename,
475 pszTranslateSection, pszTranslateKey, pszBuffer, dwBufferSize,
476 pdwRequiredSize, pvReserved);
478 if (!hInf || !pszInfFilename || !pszTranslateSection || !pszTranslateKey)
481 if (!SetupGetLineTextA(NULL, hInf, pszTranslateSection, pszTranslateKey,
482 pszBuffer, dwBufferSize, pdwRequiredSize))
484 if (dwBufferSize < *pdwRequiredSize)
485 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
487 return SPAPI_E_LINE_NOT_FOUND;
493 /***********************************************************************
494 * UserInstStubWrapperA (ADVPACK.@)
496 HRESULT WINAPI UserInstStubWrapperA(HWND hWnd, HINSTANCE hInstance,
497 LPSTR pszParms, INT nShow)
499 FIXME("(%p, %p, %p, %i) stub\n", hWnd, hInstance, pszParms, nShow);
504 /***********************************************************************
505 * UserUnInstStubWrapperA (ADVPACK.@)
507 HRESULT WINAPI UserUnInstStubWrapperA(HWND hWnd, HINSTANCE hInstance,
508 LPSTR pszParms, INT nShow)
510 FIXME("(%p, %p, %p, %i) stub\n", hWnd, hInstance, pszParms, nShow);