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