Added a test for ConvertSidToStringSidW.
[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 MsiApplyPatchA(LPCSTR szPatchPackage, LPCSTR szInstallPackage, INSTALLTYPE eInstallType, LPCSTR szCommandLine)
577 {
578         FIXME("%s %s %d %s\n", debugstr_a(szPatchPackage), debugstr_a(szInstallPackage), eInstallType, debugstr_a(szCommandLine));
579         return ERROR_CALL_NOT_IMPLEMENTED;
580 }
581
582 UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage, INSTALLTYPE eInstallType, LPCWSTR szCommandLine)
583 {
584         FIXME("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage), eInstallType, debugstr_w(szCommandLine));
585         return ERROR_CALL_NOT_IMPLEMENTED;
586 }
587
588 UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel, INSTALLSTATE eInstallState)
589 {
590     LPWSTR szwProduct = NULL;
591     UINT hr = ERROR_SUCCESS;
592
593     FIXME("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState);
594
595     if( szProduct )
596     {
597         UINT len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
598         szwProduct = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
599         if( !szwProduct )
600             goto end;
601         MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
602     }
603
604     hr = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState );
605
606 end:
607     if( szwProduct )
608         HeapFree( GetProcessHeap(), 0, szwProduct );
609
610     return hr;
611 }
612
613 UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel, INSTALLSTATE eInstallState)
614 {
615     FIXME("%s %d %d\n",debugstr_w(szProduct), iInstallLevel, eInstallState);
616     return ERROR_CALL_NOT_IMPLEMENTED;
617 }
618
619 UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer)
620 {
621     LPWSTR szwComponent = NULL, szwBuffer = NULL;
622     UINT hr = ERROR_INSTALL_FAILURE;
623
624     FIXME("%s %s\n",debugstr_a(szComponent), debugstr_a(szBuffer));
625
626     if( szComponent )
627     {
628         UINT len = MultiByteToWideChar( CP_ACP, 0, szComponent, -1, NULL, 0 );
629         szwComponent = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
630         if( !szwComponent )
631             goto end;
632         MultiByteToWideChar( CP_ACP, 0, szComponent, -1, szwComponent, len );
633     } else {
634       return ERROR_INVALID_PARAMETER;
635     }
636
637     {
638         szwBuffer = HeapAlloc( GetProcessHeap(), 0, GUID_SIZE * sizeof(WCHAR) );
639         if( !szwBuffer )         
640             goto end;
641     }
642
643     hr = MsiGetProductCodeW( szwComponent, szwBuffer );
644
645     if( ERROR_SUCCESS == hr )
646     {
647         WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, GUID_SIZE, NULL, NULL);
648     }
649
650 end:
651     if( szwComponent )
652         HeapFree( GetProcessHeap(), 0, szwComponent );
653     if( szwBuffer )
654         HeapFree( GetProcessHeap(), 0, szwBuffer );
655
656     return hr;
657 }
658
659 UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer)
660 {
661     FIXME("%s %s\n",debugstr_w(szComponent), debugstr_w(szBuffer));
662     if (NULL == szComponent) {
663       return ERROR_INVALID_PARAMETER;
664     }
665     return ERROR_CALL_NOT_IMPLEMENTED;
666 }
667
668
669
670
671 UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute, LPSTR szBuffer, DWORD *pcchValueBuf)
672 {
673     LPWSTR szwProduct = NULL, szwAttribute = NULL, szwBuffer = NULL;
674     UINT hr = ERROR_INSTALL_FAILURE;
675
676     FIXME("%s %s %p %p\n",debugstr_a(szProduct), debugstr_a(szAttribute), szBuffer, pcchValueBuf);
677
678     if (NULL != szBuffer && NULL == pcchValueBuf) {
679       return ERROR_INVALID_PARAMETER;
680     }
681     if( szProduct )
682     {
683         UINT len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
684         szwProduct = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
685         if( !szwProduct )
686             goto end;
687         MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
688     } else {
689       return ERROR_INVALID_PARAMETER;
690     }
691     
692     if( szAttribute )
693     {
694         UINT len = MultiByteToWideChar( CP_ACP, 0, szAttribute, -1, NULL, 0 );
695         szwAttribute = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
696         if( !szwAttribute )
697             goto end;
698         MultiByteToWideChar( CP_ACP, 0, szAttribute, -1, szwAttribute, len );
699     } else {
700       return ERROR_INVALID_PARAMETER;
701     }
702
703     if( szBuffer )
704     {
705         szwBuffer = HeapAlloc( GetProcessHeap(), 0, (*pcchValueBuf) * sizeof(WCHAR) );
706         if( !szwBuffer )         
707             goto end;
708     }
709
710     hr = MsiGetProductInfoW( szwProduct, szwAttribute, szwBuffer, pcchValueBuf );
711
712     if( ERROR_SUCCESS == hr )
713     {
714         WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, *pcchValueBuf, NULL, NULL);
715     }
716
717 end:
718     if( szwProduct )
719         HeapFree( GetProcessHeap(), 0, szwProduct );
720     if( szwAttribute )
721         HeapFree( GetProcessHeap(), 0, szwAttribute );
722     if( szwBuffer )
723         HeapFree( GetProcessHeap(), 0, szwBuffer );
724
725     return hr;    
726 }
727
728 UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute, LPWSTR szBuffer, DWORD *pcchValueBuf)
729 {
730     MSIHANDLE hProduct;
731     UINT hr;
732     
733     FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szAttribute), szBuffer, pcchValueBuf);
734
735     if (NULL != szBuffer && NULL == pcchValueBuf) {
736       return ERROR_INVALID_PARAMETER;
737     }
738     if (NULL == szProduct || NULL == szAttribute) {
739       return ERROR_INVALID_PARAMETER;
740     }
741
742     hr = MsiOpenProductW(szProduct, &hProduct);
743     if (ERROR_SUCCESS != hr) return hr;
744
745     hr = MsiGetPropertyW(hProduct, szAttribute, szBuffer, pcchValueBuf);
746     MsiCloseHandle(hProduct);
747     return hr;
748 }
749
750 UINT WINAPI MsiDatabaseImportA(LPCSTR szFolderPath, LPCSTR szFilename)
751 {
752     FIXME("%s %s\n",debugstr_a(szFolderPath), debugstr_a(szFilename));
753     return ERROR_CALL_NOT_IMPLEMENTED;
754 }
755
756 UINT WINAPI MsiDatabaseImportW(LPCWSTR szFolderPath, LPCWSTR szFilename)
757 {
758     FIXME("%s %s\n",debugstr_w(szFolderPath), debugstr_w(szFilename));
759     return ERROR_CALL_NOT_IMPLEMENTED;
760 }
761
762 UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes)
763 {
764     LPWSTR szwLogFile = NULL;
765     UINT hr = ERROR_INSTALL_FAILURE;
766
767     FIXME("%08lx %s %08lx\n", dwLogMode, debugstr_a(szLogFile), attributes);
768
769     if( szLogFile )
770     {
771         UINT len = MultiByteToWideChar( CP_ACP, 0, szLogFile, -1, NULL, 0 );
772         szwLogFile = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
773         if( !szwLogFile )
774             goto end;
775         MultiByteToWideChar( CP_ACP, 0, szLogFile, -1, szwLogFile, len );
776     } else {
777       return ERROR_INVALID_PARAMETER;
778     }
779
780     hr = MsiEnableLogW( dwLogMode, szwLogFile, attributes );
781
782 end:
783     if( szwLogFile )
784         HeapFree( GetProcessHeap(), 0, szwLogFile );
785
786     return hr;
787 }
788
789 UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes)
790 {
791     HANDLE the_file = INVALID_HANDLE_VALUE;
792     TRACE("%08lx %s %08lx\n", dwLogMode, debugstr_w(szLogFile), attributes);
793     strcpyW(gszLogFile,szLogFile);
794     if (!(attributes & INSTALLLOGATTRIBUTES_APPEND))
795         DeleteFileW(szLogFile);
796     the_file = CreateFileW(szLogFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
797                            FILE_ATTRIBUTE_NORMAL, NULL);
798     if (the_file != INVALID_HANDLE_VALUE)
799         CloseHandle(the_file);
800     else
801         ERR("Unable to enable log %s\n",debugstr_w(szLogFile));
802
803     return ERROR_SUCCESS;
804 }
805
806 INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct)
807 {
808     FIXME("%s\n", debugstr_a(szProduct));
809     return INSTALLSTATE_UNKNOWN;
810 }
811
812 INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct)
813 {
814     FIXME("%s\n", debugstr_w(szProduct));
815     return INSTALLSTATE_UNKNOWN;
816 }
817
818 INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd)
819 {
820     INSTALLUILEVEL old = gUILevel;
821     HWND oldwnd = gUIhwnd;
822     TRACE("%08x %p\n", dwUILevel, phWnd);
823
824     gUILevel = dwUILevel;
825     if (phWnd)
826     {
827         gUIhwnd = *phWnd;
828         *phWnd = oldwnd;
829     }
830     return old;
831 }
832
833 INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler, 
834                                   DWORD dwMessageFilter, LPVOID pvContext)
835 {
836     INSTALLUI_HANDLERA prev = gUIHandler;
837
838     TRACE("(%p %lx %p)\n",puiHandler,dwMessageFilter,pvContext);
839     gUIHandler = puiHandler;
840     gUIFilter = dwMessageFilter;
841     gUIContext = pvContext;
842
843     return prev;
844 }
845
846 UINT WINAPI MsiLoadStringA(HINSTANCE hInstance, UINT uID, LPSTR lpBuffer, int nBufferMax, DWORD e)
847 {
848     /*FIXME("%08lx %08lx %08lx %08lx %08lx\n",a,b,c,d,e);*/
849     FIXME("%p %u %p %d %08lx\n",hInstance,uID,lpBuffer,nBufferMax,e);
850     return ERROR_CALL_NOT_IMPLEMENTED;
851 }
852
853 UINT WINAPI MsiLoadStringW(HINSTANCE hInstance, UINT uID, LPWSTR lpBuffer, int nBufferMax, DWORD e)
854 {
855     FIXME("%p %u %p %d %08lx\n",hInstance,uID,lpBuffer,nBufferMax,e);
856     /*
857     int ret =  LoadStringW(hInstance,uID,lpBuffer,nBufferMax);
858     FIXME("%s\n",debugstr_w(lpBuffer));
859     return ret;
860     */
861     return ERROR_CALL_NOT_IMPLEMENTED;
862 }
863
864 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf, DWORD *pcchBuf)
865 {
866     FIXME("%s %p %08lx\n", debugstr_a(szComponent), lpPathBuf, *pcchBuf);
867     return INSTALLSTATE_UNKNOWN;
868 }
869
870 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPSTR lpPathBuf, DWORD *pcchBuf)
871 {
872     FIXME("%s %p %08lx\n", debugstr_w(szComponent), lpPathBuf, *pcchBuf);
873     return INSTALLSTATE_UNKNOWN;
874 }
875
876 #include "winuser.h"
877
878 UINT WINAPI MsiMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, WORD wLanguageId, DWORD f)
879 {
880     FIXME("%p %s %s %u %08x %08lx\n",hWnd,debugstr_a(lpText),debugstr_a(lpCaption),uType,wLanguageId,f);
881     /*
882     MessageBoxExA(hWnd,lpText,lpCaption,uType|MB_OK,wLanguageId);
883     */
884     return ERROR_CALL_NOT_IMPLEMENTED;
885 }
886
887 UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType, WORD wLanguageId, DWORD f)
888 {
889     /*FIXME("%08lx %08lx %08lx %08lx %08lx %08lx\n",a,b,c,d,e,f);*/
890     FIXME("%p %s %s %u %08x %08lx\n",hWnd,debugstr_w(lpText),debugstr_w(lpCaption),uType,wLanguageId,f);
891     /*
892     MessageBoxExW(hWnd,lpText,lpCaption,uType|MB_OK,wLanguageId);
893     */
894     return ERROR_CALL_NOT_IMPLEMENTED;
895 }
896
897 UINT WINAPI MsiEnumProductsA(DWORD index, LPSTR lpguid)
898 {
899     DWORD r;
900     WCHAR szwGuid[GUID_SIZE];
901
902     TRACE("%ld %p\n",index,lpguid);
903     
904     if (NULL == lpguid) {
905       return ERROR_INVALID_PARAMETER;
906     }
907     r = MsiEnumProductsW(index, szwGuid);
908     if( r == ERROR_SUCCESS )
909         WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
910
911     return r;
912 }
913
914 UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid)
915 {
916     HKEY hkey = 0, hkeyFeatures = 0;
917     DWORD r;
918     WCHAR szKeyName[33];
919
920     TRACE("%ld %p\n",index,lpguid);
921
922     if (NULL == lpguid) {
923       return ERROR_INVALID_PARAMETER;
924     }
925     r = RegOpenKeyW(HKEY_LOCAL_MACHINE, szInstaller, &hkey);
926     if( r != ERROR_SUCCESS )
927         goto end;
928
929     r = RegOpenKeyW(hkey, szFeatures, &hkeyFeatures);
930     if( r != ERROR_SUCCESS )
931         goto end;
932
933     r = RegEnumKeyW(hkeyFeatures, index, szKeyName, GUID_SIZE);
934
935     unsquash_guid(szKeyName, lpguid);
936
937 end:
938
939     if( hkeyFeatures )
940         RegCloseKey(hkeyFeatures);
941     if( hkey )
942         RegCloseKey(hkey);
943
944     return r;
945 }
946
947 UINT WINAPI MsiEnumFeaturesA(LPCSTR szProduct, DWORD index, 
948       LPSTR szFeature, LPSTR szParent)
949 {
950     DWORD r;
951     WCHAR szwFeature[GUID_SIZE], szwParent[GUID_SIZE];
952     LPWSTR szwProduct = NULL;
953
954     TRACE("%s %ld %p %p\n",debugstr_a(szProduct),index,szFeature,szParent);
955
956     if( szProduct )
957     {
958         UINT len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
959         szwProduct = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
960         if( szwProduct )
961             MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
962         else
963             return ERROR_FUNCTION_FAILED;
964     }
965
966     r = MsiEnumFeaturesW(szwProduct, index, szwFeature, szwParent);
967     if( r == ERROR_SUCCESS )
968     {
969         WideCharToMultiByte(CP_ACP, 0, szwFeature, -1,
970                             szFeature, GUID_SIZE, NULL, NULL);
971         WideCharToMultiByte(CP_ACP, 0, szwParent, -1,
972                             szParent, GUID_SIZE, NULL, NULL);
973     }
974
975     if( szwProduct )
976         HeapFree( GetProcessHeap(), 0, szwProduct);
977
978     return r;
979 }
980
981 UINT WINAPI MsiEnumFeaturesW(LPCWSTR szProduct, DWORD index, 
982       LPWSTR szFeature, LPWSTR szParent)
983 {
984     HKEY hkey = 0, hkeyFeatures = 0, hkeyProduct = 0;
985     DWORD r, sz;
986     WCHAR szRegName[GUID_SIZE];
987
988     TRACE("%s %ld %p %p\n",debugstr_w(szProduct),index,szFeature,szParent);
989
990     if( !squash_guid(szProduct, szRegName) )
991         return ERROR_INVALID_PARAMETER;
992
993     r = RegOpenKeyW(HKEY_LOCAL_MACHINE, szInstaller, &hkey);
994     if( r != ERROR_SUCCESS )
995         goto end;
996
997     r = RegOpenKeyW(hkey, szFeatures, &hkeyFeatures);
998     if( r != ERROR_SUCCESS )
999         goto end;
1000
1001     r = RegOpenKeyW(hkeyFeatures, szRegName, &hkeyProduct);
1002     if( r != ERROR_SUCCESS )
1003         goto end;
1004
1005     sz = GUID_SIZE;
1006     r = RegEnumValueW(hkeyProduct, index, szFeature, &sz, NULL, NULL, NULL, NULL);
1007
1008 end:
1009     if( hkeyProduct )
1010         RegCloseKey(hkeyProduct);
1011     if( hkeyFeatures )
1012         RegCloseKey(hkeyFeatures);
1013     if( hkey )
1014         RegCloseKey(hkey);
1015
1016     return r;
1017 }
1018
1019 UINT WINAPI MsiEnumComponentsA(DWORD index, LPSTR lpguid)
1020 {
1021     DWORD r;
1022     WCHAR szwGuid[GUID_SIZE];
1023
1024     TRACE("%ld %p\n",index,lpguid);
1025
1026     r = MsiEnumComponentsW(index, szwGuid);
1027     if( r == ERROR_SUCCESS )
1028         WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
1029
1030     return r;
1031 }
1032
1033 UINT WINAPI MsiEnumComponentsW(DWORD index, LPWSTR lpguid)
1034 {
1035     HKEY hkey = 0, hkeyComponents = 0;
1036     DWORD r;
1037     WCHAR szKeyName[33];
1038
1039     TRACE("%ld %p\n",index,lpguid);
1040
1041     r = RegOpenKeyW(HKEY_LOCAL_MACHINE, szInstaller, &hkey);
1042     if( r != ERROR_SUCCESS )
1043         goto end;
1044
1045     r = RegOpenKeyW(hkey, szComponents, &hkeyComponents);
1046     if( r != ERROR_SUCCESS )
1047         goto end;
1048
1049     r = RegEnumKeyW(hkeyComponents, index, szKeyName, GUID_SIZE);
1050
1051     unsquash_guid(szKeyName, lpguid);
1052
1053 end:
1054
1055     if( hkeyComponents )
1056         RegCloseKey(hkeyComponents);
1057     if( hkey )
1058         RegCloseKey(hkey);
1059
1060     return r;
1061 }
1062
1063 UINT WINAPI MsiEnumClientsA(LPCSTR szComponent, DWORD index, LPSTR szProduct)
1064 {
1065     DWORD r;
1066     WCHAR szwProduct[GUID_SIZE];
1067     LPWSTR szwComponent = NULL;
1068
1069     TRACE("%s %ld %p\n",debugstr_a(szComponent),index,szProduct);
1070
1071     if( szComponent )
1072     {
1073         UINT len = MultiByteToWideChar( CP_ACP, 0, szComponent, -1, NULL, 0 );
1074         szwComponent = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
1075         if( szwComponent )
1076             MultiByteToWideChar( CP_ACP, 0, szComponent, -1, szwComponent, len );
1077         else
1078             return ERROR_FUNCTION_FAILED;
1079     }
1080
1081     r = MsiEnumClientsW(szComponent?szwComponent:NULL, index, szwProduct);
1082     if( r == ERROR_SUCCESS )
1083     {
1084         WideCharToMultiByte(CP_ACP, 0, szwProduct, -1,
1085                             szProduct, GUID_SIZE, NULL, NULL);
1086     }
1087
1088     if( szwComponent )
1089         HeapFree( GetProcessHeap(), 0, szwComponent);
1090
1091     return r;
1092 }
1093
1094 UINT WINAPI MsiEnumClientsW(LPCWSTR szComponent, DWORD index, LPWSTR szProduct)
1095 {
1096     HKEY hkey = 0, hkeyComponents = 0, hkeyComp = 0;
1097     DWORD r, sz;
1098     WCHAR szRegName[GUID_SIZE], szValName[GUID_SIZE];
1099
1100     TRACE("%s %ld %p\n",debugstr_w(szComponent),index,szProduct);
1101
1102     if( !squash_guid(szComponent, szRegName) )
1103         return ERROR_INVALID_PARAMETER;
1104
1105     r = RegOpenKeyW(HKEY_LOCAL_MACHINE, szInstaller, &hkey);
1106     if( r != ERROR_SUCCESS )
1107         goto end;
1108
1109     r = RegOpenKeyW(hkey, szComponents, &hkeyComponents);
1110     if( r != ERROR_SUCCESS )
1111         goto end;
1112
1113     r = RegOpenKeyW(hkeyComponents, szRegName, &hkeyComp);
1114     if( r != ERROR_SUCCESS )
1115         goto end;
1116
1117     sz = GUID_SIZE;
1118     r = RegEnumValueW(hkeyComp, index, szValName, &sz, NULL, NULL, NULL, NULL);
1119     if( r != ERROR_SUCCESS )
1120         goto end;
1121
1122     unsquash_guid(szValName, szProduct);
1123
1124 end:
1125     if( hkeyComp )
1126         RegCloseKey(hkeyComp);
1127     if( hkeyComponents )
1128         RegCloseKey(hkeyComponents);
1129     if( hkey )
1130         RegCloseKey(hkey);
1131
1132     return r;
1133 }
1134
1135 UINT WINAPI MsiEnumComponentQualifiersA(
1136     LPSTR szComponent, DWORD iIndex, LPSTR lpQualifierBuf, DWORD* pcchQualifierBuf, LPSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf)
1137 {
1138 FIXME("%s 0x%08lx %p %p %p %p\n", debugstr_a(szComponent), iIndex, lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf, pcchApplicationDataBuf);
1139     return ERROR_CALL_NOT_IMPLEMENTED;
1140 }
1141
1142 UINT WINAPI MsiEnumComponentQualifiersW(
1143     LPWSTR szComponent, DWORD iIndex, LPWSTR lpQualifierBuf, DWORD* pcchQualifierBuf, LPWSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf)
1144 {
1145 FIXME("%s 0x%08lx %p %p %p %p\n", debugstr_w(szComponent), iIndex, lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf, pcchApplicationDataBuf);
1146     return ERROR_CALL_NOT_IMPLEMENTED;
1147 }
1148
1149 UINT WINAPI MsiProvideAssemblyA(
1150     LPCSTR szAssemblyName, LPCSTR szAppContext, DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf, DWORD* pcchPathBuf) 
1151 {
1152     FIXME("%s %s 0x%08lx 0x%08lx %p %p\n", 
1153         debugstr_a(szAssemblyName),  debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf, pcchPathBuf);
1154     return ERROR_CALL_NOT_IMPLEMENTED;
1155 }
1156
1157 UINT WINAPI MsiProvideAssemblyW(
1158     LPCWSTR szAssemblyName, LPCWSTR szAppContext, DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf, DWORD* pcchPathBuf) 
1159 {
1160     FIXME("%s %s 0x%08lx 0x%08lx %p %p\n", 
1161         debugstr_w(szAssemblyName),  debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf, pcchPathBuf);
1162     return ERROR_CALL_NOT_IMPLEMENTED;
1163 }
1164
1165 UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor, LPSTR szPath, DWORD *pcchPath, DWORD *pcchArgs )
1166 {
1167     FIXME("%s %p %p %p\n", debugstr_a(szDescriptor), szPath, pcchPath, pcchArgs );
1168     return ERROR_CALL_NOT_IMPLEMENTED;
1169 }
1170
1171 UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor, LPWSTR szPath, DWORD *pcchPath, DWORD *pcchArgs )
1172 {
1173     FIXME("%s %p %p %p\n", debugstr_w(szDescriptor), szPath, pcchPath, pcchArgs );
1174     return ERROR_CALL_NOT_IMPLEMENTED;
1175 }
1176
1177 HRESULT WINAPI MsiGetFileSignatureInformationA(
1178   LPCSTR szSignedObjectPath, DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData, DWORD* pcbHashData)
1179 {
1180     FIXME("%s 0x%08lx %p %p %p\n", debugstr_a(szSignedObjectPath), dwFlags, ppcCertContext, pbHashData, pcbHashData);
1181     return ERROR_CALL_NOT_IMPLEMENTED;
1182 }
1183
1184 HRESULT WINAPI MsiGetFileSignatureInformationW(
1185   LPCWSTR szSignedObjectPath, DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData, DWORD* pcbHashData)
1186 {
1187     FIXME("%s 0x%08lx %p %p %p\n", debugstr_w(szSignedObjectPath), dwFlags, ppcCertContext, pbHashData, pcbHashData);
1188     return ERROR_CALL_NOT_IMPLEMENTED;
1189 }
1190
1191 UINT WINAPI MsiGetProductPropertyA( MSIHANDLE hProduct, LPCSTR szProperty,
1192                                     LPSTR szValue, DWORD *pccbValue )
1193 {
1194     FIXME("%ld %s %p %p\n", hProduct, debugstr_a(szProperty), szValue, pccbValue);
1195     return ERROR_CALL_NOT_IMPLEMENTED;
1196 }
1197
1198 UINT WINAPI MsiGetProductPropertyW( MSIHANDLE hProduct, LPCWSTR szProperty,
1199                                     LPWSTR szValue, DWORD *pccbValue )
1200 {
1201     FIXME("%ld %s %p %p\n", hProduct, debugstr_w(szProperty), szValue, pccbValue);
1202     return ERROR_CALL_NOT_IMPLEMENTED;
1203 }
1204
1205 UINT WINAPI MsiVerifyPackageA( LPCSTR szPackage )
1206 {
1207     UINT r, len;
1208     LPWSTR szPack = NULL;
1209
1210     TRACE("%s\n", debugstr_a(szPackage) );
1211
1212     if( szPackage )
1213     {
1214         len = MultiByteToWideChar( CP_ACP, 0, szPackage, -1, NULL, 0 );
1215         szPack = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1216         if( !szPack )
1217             return ERROR_OUTOFMEMORY;
1218         MultiByteToWideChar( CP_ACP, 0, szPackage, -1, szPack, len );
1219     }
1220
1221     r = MsiVerifyPackageW( szPack );
1222
1223     HeapFree( GetProcessHeap(), 0, szPack );
1224
1225     return r;
1226 }
1227
1228 UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage )
1229 {
1230     MSIHANDLE handle;
1231     UINT r;
1232
1233     TRACE("%s\n", debugstr_w(szPackage) );
1234
1235     r = MsiOpenDatabaseW( szPackage, MSIDBOPEN_READONLY, &handle );
1236     MsiCloseHandle( handle );
1237
1238     return r;
1239 }
1240
1241 INSTALLSTATE WINAPI MsiGetComponentPathA(LPCSTR szProduct, LPCSTR szComponent,
1242                                          LPSTR lpPathBuf, DWORD* pcchBuf)
1243 {
1244     INSTALLSTATE rc;
1245     UINT len;
1246     LPWSTR szwProduct= NULL;
1247     LPWSTR szwComponent= NULL;
1248     LPWSTR lpwPathBuf= NULL;
1249
1250     if( szProduct)
1251     {
1252         len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
1253         szwProduct= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1254         if( !szwProduct)
1255             return ERROR_OUTOFMEMORY;
1256         MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
1257     }
1258
1259     if( szComponent)
1260     {
1261         len = MultiByteToWideChar( CP_ACP, 0, szComponent, -1, NULL, 0 );
1262         szwComponent= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1263         if( !szwComponent)
1264             return ERROR_OUTOFMEMORY;
1265         MultiByteToWideChar( CP_ACP, 0, szComponent, -1, szwComponent, len );
1266     }
1267
1268     if (pcchBuf && *pcchBuf > 0)
1269         lpwPathBuf = HeapAlloc( GetProcessHeap(), 0, *pcchBuf * sizeof(WCHAR));
1270     else
1271         lpwPathBuf = NULL;
1272
1273     rc = MsiGetComponentPathW(szwProduct, szwComponent, lpwPathBuf, pcchBuf);
1274
1275     HeapFree( GetProcessHeap(), 0, szwProduct);
1276     HeapFree( GetProcessHeap(), 0, szwComponent);
1277     if (lpwPathBuf)
1278     {
1279         WideCharToMultiByte(CP_ACP, 0, lpwPathBuf, *pcchBuf,
1280                             lpPathBuf, GUID_SIZE, NULL, NULL);
1281         HeapFree( GetProcessHeap(), 0, lpwPathBuf);
1282     }
1283
1284     return rc;
1285 }
1286
1287 INSTALLSTATE WINAPI MsiGetComponentPathW(LPCWSTR szProduct, LPCWSTR szComponent,
1288                                          LPWSTR lpPathBuf, DWORD* pcchBuf)
1289 {
1290     FIXME("STUB: (%s %s %p %p)\n", debugstr_w(szProduct),
1291            debugstr_w(szComponent), lpPathBuf, pcchBuf);
1292
1293     return INSTALLSTATE_UNKNOWN;
1294 }
1295
1296 INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature)
1297 {
1298     INSTALLSTATE rc;
1299     UINT len;
1300     LPWSTR szwProduct= NULL;
1301     LPWSTR szwFeature= NULL;
1302
1303     if( szProduct)
1304     {
1305         len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
1306         szwProduct= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1307         if( !szwProduct)
1308             return ERROR_OUTOFMEMORY;
1309         MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
1310     }
1311
1312     if( szFeature)
1313     {
1314         len = MultiByteToWideChar( CP_ACP, 0, szFeature, -1, NULL, 0 );
1315         szwFeature= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1316         if( !szwFeature)
1317             return ERROR_OUTOFMEMORY;
1318         MultiByteToWideChar( CP_ACP, 0, szFeature, -1, szwFeature, len );
1319     }
1320
1321     rc = MsiQueryFeatureStateW(szwProduct, szwFeature);
1322
1323     HeapFree( GetProcessHeap(), 0, szwProduct);
1324     HeapFree( GetProcessHeap(), 0, szwFeature);
1325
1326     return rc;
1327 }
1328
1329 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
1330 {
1331     FIXME("STUB: (%s %s)\n", debugstr_w(szProduct), debugstr_w(szFeature));
1332     return INSTALLSTATE_UNKNOWN;
1333 }
1334
1335
1336 /******************************************************************
1337  *              DllMain
1338  *
1339  * @todo: maybe we can check here if MsiServer service is declared no ?
1340  */
1341 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
1342   if (fdwReason == DLL_PROCESS_ATTACH) {
1343     DisableThreadLibraryCalls(hinstDLL);
1344     /*
1345      * UI Initialization
1346      */
1347     gUILevel = INSTALLUILEVEL_BASIC;
1348     gUIhwnd = 0;
1349     gUIHandler = NULL;
1350     gUIFilter = 0;
1351     gUIContext = NULL;
1352     gszLogFile[0]=0;
1353     /* FIXME: Initialisation */
1354   } else if (fdwReason == DLL_PROCESS_DETACH) {
1355     /* FIXME: Cleanup */
1356   }
1357   /*
1358   static const WCHAR szMSIServerSvc[] = { 'M','S','I','S','e','r','v','e','r',0 };
1359   static const WCHAR szNull[] = { 0 };
1360   if (!strcmpW(lpServiceName, szMSIServerSvc)) {
1361     hKey = CreateServiceW(hSCManager, 
1362                           szMSIServerSvc, 
1363                           szMSIServerSvc, 
1364                           SC_MANAGER_ALL_ACCESS, 
1365                           SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS, 
1366                           SERVICE_AUTO_START, 
1367                           SERVICE_ERROR_IGNORE,
1368                           szNull, 
1369                           NULL, 
1370                           NULL,
1371                           NULL,
1372                           NULL,
1373                           szNull);
1374   */
1375   return TRUE;
1376 }
1377
1378 typedef struct {
1379   /* IUnknown fields */
1380   ICOM_VFIELD(IClassFactory);
1381   DWORD                       ref;
1382 } IClassFactoryImpl;
1383
1384 static HRESULT WINAPI MsiCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
1385   ICOM_THIS(IClassFactoryImpl,iface);
1386   FIXME("(%p, %s, %p): stub\n",This,debugstr_guid(riid),ppobj);
1387   return E_NOINTERFACE;
1388 }
1389
1390 static ULONG WINAPI MsiCF_AddRef(LPCLASSFACTORY iface) {
1391   ICOM_THIS(IClassFactoryImpl,iface);
1392   return ++(This->ref);
1393 }
1394
1395 static ULONG WINAPI MsiCF_Release(LPCLASSFACTORY iface) {
1396   ICOM_THIS(IClassFactoryImpl,iface);
1397   /* static class, won't be  freed */
1398   return --(This->ref);
1399 }
1400
1401 static HRESULT WINAPI MsiCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) {
1402   ICOM_THIS(IClassFactoryImpl,iface);
1403   FIXME ("(%p, %p, %s, %p): to implement\n", This, pOuter, debugstr_guid(riid), ppobj);
1404   return 0;
1405 }
1406
1407 static HRESULT WINAPI MsiCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
1408   ICOM_THIS(IClassFactoryImpl,iface);
1409   FIXME("(%p, %d): stub\n", This, dolock);
1410   return S_OK;
1411 }
1412
1413 static ICOM_VTABLE(IClassFactory) MsiCF_Vtbl = {
1414   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1415   MsiCF_QueryInterface,
1416   MsiCF_AddRef,
1417   MsiCF_Release,
1418   MsiCF_CreateInstance,
1419   MsiCF_LockServer
1420 };
1421
1422 static IClassFactoryImpl Msi_CF = {&MsiCF_Vtbl, 1 };
1423
1424 /******************************************************************
1425  *              DllGetClassObject (MSI.@)
1426  */
1427 HRESULT WINAPI MSI_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) {
1428   FIXME("(%s, %s, %p): almost a stub.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
1429   if (IsEqualCLSID (rclsid, &CLSID_IMsiServer)) {
1430     *ppv = (LPVOID) &Msi_CF;
1431     IClassFactory_AddRef((IClassFactory*)*ppv);
1432     return S_OK;
1433   } else if (IsEqualCLSID (rclsid, &CLSID_IMsiServerMessage)) {
1434     *ppv = (LPVOID) &Msi_CF;
1435     IClassFactory_AddRef((IClassFactory*)*ppv);
1436     return S_OK;
1437   } else if (IsEqualCLSID (rclsid, &CLSID_IMsiServerX1)) {
1438     *ppv = (LPVOID) &Msi_CF;
1439     IClassFactory_AddRef((IClassFactory*)*ppv);
1440     return S_OK;
1441   } else if (IsEqualCLSID (rclsid, &CLSID_IMsiServerX2)) {
1442     *ppv = (LPVOID) &Msi_CF;
1443     IClassFactory_AddRef((IClassFactory*)*ppv);
1444     return S_OK;
1445   } else if (IsEqualCLSID (rclsid, &CLSID_IMsiServerX3)) {
1446     *ppv = (LPVOID) &Msi_CF;
1447     IClassFactory_AddRef((IClassFactory*)*ppv);
1448     return S_OK;
1449   }
1450   WARN("(%s, %s, %p): no interface found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
1451   return CLASS_E_CLASSNOTAVAILABLE;
1452 }
1453
1454 /******************************************************************
1455  *              DllGetVersion (MSI.@)
1456  */
1457 HRESULT WINAPI MSI_DllGetVersion(DLLVERSIONINFO *pdvi)
1458 {
1459   TRACE("%p\n",pdvi);
1460   
1461   if (pdvi->cbSize != sizeof(DLLVERSIONINFO))
1462     return E_INVALIDARG;
1463   
1464   pdvi->dwMajorVersion = MSI_MAJORVERSION;
1465   pdvi->dwMinorVersion = MSI_MINORVERSION;
1466   pdvi->dwBuildNumber = MSI_BUILDNUMBER;
1467   pdvi->dwPlatformID = 1;
1468   
1469   return S_OK;
1470 }
1471
1472 /******************************************************************
1473  *              DllCanUnloadNow (MSI.@)
1474  */
1475 BOOL WINAPI MSI_DllCanUnloadNow(void)
1476 {
1477   return S_FALSE;
1478 }
1479
1480 UINT WINAPI MsiEnumRelatedProductsA (LPCSTR lpUpgradeCode, DWORD dwReserved,
1481                                     DWORD iProductIndex, LPSTR lpProductBuf)
1482 {
1483     FIXME("STUB: (%s, %li %li %s)\n",lpUpgradeCode, dwReserved, iProductIndex,
1484           lpProductBuf);
1485     return ERROR_CALL_NOT_IMPLEMENTED;
1486 }