Stub implementations for functions handling paged search results.
[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  *      AdvInstallFile (ADVPACK.@)
41  *
42  * Copies a file from the source to a destination.
43  *
44  * PARAMS
45  *   hwnd           [I] Handle to the window used for messages.
46  *   lpszSourceDir  [I] Source directory.
47  *   lpszSourceFile [I] Source filename.
48  *   lpszDestDir    [I] Destination directory.
49  *   lpszDestFile   [I] Optional destination filename.
50  *   dwFlags        [I] See advpub.h.
51  *   dwReserved     [I] Reserved.  Must be 0.
52  *
53  * RETURNS
54  *   Success: S_OK.
55  *   Failure: E_FAIL.
56  *
57  * NOTES
58  *   If lpszDestFile is NULL, the destination filename is the same as
59  *   lpszSourceFIle.
60  *
61  * BUGS
62  *   Unimplemented.
63  */
64 HRESULT WINAPI AdvInstallFile(HWND hwnd, LPCSTR lpszSourceDir, LPCSTR lpszSourceFile,
65                               LPCSTR lpszDestDir, LPCSTR lpszDestFile,
66                               DWORD dwFlags, DWORD dwReserved)
67 {
68     FIXME("(%p,%p,%p,%p,%p,%ld,%ld) stub\n", hwnd, debugstr_a(lpszSourceDir),
69           debugstr_a(lpszSourceFile), debugstr_a(lpszDestDir),
70           debugstr_a(lpszDestFile), dwFlags, dwReserved);
71     return E_FAIL;
72 }
73
74 /***********************************************************************
75  *           DllMain (ADVPACK.@)
76  */
77 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
78 {
79     TRACE("(%p, %ld, %p)\n",hinstDLL, fdwReason, lpvReserved);
80
81     if (fdwReason == DLL_PROCESS_ATTACH)
82         DisableThreadLibraryCalls(hinstDLL);
83
84     return TRUE;
85 }
86
87 /***********************************************************************
88  *              RunSetupCommand  (ADVPACK.@)
89  *
90  * Executes an install section in an INF file or a program.
91  *
92  * PARAMS
93  *   hWnd          [I] Handle to parent window, NULL for quiet mode
94  *   szCmdName     [I] Inf or EXE filename to execute
95  *   szInfSection  [I] Inf section to install, NULL for DefaultInstall
96  *   szDir         [I] Path to extracted files
97  *   szTitle       [I] Title of all dialogs
98  *   phEXE         [O] Handle of EXE to wait for
99  *   dwFlags       [I] Flags; see include/advpub.h
100  *   pvReserved    [I] Reserved
101  *
102  * RETURNS
103  *   S_OK                                 Everything OK
104  *   S_ASYNCHRONOUS                       OK, required to wait on phEXE
105  *   ERROR_SUCCESS_REBOOT_REQUIRED        Reboot required
106  *   E_INVALIDARG                         Invalid argument given
107  *   HRESULT_FROM_WIN32(ERROR_OLD_WIN_VERSION)
108  *                                        Not supported on this Windows version
109  *   E_UNEXPECTED                         Unexpected error
110  *   HRESULT_FROM_WIN32(GetLastError())   Some other error
111  *
112  * BUGS
113  *   Unimplemented
114  */
115 HRESULT WINAPI RunSetupCommand( HWND hWnd, LPCSTR szCmdName,
116                                 LPCSTR szInfSection, LPCSTR szDir,
117                                 LPCSTR lpszTitle, HANDLE *phEXE,
118                                 DWORD dwFlags, LPVOID pvReserved )
119 {
120     FIXME("(%p, %s, %s, %s, %s, %p, 0x%08lx, %p): stub\n",
121            hWnd, debugstr_a(szCmdName), debugstr_a(szInfSection),
122            debugstr_a(szDir), debugstr_a(lpszTitle),
123            phEXE, dwFlags, pvReserved);
124     return E_UNEXPECTED;
125 }
126
127 /***********************************************************************
128  *              LaunchINFSection  (ADVPACK.@)
129  */
130 INT WINAPI LaunchINFSection( HWND hWnd, HINSTANCE hInst, LPSTR cmdline, INT show )
131 {
132     FIXME("(%p %p %s %d): stub\n", hWnd, hInst, debugstr_a(cmdline), show );
133     return 0;
134 }
135
136 /***********************************************************************
137  *              LaunchINFSectionEx  (ADVPACK.@)
138  */
139 HRESULT WINAPI LaunchINFSectionEx( HWND hWnd, HINSTANCE hInst, LPSTR cmdline, INT show )
140 {
141     FIXME("(%p %p %s %d): stub\n", hWnd, hInst, debugstr_a(cmdline), show );
142     return E_FAIL;
143 }
144
145 /* this structure very closely resembles parameters of RunSetupCommand() */
146 typedef struct
147 {
148     HWND hwnd;
149     LPCSTR title;
150     LPCSTR inf_name;
151     LPCSTR dir;
152     LPCSTR section_name;
153 } SETUPCOMMAND_PARAMS;
154
155 /***********************************************************************
156  *              DoInfInstall  (ADVPACK.@)
157  */
158 BOOL WINAPI DoInfInstall(const SETUPCOMMAND_PARAMS *setup)
159 {
160     BOOL ret;
161     HINF hinf;
162     void *callback_context;
163
164     TRACE("%p %s %s %s %s\n", setup->hwnd, debugstr_a(setup->title),
165           debugstr_a(setup->inf_name), debugstr_a(setup->dir),
166           debugstr_a(setup->section_name));
167
168     hinf = SetupOpenInfFileA(setup->inf_name, NULL, INF_STYLE_WIN4, NULL);
169     if (hinf == INVALID_HANDLE_VALUE) return FALSE;
170
171     callback_context = SetupInitDefaultQueueCallback(setup->hwnd);
172
173     ret = SetupInstallFromInfSectionA(NULL, hinf, setup->section_name, SPINST_ALL,
174                                       NULL, NULL, 0, SetupDefaultQueueCallbackA,
175                                       callback_context, NULL, NULL);
176     SetupTermDefaultQueueCallback(callback_context);
177     SetupCloseInfFile(hinf);
178
179     return ret;
180 }
181
182 /***********************************************************************
183  *              IsNTAdmin       (ADVPACK.@)
184  */
185 BOOL WINAPI IsNTAdmin( DWORD reserved, LPDWORD pReserved )
186 {
187     FIXME("(0x%08lx, %p): stub\n", reserved, pReserved);
188     return TRUE;
189 }
190
191 /***********************************************************************
192  *             NeedRebootInit  (ADVPACK.@)
193  */
194 DWORD WINAPI NeedRebootInit(VOID)
195 {
196     FIXME("(): stub\n");
197     return 0;
198 }
199
200 /***********************************************************************
201  *             NeedReboot      (ADVPACK.@)
202  */
203 BOOL WINAPI NeedReboot(DWORD dwRebootCheck)
204 {
205     FIXME("(0x%08lx): stub\n", dwRebootCheck);
206     return FALSE;
207 }
208
209 /***********************************************************************
210  *             GetVersionFromFile      (ADVPACK.@)
211  */
212 HRESULT WINAPI GetVersionFromFile( LPSTR Filename, LPDWORD MajorVer,
213                                    LPDWORD MinorVer, BOOL Version )
214 {
215     TRACE("(%s, %p, %p, %d)\n", Filename, MajorVer, MinorVer, Version);
216     return GetVersionFromFileEx(Filename, MajorVer, MinorVer, Version);
217 }
218
219 /* data for GetVersionFromFileEx */
220 typedef struct tagLANGANDCODEPAGE
221 {
222     WORD wLanguage;
223     WORD wCodePage;
224 } LANGANDCODEPAGE;
225
226 /***********************************************************************
227  *             GetVersionFromFileEx    (ADVPACK.@)
228  */
229 HRESULT WINAPI GetVersionFromFileEx( LPSTR lpszFilename, LPDWORD pdwMSVer,
230                                      LPDWORD pdwLSVer, BOOL bVersion )
231 {
232     VS_FIXEDFILEINFO *pFixedVersionInfo;
233     LANGANDCODEPAGE *pLangAndCodePage;
234     DWORD dwHandle, dwInfoSize;
235     CHAR szWinDir[MAX_PATH];
236     CHAR szFile[MAX_PATH];
237     LPVOID pVersionInfo = NULL;
238     BOOL bFileCopied = FALSE;
239     UINT uValueLen;
240
241     TRACE("(%s, %p, %p, %d)\n", lpszFilename, pdwMSVer, pdwLSVer, bVersion);
242
243     *pdwLSVer = 0;
244     *pdwMSVer = 0;
245
246     lstrcpynA(szFile, lpszFilename, MAX_PATH);
247
248     dwInfoSize = GetFileVersionInfoSizeA(szFile, &dwHandle);
249     if (!dwInfoSize)
250     {
251         /* check that the file exists */
252         if (GetFileAttributesA(szFile) == INVALID_FILE_ATTRIBUTES)
253             return S_OK;
254
255         /* file exists, but won't be found by GetFileVersionInfoSize,
256         * so copy it to the temp dir where it will be found.
257         */
258         GetWindowsDirectoryA(szWinDir, MAX_PATH);
259         GetTempFileNameA(szWinDir, NULL, 0, szFile);
260         CopyFileA(lpszFilename, szFile, FALSE);
261         bFileCopied = TRUE;
262
263         dwInfoSize = GetFileVersionInfoSizeA(szFile, &dwHandle);
264         if (!dwInfoSize)
265             goto done;
266     }
267
268     pVersionInfo = HeapAlloc(GetProcessHeap(), 0, dwInfoSize);
269     if (!pVersionInfo)
270         goto done;
271
272     if (!GetFileVersionInfoA(szFile, dwHandle, dwInfoSize, pVersionInfo))
273         goto done;
274
275     if (bVersion)
276     {
277         if (!VerQueryValueA(pVersionInfo, "\\",
278             (LPVOID *)&pFixedVersionInfo, &uValueLen))
279             goto done;
280
281         if (!uValueLen)
282             goto done;
283
284         *pdwMSVer = pFixedVersionInfo->dwFileVersionMS;
285         *pdwLSVer = pFixedVersionInfo->dwFileVersionLS;
286     }
287     else
288     {
289         if (!VerQueryValueA(pVersionInfo, "\\VarFileInfo\\Translation",
290              (LPVOID *)&pLangAndCodePage, &uValueLen))
291             goto done;
292
293         if (!uValueLen)
294             goto done;
295
296         *pdwMSVer = pLangAndCodePage->wLanguage;
297         *pdwLSVer = pLangAndCodePage->wCodePage;
298     }
299
300 done:
301     HeapFree(GetProcessHeap(), 0, pVersionInfo);
302
303     if (bFileCopied)
304         DeleteFileA(szFile);
305
306     return S_OK;
307 }
308
309 /***********************************************************************
310  *             RegisterOCX    (ADVPACK.@)
311  */
312 void WINAPI RegisterOCX( HWND hWnd, HINSTANCE hInst, LPCSTR cmdline, INT show )
313 {
314     WCHAR wszBuff[MAX_PATH];
315     WCHAR* pwcComma;
316     HMODULE hm;
317     DLLREGISTER pfnRegister;
318     HRESULT hr;
319
320     TRACE("(%s)\n", cmdline);
321
322     MultiByteToWideChar(CP_ACP, 0, cmdline, strlen(cmdline), wszBuff, MAX_PATH);
323     if ((pwcComma = strchrW( wszBuff, ',' ))) *pwcComma = 0;
324
325     TRACE("Parsed DLL name (%s)\n", debugstr_w(wszBuff));
326
327     hm = LoadLibraryExW(wszBuff, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
328     if (!hm)
329     {
330         ERR("Couldn't load DLL: %s\n", debugstr_w(wszBuff));
331         return;
332     }
333
334     pfnRegister = (DLLREGISTER)GetProcAddress(hm, "DllRegisterServer");
335     if (pfnRegister == NULL)
336     {
337         ERR("DllRegisterServer entry point not found\n");
338     }
339     else
340     {
341         hr = pfnRegister();
342         if (hr != S_OK)
343         {
344             ERR("DllRegisterServer entry point returned %08lx\n", hr);
345         }
346     }
347
348     TRACE("Successfully registered OCX\n");
349
350     FreeLibrary(hm);
351 }
352
353 static HRESULT DELNODE_recurse_dirtree(LPSTR fname, DWORD flags)
354 {
355     DWORD fattrs = GetFileAttributesA(fname);
356     HRESULT ret = E_FAIL;
357
358     if (fattrs & FILE_ATTRIBUTE_DIRECTORY)
359     {
360         HANDLE hFindFile;
361         WIN32_FIND_DATAA w32fd;
362         BOOL done = TRUE;
363         int fname_len = lstrlenA(fname);
364
365         /* Generate a path with wildcard suitable for iterating */
366         if (CharPrevA(fname, fname + fname_len) != "\\")
367         {
368             lstrcpyA(fname + fname_len, "\\");
369             ++fname_len;
370         }
371         lstrcpyA(fname + fname_len, "*");
372
373         if ((hFindFile = FindFirstFileA(fname, &w32fd)) != INVALID_HANDLE_VALUE)
374         {
375             /* Iterate through the files in the directory */
376             for (done = FALSE; !done; done = !FindNextFileA(hFindFile, &w32fd))
377             {
378                 TRACE("%s\n", w32fd.cFileName);
379                 if (lstrcmpA(".", w32fd.cFileName) != 0 &&
380                     lstrcmpA("..", w32fd.cFileName) != 0)
381                 {
382                     lstrcpyA(fname + fname_len, w32fd.cFileName);
383                     if (DELNODE_recurse_dirtree(fname, flags) != S_OK)
384                     {
385                         break; /* Failure */
386                     }
387                 }
388             }
389             FindClose(hFindFile);
390         }
391
392         /* We're done with this directory, so restore the old path without wildcard */
393         *(fname + fname_len) = '\0';
394
395         if (done)
396         {
397             TRACE("%s: directory\n", fname);
398             if (SetFileAttributesA(fname, FILE_ATTRIBUTE_NORMAL) && RemoveDirectoryA(fname))
399             {
400                 ret = S_OK;
401             }
402         }
403     }
404     else
405     {
406         TRACE("%s: file\n", fname);
407         if (SetFileAttributesA(fname, FILE_ATTRIBUTE_NORMAL) && DeleteFileA(fname))
408         {
409             ret = S_OK;
410         }
411     }
412     
413     return ret;
414 }
415
416 /***********************************************************************
417  *              DelNode    (ADVPACK.@)
418  *
419  * Deletes a file or directory
420  *
421  * PARAMS
422  *   pszFileOrDirName   [I] Name of file or directory to delete
423  *   dwFlags            [I] Flags; see include/advpub.h
424  *
425  * RETURNS 
426  *   Success: S_OK
427  *   Failure: E_FAIL
428  *
429  * BUGS
430  *   - Ignores flags
431  *   - Native version apparently does a lot of checking to make sure
432  *     we're not trying to delete a system directory etc.
433  */
434 HRESULT WINAPI DelNode( LPCSTR pszFileOrDirName, DWORD dwFlags )
435 {
436     CHAR fname[MAX_PATH];
437     HRESULT ret = E_FAIL;
438
439     FIXME("(%s, 0x%08lx): flags ignored\n", debugstr_a(pszFileOrDirName), dwFlags);
440     if (pszFileOrDirName && *pszFileOrDirName)
441     {
442         lstrcpyA(fname, pszFileOrDirName);
443
444         /* TODO: Should check for system directory deletion etc. here */
445
446         ret = DELNODE_recurse_dirtree(fname, dwFlags);
447     }
448
449     return ret;
450 }
451
452 /***********************************************************************
453  *             DelNodeRunDLL32    (ADVPACK.@)
454  *
455  * BUGS
456  *   Unimplemented
457  */
458 HRESULT WINAPI DelNodeRunDLL32( HWND hWnd, HINSTANCE hInst, LPSTR cmdline, INT show )
459 {
460     FIXME("(%s): stub\n", debugstr_a(cmdline));
461     return E_FAIL;
462 }
463
464 /***********************************************************************
465  *             ExecuteCab    (ADVPACK.@)
466  *
467  * BUGS
468  *   Unimplemented
469  */
470 HRESULT WINAPI ExecuteCab( HWND hwnd, PCABINFO pCab, LPVOID pReserved )
471 {
472     FIXME("(%p %p %p): stub\n", hwnd, pCab, pReserved);
473     return E_FAIL;
474 }
475
476 /***********************************************************************
477  *             ExtractFiles    (ADVPACK.@)
478  *
479  * BUGS
480  *   Unimplemented
481  */
482
483 HRESULT WINAPI ExtractFiles ( LPCSTR CabName, LPCSTR ExpandDir, DWORD Flags,
484                               LPCSTR FileList, LPVOID LReserved, DWORD Reserved)
485 {
486     FIXME("(%p %p 0x%08lx %p %p 0x%08lx): stub\n", CabName, ExpandDir, Flags, 
487           FileList, LReserved, Reserved);
488     return E_FAIL;
489 }
490
491 /***********************************************************************
492  *             TranslateInfString    (ADVPACK.@)
493  *
494  * Translates the value of a specified key in an inf file into the
495  * current locale by expanding string macros.
496  *
497  * PARAMS
498  *   pszInfFilename      [I] Filename of the inf file.
499  *   pszInstallSection   [I]
500  *   pszTranslateSection [I] Inf section where the key exists.
501  *   pszTranslateKey     [I] Key to translate.
502  *   pszBuffer           [O] Contains the translated string on exit.
503  *   dwBufferSize        [I] Size on input of pszBuffer.
504  *   pdwRequiredSize     [O] Length of the translated key.
505  *   pvReserved          [I] Reserved, must be NULL.
506  *
507  * RETURNS
508  *   Success: S_OK.
509  *   Failure: An hresult error code.
510  */
511 HRESULT WINAPI TranslateInfString(PCSTR pszInfFilename, PCSTR pszInstallSection,
512                 PCSTR pszTranslateSection, PCSTR pszTranslateKey, PSTR pszBuffer,
513                 DWORD dwBufferSize, PDWORD pdwRequiredSize, PVOID pvReserved)
514 {
515     HINF hInf;
516
517     TRACE("(%s %s %s %s %p %ld %p %p)\n",
518           debugstr_a(pszInfFilename), debugstr_a(pszInstallSection),
519           debugstr_a(pszTranslateSection), debugstr_a(pszTranslateKey),
520           pszBuffer, dwBufferSize,pdwRequiredSize, pvReserved);
521
522     if (!pszInfFilename || !pszTranslateSection ||
523         !pszTranslateKey || !pdwRequiredSize)
524         return E_INVALIDARG;
525
526     hInf = SetupOpenInfFileA(pszInfFilename, NULL, INF_STYLE_WIN4, NULL);
527     if (hInf == INVALID_HANDLE_VALUE)
528         return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
529
530     if (!SetupGetLineTextA(NULL, hInf, pszTranslateSection, pszTranslateKey,
531                            pszBuffer, dwBufferSize, pdwRequiredSize))
532     {
533         if (dwBufferSize < *pdwRequiredSize)
534             return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
535
536         return SPAPI_E_LINE_NOT_FOUND;
537     }
538
539     return S_OK;
540 }