avifil32: Use HeapAlloc instead of Local Alloc.
[wine] / dlls / advpack / advpack.c
1 /*
2  * Advpack main
3  *
4  * Copyright 2004 Huw D M Davies
5  * Copyright 2005 Sami Aario
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include <stdarg.h>
23
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"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(advpack);
36
37 typedef HRESULT (WINAPI *DLLREGISTER) (void);
38
39 #define MAX_FIELD_LENGTH    512
40 #define PREFIX_LEN          5
41
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
46  */
47 static void get_dest_dir(HINF hInf, PCSTR pszSection, PSTR pszBuffer, DWORD dwSize)
48 {
49     INFCONTEXT context;
50     CHAR key[MAX_PATH], value[MAX_PATH];
51     CHAR prefix[PREFIX_LEN];
52     HKEY root, subkey;
53     DWORD size;
54
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);
60
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;
67
68     /* preserve the buffer size */
69     size = dwSize;
70
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))
74     {
75         SetupGetStringFieldA(&context, 6, pszBuffer, dwSize, &size);
76     }
77
78     RegCloseKey(subkey);
79 }
80
81 /* loads the LDIDs specified in the install section of an INF */
82 static void set_ldids(HINF hInf, PCSTR pszInstallSection)
83 {
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;
90
91     if (!SetupGetLineTextA(NULL, hInf, pszInstallSection, "CustomDestination",
92                            field, MAX_FIELD_LENGTH, &size))
93         return;
94
95     if (!SetupFindFirstLineA(hInf, field, NULL, &context))
96         return;
97
98     do
99     {
100         SetupGetIntField(&context, 0, &ldid);
101         SetupGetLineTextA(&context, NULL, NULL, NULL,
102                           key, MAX_FIELD_LENGTH, &size);
103
104         get_dest_dir(hInf, key, dest, MAX_PATH);
105
106         SetupSetDirectoryIdA(hInf, ldid, dest);
107     } while (SetupFindNextLine(&context, &context));
108 }
109
110 /***********************************************************************
111  *           CloseINFEngine (ADVPACK.@)
112  *
113  * Closes a handle to an INF file opened with OpenINFEngine.
114  *
115  * PARAMS
116  *   hInf [I] Handle to the INF file to close.
117  *
118  * RETURNS
119  *   Success: S_OK.
120  *   Failure: E_FAIL.
121  */
122 HRESULT WINAPI CloseINFEngine(HINF hInf)
123 {
124     TRACE("(%p)\n", hInf);
125
126     if (!hInf)
127         return E_INVALIDARG;
128
129     SetupCloseInfFile(hInf);
130     return S_OK;
131 }
132
133 /***********************************************************************
134  *           DllMain (ADVPACK.@)
135  */
136 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
137 {
138     TRACE("(%p, %ld, %p)\n",hinstDLL, fdwReason, lpvReserved);
139
140     if (fdwReason == DLL_PROCESS_ATTACH)
141         DisableThreadLibraryCalls(hinstDLL);
142
143     return TRUE;
144 }
145
146 /***********************************************************************
147  *              IsNTAdmin       (ADVPACK.@)
148  *
149  * Checks if the user has admin privileges.
150  *
151  * PARAMS
152  *   reserved  [I] Reserved.  Must be 0.
153  *   pReserved [I] Reserved.  Must be NULL.
154  *
155  * RETURNS
156  *   TRUE if user has admin rights, FALSE otherwise.
157  */
158 BOOL WINAPI IsNTAdmin( DWORD reserved, LPDWORD pReserved )
159 {
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;
166
167     TRACE("(0x%08lx, %p)\n", reserved, pReserved);
168
169     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
170         return FALSE;
171
172     if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwSize))
173     {
174         if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
175         {
176             CloseHandle(hToken);
177             return FALSE;
178         }
179     }
180
181     pTokenGroups = HeapAlloc(GetProcessHeap(), 0, dwSize);
182     if (!pTokenGroups)
183     {
184         CloseHandle(hToken);
185         return FALSE;
186     }
187
188     if (!GetTokenInformation(hToken, TokenGroups, pTokenGroups, dwSize, &dwSize))
189     {
190         HeapFree(GetProcessHeap(), 0, pTokenGroups);
191         CloseHandle(hToken);
192         return FALSE;
193     }
194
195     CloseHandle(hToken);
196
197     if (!AllocateAndInitializeSid(&SidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
198                                   DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pSid))
199     {
200         HeapFree(GetProcessHeap(), 0, pTokenGroups);
201         return FALSE;
202     }
203
204     for (i = 0; i < pTokenGroups->GroupCount; i++)
205     {
206         if (EqualSid(pSid, pTokenGroups->Groups[i].Sid))
207         {
208             bSidFound = TRUE;
209             break;
210         }
211     }
212
213     HeapFree(GetProcessHeap(), 0, pTokenGroups);
214     FreeSid(pSid);
215
216     return bSidFound;
217 }
218
219 /***********************************************************************
220  *             NeedRebootInit  (ADVPACK.@)
221  *
222  * Sets up conditions for reboot checking.
223  *
224  * RETURNS
225  *   Value required by NeedReboot.
226  */
227 DWORD WINAPI NeedRebootInit(VOID)
228 {
229     FIXME("(): stub\n");
230     return 0;
231 }
232
233 /***********************************************************************
234  *             NeedReboot      (ADVPACK.@)
235  *
236  * Determines whether a reboot is required.
237  *
238  * PARAMS
239  *   dwRebootCheck [I] Value from NeedRebootInit.
240  *
241  * RETURNS
242  *   TRUE if a reboot is needed, FALSE otherwise.
243  *
244  * BUGS
245  *   Unimplemented.
246  */
247 BOOL WINAPI NeedReboot(DWORD dwRebootCheck)
248 {
249     FIXME("(0x%08lx): stub\n", dwRebootCheck);
250     return FALSE;
251 }
252
253 /***********************************************************************
254  *             OpenINFEngineA   (ADVPACK.@)
255  *
256  * Opens and returns a handle to an INF file to be used by
257  * TranslateInfStringEx to continuously translate the INF file.
258  *
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.
265  *
266  * RETURNS
267  *   Success: S_OK.
268  *   Failure: E_FAIL.
269  */
270 HRESULT WINAPI OpenINFEngineA(LPCSTR pszInfFilename, LPCSTR pszInstallSection,
271                              DWORD dwFlags, HINF *phInf, PVOID pvReserved)
272 {
273     TRACE("(%p, %p, %ld, %p, %p)\n", pszInfFilename, pszInstallSection,
274           dwFlags, phInf, pvReserved);
275
276     if (!pszInfFilename || !phInf)
277         return E_INVALIDARG;
278
279     *phInf = SetupOpenInfFileA(pszInfFilename, NULL, INF_STYLE_WIN4, NULL);
280     if (*phInf == INVALID_HANDLE_VALUE)
281         return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
282
283     set_ldids(*phInf, pszInstallSection);
284     
285     return S_OK;
286 }
287
288 /***********************************************************************
289  *             RebootCheckOnInstallA   (ADVPACK.@)
290  *
291  * Checks if a reboot is required for an installed INF section.
292  *
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.
298  *
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().
303  *
304  * NOTES
305  *   if pszSec is NULL, RebootCheckOnInstall checks the DefaultInstall
306  *   or DefaultInstall.NT section.
307  *
308  * BUGS
309  *   Unimplemented.
310  */
311 HRESULT WINAPI RebootCheckOnInstallA(HWND hWnd, LPCSTR pszINF,
312                                     LPSTR pszSec, DWORD dwReserved)
313 {
314     FIXME("(%p, %p, %p, %ld) stub\n", hWnd, pszINF, pszSec, dwReserved);
315
316     return E_FAIL;
317 }
318
319 /***********************************************************************
320  *             RegisterOCX    (ADVPACK.@)
321  */
322 void WINAPI RegisterOCX( HWND hWnd, HINSTANCE hInst, LPCSTR cmdline, INT show )
323 {
324     WCHAR wszBuff[MAX_PATH];
325     WCHAR* pwcComma;
326     HMODULE hm;
327     DLLREGISTER pfnRegister;
328     HRESULT hr;
329
330     TRACE("(%s)\n", cmdline);
331
332     MultiByteToWideChar(CP_ACP, 0, cmdline, strlen(cmdline), wszBuff, MAX_PATH);
333     if ((pwcComma = strchrW( wszBuff, ',' ))) *pwcComma = 0;
334
335     TRACE("Parsed DLL name (%s)\n", debugstr_w(wszBuff));
336
337     hm = LoadLibraryExW(wszBuff, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
338     if (!hm)
339     {
340         ERR("Couldn't load DLL: %s\n", debugstr_w(wszBuff));
341         return;
342     }
343
344     pfnRegister = (DLLREGISTER)GetProcAddress(hm, "DllRegisterServer");
345     if (pfnRegister == NULL)
346     {
347         ERR("DllRegisterServer entry point not found\n");
348     }
349     else
350     {
351         hr = pfnRegister();
352         if (hr != S_OK)
353         {
354             ERR("DllRegisterServer entry point returned %08lx\n", hr);
355         }
356     }
357
358     TRACE("Successfully registered OCX\n");
359
360     FreeLibrary(hm);
361 }
362
363 /***********************************************************************
364  *             SetPerUserSecValuesA   (ADVPACK.@)
365  *
366  * Prepares the per-user stub values under IsInstalled\{GUID} that
367  * control the per-user installation.
368  *
369  * PARAMS
370  *   pPerUser [I] Per-user stub values.
371  *
372  * RETURNS
373  *   Success: S_OK.
374  *   Failure: E_FAIL.
375  *
376  * BUGS
377  *   Unimplemented.
378  */
379 HRESULT WINAPI SetPerUserSecValuesA(PERUSERSECTIONA* pPerUser)
380 {
381     FIXME("(%p) stub\n", pPerUser);
382
383     return E_FAIL;
384 }
385
386 /***********************************************************************
387  *             TranslateInfStringA   (ADVPACK.@)
388  *
389  * Translates the value of a specified key in an inf file into the
390  * current locale by expanding string macros.
391  *
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.
401  *
402  * RETURNS
403  *   Success: S_OK.
404  *   Failure: An hresult error code.
405  */
406 HRESULT WINAPI TranslateInfStringA(LPCSTR pszInfFilename, LPCSTR pszInstallSection,
407                 LPCSTR pszTranslateSection, LPCSTR pszTranslateKey, LPSTR pszBuffer,
408                 DWORD dwBufferSize, PDWORD pdwRequiredSize, PVOID pvReserved)
409 {
410     HINF hInf;
411
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);
416
417     if (!pszInfFilename || !pszTranslateSection ||
418         !pszTranslateKey || !pdwRequiredSize)
419         return E_INVALIDARG;
420
421     hInf = SetupOpenInfFileA(pszInfFilename, NULL, INF_STYLE_WIN4, NULL);
422     if (hInf == INVALID_HANDLE_VALUE)
423         return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
424
425     set_ldids(hInf, pszInstallSection);
426
427     if (!SetupGetLineTextA(NULL, hInf, pszTranslateSection, pszTranslateKey,
428                            pszBuffer, dwBufferSize, pdwRequiredSize))
429     {
430         if (dwBufferSize < *pdwRequiredSize)
431             return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
432
433         return SPAPI_E_LINE_NOT_FOUND;
434     }
435
436     SetupCloseInfFile(hInf);
437     return S_OK;
438 }
439
440 /***********************************************************************
441  *             TranslateInfStringExA   (ADVPACK.@)
442  *
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.
446  *
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.
456  *
457  * RETURNS
458  *   Success: S_OK.
459  *   Failure: E_FAIL.
460  *
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.
468  */
469 HRESULT WINAPI TranslateInfStringExA(HINF hInf, LPCSTR pszInfFilename,
470                                     LPCSTR pszTranslateSection, LPCSTR pszTranslateKey,
471                                     LPSTR pszBuffer, DWORD dwBufferSize,
472                                     PDWORD pdwRequiredSize, PVOID pvReserved)
473 {
474     TRACE("(%p, %p, %p, %p, %p, %ld, %p, %p)\n", hInf, pszInfFilename,
475           pszTranslateSection, pszTranslateKey, pszBuffer, dwBufferSize,
476           pdwRequiredSize, pvReserved);
477
478     if (!hInf || !pszInfFilename || !pszTranslateSection || !pszTranslateKey)
479         return E_INVALIDARG;
480
481     if (!SetupGetLineTextA(NULL, hInf, pszTranslateSection, pszTranslateKey,
482                            pszBuffer, dwBufferSize, pdwRequiredSize))
483     {
484         if (dwBufferSize < *pdwRequiredSize)
485             return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
486
487         return SPAPI_E_LINE_NOT_FOUND;
488     }
489
490     return S_OK;   
491 }
492
493 /***********************************************************************
494  *             UserInstStubWrapperA   (ADVPACK.@)
495  */
496 HRESULT WINAPI UserInstStubWrapperA(HWND hWnd, HINSTANCE hInstance,
497                                    LPSTR pszParms, INT nShow)
498 {
499     FIXME("(%p, %p, %p, %i) stub\n", hWnd, hInstance, pszParms, nShow);
500
501     return E_FAIL;
502 }
503
504 /***********************************************************************
505  *             UserUnInstStubWrapperA   (ADVPACK.@)
506  */
507 HRESULT WINAPI UserUnInstStubWrapperA(HWND hWnd, HINSTANCE hInstance,
508                                      LPSTR pszParms, INT nShow)
509 {
510     FIXME("(%p, %p, %p, %i) stub\n", hWnd, hInstance, pszParms, nShow);
511
512     return E_FAIL;
513 }