Added more implementation of IDocumentView.
[wine] / dlls / msi / msi.c
1 /*
2  * Implementation of the Microsoft Installer (msi.dll)
3  *
4  * Copyright 2002,2003,2004,2005 Mike McCormack for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <stdarg.h>
22
23 #define COBJMACROS
24 #define NONAMELESSUNION
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "winnls.h"
30 #include "shlwapi.h"
31 #include "wine/debug.h"
32 #include "msi.h"
33 #include "msiquery.h"
34 #include "msipriv.h"
35 #include "wincrypt.h"
36 #include "winver.h"
37 #include "winuser.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(msi);
40
41 /*
42  * The MSVC headers define the MSIDBOPEN_* macros cast to LPCTSTR,
43  *  which is a problem because LPCTSTR isn't defined when compiling wine.
44  * To work around this problem, we need to define LPCTSTR as LPCWSTR here,
45  *  and make sure to only use it in W functions.
46  */
47 #define LPCTSTR LPCWSTR
48
49 /* the UI level */
50 INSTALLUILEVEL gUILevel = INSTALLUILEVEL_BASIC;
51 HWND           gUIhwnd = 0;
52 INSTALLUI_HANDLERA gUIHandlerA = NULL;
53 INSTALLUI_HANDLERW gUIHandlerW = NULL;
54 DWORD gUIFilter = 0;
55 LPVOID gUIContext = NULL;
56 WCHAR gszLogFile[MAX_PATH];
57 HINSTANCE msi_hInstance;
58
59 UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct)
60 {
61     UINT r;
62     LPWSTR szwProd = NULL;
63
64     TRACE("%s %p\n",debugstr_a(szProduct), phProduct);
65
66     if( szProduct )
67     {
68         szwProd = strdupAtoW( szProduct );
69         if( !szwProd )
70             return ERROR_OUTOFMEMORY;
71     }
72
73     r = MsiOpenProductW( szwProd, phProduct );
74
75     HeapFree( GetProcessHeap(), 0, szwProd );
76
77     return r;
78 }
79
80 UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct)
81 {
82     static const WCHAR szLocalPackage[] = {
83         'L','o','c','a','l','P','a','c','k','a','g','e', 0
84     };
85     LPWSTR path = NULL;
86     UINT r;
87     HKEY hKeyProduct = NULL;
88     DWORD count, type;
89
90     TRACE("%s %p\n",debugstr_w(szProduct), phProduct);
91
92     r = MSIREG_OpenUninstallKey(szProduct,&hKeyProduct,FALSE);
93     if( r != ERROR_SUCCESS )
94     {
95         r = ERROR_UNKNOWN_PRODUCT;
96         goto end;
97     }
98
99     /* find the size of the path */
100     type = count = 0;
101     r = RegQueryValueExW( hKeyProduct, szLocalPackage,
102                           NULL, &type, NULL, &count );
103     if( r != ERROR_SUCCESS )
104     {
105         r = ERROR_UNKNOWN_PRODUCT;
106         goto end;
107     }
108
109     /* now alloc and fetch the path of the database to open */
110     path = HeapAlloc( GetProcessHeap(), 0, count );
111     if( !path )
112         goto end;
113
114     r = RegQueryValueExW( hKeyProduct, szLocalPackage,
115                           NULL, &type, (LPBYTE) path, &count );
116     if( r != ERROR_SUCCESS )
117     {
118         r = ERROR_UNKNOWN_PRODUCT;
119         goto end;
120     }
121
122     r = MsiOpenPackageW( path, phProduct );
123
124 end:
125     HeapFree( GetProcessHeap(), 0, path );
126     if( hKeyProduct )
127         RegCloseKey( hKeyProduct );
128
129     return r;
130 }
131
132 UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
133                 LPCSTR szTransforms, LANGID lgidLanguage)
134 {
135     FIXME("%s %s %s %08x\n",debugstr_a(szPackagePath),
136           debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage);
137     return ERROR_CALL_NOT_IMPLEMENTED;
138 }
139
140 UINT WINAPI MsiAdvertiseProductW(LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
141                 LPCWSTR szTransforms, LANGID lgidLanguage)
142 {
143     FIXME("%s %s %s %08x\n",debugstr_w(szPackagePath),
144           debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage);
145     return ERROR_CALL_NOT_IMPLEMENTED;
146 }
147
148 UINT WINAPI MsiAdvertiseProductExA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
149       LPCSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
150 {
151     FIXME("%s %s %s %08x %08lx %08lx\n", debugstr_a(szPackagePath),
152           debugstr_a(szScriptfilePath), debugstr_a(szTransforms),
153           lgidLanguage, dwPlatform, dwOptions);
154     return ERROR_CALL_NOT_IMPLEMENTED;
155 }
156
157 UINT WINAPI MsiAdvertiseProductExW( LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
158       LPCWSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
159 {
160     FIXME("%s %s %s %08x %08lx %08lx\n", debugstr_w(szPackagePath),
161           debugstr_w(szScriptfilePath), debugstr_w(szTransforms),
162           lgidLanguage, dwPlatform, dwOptions);
163     return ERROR_CALL_NOT_IMPLEMENTED;
164 }
165
166 UINT WINAPI MsiInstallProductA(LPCSTR szPackagePath, LPCSTR szCommandLine)
167 {
168     LPWSTR szwPath = NULL, szwCommand = NULL;
169     UINT r = ERROR_OUTOFMEMORY;
170
171     TRACE("%s %s\n",debugstr_a(szPackagePath), debugstr_a(szCommandLine));
172
173     if( szPackagePath )
174     {
175         szwPath = strdupAtoW( szPackagePath );
176         if( !szwPath )
177             goto end;
178     }
179
180     if( szCommandLine )
181     {
182         szwCommand = strdupAtoW( szCommandLine );
183         if( !szwCommand )
184             goto end;
185     }
186
187     r = MsiInstallProductW( szwPath, szwCommand );
188
189 end:
190     HeapFree( GetProcessHeap(), 0, szwPath );
191     HeapFree( GetProcessHeap(), 0, szwCommand );
192
193     return r;
194 }
195
196 UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
197 {
198     MSIPACKAGE *package = NULL;
199     UINT r;
200     MSIHANDLE handle;
201
202     FIXME("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
203
204     r = MsiVerifyPackageW(szPackagePath);
205     if (r != ERROR_SUCCESS)
206         return r;
207
208     r = MSI_OpenPackageW(szPackagePath,&package);
209     if (r != ERROR_SUCCESS)
210         return r;
211
212     handle = alloc_msihandle( &package->hdr );
213
214     r = ACTION_DoTopLevelINSTALL(package, szPackagePath, szCommandLine);
215
216     MsiCloseHandle(handle);
217     msiobj_release( &package->hdr );
218     return r;
219 }
220
221 UINT WINAPI MsiReinstallProductA(LPCSTR szProduct, DWORD dwReinstallMode)
222 {
223     FIXME("%s %08lx\n", debugstr_a(szProduct), dwReinstallMode);
224     return ERROR_CALL_NOT_IMPLEMENTED;
225 }
226
227 UINT WINAPI MsiReinstallProductW(LPCWSTR szProduct, DWORD dwReinstallMode)
228 {
229     FIXME("%s %08lx\n", debugstr_w(szProduct), dwReinstallMode);
230     return ERROR_CALL_NOT_IMPLEMENTED;
231 }
232
233 UINT WINAPI MsiApplyPatchA(LPCSTR szPatchPackage, LPCSTR szInstallPackage,
234         INSTALLTYPE eInstallType, LPCSTR szCommandLine)
235 {
236     FIXME("%s %s %d %s\n", debugstr_a(szPatchPackage), debugstr_a(szInstallPackage),
237           eInstallType, debugstr_a(szCommandLine));
238     return ERROR_CALL_NOT_IMPLEMENTED;
239 }
240
241 UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage,
242          INSTALLTYPE eInstallType, LPCWSTR szCommandLine)
243 {
244     FIXME("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage),
245           eInstallType, debugstr_w(szCommandLine));
246     return ERROR_CALL_NOT_IMPLEMENTED;
247 }
248
249 UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
250                         INSTALLSTATE eInstallState, LPCWSTR szCommandLine)
251 {
252     MSIHANDLE handle;
253     MSIPACKAGE* package;
254     UINT rc;
255     HKEY hkey=0,hkey1=0;
256     DWORD sz;
257     static const WCHAR szSouceList[] = {
258         'S','o','u','r','c','e','L','i','s','t',0};
259     static const WCHAR szLUS[] = {
260         'L','a','s','t','U','s','e','d','S','o','u','r','c','e',0};
261     WCHAR sourcepath[0x200];
262     static const WCHAR szInstalled[] = {
263         ' ','I','n','s','t','a','l','l','e','d','=','1',0};
264     LPWSTR commandline;
265
266     FIXME("%s %d %d %s\n",debugstr_w(szProduct), iInstallLevel, eInstallState,
267           debugstr_w(szCommandLine));
268
269     if (eInstallState != INSTALLSTATE_LOCAL &&
270         eInstallState != INSTALLSTATE_DEFAULT)
271     {
272         FIXME("Not implemented for anything other than local installs\n");
273         return ERROR_CALL_NOT_IMPLEMENTED;
274     }
275
276     rc = MSIREG_OpenUserProductsKey(szProduct,&hkey,FALSE);
277     if (rc != ERROR_SUCCESS)
278         goto end;
279
280     rc = RegOpenKeyW(hkey,szSouceList,&hkey1);
281     if (rc != ERROR_SUCCESS)
282         goto end;
283
284     sz = sizeof(sourcepath);
285     rc = RegQueryValueExW(hkey1, szLUS, NULL, NULL,(LPBYTE)sourcepath, &sz);
286     if (rc != ERROR_SUCCESS)
287         goto end;
288
289     RegCloseKey(hkey1);
290     /*
291      * ok 1, we need to find the msi file for this product.
292      *    2, find the source dir for the files
293      *    3, do the configure/install.
294      *    4, cleanupany runonce entry.
295      */
296
297     rc = MsiOpenProductW(szProduct,&handle);
298     if (rc != ERROR_SUCCESS)
299         goto end;
300
301     package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
302     if (!package)
303     {
304         rc = ERROR_INVALID_HANDLE;
305         goto end;
306     }
307
308     sz = lstrlenW(szInstalled);
309
310     if (szCommandLine)
311         sz += lstrlenW(szCommandLine);
312
313     commandline = HeapAlloc(GetProcessHeap(),0,sz * sizeof(WCHAR));
314
315     if (szCommandLine)
316         lstrcpyW(commandline,szCommandLine);
317     else
318         commandline[0] = 0;
319
320     if (MsiQueryProductStateW(szProduct) != INSTALLSTATE_UNKNOWN)
321         lstrcatW(commandline,szInstalled);
322
323     rc = ACTION_DoTopLevelINSTALL(package, sourcepath, commandline);
324
325     msiobj_release( &package->hdr );
326
327     HeapFree(GetProcessHeap(),0,commandline);
328 end:
329     RegCloseKey(hkey);
330
331     return rc;
332 }
333
334 UINT WINAPI MsiConfigureProductExA(LPCSTR szProduct, int iInstallLevel,
335                         INSTALLSTATE eInstallState, LPCSTR szCommandLine)
336 {
337     LPWSTR szwProduct = NULL;
338     LPWSTR szwCommandLine = NULL;
339     UINT r = ERROR_OUTOFMEMORY;
340
341     if( szProduct )
342     {
343         szwProduct = strdupAtoW( szProduct );
344         if( !szwProduct )
345             goto end;
346     }
347
348     if( szCommandLine)
349     {
350         szwCommandLine = strdupAtoW( szCommandLine );
351         if( !szwCommandLine)
352             goto end;
353     }
354
355     r = MsiConfigureProductExW( szwProduct, iInstallLevel, eInstallState,
356                                 szwCommandLine );
357 end:
358     HeapFree( GetProcessHeap(), 0, szwProduct );
359     HeapFree( GetProcessHeap(), 0, szwCommandLine);
360
361     return r;
362 }
363
364 UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel,
365                                  INSTALLSTATE eInstallState)
366 {
367     LPWSTR szwProduct = NULL;
368     UINT r;
369
370     TRACE("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState);
371
372     if( szProduct )
373     {
374         szwProduct = strdupAtoW( szProduct );
375         if( !szwProduct )
376             return ERROR_OUTOFMEMORY;
377     }
378
379     r = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState );
380     HeapFree( GetProcessHeap(), 0, szwProduct );
381
382     return r;
383 }
384
385 UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel,
386                                  INSTALLSTATE eInstallState)
387 {
388     FIXME("%s %d %d\n", debugstr_w(szProduct), iInstallLevel, eInstallState);
389
390     return MsiConfigureProductExW(szProduct, iInstallLevel, eInstallState, NULL);
391 }
392
393 UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer)
394 {
395     LPWSTR szwComponent = NULL;
396     UINT r;
397     WCHAR szwBuffer[GUID_SIZE];
398
399     TRACE("%s %s\n",debugstr_a(szComponent), debugstr_a(szBuffer));
400
401     if( szComponent )
402     {
403         szwComponent = strdupAtoW( szComponent );
404         if( !szwComponent )
405             return ERROR_OUTOFMEMORY;
406     }
407
408     r = MsiGetProductCodeW( szwComponent, szwBuffer );
409
410     if( ERROR_SUCCESS == r )
411         WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, GUID_SIZE, NULL, NULL);
412
413     HeapFree( GetProcessHeap(), 0, szwComponent );
414
415     return r;
416 }
417
418 UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer)
419 {
420     FIXME("%s %p\n",debugstr_w(szComponent), szBuffer);
421
422     if (NULL == szComponent)
423         return ERROR_INVALID_PARAMETER;
424     return ERROR_CALL_NOT_IMPLEMENTED;
425 }
426
427 UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute,
428                  LPSTR szBuffer, DWORD *pcchValueBuf)
429 {
430     LPWSTR szwProduct = NULL, szwAttribute = NULL, szwBuffer = NULL;
431     UINT r = ERROR_OUTOFMEMORY;
432
433     TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szAttribute),
434           szBuffer, pcchValueBuf);
435
436     if( szProduct )
437     {
438         szwProduct = strdupAtoW( szProduct );
439         if( !szwProduct )
440             goto end;
441     }
442     
443     if( szAttribute )
444     {
445         szwAttribute = strdupAtoW( szAttribute );
446         if( !szwAttribute )
447             goto end;
448     }
449
450     if( szBuffer )
451     {
452         szwBuffer = HeapAlloc( GetProcessHeap(), 0, (*pcchValueBuf) * sizeof(WCHAR) );
453         if( !szwBuffer )     
454             goto end;
455     }
456
457     r = MsiGetProductInfoW( szwProduct, szwAttribute, szwBuffer, pcchValueBuf );
458
459     if( ERROR_SUCCESS == r )
460         WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, *pcchValueBuf, NULL, NULL);
461
462 end:
463     HeapFree( GetProcessHeap(), 0, szwProduct );
464     HeapFree( GetProcessHeap(), 0, szwAttribute );
465     HeapFree( GetProcessHeap(), 0, szwBuffer );
466
467     return r;
468 }
469
470 UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
471                 LPWSTR szBuffer, DWORD *pcchValueBuf)
472 {
473     MSIHANDLE hProduct;
474     UINT r;
475
476     FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szAttribute),
477           szBuffer, pcchValueBuf);
478
479     if (NULL != szBuffer && NULL == pcchValueBuf)
480         return ERROR_INVALID_PARAMETER;
481     if (NULL == szProduct || NULL == szAttribute)
482         return ERROR_INVALID_PARAMETER;
483
484     r = MsiOpenProductW(szProduct, &hProduct);
485     if (ERROR_SUCCESS != r)
486         return r;
487
488     r = MsiGetPropertyW(hProduct, szAttribute, szBuffer, pcchValueBuf);
489     MsiCloseHandle(hProduct);
490     return r;
491 }
492
493 UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes)
494 {
495     LPWSTR szwLogFile = NULL;
496     UINT r;
497
498     TRACE("%08lx %s %08lx\n", dwLogMode, debugstr_a(szLogFile), attributes);
499
500     if( szLogFile )
501     {
502         szwLogFile = strdupAtoW( szLogFile );
503         if( !szwLogFile )
504             return ERROR_OUTOFMEMORY;
505     }
506     r = MsiEnableLogW( dwLogMode, szwLogFile, attributes );
507     HeapFree( GetProcessHeap(), 0, szwLogFile );
508     return r;
509 }
510
511 UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes)
512 {
513     HANDLE file = INVALID_HANDLE_VALUE;
514
515     TRACE("%08lx %s %08lx\n", dwLogMode, debugstr_w(szLogFile), attributes);
516
517     lstrcpyW(gszLogFile,szLogFile);
518     if (!(attributes & INSTALLLOGATTRIBUTES_APPEND))
519         DeleteFileW(szLogFile);
520     file = CreateFileW(szLogFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
521                            FILE_ATTRIBUTE_NORMAL, NULL);
522     if (file != INVALID_HANDLE_VALUE)
523         CloseHandle(file);
524     else
525         ERR("Unable to enable log %s\n",debugstr_w(szLogFile));
526
527     return ERROR_SUCCESS;
528 }
529
530 INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct)
531 {
532     LPWSTR szwProduct = NULL;
533     INSTALLSTATE r;
534
535     if( szProduct )
536     {
537          szwProduct = strdupAtoW( szProduct );
538          if( !szwProduct )
539              return ERROR_OUTOFMEMORY;
540     }
541     r = MsiQueryProductStateW( szwProduct );
542     HeapFree( GetProcessHeap(), 0, szwProduct );
543     return r;
544 }
545
546 INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct)
547 {
548     UINT rc;
549     INSTALLSTATE rrc = INSTALLSTATE_UNKNOWN;
550     HKEY hkey = 0;
551     static const WCHAR szWindowsInstaller[] = {
552          'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0 };
553     DWORD sz;
554
555     TRACE("%s\n", debugstr_w(szProduct));
556
557     rc = MSIREG_OpenUserProductsKey(szProduct,&hkey,FALSE);
558     if (rc != ERROR_SUCCESS)
559         goto end;
560
561     RegCloseKey(hkey);
562
563     rc = MSIREG_OpenUninstallKey(szProduct,&hkey,FALSE);
564     if (rc != ERROR_SUCCESS)
565         goto end;
566
567     sz = sizeof(rrc);
568     rc = RegQueryValueExW(hkey,szWindowsInstaller,NULL,NULL,(LPVOID)&rrc, &sz);
569     if (rc != ERROR_SUCCESS)
570         goto end;
571
572     switch (rrc)
573     {
574     case 1:
575         /* default */
576         rrc = INSTALLSTATE_DEFAULT;
577         break;
578     default:
579         FIXME("Unknown install state read from registry (%i)\n",rrc);
580         rrc = INSTALLSTATE_UNKNOWN;
581         break;
582     }
583 end:
584     RegCloseKey(hkey);
585     return rrc;
586 }
587
588 INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd)
589 {
590     INSTALLUILEVEL old = gUILevel;
591     HWND oldwnd = gUIhwnd;
592
593     TRACE("%08x %p\n", dwUILevel, phWnd);
594
595     gUILevel = dwUILevel;
596     if (phWnd)
597     {
598         gUIhwnd = *phWnd;
599         *phWnd = oldwnd;
600     }
601     return old;
602 }
603
604 INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler,
605                                   DWORD dwMessageFilter, LPVOID pvContext)
606 {
607     INSTALLUI_HANDLERA prev = gUIHandlerA;
608
609     TRACE("%p %lx %p\n",puiHandler, dwMessageFilter,pvContext);
610     gUIHandlerA = puiHandler;
611     gUIFilter = dwMessageFilter;
612     gUIContext = pvContext;
613
614     return prev;
615 }
616
617 INSTALLUI_HANDLERW WINAPI MsiSetExternalUIW(INSTALLUI_HANDLERW puiHandler,
618                                   DWORD dwMessageFilter, LPVOID pvContext)
619 {
620     INSTALLUI_HANDLERW prev = gUIHandlerW;
621
622     TRACE("%p %lx %p\n",puiHandler,dwMessageFilter,pvContext);
623     gUIHandlerW = puiHandler;
624     gUIFilter = dwMessageFilter;
625     gUIContext = pvContext;
626
627     return prev;
628 }
629
630 /******************************************************************
631  *  MsiLoadStringW            [MSI.@]
632  *
633  * Loads a string from MSI's string resources.
634  *
635  * PARAMS
636  *
637  *   handle        [I]  only -1 is handled currently
638  *   id            [I]  id of the string to be loaded
639  *   lpBuffer      [O]  buffer for the string to be written to
640  *   nBufferMax    [I]  maximum size of the buffer in characters
641  *   lang          [I]  the preferred language for the string
642  *
643  * RETURNS
644  *
645  *   If successful, this function returns the language id of the string loaded
646  *   If the function fails, the function returns zero.
647  *
648  * NOTES
649  *
650  *   The type of the first parameter is unknown.  LoadString's prototype
651  *  suggests that it might be a module handle.  I have made it an MSI handle
652  *  for starters, as -1 is an invalid MSI handle, but not an invalid module
653  *  handle.  Maybe strings can be stored in an MSI database somehow.
654  */
655 LANGID WINAPI MsiLoadStringW( MSIHANDLE handle, UINT id, LPWSTR lpBuffer,
656                 int nBufferMax, LANGID lang )
657 {
658     HRSRC hres;
659     HGLOBAL hResData;
660     LPWSTR p;
661     DWORD i, len;
662
663     TRACE("%ld %u %p %d %d\n", handle, id, lpBuffer, nBufferMax, lang);
664
665     if( handle != -1 )
666         FIXME("don't know how to deal with handle = %08lx\n", handle);
667
668     if( !lang )
669         lang = GetUserDefaultLangID();
670
671     hres = FindResourceExW( msi_hInstance, (LPCWSTR) RT_STRING,
672                             (LPWSTR)1, lang );
673     if( !hres )
674         return 0;
675     hResData = LoadResource( msi_hInstance, hres );
676     if( !hResData )
677         return 0;
678     p = LockResource( hResData );
679     if( !p )
680         return 0;
681
682     for (i = 0; i < (id&0xf); i++)
683         p += *p + 1;
684     len = *p;
685
686     if( nBufferMax <= len )
687         return 0;
688
689     memcpy( lpBuffer, p+1, len * sizeof(WCHAR));
690     lpBuffer[ len ] = 0;
691
692     TRACE("found -> %s\n", debugstr_w(lpBuffer));
693
694     return lang;
695 }
696
697 LANGID WINAPI MsiLoadStringA( MSIHANDLE handle, UINT id, LPSTR lpBuffer,
698                 int nBufferMax, LANGID lang )
699 {
700     LPWSTR bufW;
701     LANGID r;
702     DWORD len;
703
704     bufW = HeapAlloc(GetProcessHeap(), 0, nBufferMax*sizeof(WCHAR));
705     r = MsiLoadStringW(handle, id, bufW, nBufferMax, lang);
706     if( r )
707     {
708         len = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL );
709         if( len <= nBufferMax )
710             WideCharToMultiByte( CP_ACP, 0, bufW, -1,
711                                  lpBuffer, nBufferMax, NULL, NULL );
712         else
713             r = 0;
714     }
715     HeapFree(GetProcessHeap(), 0, bufW);
716     return r;
717 }
718
719 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf,
720                 DWORD *pcchBuf)
721 {
722     FIXME("%s %p %08lx\n", debugstr_a(szComponent), lpPathBuf, *pcchBuf);
723     return INSTALLSTATE_UNKNOWN;
724 }
725
726 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPSTR lpPathBuf,
727                 DWORD *pcchBuf)
728 {
729     FIXME("%s %p %08lx\n", debugstr_w(szComponent), lpPathBuf, *pcchBuf);
730     return INSTALLSTATE_UNKNOWN;
731 }
732
733 UINT WINAPI MsiMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType,
734                 WORD wLanguageId, DWORD f)
735 {
736     FIXME("%p %s %s %u %08x %08lx\n",hWnd,debugstr_a(lpText),debugstr_a(lpCaption),
737           uType,wLanguageId,f);
738     return ERROR_CALL_NOT_IMPLEMENTED;
739 }
740
741 UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType,
742                 WORD wLanguageId, DWORD f)
743 {
744     FIXME("%p %s %s %u %08x %08lx\n",hWnd,debugstr_w(lpText),debugstr_w(lpCaption),
745           uType,wLanguageId,f);
746     return ERROR_CALL_NOT_IMPLEMENTED;
747 }
748
749 UINT WINAPI MsiProvideAssemblyA( LPCSTR szAssemblyName, LPCSTR szAppContext,
750                 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf,
751                 DWORD* pcchPathBuf )
752 {
753     FIXME("%s %s %08lx %08lx %p %p\n", debugstr_a(szAssemblyName),
754           debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
755           pcchPathBuf);
756     return ERROR_CALL_NOT_IMPLEMENTED;
757 }
758
759 UINT WINAPI MsiProvideAssemblyW( LPCWSTR szAssemblyName, LPCWSTR szAppContext,
760                 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf,
761                 DWORD* pcchPathBuf )
762 {
763     FIXME("%s %s %08lx %08lx %p %p\n", debugstr_w(szAssemblyName),
764           debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
765           pcchPathBuf);
766     return ERROR_CALL_NOT_IMPLEMENTED;
767 }
768
769 UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor,
770                 LPSTR szPath, DWORD *pcchPath, DWORD *pcchArgs )
771 {
772     FIXME("%s %p %p %p\n", debugstr_a(szDescriptor), szPath, pcchPath, pcchArgs );
773     return ERROR_CALL_NOT_IMPLEMENTED;
774 }
775
776 UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor,
777                 LPWSTR szPath, DWORD *pcchPath, DWORD *pcchArgs )
778 {
779     FIXME("%s %p %p %p\n", debugstr_w(szDescriptor), szPath, pcchPath, pcchArgs );
780     return ERROR_CALL_NOT_IMPLEMENTED;
781 }
782
783 HRESULT WINAPI MsiGetFileSignatureInformationA( LPCSTR szSignedObjectPath,
784                 DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData,
785                 DWORD* pcbHashData)
786 {
787     FIXME("%s %08lx %p %p %p\n", debugstr_a(szSignedObjectPath), dwFlags,
788           ppcCertContext, pbHashData, pcbHashData);
789     return ERROR_CALL_NOT_IMPLEMENTED;
790 }
791
792 HRESULT WINAPI MsiGetFileSignatureInformationW( LPCWSTR szSignedObjectPath,
793                 DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData,
794                 DWORD* pcbHashData)
795 {
796     FIXME("%s %08lx %p %p %p\n", debugstr_w(szSignedObjectPath), dwFlags,
797           ppcCertContext, pbHashData, pcbHashData);
798     return ERROR_CALL_NOT_IMPLEMENTED;
799 }
800
801 UINT WINAPI MsiGetProductPropertyA( MSIHANDLE hProduct, LPCSTR szProperty,
802                                     LPSTR szValue, DWORD *pccbValue )
803 {
804     FIXME("%ld %s %p %p\n", hProduct, debugstr_a(szProperty), szValue, pccbValue);
805     return ERROR_CALL_NOT_IMPLEMENTED;
806 }
807
808 UINT WINAPI MsiGetProductPropertyW( MSIHANDLE hProduct, LPCWSTR szProperty,
809                                     LPWSTR szValue, DWORD *pccbValue )
810 {
811     FIXME("%ld %s %p %p\n", hProduct, debugstr_w(szProperty), szValue, pccbValue);
812     return ERROR_CALL_NOT_IMPLEMENTED;
813 }
814
815 UINT WINAPI MsiVerifyPackageA( LPCSTR szPackage )
816 {
817     UINT r;
818     LPWSTR szPack = NULL;
819
820     TRACE("%s\n", debugstr_a(szPackage) );
821
822     if( szPackage )
823     {
824         szPack = strdupAtoW( szPackage );
825         if( !szPack )
826             return ERROR_OUTOFMEMORY;
827     }
828
829     r = MsiVerifyPackageW( szPack );
830
831     HeapFree( GetProcessHeap(), 0, szPack );
832
833     return r;
834 }
835
836 UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage )
837 {
838     MSIHANDLE handle;
839     UINT r;
840
841     TRACE("%s\n", debugstr_w(szPackage) );
842
843     r = MsiOpenDatabaseW( szPackage, MSIDBOPEN_READONLY, &handle );
844     MsiCloseHandle( handle );
845
846     return r;
847 }
848
849 INSTALLSTATE WINAPI MsiGetComponentPathA(LPCSTR szProduct, LPCSTR szComponent,
850                                          LPSTR lpPathBuf, DWORD* pcchBuf)
851 {
852     LPWSTR szwProduct = NULL, szwComponent = NULL, lpwPathBuf= NULL;
853     INSTALLSTATE rc;
854     UINT incoming_len;
855
856     if( szProduct )
857     {
858         szwProduct = strdupAtoW( szProduct );
859         if( !szwProduct)
860             return ERROR_OUTOFMEMORY;
861     }
862
863     if( szComponent )
864     {
865         szwComponent = strdupAtoW( szComponent );
866         if( !szwComponent )
867         {
868             HeapFree( GetProcessHeap(), 0, szwProduct);
869             return ERROR_OUTOFMEMORY;
870         }
871     }
872
873     if( pcchBuf && *pcchBuf > 0 )
874         lpwPathBuf = HeapAlloc( GetProcessHeap(), 0, *pcchBuf * sizeof(WCHAR));
875     else
876         lpwPathBuf = NULL;
877
878     incoming_len = *pcchBuf;
879     rc = MsiGetComponentPathW(szwProduct, szwComponent, lpwPathBuf, pcchBuf);
880
881     HeapFree( GetProcessHeap(), 0, szwProduct);
882     HeapFree( GetProcessHeap(), 0, szwComponent);
883     if (lpwPathBuf)
884     {
885         if (rc != INSTALLSTATE_UNKNOWN)
886             WideCharToMultiByte(CP_ACP, 0, lpwPathBuf, incoming_len,
887                             lpPathBuf, incoming_len, NULL, NULL);
888         HeapFree( GetProcessHeap(), 0, lpwPathBuf);
889     }
890
891     return rc;
892 }
893
894 INSTALLSTATE WINAPI MsiGetComponentPathW(LPCWSTR szProduct, LPCWSTR szComponent,
895                                          LPWSTR lpPathBuf, DWORD* pcchBuf)
896 {
897     WCHAR squished_pc[GUID_SIZE];
898     UINT rc;
899     INSTALLSTATE rrc = INSTALLSTATE_UNKNOWN;
900     HKEY hkey = 0;
901     LPWSTR path = NULL;
902     DWORD sz, type;
903
904     TRACE("%s %s %p %p\n", debugstr_w(szProduct),
905            debugstr_w(szComponent), lpPathBuf, pcchBuf);
906
907     if( lpPathBuf && !pcchBuf )
908         return INSTALLSTATE_INVALIDARG;
909
910     squash_guid(szProduct,squished_pc);
911
912     rc = MSIREG_OpenProductsKey( szProduct, &hkey, FALSE);
913     if( rc != ERROR_SUCCESS )
914         goto end;
915
916     RegCloseKey(hkey);
917
918     rc = MSIREG_OpenComponentsKey( szComponent, &hkey, FALSE);
919     if( rc != ERROR_SUCCESS )
920         goto end;
921
922     sz = 0;
923     type = 0;
924     rc = RegQueryValueExW( hkey, squished_pc, NULL, &type, NULL, &sz );
925     if( rc != ERROR_SUCCESS )
926         goto end;
927     if( type != REG_SZ )
928         goto end;
929
930     sz += sizeof(WCHAR);
931     path = HeapAlloc( GetProcessHeap(), 0, sz );
932     if( !path )
933         goto end;
934
935     rc = RegQueryValueExW( hkey, squished_pc, NULL, NULL, (LPVOID) path, &sz );
936     if( rc != ERROR_SUCCESS )
937         goto end;
938
939     TRACE("found path of (%s:%s)(%s)\n", debugstr_w(szComponent),
940            debugstr_w(szProduct), debugstr_w(path));
941
942     if (path[0]=='0')
943     {
944         FIXME("Registry entry.. check entry\n");
945         rrc = INSTALLSTATE_LOCAL;
946     }
947     else
948     {
949         /* PROBABLY a file */
950         if ( GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES )
951             rrc = INSTALLSTATE_LOCAL;
952         else
953             rrc = INSTALLSTATE_ABSENT;
954     }
955
956     if( pcchBuf )
957     {
958         sz = sz / sizeof(WCHAR);
959         if( *pcchBuf >= sz )
960             lstrcpyW( lpPathBuf, path );
961         *pcchBuf = sz;
962     }
963
964 end:
965     HeapFree(GetProcessHeap(), 0, path );
966     RegCloseKey(hkey);
967     return rrc;
968 }
969
970 INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature)
971 {
972     INSTALLSTATE rc;
973     LPWSTR szwProduct= NULL;
974     LPWSTR szwFeature= NULL;
975
976     if( szProduct )
977     {
978         szwProduct = strdupAtoW( szProduct );
979         if( !szwProduct)
980             return ERROR_OUTOFMEMORY;
981     }
982
983     if( szFeature )
984     {
985         szwFeature = strdupAtoW( szFeature );
986         if( !szwFeature)
987         {
988             HeapFree( GetProcessHeap(), 0, szwProduct);
989             return ERROR_OUTOFMEMORY;
990         }
991     }
992
993     rc = MsiQueryFeatureStateW(szwProduct, szwFeature);
994
995     HeapFree( GetProcessHeap(), 0, szwProduct);
996     HeapFree( GetProcessHeap(), 0, szwFeature);
997
998     return rc;
999 }
1000
1001 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
1002 {
1003     FIXME("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature));
1004     /*
1005      * Iterates all the features components and the features parents components
1006      */
1007     return INSTALLSTATE_LOCAL;
1008 }
1009
1010 UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf,
1011                 DWORD* pcchVersionBuf, LPSTR lpLangBuf, DWORD* pcchLangBuf)
1012 {
1013     LPWSTR szwFilePath = NULL, lpwVersionBuff = NULL, lpwLangBuff = NULL;
1014     UINT ret = ERROR_OUTOFMEMORY;
1015
1016     if( szFilePath )
1017     {
1018         szwFilePath = strdupAtoW( szFilePath );
1019         if( !szwFilePath )
1020             goto end;
1021     }
1022
1023     if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf )
1024     {
1025         lpwVersionBuff = HeapAlloc(GetProcessHeap(), 0, *pcchVersionBuf*sizeof(WCHAR));
1026         if( !lpwVersionBuff )
1027             goto end;
1028     }
1029
1030     if( lpLangBuf && pcchLangBuf && *pcchLangBuf )
1031     {
1032         lpwLangBuff = HeapAlloc(GetProcessHeap(), 0, *pcchVersionBuf*sizeof(WCHAR));
1033         if( !lpwLangBuff )
1034             goto end;
1035     }
1036
1037     ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf,
1038                              lpwLangBuff, pcchLangBuf);
1039
1040     if( lpwVersionBuff )
1041         WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1,
1042                             lpVersionBuf, *pcchVersionBuf, NULL, NULL);
1043     if( lpwLangBuff )
1044         WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1,
1045                             lpLangBuf, *pcchLangBuf, NULL, NULL);
1046
1047 end:
1048     HeapFree(GetProcessHeap(), 0, szwFilePath);
1049     HeapFree(GetProcessHeap(), 0, lpwVersionBuff);
1050     HeapFree(GetProcessHeap(), 0, lpwLangBuff);
1051
1052     return ret;
1053 }
1054
1055 UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf,
1056                 DWORD* pcchVersionBuf, LPWSTR lpLangBuf, DWORD* pcchLangBuf)
1057 {
1058     static const WCHAR szVersionResource[] = {'\\',0};
1059     static const WCHAR szVersionFormat[] = {
1060         '%','d','.','%','d','.','%','d','.','%','d',0};
1061     static const WCHAR szLangFormat[] = {'%','d',0};
1062     UINT ret = 0;
1063     DWORD dwVerLen;
1064     LPVOID lpVer = NULL;
1065     VS_FIXEDFILEINFO *ffi;
1066     UINT puLen;
1067     WCHAR tmp[32];
1068
1069     TRACE("%s %p %ld %p %ld\n", debugstr_w(szFilePath),
1070           lpVersionBuf, pcchVersionBuf?*pcchVersionBuf:0,
1071           lpLangBuf, pcchLangBuf?*pcchLangBuf:0);
1072
1073     dwVerLen = GetFileVersionInfoSizeW(szFilePath, NULL);
1074     if( !dwVerLen )
1075         return GetLastError();
1076
1077     lpVer = HeapAlloc(GetProcessHeap(), 0, dwVerLen);
1078     if( !lpVer )
1079     {
1080         ret = ERROR_OUTOFMEMORY;
1081         goto end;
1082     }
1083
1084     if( !GetFileVersionInfoW(szFilePath, 0, dwVerLen, lpVer) )
1085     {
1086         ret = GetLastError();
1087         goto end;
1088     }
1089     if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf )
1090     {
1091         if( VerQueryValueW(lpVer, szVersionResource, (LPVOID*)&ffi, &puLen) &&
1092             (puLen > 0) )
1093         {
1094             wsprintfW(tmp, szVersionFormat,
1095                   HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS),
1096                   HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS));
1097             lstrcpynW(lpVersionBuf, tmp, *pcchVersionBuf);
1098             *pcchVersionBuf = lstrlenW(lpVersionBuf);
1099         }
1100         else
1101         {
1102             *lpVersionBuf = 0;
1103             *pcchVersionBuf = 0;
1104         }
1105     }
1106
1107     if( lpLangBuf && pcchLangBuf && *pcchLangBuf )
1108     {
1109         DWORD lang = GetUserDefaultLangID();
1110
1111         FIXME("Retrieve language from file\n");
1112         wsprintfW(tmp, szLangFormat, lang);
1113         lstrcpynW(lpLangBuf, tmp, *pcchLangBuf);
1114         *pcchLangBuf = lstrlenW(lpLangBuf);
1115     }
1116
1117 end:
1118     HeapFree(GetProcessHeap(), 0, lpVer);
1119     return ret;
1120 }
1121
1122
1123 /******************************************************************
1124  *      DllMain
1125  */
1126 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
1127 {
1128     switch(fdwReason)
1129     {
1130     case DLL_PROCESS_ATTACH:
1131         msi_hInstance = hinstDLL;
1132         DisableThreadLibraryCalls(hinstDLL);
1133         msi_dialog_register_class();
1134         break;
1135     case DLL_PROCESS_DETACH:
1136         msi_dialog_unregister_class();
1137         /* FIXME: Cleanup */
1138         break;
1139     }
1140     return TRUE;
1141 }
1142
1143 typedef struct tagIClassFactoryImpl
1144 {
1145     IClassFactoryVtbl *lpVtbl;
1146 } IClassFactoryImpl;
1147
1148 static HRESULT WINAPI MsiCF_QueryInterface(LPCLASSFACTORY iface,
1149                 REFIID riid,LPVOID *ppobj)
1150 {
1151     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
1152     FIXME("%p %s %p\n",This,debugstr_guid(riid),ppobj);
1153     return E_NOINTERFACE;
1154 }
1155
1156 static ULONG WINAPI MsiCF_AddRef(LPCLASSFACTORY iface)
1157 {
1158     return 2;
1159 }
1160
1161 static ULONG WINAPI MsiCF_Release(LPCLASSFACTORY iface)
1162 {
1163     return 1;
1164 }
1165
1166 static HRESULT WINAPI MsiCF_CreateInstance(LPCLASSFACTORY iface,
1167     LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj)
1168 {
1169     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
1170
1171     FIXME("%p %p %s %p\n", This, pOuter, debugstr_guid(riid), ppobj);
1172     return E_FAIL;
1173 }
1174
1175 static HRESULT WINAPI MsiCF_LockServer(LPCLASSFACTORY iface, BOOL dolock)
1176 {
1177     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
1178
1179     FIXME("%p %d\n", This, dolock);
1180     return S_OK;
1181 }
1182
1183 static IClassFactoryVtbl MsiCF_Vtbl =
1184 {
1185     MsiCF_QueryInterface,
1186     MsiCF_AddRef,
1187     MsiCF_Release,
1188     MsiCF_CreateInstance,
1189     MsiCF_LockServer
1190 };
1191
1192 static IClassFactoryImpl Msi_CF = { &MsiCF_Vtbl };
1193
1194 /******************************************************************
1195  *      DllGetClassObject [MSI.@]
1196  */
1197 HRESULT WINAPI MSI_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
1198 {
1199     TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
1200
1201     if( IsEqualCLSID (rclsid, &CLSID_IMsiServer) ||
1202         IsEqualCLSID (rclsid, &CLSID_IMsiServerMessage) ||
1203         IsEqualCLSID (rclsid, &CLSID_IMsiServerX1) ||
1204         IsEqualCLSID (rclsid, &CLSID_IMsiServerX2) ||
1205         IsEqualCLSID (rclsid, &CLSID_IMsiServerX3) )
1206     {
1207         *ppv = (LPVOID) &Msi_CF;
1208         return S_OK;
1209     }
1210     return CLASS_E_CLASSNOTAVAILABLE;
1211 }
1212
1213 /******************************************************************
1214  *      DllGetVersion [MSI.@]
1215  */
1216 HRESULT WINAPI MSI_DllGetVersion(DLLVERSIONINFO *pdvi)
1217 {
1218     TRACE("%p\n",pdvi);
1219
1220     if (pdvi->cbSize != sizeof(DLLVERSIONINFO))
1221         return E_INVALIDARG;
1222
1223     pdvi->dwMajorVersion = MSI_MAJORVERSION;
1224     pdvi->dwMinorVersion = MSI_MINORVERSION;
1225     pdvi->dwBuildNumber = MSI_BUILDNUMBER;
1226     pdvi->dwPlatformID = 1;
1227
1228     return S_OK;
1229 }
1230
1231 /******************************************************************
1232  *      DllCanUnloadNow [MSI.@]
1233  */
1234 BOOL WINAPI MSI_DllCanUnloadNow(void)
1235 {
1236     return S_FALSE;
1237 }
1238
1239 UINT WINAPI MsiGetFeatureUsageW(LPCWSTR szProduct, LPCWSTR szFeature,
1240                                 DWORD* pdwUseCount, WORD* pwDateUsed)
1241 {
1242     FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szFeature),
1243           pdwUseCount, pwDateUsed);
1244     return ERROR_CALL_NOT_IMPLEMENTED;
1245 }
1246
1247 UINT WINAPI MsiGetFeatureUsageA(LPCSTR szProduct, LPCSTR szFeature,
1248                                 DWORD* pdwUseCount, WORD* pwDateUsed)
1249 {
1250     FIXME("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szFeature),
1251           pdwUseCount, pwDateUsed);
1252     return ERROR_CALL_NOT_IMPLEMENTED;
1253 }
1254
1255 INSTALLSTATE WINAPI MsiUseFeatureExW(LPCWSTR szProduct, LPCWSTR szFeature,
1256                              DWORD dwInstallMode, DWORD dwReserved)
1257 {
1258     FIXME("%s %s %li %li\n", debugstr_w(szProduct), debugstr_w(szFeature),
1259           dwInstallMode, dwReserved);
1260
1261     /*
1262      * Polls all the components of the feature to find install state and then
1263      *  writes:
1264      *    Software\\Microsoft\\Windows\\CurrentVersion\\
1265      *    Installer\\Products\\<squishguid>\\<feature>
1266      *      "Usage"=dword:........
1267      */
1268
1269     return INSTALLSTATE_LOCAL;
1270 }
1271
1272 INSTALLSTATE WINAPI MsiUseFeatureExA(LPCSTR szProduct, LPCSTR szFeature,
1273                              DWORD dwInstallMode, DWORD dwReserved)
1274 {
1275     FIXME("%s %s %li %li\n", debugstr_a(szProduct), debugstr_a(szFeature),
1276           dwInstallMode, dwReserved);
1277
1278     return INSTALLSTATE_LOCAL;
1279 }
1280
1281 INSTALLSTATE WINAPI MsiUseFeatureW(LPCWSTR szProduct, LPCWSTR szFeature)
1282 {
1283     FIXME("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature));
1284
1285     return INSTALLSTATE_LOCAL;
1286 }
1287
1288 INSTALLSTATE WINAPI MsiUseFeatureA(LPCSTR szProduct, LPCSTR szFeature)
1289 {
1290     FIXME("%s %s\n", debugstr_a(szProduct), debugstr_a(szFeature));
1291
1292     return INSTALLSTATE_LOCAL;
1293 }
1294
1295 UINT WINAPI MsiProvideQualifiedComponentExW(LPCWSTR szComponent,
1296                 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR szProduct,
1297                 DWORD Unused1, DWORD Unused2, LPWSTR lpPathBuf,
1298                 DWORD* pcchPathBuf)
1299 {
1300     FIXME("%s %s %li %s %li %li %p %p\n", debugstr_w(szComponent),
1301           debugstr_w(szQualifier), dwInstallMode, debugstr_w(szProduct),
1302           Unused1, Unused2, lpPathBuf, pcchPathBuf);
1303
1304     return ERROR_INDEX_ABSENT;
1305 }
1306
1307 USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct, LPWSTR lpUserNameBuf,
1308                 DWORD* pcchUserNameBuf, LPWSTR lpOrgNameBuf,
1309                 DWORD* pcchOrgNameBuf, LPWSTR lpSerialBuf, DWORD* pcchSerialBuf)
1310 {
1311     FIXME("%s %p %p %p %p %p %p\n",debugstr_w(szProduct), lpUserNameBuf,
1312           pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf,
1313           pcchSerialBuf);
1314
1315     return USERINFOSTATE_UNKNOWN;
1316 }
1317
1318 USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR szProduct, LPSTR lpUserNameBuf,
1319                 DWORD* pcchUserNameBuf, LPSTR lpOrgNameBuf,
1320                 DWORD* pcchOrgNameBuf, LPSTR lpSerialBuf, DWORD* pcchSerialBuf)
1321 {
1322     FIXME("%s %p %p %p %p %p %p\n",debugstr_a(szProduct), lpUserNameBuf,
1323           pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf,
1324           pcchSerialBuf);
1325
1326     return USERINFOSTATE_UNKNOWN;
1327 }
1328
1329 UINT WINAPI MsiCollectUserInfoW(LPCWSTR szProduct)
1330 {
1331     FIXME("%s\n",debugstr_w(szProduct));
1332     return ERROR_CALL_NOT_IMPLEMENTED;
1333 }
1334
1335 UINT WINAPI MsiCollectUserInfoA(LPCSTR szProduct)
1336 {
1337     FIXME("%s\n",debugstr_a(szProduct));
1338     return ERROR_CALL_NOT_IMPLEMENTED;
1339 }
1340
1341 UINT WINAPI MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved)
1342 {
1343     FIXME("%ld\n", dwReserved);
1344     return ERROR_CALL_NOT_IMPLEMENTED;
1345 }
1346
1347 UINT WINAPI MsiGetShortcutTargetA( LPCSTR szShortcutTarget,
1348                                    LPSTR szProductCode, LPSTR szFeatureId,
1349                                    LPSTR szComponentCode )
1350 {
1351     FIXME("\n");
1352     return ERROR_CALL_NOT_IMPLEMENTED;
1353 }
1354
1355 UINT WINAPI MsiGetShortcutTargetW( LPCWSTR szShortcutTarget,
1356                                    LPWSTR szProductCode, LPWSTR szFeatureId,
1357                                    LPWSTR szComponentCode )
1358 {
1359     FIXME("\n");
1360     return ERROR_CALL_NOT_IMPLEMENTED;
1361 }
1362
1363 UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature,
1364                                   DWORD dwReinstallMode )
1365 {
1366     FIXME("%s %s %li\n", debugstr_w(szProduct), debugstr_w(szFeature),
1367                            dwReinstallMode);
1368     return ERROR_SUCCESS;
1369 }
1370
1371 UINT WINAPI MsiReinstallFeatureA( LPCSTR szProduct, LPCSTR szFeature,
1372                                   DWORD dwReinstallMode )
1373 {
1374     FIXME("%s %s %li\n", debugstr_a(szProduct), debugstr_a(szFeature),
1375                            dwReinstallMode);
1376     return ERROR_SUCCESS;
1377 }