advpack: Add tests for the TranslateInfStringEx trio of functions and
[wine/gsoc_dplay.git] / dlls / advpack / advpack.c
blob0fa362f0a846ae53669ec0a2eb2f46dac709a649
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <stdarg.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "winreg.h"
28 #include "winver.h"
29 #include "winnls.h"
30 #include "setupapi.h"
31 #include "advpub.h"
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
40 #define PREFIX_LEN 5
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)
49 INFCONTEXT context;
50 CHAR key[MAX_PATH], value[MAX_PATH];
51 CHAR prefix[PREFIX_LEN];
52 HKEY root, subkey;
53 DWORD size;
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;
65 else
66 root = NULL;
68 /* preserve the buffer size */
69 size = dwSize;
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);
78 RegCloseKey(subkey);
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];
86 CHAR dest[MAX_PATH];
87 INFCONTEXT context;
88 DWORD size;
89 int ldid;
91 if (!SetupGetLineTextA(NULL, hInf, pszInstallSection, "CustomDestination",
92 field, MAX_FIELD_LENGTH, &size))
93 return;
95 if (!SetupFindFirstLineA(hInf, field, NULL, &context))
96 return;
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.
115 * PARAMS
116 * hInf [I] Handle to the INF file to close.
118 * RETURNS
119 * Success: S_OK.
120 * Failure: E_FAIL.
122 HRESULT WINAPI CloseINFEngine(HINF hInf)
124 TRACE("(%p)\n", hInf);
126 if (!hInf)
127 return E_INVALIDARG;
129 SetupCloseInfFile(hInf);
130 return S_OK;
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);
143 return TRUE;
146 /***********************************************************************
147 * IsNTAdmin (ADVPACK.@)
149 * Checks if the user has admin privileges.
151 * PARAMS
152 * reserved [I] Reserved. Must be 0.
153 * pReserved [I] Reserved. Must be NULL.
155 * RETURNS
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;
163 DWORD dwSize, i;
164 HANDLE hToken;
165 PSID pSid;
167 TRACE("(0x%08lx, %p)\n", reserved, pReserved);
169 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
170 return FALSE;
172 if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwSize))
174 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
176 CloseHandle(hToken);
177 return FALSE;
181 pTokenGroups = HeapAlloc(GetProcessHeap(), 0, dwSize);
182 if (!pTokenGroups)
184 CloseHandle(hToken);
185 return FALSE;
188 if (!GetTokenInformation(hToken, TokenGroups, pTokenGroups, dwSize, &dwSize))
190 HeapFree(GetProcessHeap(), 0, pTokenGroups);
191 CloseHandle(hToken);
192 return FALSE;
195 CloseHandle(hToken);
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);
201 return FALSE;
204 for (i = 0; i < pTokenGroups->GroupCount; i++)
206 if (EqualSid(pSid, pTokenGroups->Groups[i].Sid))
208 bSidFound = TRUE;
209 break;
213 HeapFree(GetProcessHeap(), 0, pTokenGroups);
214 FreeSid(pSid);
216 return bSidFound;
219 /***********************************************************************
220 * NeedRebootInit (ADVPACK.@)
222 * Sets up conditions for reboot checking.
224 * RETURNS
225 * Value required by NeedReboot.
227 DWORD WINAPI NeedRebootInit(VOID)
229 FIXME("(): stub\n");
230 return 0;
233 /***********************************************************************
234 * NeedReboot (ADVPACK.@)
236 * Determines whether a reboot is required.
238 * PARAMS
239 * dwRebootCheck [I] Value from NeedRebootInit.
241 * RETURNS
242 * TRUE if a reboot is needed, FALSE otherwise.
244 * BUGS
245 * Unimplemented.
247 BOOL WINAPI NeedReboot(DWORD dwRebootCheck)
249 FIXME("(0x%08lx): stub\n", dwRebootCheck);
250 return FALSE;
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.
259 * PARAMS
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.
266 * RETURNS
267 * Success: S_OK.
268 * Failure: E_FAIL.
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)
277 return E_INVALIDARG;
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);
285 return S_OK;
288 /***********************************************************************
289 * RebootCheckOnInstallA (ADVPACK.@)
291 * Checks if a reboot is required for an installed INF section.
293 * PARAMS
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.
299 * RETURNS
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().
304 * NOTES
305 * if pszSec is NULL, RebootCheckOnInstall checks the DefaultInstall
306 * or DefaultInstall.NT section.
308 * BUGS
309 * Unimplemented.
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);
316 return E_FAIL;
319 /***********************************************************************
320 * RegisterOCX (ADVPACK.@)
322 void WINAPI RegisterOCX( HWND hWnd, HINSTANCE hInst, LPCSTR cmdline, INT show )
324 WCHAR wszBuff[MAX_PATH];
325 WCHAR* pwcComma;
326 HMODULE hm;
327 DLLREGISTER pfnRegister;
328 HRESULT hr;
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);
338 if (!hm)
340 ERR("Couldn't load DLL: %s\n", debugstr_w(wszBuff));
341 return;
344 pfnRegister = (DLLREGISTER)GetProcAddress(hm, "DllRegisterServer");
345 if (pfnRegister == NULL)
347 ERR("DllRegisterServer entry point not found\n");
349 else
351 hr = pfnRegister();
352 if (hr != S_OK)
354 ERR("DllRegisterServer entry point returned %08lx\n", hr);
358 TRACE("Successfully registered OCX\n");
360 FreeLibrary(hm);
363 /***********************************************************************
364 * SetPerUserSecValuesA (ADVPACK.@)
366 * Prepares the per-user stub values under IsInstalled\{GUID} that
367 * control the per-user installation.
369 * PARAMS
370 * pPerUser [I] Per-user stub values.
372 * RETURNS
373 * Success: S_OK.
374 * Failure: E_FAIL.
376 * BUGS
377 * Unimplemented.
379 HRESULT WINAPI SetPerUserSecValuesA(PERUSERSECTIONA* pPerUser)
381 FIXME("(%p) stub\n", pPerUser);
383 return E_FAIL;
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.
392 * PARAMS
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.
402 * RETURNS
403 * Success: S_OK.
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)
410 HINF hInf;
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)
419 return E_INVALIDARG;
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);
437 return S_OK;
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.
447 * PARAMS
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.
457 * RETURNS
458 * Success: S_OK.
459 * Failure: E_FAIL.
461 * NOTES
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
467 * opened once.
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)
479 return E_INVALIDARG;
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;
490 return S_OK;
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);
501 return E_FAIL;
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);
512 return E_FAIL;