Dump DirectSound capabilities flags.
[wine] / dlls / msi / msi.c
1 /*
2  * Implementation of the Microsoft Installer (msi.dll)
3  *
4  * Copyright 2002,2003,2004 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 #define NONAMELESSUNION
22
23 #include <stdarg.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winreg.h"
28 #include "winnls.h"
29 #include "shlwapi.h"
30 #include "wine/debug.h"
31 #include "msi.h"
32 #include "msiquery.h"
33 #include "msipriv.h"
34 #include "objidl.h"
35 #include "wincrypt.h"
36 #include "wine/unicode.h"
37 #include "objbase.h"
38
39 #include "initguid.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(msi);
42
43 /*
44  * The MSVC headers define the MSIDBOPEN_* macros cast to LPCTSTR,
45  *  which is a problem because LPCTSTR isn't defined when compiling wine.
46  * To work around this problem, we need to define LPCTSTR as LPCWSTR here,
47  *  and make sure to only use it in W functions.
48  */
49 #define LPCTSTR LPCWSTR
50
51 DEFINE_GUID( CLSID_MsiDatabase, 0x000c1084, 0x0000, 0x0000, 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
52
53 static const WCHAR szInstaller[] = {
54 'S','o','f','t','w','a','r','e','\\',
55 'M','i','c','r','o','s','o','f','t','\\',
56 'W','i','n','d','o','w','s','\\',
57 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
58 'I','n','s','t','a','l','l','e','r',0 };
59
60 static const WCHAR szFeatures[] = {
61 'F','e','a','t','u','r','e','s',0 };
62 static const WCHAR szComponents[] = {
63 'C','o','m','p','o','n','e','n','t','s',0 };
64
65 /* the UI level */
66 INSTALLUILEVEL gUILevel;
67 HWND           gUIhwnd;
68 INSTALLUI_HANDLERA gUIHandler;
69 DWORD gUIFilter;
70 LPVOID gUIContext;
71 WCHAR gszLogFile[MAX_PATH];
72
73 /*
74  *  .MSI  file format
75  *
76  *  A .msi file is a structured storage file.
77  *  It should contain a number of streams.
78  */
79
80 BOOL unsquash_guid(LPCWSTR in, LPWSTR out)
81 {
82     DWORD i,n=0;
83
84     out[n++]='{';
85     for(i=0; i<8; i++)
86         out[n++] = in[7-i];
87     out[n++]='-';
88     for(i=0; i<4; i++)
89         out[n++] = in[11-i];
90     out[n++]='-';
91     for(i=0; i<4; i++)
92         out[n++] = in[15-i];
93     out[n++]='-';
94     for(i=0; i<2; i++)
95     {
96         out[n++] = in[17+i*2];
97         out[n++] = in[16+i*2];
98     }
99     out[n++]='-';
100     for( ; i<8; i++)
101     {
102         out[n++] = in[17+i*2];
103         out[n++] = in[16+i*2];
104     }
105     out[n++]='}';
106     out[n]=0;
107     return TRUE;
108 }
109
110 BOOL squash_guid(LPCWSTR in, LPWSTR out)
111 {
112     DWORD i,n=0;
113
114     if(in[n++] != '{')
115         return FALSE;
116     for(i=0; i<8; i++)
117         out[7-i] = in[n++];
118     if(in[n++] != '-')
119         return FALSE;
120     for(i=0; i<4; i++)
121         out[11-i] = in[n++];
122     if(in[n++] != '-')
123         return FALSE;
124     for(i=0; i<4; i++)
125         out[15-i] = in[n++];
126     if(in[n++] != '-')
127         return FALSE;
128     for(i=0; i<2; i++)
129     {
130         out[17+i*2] = in[n++];
131         out[16+i*2] = in[n++];
132     }
133     if(in[n++] != '-')
134         return FALSE;
135     for( ; i<8; i++)
136     {
137         out[17+i*2] = in[n++];
138         out[16+i*2] = in[n++];
139     }
140     out[32]=0;
141     if(in[n++] != '}')
142         return FALSE;
143     if(in[n])
144         return FALSE;
145     return TRUE;
146 }
147
148 /* tables for encoding and decoding base85 */
149 static const unsigned char table_dec85[0x80] = {
150 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
151 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
152 0xff,0x00,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff,
153 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0xff,0xff,0xff,0x16,0xff,0x17,
154 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
155 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0xff,0x34,0x35,0x36,
156 0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,
157 0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0xff,0x53,0x54,0xff,
158 };
159
160 static const char table_enc85[] =
161 "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
162 "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
163 "yz{}~";
164
165 /*
166  *  Converts a base85 encoded guid into a GUID pointer
167  *  Base85 encoded GUIDs should be 20 characters long.
168  *
169  *  returns TRUE if successful, FALSE if not
170  */
171 BOOL decode_base85_guid( LPCWSTR str, GUID *guid )
172 {
173     DWORD i, val = 0, base = 1, *p;
174
175     p = (DWORD*) guid;
176     for( i=0; i<20; i++ )
177     {
178         if( (i%5) == 0 )
179         {
180             val = 0;
181             base = 1;
182         }
183         val += table_dec85[str[i]] * base;
184         if( str[i] >= 0x80 )
185             return FALSE;
186         if( table_dec85[str[i]] == 0xff )
187             return FALSE;
188         if( (i%5) == 4 )
189             p[i/5] = val;
190         base *= 85;
191     }
192     return TRUE;
193 }
194
195 /*
196  *  Encodes a base85 guid given a GUID pointer
197  *  Caller should provide a 21 character buffer for the encoded string.
198  *
199  *  returns TRUE if successful, FALSE if not
200  */
201 BOOL encode_base85_guid( GUID *guid, LPWSTR str )
202 {
203     unsigned int x, *p, i;
204
205     p = (unsigned int*) guid;
206     for( i=0; i<4; i++ )
207     {
208         x = p[i];
209         *str++ = table_enc85[x%85];
210         x = x/85;
211         *str++ = table_enc85[x%85];
212         x = x/85;
213         *str++ = table_enc85[x%85];
214         x = x/85;
215         *str++ = table_enc85[x%85];
216         x = x/85;
217         *str++ = table_enc85[x%85];
218     }
219     *str = 0;
220     
221     return TRUE;
222 }
223
224
225 VOID MSI_CloseDatabase( MSIOBJECTHDR *arg )
226 {
227     MSIDATABASE *db = (MSIDATABASE *) arg;
228
229     free_cached_tables( db );
230     IStorage_Release( db->storage );
231 }
232
233 UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
234 {
235     IStorage *stg = NULL;
236     HRESULT r;
237     MSIDATABASE *db = NULL;
238     UINT ret = ERROR_FUNCTION_FAILED;
239     LPWSTR szMode;
240     STATSTG stat;
241
242     TRACE("%s %s\n",debugstr_w(szDBPath),debugstr_w(szPersist) );
243
244     if( !pdb )
245         return ERROR_INVALID_PARAMETER;
246
247     szMode = (LPWSTR) szPersist;
248     if( HIWORD( szPersist ) )
249     {
250         /* UINT len = lstrlenW( szPerist ) + 1; */
251         FIXME("don't support persist files yet\b");
252         return ERROR_INVALID_PARAMETER;
253         /* szMode = HeapAlloc( GetProcessHeap(), 0, len * sizeof (DWORD) ); */
254     }
255     else if( szPersist == MSIDBOPEN_READONLY )
256     {
257         r = StgOpenStorage( szDBPath, NULL,
258               STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
259     }
260     else if( szPersist == MSIDBOPEN_CREATE )
261     {
262         r = StgCreateDocfile( szDBPath, 
263               STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, 0, &stg);
264         if( r == ERROR_SUCCESS )
265         {
266             IStorage_SetClass( stg, &CLSID_MsiDatabase );
267             r = init_string_table( stg );
268         }
269     }
270     else if( szPersist == MSIDBOPEN_TRANSACT )
271     {
272         r = StgOpenStorage( szDBPath, NULL,
273               STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
274     }
275     else
276     {
277         ERR("unknown flag %p\n",szPersist);
278         return ERROR_INVALID_PARAMETER;
279     }
280
281     if( FAILED( r ) )
282     {
283         FIXME("open failed r = %08lx!\n",r);
284         return ERROR_FUNCTION_FAILED;
285     }
286
287     r = IStorage_Stat( stg, &stat, STATFLAG_NONAME );
288     if( FAILED( r ) )
289     {
290         FIXME("Failed to stat storage\n");
291         goto end;
292     }
293
294     if( memcmp( &stat.clsid, &CLSID_MsiDatabase, sizeof (GUID) ) )
295     {
296         ERR("storage GUID is not a MSI database GUID %s\n",
297              debugstr_guid(&stat.clsid) );
298         goto end;
299     }
300
301
302     db = alloc_msiobject( MSIHANDLETYPE_DATABASE, sizeof (MSIDATABASE),
303                               MSI_CloseDatabase );
304     if( !db )
305     {
306         FIXME("Failed to allocate a handle\n");
307         goto end;
308     }
309
310     if( TRACE_ON( msi ) )
311         enum_stream_names( stg );
312
313     db->storage = stg;
314     db->mode = szMode;
315
316     ret = load_string_table( db );
317     if( ret != ERROR_SUCCESS )
318         goto end;
319
320     msiobj_addref( &db->hdr );
321     IStorage_AddRef( stg );
322     *pdb = db;
323
324 end:
325     if( db )
326         msiobj_release( &db->hdr );
327     if( stg )
328         IStorage_Release( stg );
329
330     return ret;
331 }
332
333 UINT WINAPI MsiOpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIHANDLE *phDB)
334 {
335     MSIDATABASE *db;
336     UINT ret;
337
338     TRACE("%s %s %p\n",debugstr_w(szDBPath),debugstr_w(szPersist), phDB);
339
340     ret = MSI_OpenDatabaseW( szDBPath, szPersist, &db );
341     if( ret == ERROR_SUCCESS )
342     {
343         *phDB = alloc_msihandle( &db->hdr );
344         msiobj_release( &db->hdr );
345     }
346
347     return ret;
348 }
349
350 UINT WINAPI MsiOpenDatabaseA(LPCSTR szDBPath, LPCSTR szPersist, MSIHANDLE *phDB)
351 {
352     HRESULT r = ERROR_FUNCTION_FAILED;
353     LPWSTR szwDBPath = NULL, szwPersist = NULL;
354     UINT len;
355
356     TRACE("%s %s %p\n", debugstr_a(szDBPath), debugstr_a(szPersist), phDB);
357
358     if( szDBPath )
359     {
360         len = MultiByteToWideChar( CP_ACP, 0, szDBPath, -1, NULL, 0 );
361         szwDBPath = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
362         if( !szwDBPath )
363             goto end;
364         MultiByteToWideChar( CP_ACP, 0, szDBPath, -1, szwDBPath, len );
365     }
366
367     if( HIWORD(szPersist) )
368     {
369         len = MultiByteToWideChar( CP_ACP, 0, szPersist, -1, NULL, 0 );
370         szwPersist = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
371         if( !szwPersist )
372             goto end;
373         MultiByteToWideChar( CP_ACP, 0, szPersist, -1, szwPersist, len );
374     }
375     else
376         szwPersist = (LPWSTR) szPersist;
377
378     r = MsiOpenDatabaseW( szwDBPath, szwPersist, phDB );
379
380 end:
381     if( szwPersist )
382         HeapFree( GetProcessHeap(), 0, szwPersist );
383     if( szwDBPath )
384         HeapFree( GetProcessHeap(), 0, szwDBPath );
385
386     return r;
387 }
388
389 UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct)
390 {
391     UINT len, ret;
392     LPWSTR szwProd = NULL;
393
394     TRACE("%s %p\n",debugstr_a(szProduct), phProduct);
395
396     if( szProduct )
397     {
398         len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
399         szwProd = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
400         if( szwProd )
401             MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProd, len );
402     }
403
404     ret = MsiOpenProductW( szwProd, phProduct );
405
406     if( szwProd )
407         HeapFree( GetProcessHeap(), 0, szwProd );
408
409     return ret;
410 }
411
412 UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct)
413 {
414     static const WCHAR szKey[] = {
415         'S','o','f','t','w','a','r','e','\\',
416         'M','i','c','r','o','s','o','f','t','\\',
417         'W','i','n','d','o','w','s','\\',
418         'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
419         'U','n','i','n','s','t','a','l','l',0 };
420     static const WCHAR szLocalPackage[] = {
421         'L','o','c','a','l','P','a','c','k','a','g','e', 0
422     };
423     LPWSTR path = NULL;
424     UINT r;
425     HKEY hKeyProduct = NULL, hKeyUninstall = NULL;
426     DWORD count, type;
427
428     TRACE("%s %p\n",debugstr_w(szProduct), phProduct);
429
430     r = RegOpenKeyW( HKEY_LOCAL_MACHINE, szKey, &hKeyUninstall );
431     if( r != ERROR_SUCCESS )
432         return ERROR_UNKNOWN_PRODUCT;
433
434     r = RegOpenKeyW( hKeyUninstall, szProduct, &hKeyProduct );
435     if( r != ERROR_SUCCESS )
436     {
437         r = ERROR_UNKNOWN_PRODUCT;
438         goto end;
439     }
440
441     /* find the size of the path */
442     type = count = 0;
443     r = RegQueryValueExW( hKeyProduct, szLocalPackage,
444                           NULL, &type, NULL, &count );
445     if( r != ERROR_SUCCESS )
446     {
447         r = ERROR_UNKNOWN_PRODUCT;
448         goto end;
449     }
450
451     /* now alloc and fetch the path of the database to open */
452     path = HeapAlloc( GetProcessHeap(), 0, count );
453     if( !path )
454         goto end;
455
456     r = RegQueryValueExW( hKeyProduct, szLocalPackage,
457                           NULL, &type, (LPBYTE) path, &count );
458     if( r != ERROR_SUCCESS )
459     {
460         r = ERROR_UNKNOWN_PRODUCT;
461         goto end;
462     }
463
464     r = MsiOpenPackageW( path, phProduct );
465
466 end:
467     if( path )
468         HeapFree( GetProcessHeap(), 0, path );
469     if( hKeyProduct )
470         RegCloseKey( hKeyProduct );
471     RegCloseKey( hKeyUninstall );
472
473     return r;
474 }
475
476 UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath, LPCSTR szTransforms, LANGID lgidLanguage)
477 {
478     FIXME("%s %s %s 0x%08x\n",debugstr_a(szPackagePath), debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage);
479     return ERROR_CALL_NOT_IMPLEMENTED;
480 }
481
482 UINT WINAPI MsiAdvertiseProductW(LPCWSTR szPackagePath, LPCWSTR szScriptfilePath, LPCWSTR szTransforms, LANGID lgidLanguage)
483 {
484     FIXME("%s %s %s 0x%08x\n",debugstr_w(szPackagePath), debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage);
485     return ERROR_CALL_NOT_IMPLEMENTED;
486 }
487
488 UINT WINAPI MsiAdvertiseProductExA(LPCSTR szPackagePath, LPCSTR szScriptfilePath, LPCSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
489 {
490     FIXME("%s %s %s 0x%08x 0x%08lx 0x%08lx\n",
491         debugstr_a(szPackagePath), debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage, dwPlatform, dwOptions);
492     return ERROR_CALL_NOT_IMPLEMENTED;
493 }
494
495 UINT WINAPI MsiAdvertiseProductExW( LPCWSTR szPackagePath, LPCWSTR szScriptfilePath, LPCWSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
496 {
497     FIXME("%s %s %s 0x%08x 0x%08lx 0x%08lx\n",
498         debugstr_w(szPackagePath), debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage, dwPlatform, dwOptions);
499     return ERROR_CALL_NOT_IMPLEMENTED;
500 }
501
502 UINT WINAPI MsiInstallProductA(LPCSTR szPackagePath, LPCSTR szCommandLine)
503 {
504     LPWSTR szwPath = NULL, szwCommand = NULL;
505     UINT r = ERROR_FUNCTION_FAILED; /* FIXME: check return code */
506
507     TRACE("%s %s\n",debugstr_a(szPackagePath), debugstr_a(szCommandLine));
508
509     if( szPackagePath )
510     {
511         UINT len = MultiByteToWideChar( CP_ACP, 0, szPackagePath, -1, NULL, 0 );
512         szwPath = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
513         if( !szwPath )
514             goto end;
515         MultiByteToWideChar( CP_ACP, 0, szPackagePath, -1, szwPath, len );
516     }
517
518     if( szCommandLine )
519     {
520         UINT len = MultiByteToWideChar( CP_ACP, 0, szCommandLine, -1, NULL, 0 );
521         szwCommand = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
522         if( !szwCommand )
523             goto end;
524         MultiByteToWideChar( CP_ACP, 0, szCommandLine, -1, szwCommand, len );
525     }
526  
527     r = MsiInstallProductW( szwPath, szwCommand );
528
529 end:
530     if( szwPath )
531         HeapFree( GetProcessHeap(), 0, szwPath );
532     
533     if( szwCommand )
534         HeapFree( GetProcessHeap(), 0, szwCommand );
535
536     return r;
537 }
538
539 UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
540 {
541     MSIPACKAGE *package = NULL;
542     UINT rc = ERROR_SUCCESS; 
543     MSIHANDLE handle;
544
545     FIXME("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
546
547     rc = MsiVerifyPackageW(szPackagePath);
548     if (rc != ERROR_SUCCESS)
549         return rc;
550
551     rc = MSI_OpenPackageW(szPackagePath,&package);
552     if (rc != ERROR_SUCCESS)
553         return rc;
554
555     handle = alloc_msihandle( &package->hdr );
556
557     rc = ACTION_DoTopLevelINSTALL(package, szPackagePath, szCommandLine);
558
559     MsiCloseHandle(handle);
560     msiobj_release( &package->hdr );
561     return rc;
562 }
563
564 UINT WINAPI MsiReinstallProductA(LPCSTR szProduct, DWORD dwReinstallMode)
565 {
566         FIXME("%s 0x%08lx\n", debugstr_a(szProduct), dwReinstallMode);
567         return ERROR_CALL_NOT_IMPLEMENTED;
568 }
569
570 UINT WINAPI MsiReinstallProductW(LPCWSTR szProduct, DWORD dwReinstallMode)
571 {
572         FIXME("%s 0x%08lx\n", debugstr_w(szProduct), dwReinstallMode);
573         return ERROR_CALL_NOT_IMPLEMENTED;
574 }
575
576 UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel, INSTALLSTATE eInstallState)
577 {
578     LPWSTR szwProduct = NULL;
579     UINT hr = ERROR_SUCCESS;
580
581     FIXME("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState);
582
583     if( szProduct )
584     {
585         UINT len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
586         szwProduct = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
587         if( !szwProduct )
588             goto end;
589         MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
590     }
591
592     hr = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState );
593
594 end:
595     if( szwProduct )
596         HeapFree( GetProcessHeap(), 0, szwProduct );
597
598     return hr;
599 }
600
601 UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel, INSTALLSTATE eInstallState)
602 {
603     FIXME("%s %d %d\n",debugstr_w(szProduct), iInstallLevel, eInstallState);
604     return ERROR_CALL_NOT_IMPLEMENTED;
605 }
606
607 UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer)
608 {
609     LPWSTR szwComponent = NULL, szwBuffer = NULL;
610     UINT hr = ERROR_INSTALL_FAILURE;
611
612     FIXME("%s %s\n",debugstr_a(szComponent), debugstr_a(szBuffer));
613
614     if( szComponent )
615     {
616         UINT len = MultiByteToWideChar( CP_ACP, 0, szComponent, -1, NULL, 0 );
617         szwComponent = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
618         if( !szwComponent )
619             goto end;
620         MultiByteToWideChar( CP_ACP, 0, szComponent, -1, szwComponent, len );
621     } else {
622       return ERROR_INVALID_PARAMETER;
623     }
624
625     {
626         szwBuffer = HeapAlloc( GetProcessHeap(), 0, GUID_SIZE * sizeof(WCHAR) );
627         if( !szwBuffer )         
628             goto end;
629     }
630
631     hr = MsiGetProductCodeW( szwComponent, szwBuffer );
632
633     if( ERROR_SUCCESS == hr )
634     {
635         WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, GUID_SIZE, NULL, NULL);
636     }
637
638 end:
639     if( szwComponent )
640         HeapFree( GetProcessHeap(), 0, szwComponent );
641     if( szwBuffer )
642         HeapFree( GetProcessHeap(), 0, szwBuffer );
643
644     return hr;
645 }
646
647 UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer)
648 {
649     FIXME("%s %s\n",debugstr_w(szComponent), debugstr_w(szBuffer));
650     if (NULL == szComponent) {
651       return ERROR_INVALID_PARAMETER;
652     }
653     return ERROR_CALL_NOT_IMPLEMENTED;
654 }
655
656
657
658
659 UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute, LPSTR szBuffer, DWORD *pcchValueBuf)
660 {
661     LPWSTR szwProduct = NULL, szwAttribute = NULL, szwBuffer = NULL;
662     UINT hr = ERROR_INSTALL_FAILURE;
663
664     FIXME("%s %s %p %p\n",debugstr_a(szProduct), debugstr_a(szAttribute), szBuffer, pcchValueBuf);
665
666     if (NULL != szBuffer && NULL == pcchValueBuf) {
667       return ERROR_INVALID_PARAMETER;
668     }
669     if( szProduct )
670     {
671         UINT len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
672         szwProduct = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
673         if( !szwProduct )
674             goto end;
675         MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
676     } else {
677       return ERROR_INVALID_PARAMETER;
678     }
679     
680     if( szAttribute )
681     {
682         UINT len = MultiByteToWideChar( CP_ACP, 0, szAttribute, -1, NULL, 0 );
683         szwAttribute = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
684         if( !szwAttribute )
685             goto end;
686         MultiByteToWideChar( CP_ACP, 0, szAttribute, -1, szwAttribute, len );
687     } else {
688       return ERROR_INVALID_PARAMETER;
689     }
690
691     if( szBuffer )
692     {
693         szwBuffer = HeapAlloc( GetProcessHeap(), 0, (*pcchValueBuf) * sizeof(WCHAR) );
694         if( !szwBuffer )         
695             goto end;
696     }
697
698     hr = MsiGetProductInfoW( szwProduct, szwAttribute, szwBuffer, pcchValueBuf );
699
700     if( ERROR_SUCCESS == hr )
701     {
702         WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, *pcchValueBuf, NULL, NULL);
703     }
704
705 end:
706     if( szwProduct )
707         HeapFree( GetProcessHeap(), 0, szwProduct );
708     if( szwAttribute )
709         HeapFree( GetProcessHeap(), 0, szwAttribute );
710     if( szwBuffer )
711         HeapFree( GetProcessHeap(), 0, szwBuffer );
712
713     return hr;    
714 }
715
716 UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute, LPWSTR szBuffer, DWORD *pcchValueBuf)
717 {
718     MSIHANDLE hProduct;
719     UINT hr;
720     
721     FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szAttribute), szBuffer, pcchValueBuf);
722
723     if (NULL != szBuffer && NULL == pcchValueBuf) {
724       return ERROR_INVALID_PARAMETER;
725     }
726     if (NULL == szProduct || NULL == szAttribute) {
727       return ERROR_INVALID_PARAMETER;
728     }
729
730     hr = MsiOpenProductW(szProduct, &hProduct);
731     if (ERROR_SUCCESS != hr) return hr;
732
733     hr = MsiGetPropertyW(hProduct, szAttribute, szBuffer, pcchValueBuf);
734     MsiCloseHandle(hProduct);
735     return hr;
736 }
737
738 UINT WINAPI MsiDatabaseImportA(LPCSTR szFolderPath, LPCSTR szFilename)
739 {
740     FIXME("%s %s\n",debugstr_a(szFolderPath), debugstr_a(szFilename));
741     return ERROR_CALL_NOT_IMPLEMENTED;
742 }
743
744 UINT WINAPI MsiDatabaseImportW(LPCWSTR szFolderPath, LPCWSTR szFilename)
745 {
746     FIXME("%s %s\n",debugstr_w(szFolderPath), debugstr_w(szFilename));
747     return ERROR_CALL_NOT_IMPLEMENTED;
748 }
749
750 UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, BOOL fAppend)
751 {
752     LPWSTR szwLogFile = NULL;
753     UINT hr = ERROR_INSTALL_FAILURE;
754
755     FIXME("%08lx %s %d\n", dwLogMode, debugstr_a(szLogFile), fAppend);
756
757     if( szLogFile )
758     {
759         UINT len = MultiByteToWideChar( CP_ACP, 0, szLogFile, -1, NULL, 0 );
760         szwLogFile = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
761         if( !szwLogFile )
762             goto end;
763         MultiByteToWideChar( CP_ACP, 0, szLogFile, -1, szwLogFile, len );
764     } else {
765       return ERROR_INVALID_PARAMETER;
766     }
767
768     hr = MsiEnableLogW( dwLogMode, szwLogFile, fAppend );
769
770 end:
771     if( szwLogFile )
772         HeapFree( GetProcessHeap(), 0, szwLogFile );
773
774     return hr;
775 }
776
777 UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, BOOL fAppend)
778 {
779     HANDLE the_file = INVALID_HANDLE_VALUE;
780     TRACE("%08lx %s %d\n", dwLogMode, debugstr_w(szLogFile), fAppend);
781     strcpyW(gszLogFile,szLogFile);
782     if (!fAppend)
783         DeleteFileW(szLogFile);
784     the_file = CreateFileW(szLogFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
785                            FILE_ATTRIBUTE_NORMAL, NULL);
786     if (the_file != INVALID_HANDLE_VALUE)
787         CloseHandle(the_file);
788     else
789         ERR("Unable to enable log %s\n",debugstr_w(szLogFile));
790
791     return ERROR_SUCCESS;
792 }
793
794 INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct)
795 {
796     FIXME("%s\n", debugstr_a(szProduct));
797     return INSTALLSTATE_UNKNOWN;
798 }
799
800 INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct)
801 {
802     FIXME("%s\n", debugstr_w(szProduct));
803     return INSTALLSTATE_UNKNOWN;
804 }
805
806 INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd)
807 {
808     INSTALLUILEVEL old = gUILevel;
809     HWND oldwnd = gUIhwnd;
810     TRACE("%08x %p\n", dwUILevel, phWnd);
811
812     gUILevel = dwUILevel;
813     if (phWnd)
814     {
815         gUIhwnd = *phWnd;
816         *phWnd = oldwnd;
817     }
818     return old;
819 }
820
821 INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler, 
822                                   DWORD dwMessageFilter, LPVOID pvContext)
823 {
824     INSTALLUI_HANDLERA prev = gUIHandler;
825
826     TRACE("(%p %lx %p)\n",puiHandler,dwMessageFilter,pvContext);
827     gUIHandler = puiHandler;
828     gUIFilter = dwMessageFilter;
829     gUIContext = pvContext;
830
831     return prev;
832 }
833
834 UINT WINAPI MsiLoadStringA(HINSTANCE hInstance, UINT uID, LPSTR lpBuffer, int nBufferMax, DWORD e)
835 {
836     /*FIXME("%08lx %08lx %08lx %08lx %08lx\n",a,b,c,d,e);*/
837     FIXME("%p %u %p %d %08lx\n",hInstance,uID,lpBuffer,nBufferMax,e);
838     return ERROR_CALL_NOT_IMPLEMENTED;
839 }
840
841 UINT WINAPI MsiLoadStringW(HINSTANCE hInstance, UINT uID, LPWSTR lpBuffer, int nBufferMax, DWORD e)
842 {
843     FIXME("%p %u %p %d %08lx\n",hInstance,uID,lpBuffer,nBufferMax,e);
844     /*
845     int ret =  LoadStringW(hInstance,uID,lpBuffer,nBufferMax);
846     FIXME("%s\n",debugstr_w(lpBuffer));
847     return ret;
848     */
849     return ERROR_CALL_NOT_IMPLEMENTED;
850 }
851
852 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf, DWORD *pcchBuf)
853 {
854     FIXME("%s %p %08lx\n", debugstr_a(szComponent), lpPathBuf, *pcchBuf);
855     return INSTALLSTATE_UNKNOWN;
856 }
857
858 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPSTR lpPathBuf, DWORD *pcchBuf)
859 {
860     FIXME("%s %p %08lx\n", debugstr_w(szComponent), lpPathBuf, *pcchBuf);
861     return INSTALLSTATE_UNKNOWN;
862 }
863
864 #include "winuser.h"
865
866 UINT WINAPI MsiMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, WORD wLanguageId, DWORD f)
867 {
868     FIXME("%p %s %s %u %08x %08lx\n",hWnd,debugstr_a(lpText),debugstr_a(lpCaption),uType,wLanguageId,f);
869     /*
870     MessageBoxExA(hWnd,lpText,lpCaption,uType|MB_OK,wLanguageId);
871     */
872     return ERROR_CALL_NOT_IMPLEMENTED;
873 }
874
875 UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType, WORD wLanguageId, DWORD f)
876 {
877     /*FIXME("%08lx %08lx %08lx %08lx %08lx %08lx\n",a,b,c,d,e,f);*/
878     FIXME("%p %s %s %u %08x %08lx\n",hWnd,debugstr_w(lpText),debugstr_w(lpCaption),uType,wLanguageId,f);
879     /*
880     MessageBoxExW(hWnd,lpText,lpCaption,uType|MB_OK,wLanguageId);
881     */
882     return ERROR_CALL_NOT_IMPLEMENTED;
883 }
884
885 UINT WINAPI MsiEnumProductsA(DWORD index, LPSTR lpguid)
886 {
887     DWORD r;
888     WCHAR szwGuid[GUID_SIZE];
889
890     TRACE("%ld %p\n",index,lpguid);
891     
892     if (NULL == lpguid) {
893       return ERROR_INVALID_PARAMETER;
894     }
895     r = MsiEnumProductsW(index, szwGuid);
896     if( r == ERROR_SUCCESS )
897         WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
898
899     return r;
900 }
901
902 UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid)
903 {
904     HKEY hkey = 0, hkeyFeatures = 0;
905     DWORD r;
906     WCHAR szKeyName[33];
907
908     TRACE("%ld %p\n",index,lpguid);
909
910     if (NULL == lpguid) {
911       return ERROR_INVALID_PARAMETER;
912     }
913     r = RegOpenKeyW(HKEY_LOCAL_MACHINE, szInstaller, &hkey);
914     if( r != ERROR_SUCCESS )
915         goto end;
916
917     r = RegOpenKeyW(hkey, szFeatures, &hkeyFeatures);
918     if( r != ERROR_SUCCESS )
919         goto end;
920
921     r = RegEnumKeyW(hkeyFeatures, index, szKeyName, GUID_SIZE);
922
923     unsquash_guid(szKeyName, lpguid);
924
925 end:
926
927     if( hkeyFeatures )
928         RegCloseKey(hkeyFeatures);
929     if( hkey )
930         RegCloseKey(hkey);
931
932     return r;
933 }
934
935 UINT WINAPI MsiEnumFeaturesA(LPCSTR szProduct, DWORD index, 
936       LPSTR szFeature, LPSTR szParent)
937 {
938     DWORD r;
939     WCHAR szwFeature[GUID_SIZE], szwParent[GUID_SIZE];
940     LPWSTR szwProduct = NULL;
941
942     TRACE("%s %ld %p %p\n",debugstr_a(szProduct),index,szFeature,szParent);
943
944     if( szProduct )
945     {
946         UINT len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
947         szwProduct = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
948         if( szwProduct )
949             MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
950         else
951             return ERROR_FUNCTION_FAILED;
952     }
953
954     r = MsiEnumFeaturesW(szwProduct, index, szwFeature, szwParent);
955     if( r == ERROR_SUCCESS )
956     {
957         WideCharToMultiByte(CP_ACP, 0, szwFeature, -1,
958                             szFeature, GUID_SIZE, NULL, NULL);
959         WideCharToMultiByte(CP_ACP, 0, szwParent, -1,
960                             szParent, GUID_SIZE, NULL, NULL);
961     }
962
963     if( szwProduct )
964         HeapFree( GetProcessHeap(), 0, szwProduct);
965
966     return r;
967 }
968
969 UINT WINAPI MsiEnumFeaturesW(LPCWSTR szProduct, DWORD index, 
970       LPWSTR szFeature, LPWSTR szParent)
971 {
972     HKEY hkey = 0, hkeyFeatures = 0, hkeyProduct = 0;
973     DWORD r, sz;
974     WCHAR szRegName[GUID_SIZE];
975
976     TRACE("%s %ld %p %p\n",debugstr_w(szProduct),index,szFeature,szParent);
977
978     if( !squash_guid(szProduct, szRegName) )
979         return ERROR_INVALID_PARAMETER;
980
981     r = RegOpenKeyW(HKEY_LOCAL_MACHINE, szInstaller, &hkey);
982     if( r != ERROR_SUCCESS )
983         goto end;
984
985     r = RegOpenKeyW(hkey, szFeatures, &hkeyFeatures);
986     if( r != ERROR_SUCCESS )
987         goto end;
988
989     r = RegOpenKeyW(hkeyFeatures, szRegName, &hkeyProduct);
990     if( r != ERROR_SUCCESS )
991         goto end;
992
993     sz = GUID_SIZE;
994     r = RegEnumValueW(hkeyProduct, index, szFeature, &sz, NULL, NULL, NULL, NULL);
995
996 end:
997     if( hkeyProduct )
998         RegCloseKey(hkeyProduct);
999     if( hkeyFeatures )
1000         RegCloseKey(hkeyFeatures);
1001     if( hkey )
1002         RegCloseKey(hkey);
1003
1004     return r;
1005 }
1006
1007 UINT WINAPI MsiEnumComponentsA(DWORD index, LPSTR lpguid)
1008 {
1009     DWORD r;
1010     WCHAR szwGuid[GUID_SIZE];
1011
1012     TRACE("%ld %p\n",index,lpguid);
1013
1014     r = MsiEnumComponentsW(index, szwGuid);
1015     if( r == ERROR_SUCCESS )
1016         WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
1017
1018     return r;
1019 }
1020
1021 UINT WINAPI MsiEnumComponentsW(DWORD index, LPWSTR lpguid)
1022 {
1023     HKEY hkey = 0, hkeyComponents = 0;
1024     DWORD r;
1025     WCHAR szKeyName[33];
1026
1027     TRACE("%ld %p\n",index,lpguid);
1028
1029     r = RegOpenKeyW(HKEY_LOCAL_MACHINE, szInstaller, &hkey);
1030     if( r != ERROR_SUCCESS )
1031         goto end;
1032
1033     r = RegOpenKeyW(hkey, szComponents, &hkeyComponents);
1034     if( r != ERROR_SUCCESS )
1035         goto end;
1036
1037     r = RegEnumKeyW(hkeyComponents, index, szKeyName, GUID_SIZE);
1038
1039     unsquash_guid(szKeyName, lpguid);
1040
1041 end:
1042
1043     if( hkeyComponents )
1044         RegCloseKey(hkeyComponents);
1045     if( hkey )
1046         RegCloseKey(hkey);
1047
1048     return r;
1049 }
1050
1051 UINT WINAPI MsiEnumClientsA(LPCSTR szComponent, DWORD index, LPSTR szProduct)
1052 {
1053     DWORD r;
1054     WCHAR szwProduct[GUID_SIZE];
1055     LPWSTR szwComponent = NULL;
1056
1057     TRACE("%s %ld %p\n",debugstr_a(szComponent),index,szProduct);
1058
1059     if( szComponent )
1060     {
1061         UINT len = MultiByteToWideChar( CP_ACP, 0, szComponent, -1, NULL, 0 );
1062         szwComponent = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
1063         if( szwComponent )
1064             MultiByteToWideChar( CP_ACP, 0, szComponent, -1, szwComponent, len );
1065         else
1066             return ERROR_FUNCTION_FAILED;
1067     }
1068
1069     r = MsiEnumClientsW(szComponent?szwComponent:NULL, index, szwProduct);
1070     if( r == ERROR_SUCCESS )
1071     {
1072         WideCharToMultiByte(CP_ACP, 0, szwProduct, -1,
1073                             szProduct, GUID_SIZE, NULL, NULL);
1074     }
1075
1076     if( szwComponent )
1077         HeapFree( GetProcessHeap(), 0, szwComponent);
1078
1079     return r;
1080 }
1081
1082 UINT WINAPI MsiEnumClientsW(LPCWSTR szComponent, DWORD index, LPWSTR szProduct)
1083 {
1084     HKEY hkey = 0, hkeyComponents = 0, hkeyComp = 0;
1085     DWORD r, sz;
1086     WCHAR szRegName[GUID_SIZE], szValName[GUID_SIZE];
1087
1088     TRACE("%s %ld %p\n",debugstr_w(szComponent),index,szProduct);
1089
1090     if( !squash_guid(szComponent, szRegName) )
1091         return ERROR_INVALID_PARAMETER;
1092
1093     r = RegOpenKeyW(HKEY_LOCAL_MACHINE, szInstaller, &hkey);
1094     if( r != ERROR_SUCCESS )
1095         goto end;
1096
1097     r = RegOpenKeyW(hkey, szComponents, &hkeyComponents);
1098     if( r != ERROR_SUCCESS )
1099         goto end;
1100
1101     r = RegOpenKeyW(hkeyComponents, szRegName, &hkeyComp);
1102     if( r != ERROR_SUCCESS )
1103         goto end;
1104
1105     sz = GUID_SIZE;
1106     r = RegEnumValueW(hkeyComp, index, szValName, &sz, NULL, NULL, NULL, NULL);
1107     if( r != ERROR_SUCCESS )
1108         goto end;
1109
1110     unsquash_guid(szValName, szProduct);
1111
1112 end:
1113     if( hkeyComp )
1114         RegCloseKey(hkeyComp);
1115     if( hkeyComponents )
1116         RegCloseKey(hkeyComponents);
1117     if( hkey )
1118         RegCloseKey(hkey);
1119
1120     return r;
1121 }
1122
1123 UINT WINAPI MsiEnumComponentQualifiersA(
1124     LPSTR szComponent, DWORD iIndex, LPSTR lpQualifierBuf, DWORD* pcchQualifierBuf, LPSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf)
1125 {
1126 FIXME("%s 0x%08lx %p %p %p %p\n", debugstr_a(szComponent), iIndex, lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf, pcchApplicationDataBuf);
1127     return ERROR_CALL_NOT_IMPLEMENTED;
1128 }
1129
1130 UINT WINAPI MsiEnumComponentQualifiersW(
1131     LPWSTR szComponent, DWORD iIndex, LPWSTR lpQualifierBuf, DWORD* pcchQualifierBuf, LPWSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf)
1132 {
1133 FIXME("%s 0x%08lx %p %p %p %p\n", debugstr_w(szComponent), iIndex, lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf, pcchApplicationDataBuf);
1134     return ERROR_CALL_NOT_IMPLEMENTED;
1135 }
1136
1137 UINT WINAPI MsiProvideAssemblyA(
1138     LPCSTR szAssemblyName, LPCSTR szAppContext, DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf, DWORD* pcchPathBuf) 
1139 {
1140     FIXME("%s %s 0x%08lx 0x%08lx %p %p\n", 
1141         debugstr_a(szAssemblyName),  debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf, pcchPathBuf);
1142     return ERROR_CALL_NOT_IMPLEMENTED;
1143 }
1144
1145 UINT WINAPI MsiProvideAssemblyW(
1146     LPCWSTR szAssemblyName, LPCWSTR szAppContext, DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf, DWORD* pcchPathBuf) 
1147 {
1148     FIXME("%s %s 0x%08lx 0x%08lx %p %p\n", 
1149         debugstr_w(szAssemblyName),  debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf, pcchPathBuf);
1150     return ERROR_CALL_NOT_IMPLEMENTED;
1151 }
1152
1153 UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor, LPSTR szPath, DWORD *pcchPath, DWORD *pcchArgs )
1154 {
1155     FIXME("%s %p %p %p\n", debugstr_a(szDescriptor), szPath, pcchPath, pcchArgs );
1156     return ERROR_CALL_NOT_IMPLEMENTED;
1157 }
1158
1159 UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor, LPWSTR szPath, DWORD *pcchPath, DWORD *pcchArgs )
1160 {
1161     FIXME("%s %p %p %p\n", debugstr_w(szDescriptor), szPath, pcchPath, pcchArgs );
1162     return ERROR_CALL_NOT_IMPLEMENTED;
1163 }
1164
1165 HRESULT WINAPI MsiGetFileSignatureInformationA(
1166   LPCSTR szSignedObjectPath, DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData, DWORD* pcbHashData)
1167 {
1168     FIXME("%s 0x%08lx %p %p %p\n", debugstr_a(szSignedObjectPath), dwFlags, ppcCertContext, pbHashData, pcbHashData);
1169     return ERROR_CALL_NOT_IMPLEMENTED;
1170 }
1171
1172 HRESULT WINAPI MsiGetFileSignatureInformationW(
1173   LPCWSTR szSignedObjectPath, DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData, DWORD* pcbHashData)
1174 {
1175     FIXME("%s 0x%08lx %p %p %p\n", debugstr_w(szSignedObjectPath), dwFlags, ppcCertContext, pbHashData, pcbHashData);
1176     return ERROR_CALL_NOT_IMPLEMENTED;
1177 }
1178
1179 UINT WINAPI MsiGetProductPropertyA( MSIHANDLE hProduct, LPCSTR szProperty,
1180                                     LPSTR szValue, DWORD *pccbValue )
1181 {
1182     FIXME("%ld %s %p %p\n", hProduct, debugstr_a(szProperty), szValue, pccbValue);
1183     return ERROR_CALL_NOT_IMPLEMENTED;
1184 }
1185
1186 UINT WINAPI MsiGetProductPropertyW( MSIHANDLE hProduct, LPCWSTR szProperty,
1187                                     LPWSTR szValue, DWORD *pccbValue )
1188 {
1189     FIXME("%ld %s %p %p\n", hProduct, debugstr_w(szProperty), szValue, pccbValue);
1190     return ERROR_CALL_NOT_IMPLEMENTED;
1191 }
1192
1193 UINT WINAPI MsiVerifyPackageA( LPCSTR szPackage )
1194 {
1195     UINT r, len;
1196     LPWSTR szPack = NULL;
1197
1198     TRACE("%s\n", debugstr_a(szPackage) );
1199
1200     if( szPackage )
1201     {
1202         len = MultiByteToWideChar( CP_ACP, 0, szPackage, -1, NULL, 0 );
1203         szPack = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1204         if( !szPack )
1205             return ERROR_OUTOFMEMORY;
1206         MultiByteToWideChar( CP_ACP, 0, szPackage, -1, szPack, len );
1207     }
1208
1209     r = MsiVerifyPackageW( szPack );
1210
1211     HeapFree( GetProcessHeap(), 0, szPack );
1212
1213     return r;
1214 }
1215
1216 UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage )
1217 {
1218     MSIHANDLE handle;
1219     UINT r;
1220
1221     TRACE("%s\n", debugstr_w(szPackage) );
1222
1223     r = MsiOpenDatabaseW( szPackage, MSIDBOPEN_READONLY, &handle );
1224     MsiCloseHandle( handle );
1225
1226     return r;
1227 }
1228
1229 INSTALLSTATE WINAPI MsiGetComponentPathA(LPCSTR szProduct, LPCSTR szComponent,
1230                                          LPSTR lpPathBuf, DWORD* pcchBuf)
1231 {
1232     INSTALLSTATE rc;
1233     UINT len;
1234     LPWSTR szwProduct= NULL;
1235     LPWSTR szwComponent= NULL;
1236     LPWSTR lpwPathBuf= NULL;
1237
1238     if( szProduct)
1239     {
1240         len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
1241         szwProduct= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1242         if( !szwProduct)
1243             return ERROR_OUTOFMEMORY;
1244         MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
1245     }
1246
1247     if( szComponent)
1248     {
1249         len = MultiByteToWideChar( CP_ACP, 0, szComponent, -1, NULL, 0 );
1250         szwComponent= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1251         if( !szwComponent)
1252             return ERROR_OUTOFMEMORY;
1253         MultiByteToWideChar( CP_ACP, 0, szComponent, -1, szwComponent, len );
1254     }
1255
1256     if (pcchBuf && *pcchBuf > 0)
1257         lpwPathBuf = HeapAlloc( GetProcessHeap(), 0, *pcchBuf * sizeof(WCHAR));
1258     else
1259         lpwPathBuf = NULL;
1260
1261     rc = MsiGetComponentPathW(szwProduct, szwComponent, lpwPathBuf, pcchBuf);
1262
1263     HeapFree( GetProcessHeap(), 0, szwProduct);
1264     HeapFree( GetProcessHeap(), 0, szwComponent);
1265     if (lpwPathBuf)
1266     {
1267         WideCharToMultiByte(CP_ACP, 0, lpwPathBuf, *pcchBuf,
1268                             lpPathBuf, GUID_SIZE, NULL, NULL);
1269         HeapFree( GetProcessHeap(), 0, lpwPathBuf);
1270     }
1271
1272     return rc;
1273 }
1274
1275 INSTALLSTATE WINAPI MsiGetComponentPathW(LPCWSTR szProduct, LPCWSTR szComponent,
1276                                          LPWSTR lpPathBuf, DWORD* pcchBuf)
1277 {
1278     FIXME("STUB: (%s %s %p %p)\n", debugstr_w(szProduct),
1279            debugstr_w(szComponent), lpPathBuf, pcchBuf);
1280
1281     return INSTALLSTATE_UNKNOWN;
1282 }
1283
1284 INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature)
1285 {
1286     INSTALLSTATE rc;
1287     UINT len;
1288     LPWSTR szwProduct= NULL;
1289     LPWSTR szwFeature= NULL;
1290
1291     if( szProduct)
1292     {
1293         len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
1294         szwProduct= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1295         if( !szwProduct)
1296             return ERROR_OUTOFMEMORY;
1297         MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
1298     }
1299
1300     if( szFeature)
1301     {
1302         len = MultiByteToWideChar( CP_ACP, 0, szFeature, -1, NULL, 0 );
1303         szwFeature= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1304         if( !szwFeature)
1305             return ERROR_OUTOFMEMORY;
1306         MultiByteToWideChar( CP_ACP, 0, szFeature, -1, szwFeature, len );
1307     }
1308
1309     rc = MsiQueryFeatureStateW(szwProduct, szwFeature);
1310
1311     HeapFree( GetProcessHeap(), 0, szwProduct);
1312     HeapFree( GetProcessHeap(), 0, szwFeature);
1313
1314     return rc;
1315 }
1316
1317 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
1318 {
1319     FIXME("STUB: (%s %s)\n", debugstr_w(szProduct), debugstr_w(szFeature));
1320     return INSTALLSTATE_UNKNOWN;
1321 }
1322
1323
1324 /******************************************************************
1325  *              DllMain
1326  *
1327  * @todo: maybe we can check here if MsiServer service is declared no ?
1328  */
1329 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
1330   if (fdwReason == DLL_PROCESS_ATTACH) {
1331     DisableThreadLibraryCalls(hinstDLL);
1332     /*
1333      * UI Initialization
1334      */
1335     gUILevel = INSTALLUILEVEL_BASIC;
1336     gUIhwnd = 0;
1337     gUIHandler = NULL;
1338     gUIFilter = 0;
1339     gUIContext = NULL;
1340     gszLogFile[0]=0;
1341     /* FIXME: Initialisation */
1342   } else if (fdwReason == DLL_PROCESS_DETACH) {
1343     /* FIXME: Cleanup */
1344   }
1345   /*
1346   static const WCHAR szMSIServerSvc[] = { 'M','S','I','S','e','r','v','e','r',0 };
1347   static const WCHAR szNull[] = { 0 };
1348   if (!strcmpW(lpServiceName, szMSIServerSvc)) {
1349     hKey = CreateServiceW(hSCManager, 
1350                           szMSIServerSvc, 
1351                           szMSIServerSvc, 
1352                           SC_MANAGER_ALL_ACCESS, 
1353                           SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS, 
1354                           SERVICE_AUTO_START, 
1355                           SERVICE_ERROR_IGNORE,
1356                           szNull, 
1357                           NULL, 
1358                           NULL,
1359                           NULL,
1360                           NULL,
1361                           szNull);
1362   */
1363   return TRUE;
1364 }
1365
1366 typedef struct {
1367   /* IUnknown fields */
1368   ICOM_VFIELD(IClassFactory);
1369   DWORD                       ref;
1370 } IClassFactoryImpl;
1371
1372 static HRESULT WINAPI MsiCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
1373   ICOM_THIS(IClassFactoryImpl,iface);
1374   FIXME("(%p, %s, %p): stub\n",This,debugstr_guid(riid),ppobj);
1375   return E_NOINTERFACE;
1376 }
1377
1378 static ULONG WINAPI MsiCF_AddRef(LPCLASSFACTORY iface) {
1379   ICOM_THIS(IClassFactoryImpl,iface);
1380   return ++(This->ref);
1381 }
1382
1383 static ULONG WINAPI MsiCF_Release(LPCLASSFACTORY iface) {
1384   ICOM_THIS(IClassFactoryImpl,iface);
1385   /* static class, won't be  freed */
1386   return --(This->ref);
1387 }
1388
1389 static HRESULT WINAPI MsiCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) {
1390   ICOM_THIS(IClassFactoryImpl,iface);
1391   FIXME ("(%p, %p, %s, %p): to implement\n", This, pOuter, debugstr_guid(riid), ppobj);
1392   return 0;
1393 }
1394
1395 static HRESULT WINAPI MsiCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
1396   ICOM_THIS(IClassFactoryImpl,iface);
1397   FIXME("(%p, %d): stub\n", This, dolock);
1398   return S_OK;
1399 }
1400
1401 static ICOM_VTABLE(IClassFactory) MsiCF_Vtbl = {
1402   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1403   MsiCF_QueryInterface,
1404   MsiCF_AddRef,
1405   MsiCF_Release,
1406   MsiCF_CreateInstance,
1407   MsiCF_LockServer
1408 };
1409
1410 static IClassFactoryImpl Msi_CF = {&MsiCF_Vtbl, 1 };
1411
1412 /******************************************************************
1413  *              DllGetClassObject (MSI.@)
1414  */
1415 HRESULT WINAPI MSI_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) {
1416   FIXME("(%s, %s, %p): almost a stub.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
1417   if (IsEqualCLSID (rclsid, &CLSID_IMsiServer)) {
1418     *ppv = (LPVOID) &Msi_CF;
1419     IClassFactory_AddRef((IClassFactory*)*ppv);
1420     return S_OK;
1421   } else if (IsEqualCLSID (rclsid, &CLSID_IMsiServerMessage)) {
1422     *ppv = (LPVOID) &Msi_CF;
1423     IClassFactory_AddRef((IClassFactory*)*ppv);
1424     return S_OK;
1425   } else if (IsEqualCLSID (rclsid, &CLSID_IMsiServerX1)) {
1426     *ppv = (LPVOID) &Msi_CF;
1427     IClassFactory_AddRef((IClassFactory*)*ppv);
1428     return S_OK;
1429   } else if (IsEqualCLSID (rclsid, &CLSID_IMsiServerX2)) {
1430     *ppv = (LPVOID) &Msi_CF;
1431     IClassFactory_AddRef((IClassFactory*)*ppv);
1432     return S_OK;
1433   } else if (IsEqualCLSID (rclsid, &CLSID_IMsiServerX3)) {
1434     *ppv = (LPVOID) &Msi_CF;
1435     IClassFactory_AddRef((IClassFactory*)*ppv);
1436     return S_OK;
1437   }
1438   WARN("(%s, %s, %p): no interface found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
1439   return CLASS_E_CLASSNOTAVAILABLE;
1440 }
1441
1442 /******************************************************************
1443  *              DllGetVersion (MSI.@)
1444  */
1445 HRESULT WINAPI MSI_DllGetVersion(DLLVERSIONINFO *pdvi)
1446 {
1447   TRACE("%p\n",pdvi);
1448   
1449   if (pdvi->cbSize != sizeof(DLLVERSIONINFO))
1450     return E_INVALIDARG;
1451   
1452   pdvi->dwMajorVersion = MSI_MAJORVERSION;
1453   pdvi->dwMinorVersion = MSI_MINORVERSION;
1454   pdvi->dwBuildNumber = MSI_BUILDNUMBER;
1455   pdvi->dwPlatformID = 1;
1456   
1457   return S_OK;
1458 }
1459
1460 /******************************************************************
1461  *              DllCanUnloadNow (MSI.@)
1462  */
1463 BOOL WINAPI MSI_DllCanUnloadNow(void)
1464 {
1465   return S_FALSE;
1466 }
1467
1468 UINT WINAPI MsiEnumRelatedProductsA (LPCSTR lpUpgradeCode, DWORD dwReserved,
1469                                     DWORD iProductIndex, LPSTR lpProductBuf)
1470 {
1471     FIXME("STUB: (%s, %li %li %s)\n",lpUpgradeCode, dwReserved, iProductIndex,
1472           lpProductBuf);
1473     return ERROR_CALL_NOT_IMPLEMENTED;
1474 }