Allow mapi32 tests to load and exit gracefully if mapi32.dll isn't
[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 /***********************************************************************
41  *           DllMain (ADVPACK.@)
42  */
43 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
44 {
45     TRACE("(%p, %ld, %p)\n",hinstDLL, fdwReason, lpvReserved);
46
47     if (fdwReason == DLL_PROCESS_ATTACH)
48         DisableThreadLibraryCalls(hinstDLL);
49
50     return TRUE;
51 }
52
53 /***********************************************************************
54  *              RunSetupCommand  (ADVPACK.@)
55  *
56  * Executes an install section in an INF file or a program.
57  *
58  * PARAMS
59  *   hWnd          [I] Handle to parent window, NULL for quiet mode
60  *   szCmdName     [I] Inf or EXE filename to execute
61  *   szInfSection  [I] Inf section to install, NULL for DefaultInstall
62  *   szDir         [I] Path to extracted files
63  *   szTitle       [I] Title of all dialogs
64  *   phEXE         [O] Handle of EXE to wait for
65  *   dwFlags       [I] Flags; see include/advpub.h
66  *   pvReserved    [I] Reserved
67  *
68  * RETURNS
69  *   S_OK                                 Everything OK
70  *   S_ASYNCHRONOUS                       OK, required to wait on phEXE
71  *   ERROR_SUCCESS_REBOOT_REQUIRED        Reboot required
72  *   E_INVALIDARG                         Invalid argument given
73  *   HRESULT_FROM_WIN32(ERROR_OLD_WIN_VERSION)
74  *                                        Not supported on this Windows version
75  *   E_UNEXPECTED                         Unexpected error
76  *   HRESULT_FROM_WIN32(GetLastError())   Some other error
77  *
78  * BUGS
79  *   Unimplemented
80  */
81 HRESULT WINAPI RunSetupCommand( HWND hWnd, LPCSTR szCmdName,
82                                 LPCSTR szInfSection, LPCSTR szDir,
83                                 LPCSTR lpszTitle, HANDLE *phEXE,
84                                 DWORD dwFlags, LPVOID pvReserved )
85 {
86     FIXME("(%p, %s, %s, %s, %s, %p, 0x%08lx, %p): stub\n",
87            hWnd, debugstr_a(szCmdName), debugstr_a(szInfSection),
88            debugstr_a(szDir), debugstr_a(lpszTitle),
89            phEXE, dwFlags, pvReserved);
90     return E_UNEXPECTED;
91 }
92
93 /***********************************************************************
94  *              LaunchINFSection  (ADVPACK.@)
95  */
96 void WINAPI LaunchINFSection( HWND hWnd, HINSTANCE hInst, LPCSTR cmdline, INT show )
97 {
98     FIXME("(%p %p %s %d): stub\n", hWnd, hInst, debugstr_a(cmdline), show );
99 }
100
101 /***********************************************************************
102  *              LaunchINFSectionEx  (ADVPACK.@)
103  */
104 void WINAPI LaunchINFSectionEx( HWND hWnd, HINSTANCE hInst, LPCSTR cmdline, INT show )
105 {
106     FIXME("(%p %p %s %d): stub\n", hWnd, hInst, debugstr_a(cmdline), show );
107 }
108
109 /* this structure very closely resembles parameters of RunSetupCommand() */
110 typedef struct
111 {
112     HWND hwnd;
113     LPCSTR title;
114     LPCSTR inf_name;
115     LPCSTR dir;
116     LPCSTR section_name;
117 } SETUPCOMMAND_PARAMS;
118
119 /***********************************************************************
120  *              DoInfInstall  (ADVPACK.@)
121  */
122 BOOL WINAPI DoInfInstall(const SETUPCOMMAND_PARAMS *setup)
123 {
124     BOOL ret;
125     HINF hinf;
126     void *callback_context;
127
128     TRACE("%p %s %s %s %s\n", setup->hwnd, debugstr_a(setup->title),
129           debugstr_a(setup->inf_name), debugstr_a(setup->dir),
130           debugstr_a(setup->section_name));
131
132     hinf = SetupOpenInfFileA(setup->inf_name, NULL, INF_STYLE_WIN4, NULL);
133     if (hinf == INVALID_HANDLE_VALUE) return FALSE;
134
135     callback_context = SetupInitDefaultQueueCallback(setup->hwnd);
136
137     ret = SetupInstallFromInfSectionA(NULL, hinf, setup->section_name, SPINST_ALL,
138                                       NULL, NULL, 0, SetupDefaultQueueCallbackA,
139                                       callback_context, NULL, NULL);
140     SetupTermDefaultQueueCallback(callback_context);
141     SetupCloseInfFile(hinf);
142
143     return ret;
144 }
145
146 /***********************************************************************
147  *              IsNTAdmin       (ADVPACK.@)
148  */
149 BOOL WINAPI IsNTAdmin( DWORD reserved, PDWORD pReserved )
150 {
151     FIXME("(0x%08lx, %p): stub\n", reserved, pReserved);
152     return TRUE;
153 }
154
155 /***********************************************************************
156  *             NeedRebootInit  (ADVPACK.@)
157  */
158 DWORD WINAPI NeedRebootInit(VOID)
159 {
160     FIXME("(): stub\n");
161     return 0;
162 }
163
164 /***********************************************************************
165  *             NeedReboot      (ADVPACK.@)
166  */
167 BOOL WINAPI NeedReboot(DWORD dwRebootCheck)
168 {
169     FIXME("(0x%08lx): stub\n", dwRebootCheck);
170     return FALSE;
171 }
172
173 /***********************************************************************
174  *             GetVersionFromFile      (ADVPACK.@)
175  */
176 HRESULT WINAPI GetVersionFromFile( LPSTR Filename, LPDWORD MajorVer,
177                                    LPDWORD MinorVer, BOOL Version )
178 {
179     TRACE("(%s, %p, %p, %d)\n", Filename, MajorVer, MinorVer, Version);
180     return GetVersionFromFileEx(Filename, MajorVer, MinorVer, Version);
181 }
182
183 /***********************************************************************
184  *             GetVersionFromFileEx    (ADVPACK.@)
185  */
186 HRESULT WINAPI GetVersionFromFileEx( LPSTR lpszFilename, LPDWORD pdwMSVer,
187                                      LPDWORD pdwLSVer, BOOL bVersion )
188 {
189     DWORD hdl, retval;
190     LPVOID pVersionInfo;
191     BOOL boolret;
192     VS_FIXEDFILEINFO *pFixedVersionInfo;
193     UINT uiLength;
194     TRACE("(%s, %p, %p, %d)\n", lpszFilename, pdwMSVer, pdwLSVer, bVersion);
195
196     if (bVersion)
197     {
198         retval = GetFileVersionInfoSizeA(lpszFilename, &hdl);
199         if (retval == 0 || hdl != 0)
200             return E_FAIL;
201
202         pVersionInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, retval);
203         if (pVersionInfo == NULL)
204              return E_FAIL;
205         GetFileVersionInfoA( lpszFilename, 0, retval, pVersionInfo);
206
207         boolret = VerQueryValueA(pVersionInfo, "\\",
208                                  (LPVOID) &pFixedVersionInfo, &uiLength);
209
210         HeapFree(GetProcessHeap(), 0, pVersionInfo);
211
212         if (boolret)
213         {
214             *pdwMSVer = pFixedVersionInfo->dwFileVersionMS;
215             *pdwLSVer = pFixedVersionInfo->dwFileVersionLS;
216         }
217         else
218             return E_FAIL;
219     }
220     else
221     {
222         *pdwMSVer = GetUserDefaultUILanguage();
223         *pdwLSVer = GetACP();
224     }
225
226     return S_OK;
227 }
228
229 /***********************************************************************
230  *             RegisterOCX    (ADVPACK.@)
231  */
232 void WINAPI RegisterOCX( HWND hWnd, HINSTANCE hInst, LPCSTR cmdline, INT show )
233 {
234     WCHAR wszBuff[MAX_PATH];
235     WCHAR* pwcComma;
236     HMODULE hm;
237     DLLREGISTER pfnRegister;
238     HRESULT hr;
239
240     TRACE("(%s)\n", cmdline);
241
242     MultiByteToWideChar(CP_ACP, 0, cmdline, strlen(cmdline), wszBuff, MAX_PATH);
243     if ((pwcComma = strchrW( wszBuff, ',' ))) *pwcComma = 0;
244
245     TRACE("Parsed DLL name (%s)\n", debugstr_w(wszBuff));
246
247     hm = LoadLibraryExW(wszBuff, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
248     if (!hm)
249     {
250         ERR("Couldn't load DLL: %s\n", debugstr_w(wszBuff));
251         return;
252     }
253
254     pfnRegister = (DLLREGISTER)GetProcAddress(hm, "DllRegisterServer");
255     if (pfnRegister == NULL)
256     {
257         ERR("DllRegisterServer entry point not found\n");
258     }
259     else
260     {
261         hr = pfnRegister();
262         if (hr != S_OK)
263         {
264             ERR("DllRegisterServer entry point returned %08lx\n", hr);
265         }
266     }
267
268     TRACE("Successfully registered OCX\n");
269
270     FreeLibrary(hm);
271 }
272
273 static HRESULT DELNODE_recurse_dirtree(LPSTR fname, DWORD flags)
274 {
275     DWORD fattrs = GetFileAttributesA(fname);
276     HRESULT ret = E_FAIL;
277
278     if (fattrs & FILE_ATTRIBUTE_DIRECTORY)
279     {
280         HANDLE hFindFile;
281         WIN32_FIND_DATAA w32fd;
282         BOOL done = TRUE;
283         int fname_len = lstrlenA(fname);
284
285         /* Generate a path with wildcard suitable for iterating */
286         if (CharPrevA(fname, fname + fname_len) != "\\")
287         {
288             lstrcpyA(fname + fname_len, "\\");
289             ++fname_len;
290         }
291         lstrcpyA(fname + fname_len, "*");
292
293         if ((hFindFile = FindFirstFileA(fname, &w32fd)) != INVALID_HANDLE_VALUE)
294         {
295             /* Iterate through the files in the directory */
296             for (done = FALSE; !done; done = !FindNextFileA(hFindFile, &w32fd))
297             {
298                 TRACE("%s\n", w32fd.cFileName);
299                 if (lstrcmpA(".", w32fd.cFileName) != 0 &&
300                     lstrcmpA("..", w32fd.cFileName) != 0)
301                 {
302                     lstrcpyA(fname + fname_len, w32fd.cFileName);
303                     if (DELNODE_recurse_dirtree(fname, flags) != S_OK)
304                     {
305                         break; /* Failure */
306                     }
307                 }
308             }
309             FindClose(hFindFile);
310         }
311
312         /* We're done with this directory, so restore the old path without wildcard */
313         *(fname + fname_len) = '\0';
314
315         if (done)
316         {
317             TRACE("%s: directory\n", fname);
318             if (SetFileAttributesA(fname, FILE_ATTRIBUTE_NORMAL) && RemoveDirectoryA(fname))
319             {
320                 ret = S_OK;
321             }
322         }
323     }
324     else
325     {
326         TRACE("%s: file\n", fname);
327         if (SetFileAttributesA(fname, FILE_ATTRIBUTE_NORMAL) && DeleteFileA(fname))
328         {
329             ret = S_OK;
330         }
331     }
332     
333     return ret;
334 }
335
336 /***********************************************************************
337  *              DelNode    (ADVPACK.@)
338  *
339  * Deletes a file or directory
340  *
341  * PARAMS
342  *   pszFileOrDirName   [I] Name of file or directory to delete
343  *   dwFlags            [I] Flags; see include/advpub.h
344  *
345  * RETURNS 
346  *   Success: S_OK
347  *   Failure: E_FAIL
348  *
349  * BUGS
350  *   - Ignores flags
351  *   - Native version apparently does a lot of checking to make sure
352  *     we're not trying to delete a system directory etc.
353  */
354 HRESULT WINAPI DelNode( LPCSTR pszFileOrDirName, DWORD dwFlags )
355 {
356     CHAR fname[MAX_PATH];
357     HRESULT ret = E_FAIL;
358
359     FIXME("(%s, 0x%08lx): flags ignored\n", debugstr_a(pszFileOrDirName), dwFlags);
360     if (pszFileOrDirName && *pszFileOrDirName)
361     {
362         lstrcpyA(fname, pszFileOrDirName);
363
364         /* TODO: Should check for system directory deletion etc. here */
365
366         ret = DELNODE_recurse_dirtree(fname, dwFlags);
367     }
368
369     return ret;
370 }
371
372 /***********************************************************************
373  *             DelNodeRunDLL32    (ADVPACK.@)
374  *
375  * BUGS
376  *   Unimplemented
377  */
378 void WINAPI DelNodeRunDLL32( HWND hWnd, HINSTANCE hInst, LPCSTR cmdline, INT show )
379 {
380     FIXME("(%s): stub\n", debugstr_a(cmdline));
381 }
382
383 /***********************************************************************
384  *             ExecuteCab    (ADVPACK.@)
385  *
386  * BUGS
387  *   Unimplemented
388  */
389 HRESULT WINAPI ExecuteCab( HWND hwnd, PCABINFO pCab, LPVOID pReserved )
390 {
391     FIXME("(%p %p %p): stub\n", hwnd, pCab, pReserved);
392     return E_FAIL;
393 }
394
395 /***********************************************************************
396  *             TranslateInfString    (ADVPACK.@)
397  *
398  * BUGS
399  *   Unimplemented
400  */
401 HRESULT WINAPI TranslateInfString(PCSTR pszInfFilename, PCSTR pszInstallSection,
402                 PCSTR pszTranslateSection, PCSTR pszTranslateKey, PSTR pszBuffer,
403                 DWORD dwBufferSize, PDWORD pdwRequiredSize, PVOID pvReserved)
404 {
405     FIXME("(%s %s %s %s %p %ld %p %p): stub\n",
406         debugstr_a(pszInfFilename), debugstr_a(pszInstallSection),
407         debugstr_a(pszTranslateSection), debugstr_a(pszTranslateKey),
408         pszBuffer, dwBufferSize,pdwRequiredSize, pvReserved);
409     return E_FAIL;
410 }