kernel32: FindFirstChangeNotification needs a static IO_STATUS_BLOCK.
[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 /***********************************************************************
40  *           CloseINFEngine (ADVPACK.@)
41  *
42  * Closes a handle to an INF file opened with OpenINFEngine.
43  *
44  * PARAMS
45  *   hInf [I] Handle to the INF file to close.
46  *
47  * RETURNS
48  *   Success: S_OK.
49  *   Failure: E_FAIL.
50  *
51  * BUGS
52  *   Unimplemented.
53  */
54 HRESULT WINAPI CloseINFEngine(HINF hInf)
55 {
56     FIXME("(%p) stub\n", hInf);
57
58     return E_FAIL;
59 }
60
61 /***********************************************************************
62  *           DllMain (ADVPACK.@)
63  */
64 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
65 {
66     TRACE("(%p, %ld, %p)\n",hinstDLL, fdwReason, lpvReserved);
67
68     if (fdwReason == DLL_PROCESS_ATTACH)
69         DisableThreadLibraryCalls(hinstDLL);
70
71     return TRUE;
72 }
73
74 /***********************************************************************
75  *              RunSetupCommand  (ADVPACK.@)
76  *
77  * Executes an install section in an INF file or a program.
78  *
79  * PARAMS
80  *   hWnd          [I] Handle to parent window, NULL for quiet mode
81  *   szCmdName     [I] Inf or EXE filename to execute
82  *   szInfSection  [I] Inf section to install, NULL for DefaultInstall
83  *   szDir         [I] Path to extracted files
84  *   szTitle       [I] Title of all dialogs
85  *   phEXE         [O] Handle of EXE to wait for
86  *   dwFlags       [I] Flags; see include/advpub.h
87  *   pvReserved    [I] Reserved
88  *
89  * RETURNS
90  *   S_OK                                 Everything OK
91  *   S_ASYNCHRONOUS                       OK, required to wait on phEXE
92  *   ERROR_SUCCESS_REBOOT_REQUIRED        Reboot required
93  *   E_INVALIDARG                         Invalid argument given
94  *   HRESULT_FROM_WIN32(ERROR_OLD_WIN_VERSION)
95  *                                        Not supported on this Windows version
96  *   E_UNEXPECTED                         Unexpected error
97  *   HRESULT_FROM_WIN32(GetLastError())   Some other error
98  *
99  * BUGS
100  *   Unimplemented
101  */
102 HRESULT WINAPI RunSetupCommand( HWND hWnd, LPCSTR szCmdName,
103                                 LPCSTR szInfSection, LPCSTR szDir,
104                                 LPCSTR lpszTitle, HANDLE *phEXE,
105                                 DWORD dwFlags, LPVOID pvReserved )
106 {
107     FIXME("(%p, %s, %s, %s, %s, %p, 0x%08lx, %p): stub\n",
108            hWnd, debugstr_a(szCmdName), debugstr_a(szInfSection),
109            debugstr_a(szDir), debugstr_a(lpszTitle),
110            phEXE, dwFlags, pvReserved);
111     return E_UNEXPECTED;
112 }
113
114 /***********************************************************************
115  *              LaunchINFSection  (ADVPACK.@)
116  *
117  * Installs an INF section without BACKUP/ROLLBACK capabilities.
118  *
119  * PARAMS
120  *   hWnd    [I] Handle to parent window, NULL for desktop.
121  *   hInst   [I] Instance of the process.
122  *   cmdline [I] Contains parameters in the order INF,section,flags.
123  *   show    [I] Reboot behaviour:
124  *              'A' reboot always
125  *              'I' default, reboot if needed
126  *              'N' no reboot
127  *
128  * RETURNS
129  *  Success: S_OK.
130  *  Failure: S_FALSE
131  *
132  * BUGS
133  *  Unimplemented.
134  */
135 INT WINAPI LaunchINFSection( HWND hWnd, HINSTANCE hInst, LPSTR cmdline, INT show )
136 {
137     FIXME("(%p %p %s %d): stub\n", hWnd, hInst, debugstr_a(cmdline), show );
138     return 0;
139 }
140
141 /***********************************************************************
142  *              LaunchINFSectionEx  (ADVPACK.@)
143  *
144  * Installs an INF section with BACKUP/ROLLBACK capabilities.
145  *
146  * PARAMS
147  *   hWnd    [I] Handle to parent window, NULL for desktop.
148  *   hInst   [I] Instance of the process.
149  *   cmdline [I] Contains parameters in the order INF,section,CAB,flags.
150  *   show    [I] Reboot behaviour:
151  *              'A' reboot always
152  *              'I' default, reboot if needed
153  *              'N' no reboot
154  *
155  * RETURNS
156  *  Success: S_OK.
157  *  Failure: E_FAIL.
158  *
159  * BUGS
160  *  Unimplemented.
161  */
162 HRESULT WINAPI LaunchINFSectionEx( HWND hWnd, HINSTANCE hInst, LPSTR cmdline, INT show )
163 {
164     FIXME("(%p %p %s %d): stub\n", hWnd, hInst, debugstr_a(cmdline), show );
165     return E_FAIL;
166 }
167
168 /* this structure very closely resembles parameters of RunSetupCommand() */
169 typedef struct
170 {
171     HWND hwnd;
172     LPCSTR title;
173     LPCSTR inf_name;
174     LPCSTR dir;
175     LPCSTR section_name;
176 } SETUPCOMMAND_PARAMS;
177
178 /***********************************************************************
179  *              DoInfInstall  (ADVPACK.@)
180  *
181  * Install an INF section.
182  *
183  * PARAMS
184  *  setup [I] Structure containing install information.
185  *
186  * RETURNS
187  *   S_OK                                Everything OK
188  *   HRESULT_FROM_WIN32(GetLastError())  Some other error
189  */
190 HRESULT WINAPI DoInfInstall(const SETUPCOMMAND_PARAMS *setup)
191 {
192     BOOL ret;
193     HINF hinf;
194     void *callback_context;
195
196     TRACE("%p %s %s %s %s\n", setup->hwnd, debugstr_a(setup->title),
197           debugstr_a(setup->inf_name), debugstr_a(setup->dir),
198           debugstr_a(setup->section_name));
199
200     hinf = SetupOpenInfFileA(setup->inf_name, NULL, INF_STYLE_WIN4, NULL);
201     if (hinf == INVALID_HANDLE_VALUE) return HRESULT_FROM_WIN32(GetLastError());
202
203     callback_context = SetupInitDefaultQueueCallback(setup->hwnd);
204
205     ret = SetupInstallFromInfSectionA(NULL, hinf, setup->section_name, SPINST_ALL,
206                                       NULL, NULL, 0, SetupDefaultQueueCallbackA,
207                                       callback_context, NULL, NULL);
208     SetupTermDefaultQueueCallback(callback_context);
209     SetupCloseInfFile(hinf);
210
211     return ret ? S_OK : HRESULT_FROM_WIN32(GetLastError());
212 }
213
214 /***********************************************************************
215  *              IsNTAdmin       (ADVPACK.@)
216  *
217  * Checks if the user has admin privileges.
218  *
219  * PARAMS
220  *   reserved  [I] Reserved.  Must be 0.
221  *   pReserved [I] Reserved.  Must be NULL.
222  *
223  * RETURNS
224  *   TRUE if user has admin rights, FALSE otherwise.
225  */
226 BOOL WINAPI IsNTAdmin( DWORD reserved, LPDWORD pReserved )
227 {
228     SID_IDENTIFIER_AUTHORITY SidAuthority = {SECURITY_NT_AUTHORITY};
229     PTOKEN_GROUPS pTokenGroups;
230     BOOL bSidFound = FALSE;
231     DWORD dwSize, i;
232     HANDLE hToken;
233     PSID pSid;
234
235     TRACE("(0x%08lx, %p)\n", reserved, pReserved);
236
237     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
238         return FALSE;
239
240     if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwSize))
241     {
242         if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
243         {
244             CloseHandle(hToken);
245             return FALSE;
246         }
247     }
248
249     pTokenGroups = HeapAlloc(GetProcessHeap(), 0, dwSize);
250     if (!pTokenGroups)
251     {
252         CloseHandle(hToken);
253         return FALSE;
254     }
255
256     if (!GetTokenInformation(hToken, TokenGroups, pTokenGroups, dwSize, &dwSize))
257     {
258         HeapFree(GetProcessHeap(), 0, pTokenGroups);
259         CloseHandle(hToken);
260         return FALSE;
261     }
262
263     CloseHandle(hToken);
264
265     if (!AllocateAndInitializeSid(&SidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
266                                   DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pSid))
267     {
268         HeapFree(GetProcessHeap(), 0, pTokenGroups);
269         return FALSE;
270     }
271
272     for (i = 0; i < pTokenGroups->GroupCount; i++)
273     {
274         if (EqualSid(pSid, pTokenGroups->Groups[i].Sid))
275         {
276             bSidFound = TRUE;
277             break;
278         }
279     }
280
281     HeapFree(GetProcessHeap(), 0, pTokenGroups);
282     FreeSid(pSid);
283
284     return bSidFound;
285 }
286
287 /***********************************************************************
288  *             NeedRebootInit  (ADVPACK.@)
289  *
290  * Sets up conditions for reboot checking.
291  *
292  * RETURNS
293  *   Value required by NeedReboot.
294  */
295 DWORD WINAPI NeedRebootInit(VOID)
296 {
297     FIXME("(): stub\n");
298     return 0;
299 }
300
301 /***********************************************************************
302  *             NeedReboot      (ADVPACK.@)
303  *
304  * Determines whether a reboot is required.
305  *
306  * PARAMS
307  *   dwRebootCheck [I] Value from NeedRebootInit.
308  *
309  * RETURNS
310  *   TRUE if a reboot is needed, FALSE otherwise.
311  *
312  * BUGS
313  *   Unimplemented.
314  */
315 BOOL WINAPI NeedReboot(DWORD dwRebootCheck)
316 {
317     FIXME("(0x%08lx): stub\n", dwRebootCheck);
318     return FALSE;
319 }
320
321 /***********************************************************************
322  *             OpenINFEngine    (ADVPACK.@)
323  *
324  * Opens and returns a handle to an INF file to be used by
325  * TranslateInfStringEx to continuously translate the INF file.
326  *
327  * PARAMS
328  *   pszInfFilename    [I] Filename of the INF to open.
329  *   pszInstallSection [I] Name of the Install section in the INF.
330  *   dwFlags           [I] See advpub.h.
331  *   phInf             [O] Handle to the loaded INF file.
332  *   pvReserved        [I] Reserved.  Must be NULL.
333  *
334  * RETURNS
335  *   Success: S_OK.
336  *   Failure: E_FAIL.
337  *
338  * BUGS
339  *   Unimplemented.
340  */
341 HRESULT WINAPI OpenINFEngine(PCSTR pszInfFilename, PCSTR pszInstallSection,
342                              DWORD dwFlags, HINF *phInf, PVOID pvReserved)
343 {
344     FIXME("(%p, %p, %ld, %p, %p) stub\n", pszInfFilename, pszInstallSection,
345           dwFlags, phInf, pvReserved);
346
347     return E_FAIL;
348 }
349
350 /***********************************************************************
351  *             RebootCheckOnInstall    (ADVPACK.@)
352  *
353  * Checks if a reboot is required for an installed INF section.
354  *
355  * PARAMS
356  *   hWnd       [I] Handle to the window used for messages.
357  *   pszINF     [I] Filename of the INF file.
358  *   pszSec     [I] INF section to check.
359  *   dwReserved [I] Reserved.  Must be 0.
360  *
361  * RETURNS
362  *   Success: S_OK - Reboot is needed if the INF section is installed.
363  *            S_FALSE - Reboot is not needed.
364  *   Failure: HRESULT of GetLastError().
365  *
366  * NOTES
367  *   if pszSec is NULL, RebootCheckOnInstall checks the DefaultInstall
368  *   or DefaultInstall.NT section.
369  *
370  * BUGS
371  *   Unimplemented.
372  */
373 HRESULT WINAPI RebootCheckOnInstall(HWND hWnd, LPCSTR pszINF,
374                                     LPCSTR pszSec, DWORD dwReserved)
375 {
376     FIXME("(%p, %p, %p, %ld) stub\n", hWnd, pszINF, pszSec, dwReserved);
377
378     return E_FAIL;
379 }
380
381 /***********************************************************************
382  *             RegisterOCX    (ADVPACK.@)
383  */
384 void WINAPI RegisterOCX( HWND hWnd, HINSTANCE hInst, LPCSTR cmdline, INT show )
385 {
386     WCHAR wszBuff[MAX_PATH];
387     WCHAR* pwcComma;
388     HMODULE hm;
389     DLLREGISTER pfnRegister;
390     HRESULT hr;
391
392     TRACE("(%s)\n", cmdline);
393
394     MultiByteToWideChar(CP_ACP, 0, cmdline, strlen(cmdline), wszBuff, MAX_PATH);
395     if ((pwcComma = strchrW( wszBuff, ',' ))) *pwcComma = 0;
396
397     TRACE("Parsed DLL name (%s)\n", debugstr_w(wszBuff));
398
399     hm = LoadLibraryExW(wszBuff, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
400     if (!hm)
401     {
402         ERR("Couldn't load DLL: %s\n", debugstr_w(wszBuff));
403         return;
404     }
405
406     pfnRegister = (DLLREGISTER)GetProcAddress(hm, "DllRegisterServer");
407     if (pfnRegister == NULL)
408     {
409         ERR("DllRegisterServer entry point not found\n");
410     }
411     else
412     {
413         hr = pfnRegister();
414         if (hr != S_OK)
415         {
416             ERR("DllRegisterServer entry point returned %08lx\n", hr);
417         }
418     }
419
420     TRACE("Successfully registered OCX\n");
421
422     FreeLibrary(hm);
423 }
424
425 /***********************************************************************
426  *             ExecuteCab    (ADVPACK.@)
427  * 
428  * Installs the INF file extracted from a specified cabinet file.
429  * 
430  * PARAMS
431  *   hwnd      [I] Handle to the window used for the display.
432  *   pCab      [I] Information about the cabinet file.
433  *   pReserved [I] Reserved.  Must be NULL.
434  * 
435  * RETURNS
436  *   Success: S_OK.
437  *   Failure: E_FAIL.
438  *
439  * BUGS
440  *   Unimplemented
441  */
442 HRESULT WINAPI ExecuteCab( HWND hwnd, PCABINFO pCab, LPVOID pReserved )
443 {
444     FIXME("(%p %p %p): stub\n", hwnd, pCab, pReserved);
445     return E_FAIL;
446 }
447
448 /***********************************************************************
449  *             SetPerUserSecValues    (ADVPACK.@)
450  *
451  * Prepares the per-user stub values under IsInstalled\{GUID} that
452  * control the per-user installation.
453  *
454  * PARAMS
455  *   pPerUser [I] Per-user stub values.
456  *
457  * RETURNS
458  *   Success: S_OK.
459  *   Failure: E_FAIL.
460  *
461  * BUGS
462  *   Unimplemented.
463  */
464 HRESULT WINAPI SetPerUserSecValues(PPERUSERSECTION pPerUser)
465 {
466     FIXME("(%p) stub\n", pPerUser);
467
468     return E_FAIL;
469 }
470
471 /***********************************************************************
472  *             TranslateInfString    (ADVPACK.@)
473  *
474  * Translates the value of a specified key in an inf file into the
475  * current locale by expanding string macros.
476  *
477  * PARAMS
478  *   pszInfFilename      [I] Filename of the inf file.
479  *   pszInstallSection   [I]
480  *   pszTranslateSection [I] Inf section where the key exists.
481  *   pszTranslateKey     [I] Key to translate.
482  *   pszBuffer           [O] Contains the translated string on exit.
483  *   dwBufferSize        [I] Size on input of pszBuffer.
484  *   pdwRequiredSize     [O] Length of the translated key.
485  *   pvReserved          [I] Reserved, must be NULL.
486  *
487  * RETURNS
488  *   Success: S_OK.
489  *   Failure: An hresult error code.
490  */
491 HRESULT WINAPI TranslateInfString(PCSTR pszInfFilename, PCSTR pszInstallSection,
492                 PCSTR pszTranslateSection, PCSTR pszTranslateKey, PSTR pszBuffer,
493                 DWORD dwBufferSize, PDWORD pdwRequiredSize, PVOID pvReserved)
494 {
495     HINF hInf;
496
497     TRACE("(%s %s %s %s %p %ld %p %p)\n",
498           debugstr_a(pszInfFilename), debugstr_a(pszInstallSection),
499           debugstr_a(pszTranslateSection), debugstr_a(pszTranslateKey),
500           pszBuffer, dwBufferSize,pdwRequiredSize, pvReserved);
501
502     if (!pszInfFilename || !pszTranslateSection ||
503         !pszTranslateKey || !pdwRequiredSize)
504         return E_INVALIDARG;
505
506     hInf = SetupOpenInfFileA(pszInfFilename, NULL, INF_STYLE_WIN4, NULL);
507     if (hInf == INVALID_HANDLE_VALUE)
508         return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
509
510     if (!SetupGetLineTextA(NULL, hInf, pszTranslateSection, pszTranslateKey,
511                            pszBuffer, dwBufferSize, pdwRequiredSize))
512     {
513         if (dwBufferSize < *pdwRequiredSize)
514             return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
515
516         return SPAPI_E_LINE_NOT_FOUND;
517     }
518
519     return S_OK;
520 }
521
522 /***********************************************************************
523  *             TranslateInfStringEx    (ADVPACK.@)
524  *
525  * Using a handle to an INF file opened with OpenINFEngine, translates
526  * the value of a specified key in an inf file into the current locale
527  * by expanding string macros.
528  *
529  * PARAMS
530  *   hInf                [I] Handle to the INF file.
531  *   pszInfFilename      [I] Filename of the INF file.
532  *   pszTranslateSection [I] Inf section where the key exists.
533  *   pszTranslateKey     [I] Key to translate.
534  *   pszBuffer           [O] Contains the translated string on exit.
535  *   dwBufferSize        [I] Size on input of pszBuffer.
536  *   pdwRequiredSize     [O] Length of the translated key.
537  *   pvReserved          [I] Reserved.  Must be NULL.
538  *
539  * RETURNS
540  *   Success: S_OK.
541  *   Failure: E_FAIL.
542  *
543  * NOTES
544  *   To use TranslateInfStringEx to translate an INF file continuously,
545  *   open the INF file with OpenINFEngine, call TranslateInfStringEx as
546  *   many times as needed, then release the handle with CloseINFEngine.
547  *   When translating more than one keys, this method is more efficient
548  *   than calling TranslateInfString, because the INF file is only
549  *   opened once.
550  *
551  * BUGS
552  *   Unimplemented.
553  */
554 HRESULT WINAPI TranslateInfStringEx(HINF hInf, PCSTR pszInfFilename,
555                                     PCSTR pszTranslateSection, PCSTR pszTranslateKey,
556                                     PSTR pszBuffer, DWORD dwBufferSize,
557                                     PDWORD pdwRequiredSize, PVOID pvReserved)
558 {
559     FIXME("(%p, %p, %p, %p, %p, %ld, %p, %p) stub\n", hInf, pszInfFilename,
560           pszTranslateSection, pszTranslateKey, pszBuffer, dwBufferSize,
561           pdwRequiredSize, pvReserved);
562
563     return E_FAIL;   
564 }
565
566 /***********************************************************************
567  *             UserInstStubWrapper    (ADVPACK.@)
568  */
569 HRESULT WINAPI UserInstStubWrapper(HWND hWnd, HINSTANCE hInstance,
570                                    PSTR pszParms, INT nShow)
571 {
572     FIXME("(%p, %p, %p, %i) stub\n", hWnd, hInstance, pszParms, nShow);
573
574     return E_FAIL;
575 }
576
577 /***********************************************************************
578  *             UserUnInstStubWrapper    (ADVPACK.@)
579  */
580 HRESULT WINAPI UserUnInstStubWrapper(HWND hWnd, HINSTANCE hInstance,
581                                      PSTR pszParms, INT nShow)
582 {
583     FIXME("(%p, %p, %p, %i) stub\n", hWnd, hInstance, pszParms, nShow);
584
585     return E_FAIL;
586 }