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