Added a few stub implementations.
[wine] / dlls / msi / msi.c
1 /*
2  * Implementation of the Microsoft Installer (msi.dll)
3  *
4  * Copyright 2002 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 "windef.h"
24 #include "winbase.h"
25 #include "winreg.h"
26 #include "shlwapi.h"
27 #include "wine/debug.h"
28 #include "msi.h"
29 #include "msiquery.h"
30 #include "msipriv.h"
31 #include "objidl.h"
32 #include "wincrypt.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(msi);
35
36 const WCHAR szInstaller[] = {
37 'S','o','f','t','w','a','r','e','\\',
38 'M','i','c','r','o','s','o','f','t','\\',
39 'W','i','n','d','o','w','s','\\',
40 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
41 'I','n','s','t','a','l','l','e','r',0 };
42
43 const WCHAR szFeatures[] = {
44 'F','e','a','t','u','r','e','s',0 };
45 const WCHAR szComponents[] = {
46 'C','o','m','p','o','n','e','n','t','s',0 };
47
48 /*
49  *  .MSI  file format
50  *
51  *  A .msi file is a structured storage file.
52  *  It should contain a number of streams.
53  */
54
55 BOOL unsquash_guid(LPCWSTR in, LPWSTR out)
56 {
57     DWORD i,n=0;
58
59     out[n++]='{';
60     for(i=0; i<8; i++)
61         out[n++] = in[7-i];
62     out[n++]='-';
63     for(i=0; i<4; i++)
64         out[n++] = in[11-i];
65     out[n++]='-';
66     for(i=0; i<4; i++)
67         out[n++] = in[15-i];
68     out[n++]='-';
69     for(i=0; i<2; i++)
70     {
71         out[n++] = in[17+i*2];
72         out[n++] = in[16+i*2];
73     }
74     out[n++]='-';
75     for( ; i<8; i++)
76     {
77         out[n++] = in[17+i*2];
78         out[n++] = in[16+i*2];
79     }
80     out[n++]='}';
81     out[n]=0;
82     return TRUE;
83 }
84
85 BOOL squash_guid(LPCWSTR in, LPWSTR out)
86 {
87     DWORD i,n=0;
88
89     if(in[n++] != '{')
90         return FALSE;
91     for(i=0; i<8; i++)
92         out[7-i] = in[n++];
93     if(in[n++] != '-')
94         return FALSE;
95     for(i=0; i<4; i++)
96         out[11-i] = in[n++];
97     if(in[n++] != '-')
98         return FALSE;
99     for(i=0; i<4; i++)
100         out[15-i] = in[n++];
101     if(in[n++] != '-')
102         return FALSE;
103     for(i=0; i<2; i++)
104     {
105         out[17+i*2] = in[n++];
106         out[16+i*2] = in[n++];
107     }
108     if(in[n++] != '-')
109         return FALSE;
110     for( ; i<8; i++)
111     {
112         out[17+i*2] = in[n++];
113         out[16+i*2] = in[n++];
114     }
115     out[32]=0;
116     if(in[n++] != '}')
117         return FALSE;
118     if(in[n])
119         return FALSE;
120     return TRUE;
121 }
122
123 VOID MSI_CloseDatabase( VOID *arg )
124 {
125     MSIDATABASE *db = (MSIDATABASE *) arg;
126
127     free_cached_tables( db );
128     IStorage_Release( db->storage );
129 }
130
131 UINT WINAPI MsiOpenDatabaseA(
132                LPCSTR szDBPath, LPCSTR szPersist, MSIHANDLE *phDB)
133 {
134     HRESULT r = ERROR_FUNCTION_FAILED;
135     LPWSTR szwDBPath = NULL, szwPersist = NULL;
136
137     TRACE("%s %s %p\n", debugstr_a(szDBPath), debugstr_a(szPersist), phDB);
138
139     if( szDBPath )
140     {
141         szwDBPath = HEAP_strdupAtoW( GetProcessHeap(), 0, szDBPath );
142         if( !szwDBPath )
143             goto end;
144     }
145
146     if( szPersist )
147     {
148         szwPersist = HEAP_strdupAtoW( GetProcessHeap(), 0, szPersist );
149         if( !szwPersist )
150             goto end;
151     }
152
153     r = MsiOpenDatabaseW( szwDBPath, szwPersist, phDB );
154
155 end:
156     if( szwPersist )
157         HeapFree( GetProcessHeap(), 0, szwPersist );
158     if( szwDBPath )
159         HeapFree( GetProcessHeap(), 0, szwDBPath );
160
161     return r;
162 }
163
164 UINT WINAPI MsiOpenDatabaseW(
165               LPCWSTR szDBPath, LPCWSTR szPersist, MSIHANDLE *phDB)
166 {
167     IStorage *stg = NULL;
168     HRESULT r;
169     MSIHANDLE handle;
170     MSIDATABASE *db;
171     UINT ret;
172
173     TRACE("%s %s %p\n",debugstr_w(szDBPath),debugstr_w(szPersist), phDB);
174
175     if( !phDB )
176         return ERROR_INVALID_PARAMETER;
177
178     r = StgOpenStorage( szDBPath, NULL, STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
179     if( FAILED( r ) )
180     {
181         FIXME("open failed r = %08lx!\n",r);
182         return ERROR_FUNCTION_FAILED;
183     }
184
185     handle = alloc_msihandle(MSIHANDLETYPE_DATABASE, sizeof (MSIDATABASE), MSI_CloseDatabase );
186     if( !handle )
187     {
188         FIXME("Failed to allocate a handle\n");
189         ret = ERROR_FUNCTION_FAILED;
190         goto end;
191     }
192
193     db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE );
194     if( !db )
195     {
196         FIXME("Failed to get handle pointer \n");
197         ret = ERROR_FUNCTION_FAILED;
198         goto end;
199     }
200     db->storage = stg;
201     ret = load_string_table( db, &db->strings);
202     if( ret != ERROR_SUCCESS )
203         goto end;
204
205     *phDB = handle;
206
207     IStorage_AddRef( stg );
208 end:
209     if( stg )
210         IStorage_Release( stg );
211
212     return ret;
213 }
214
215 UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct)
216 {
217     FIXME("%s %p\n",debugstr_a(szProduct), phProduct);
218     return ERROR_CALL_NOT_IMPLEMENTED;
219 }
220
221 UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct)
222 {
223     FIXME("%s %p\n",debugstr_w(szProduct), phProduct);
224     return ERROR_CALL_NOT_IMPLEMENTED;
225 }
226
227 UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
228 {
229     FIXME("%s %p\n",debugstr_a(szPackage), phPackage);
230     return ERROR_CALL_NOT_IMPLEMENTED;
231 }
232
233 UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
234 {
235     FIXME("%s %p\n",debugstr_w(szPackage), phPackage);
236     return ERROR_CALL_NOT_IMPLEMENTED;
237 }
238
239 UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
240 {
241     FIXME("%s 0x%08lx %p\n",debugstr_a(szPackage), dwOptions, phPackage);
242     return ERROR_CALL_NOT_IMPLEMENTED;
243 }
244
245 UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
246 {
247     FIXME("%s 0x%08lx %p\n",debugstr_w(szPackage), dwOptions, phPackage);
248     return ERROR_CALL_NOT_IMPLEMENTED;
249 }
250
251 UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath, LPCSTR szTransforms, LANGID lgidLanguage)
252 {
253     FIXME("%s %s %s 0x%08x\n",debugstr_a(szPackagePath), debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage);
254     return ERROR_CALL_NOT_IMPLEMENTED;
255 }
256
257 UINT WINAPI MsiAdvertiseProductW(LPCWSTR szPackagePath, LPCWSTR szScriptfilePath, LPCWSTR szTransforms, LANGID lgidLanguage)
258 {
259     FIXME("%s %s %s 0x%08x\n",debugstr_w(szPackagePath), debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage);
260     return ERROR_CALL_NOT_IMPLEMENTED;
261 }
262
263 UINT WINAPI MsiAdvertiseProductExA(
264     LPCSTR szPackagePath, LPCSTR szScriptfilePath, LPCSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
265 {
266     FIXME("%s %s %s 0x%08x 0x%08lx 0x%08lx\n",
267         debugstr_a(szPackagePath), debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage, dwPlatform, dwOptions);
268     return ERROR_CALL_NOT_IMPLEMENTED;
269 }
270
271 UINT WINAPI MsiAdvertiseProductExW(
272     LPCWSTR szPackagePath, LPCWSTR szScriptfilePath, LPCWSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
273 {
274     FIXME("%s %s %s 0x%08x 0x%08lx 0x%08lx\n",
275         debugstr_w(szPackagePath), debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage, dwPlatform, dwOptions);
276     return ERROR_CALL_NOT_IMPLEMENTED;
277 }
278
279 UINT WINAPI MsiInstallProductA(LPCSTR szPackagePath, LPCSTR szCommandLine)
280 {
281     LPWSTR szwPath = NULL, szwCommand = NULL;
282     UINT r = ERROR_FUNCTION_FAILED; /* FIXME: check return code */
283
284     TRACE("%s %s\n",debugstr_a(szPackagePath), debugstr_a(szCommandLine));
285
286     if( szPackagePath )
287     {
288         szwPath = HEAP_strdupAtoW(GetProcessHeap(),0,szPackagePath);
289         if( szwPath == NULL )
290             goto end; 
291     }
292
293     if( szCommandLine )
294     {
295         szwCommand = HEAP_strdupAtoW(GetProcessHeap(),0,szCommandLine);
296         if( szwCommand == NULL )
297             goto end; 
298     }
299  
300     r = MsiInstallProductW( szwPath, szwCommand );
301
302 end:
303     if( szwPath )
304         HeapFree( GetProcessHeap(), 0, szwPath );
305     
306     if( szwCommand )
307         HeapFree( GetProcessHeap(), 0, szwCommand );
308
309     return r;
310 }
311
312 UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
313 {
314     FIXME("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
315
316     return ERROR_CALL_NOT_IMPLEMENTED;
317 }
318
319 UINT WINAPI MsiConfigureProductA(
320               LPCSTR szProduct, int iInstallLevel, INSTALLSTATE eInstallState)
321 {
322     FIXME("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState);
323     return ERROR_CALL_NOT_IMPLEMENTED;
324 }
325
326 UINT WINAPI MsiConfigureProductW(
327               LPCWSTR szProduct, int iInstallLevel, INSTALLSTATE eInstallState)
328 {
329     FIXME("%s %d %d\n",debugstr_w(szProduct), iInstallLevel, eInstallState);
330     return ERROR_CALL_NOT_IMPLEMENTED;
331 }
332
333 UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer)
334 {
335     FIXME("%s %s\n",debugstr_a(szComponent), debugstr_a(szBuffer));
336     return ERROR_CALL_NOT_IMPLEMENTED;
337 }
338
339 UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer)
340 {
341     FIXME("%s %s\n",debugstr_w(szComponent), debugstr_w(szBuffer));
342     return ERROR_CALL_NOT_IMPLEMENTED;
343 }
344
345 UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute, LPSTR szBuffer, DWORD *pcchValueBuf)
346 {
347     FIXME("%s %s %p %p\n",debugstr_a(szProduct), debugstr_a(szAttribute), szBuffer, pcchValueBuf);
348     return ERROR_CALL_NOT_IMPLEMENTED;
349 }
350
351 UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute, LPWSTR szBuffer, DWORD *pcchValueBuf)
352 {
353     FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szAttribute), szBuffer, pcchValueBuf);
354     return ERROR_CALL_NOT_IMPLEMENTED;
355 }
356
357 UINT WINAPI MsiDatabaseImportA(LPCSTR szFolderPath, LPCSTR szFilename)
358 {
359     FIXME("%s %s\n",debugstr_a(szFolderPath), debugstr_a(szFilename));
360     return ERROR_CALL_NOT_IMPLEMENTED;
361 }
362
363 UINT WINAPI MsiDatabaseImportW(LPCWSTR szFolderPath, LPCWSTR szFilename)
364 {
365     FIXME("%s %s\n",debugstr_w(szFolderPath), debugstr_w(szFilename));
366     return ERROR_CALL_NOT_IMPLEMENTED;
367 }
368
369 UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, BOOL fAppend)
370 {
371     FIXME("%08lx %s %d\n", dwLogMode, debugstr_a(szLogFile), fAppend);
372     return ERROR_SUCCESS;
373     /* return ERROR_CALL_NOT_IMPLEMENTED; */
374 }
375
376 UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, BOOL fAppend)
377 {
378     FIXME("%08lx %s %d\n", dwLogMode, debugstr_w(szLogFile), fAppend);
379     return ERROR_CALL_NOT_IMPLEMENTED;
380 }
381
382 INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct)
383 {
384     FIXME("%s\n", debugstr_a(szProduct));
385     return 0;
386 }
387
388 INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct)
389 {
390     FIXME("%s\n", debugstr_w(szProduct));
391     return 0;
392 }
393
394 INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd)
395 {
396     FIXME("%08x %p\n", dwUILevel, phWnd);
397     return dwUILevel;
398 }
399
400 UINT WINAPI MsiLoadStringA(DWORD a, DWORD b, DWORD c, DWORD d, DWORD e, DWORD f)
401 {
402     FIXME("%08lx %08lx %08lx %08lx %08lx %08lx\n",a,b,c,d,e,f);
403     return ERROR_CALL_NOT_IMPLEMENTED;
404 }
405
406 UINT WINAPI MsiLoadStringW(DWORD a, DWORD b, DWORD c, DWORD d, DWORD e, DWORD f)
407 {
408     FIXME("%08lx %08lx %08lx %08lx %08lx %08lx\n",a,b,c,d,e,f);
409     return ERROR_CALL_NOT_IMPLEMENTED;
410 }
411
412 UINT WINAPI MsiMessageBoxA(DWORD a, DWORD b, DWORD c, DWORD d, DWORD e, DWORD f)
413 {
414     FIXME("%08lx %08lx %08lx %08lx %08lx %08lx\n",a,b,c,d,e,f);
415     return ERROR_CALL_NOT_IMPLEMENTED;
416 }
417
418 UINT WINAPI MsiMessageBoxW(DWORD a, DWORD b, DWORD c, DWORD d, DWORD e, DWORD f)
419 {
420     FIXME("%08lx %08lx %08lx %08lx %08lx %08lx\n",a,b,c,d,e,f);
421     return ERROR_CALL_NOT_IMPLEMENTED;
422 }
423
424 UINT WINAPI MsiEnumProductsA(DWORD index, LPSTR lpguid)
425 {
426     DWORD r;
427     WCHAR szwGuid[GUID_SIZE];
428
429     TRACE("%ld %p\n",index,lpguid);
430
431     r = MsiEnumProductsW(index, szwGuid);
432     if( r == ERROR_SUCCESS )
433         WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
434
435     return r;
436 }
437
438 UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid)
439 {
440     HKEY hkey = 0, hkeyFeatures = 0;
441     DWORD r;
442     WCHAR szKeyName[33];
443
444     TRACE("%ld %p\n",index,lpguid);
445
446     r = RegOpenKeyW(HKEY_LOCAL_MACHINE, szInstaller, &hkey);
447     if( r != ERROR_SUCCESS )
448         goto end;
449
450     r = RegOpenKeyW(hkey, szFeatures, &hkeyFeatures);
451     if( r != ERROR_SUCCESS )
452         goto end;
453
454     r = RegEnumKeyW(hkeyFeatures, index, szKeyName, GUID_SIZE);
455
456     unsquash_guid(szKeyName, lpguid);
457
458 end:
459
460     if( hkeyFeatures )
461         RegCloseKey(hkeyFeatures);
462     if( hkey )
463         RegCloseKey(hkey);
464
465     return r;
466 }
467
468 UINT WINAPI MsiEnumFeaturesA(LPCSTR szProduct, DWORD index, 
469       LPSTR szFeature, LPSTR szParent)
470 {
471     DWORD r;
472     WCHAR szwFeature[GUID_SIZE], szwParent[GUID_SIZE];
473     LPWSTR szwProduct = NULL;
474
475     TRACE("%s %ld %p %p\n",debugstr_a(szProduct),index,szFeature,szParent);
476
477     if( szProduct )
478     {
479         szwProduct = HEAP_strdupAtoW(GetProcessHeap(),0,szProduct);
480         if( !szwProduct )
481             return ERROR_FUNCTION_FAILED;
482     }
483
484     r = MsiEnumFeaturesW(szProduct?szwProduct:NULL, 
485                          index, szwFeature, szwParent);
486     if( r == ERROR_SUCCESS )
487     {
488         WideCharToMultiByte(CP_ACP, 0, szwFeature, -1,
489                             szFeature, GUID_SIZE, NULL, NULL);
490         WideCharToMultiByte(CP_ACP, 0, szwParent, -1,
491                             szParent, GUID_SIZE, NULL, NULL);
492     }
493
494     if( szwProduct )
495         HeapFree( GetProcessHeap(), 0, szwProduct);
496
497     return r;
498 }
499
500 UINT WINAPI MsiEnumFeaturesW(LPCWSTR szProduct, DWORD index, 
501       LPWSTR szFeature, LPWSTR szParent)
502 {
503     HKEY hkey = 0, hkeyFeatures = 0, hkeyProduct = 0;
504     DWORD r, sz;
505     WCHAR szRegName[GUID_SIZE];
506
507     TRACE("%s %ld %p %p\n",debugstr_w(szProduct),index,szFeature,szParent);
508
509     if( !squash_guid(szProduct, szRegName) )
510         return ERROR_INVALID_PARAMETER;
511
512     r = RegOpenKeyW(HKEY_LOCAL_MACHINE, szInstaller, &hkey);
513     if( r != ERROR_SUCCESS )
514         goto end;
515
516     r = RegOpenKeyW(hkey, szFeatures, &hkeyFeatures);
517     if( r != ERROR_SUCCESS )
518         goto end;
519
520     r = RegOpenKeyW(hkeyFeatures, szRegName, &hkeyProduct);
521     if( r != ERROR_SUCCESS )
522         goto end;
523
524     sz = GUID_SIZE;
525     r = RegEnumValueW(hkeyProduct, index, szFeature, &sz, NULL, NULL, NULL, NULL);
526
527 end:
528     if( hkeyProduct )
529         RegCloseKey(hkeyProduct);
530     if( hkeyFeatures )
531         RegCloseKey(hkeyFeatures);
532     if( hkey )
533         RegCloseKey(hkey);
534
535     return r;
536 }
537
538 UINT WINAPI MsiEnumComponentsA(DWORD index, LPSTR lpguid)
539 {
540     DWORD r;
541     WCHAR szwGuid[GUID_SIZE];
542
543     TRACE("%ld %p\n",index,lpguid);
544
545     r = MsiEnumComponentsW(index, szwGuid);
546     if( r == ERROR_SUCCESS )
547         WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
548
549     return r;
550 }
551
552 UINT WINAPI MsiEnumComponentsW(DWORD index, LPWSTR lpguid)
553 {
554     HKEY hkey = 0, hkeyComponents = 0;
555     DWORD r;
556     WCHAR szKeyName[33];
557
558     TRACE("%ld %p\n",index,lpguid);
559
560     r = RegOpenKeyW(HKEY_LOCAL_MACHINE, szInstaller, &hkey);
561     if( r != ERROR_SUCCESS )
562         goto end;
563
564     r = RegOpenKeyW(hkey, szComponents, &hkeyComponents);
565     if( r != ERROR_SUCCESS )
566         goto end;
567
568     r = RegEnumKeyW(hkeyComponents, index, szKeyName, GUID_SIZE);
569
570     unsquash_guid(szKeyName, lpguid);
571
572 end:
573
574     if( hkeyComponents )
575         RegCloseKey(hkeyComponents);
576     if( hkey )
577         RegCloseKey(hkey);
578
579     return r;
580 }
581
582 UINT WINAPI MsiEnumClientsA(LPCSTR szComponent, DWORD index, LPSTR szProduct)
583 {
584     DWORD r;
585     WCHAR szwProduct[GUID_SIZE];
586     LPWSTR szwComponent = NULL;
587
588     TRACE("%s %ld %p\n",debugstr_a(szComponent),index,szProduct);
589
590     if( szComponent )
591     {
592         szwComponent = HEAP_strdupAtoW(GetProcessHeap(),0,szComponent);
593         if( !szwComponent )
594             return ERROR_FUNCTION_FAILED;
595     }
596
597     r = MsiEnumClientsW(szComponent?szwComponent:NULL, index, szwProduct);
598     if( r == ERROR_SUCCESS )
599     {
600         WideCharToMultiByte(CP_ACP, 0, szwProduct, -1,
601                             szProduct, GUID_SIZE, NULL, NULL);
602     }
603
604     if( szwComponent )
605         HeapFree( GetProcessHeap(), 0, szwComponent);
606
607     return r;
608 }
609
610 UINT WINAPI MsiEnumClientsW(LPCWSTR szComponent, DWORD index, LPWSTR szProduct)
611 {
612     HKEY hkey = 0, hkeyComponents = 0, hkeyComp = 0;
613     DWORD r, sz;
614     WCHAR szRegName[GUID_SIZE], szValName[GUID_SIZE];
615
616     TRACE("%s %ld %p\n",debugstr_w(szComponent),index,szProduct);
617
618     if( !squash_guid(szComponent, szRegName) )
619         return ERROR_INVALID_PARAMETER;
620
621     r = RegOpenKeyW(HKEY_LOCAL_MACHINE, szInstaller, &hkey);
622     if( r != ERROR_SUCCESS )
623         goto end;
624
625     r = RegOpenKeyW(hkey, szComponents, &hkeyComponents);
626     if( r != ERROR_SUCCESS )
627         goto end;
628
629     r = RegOpenKeyW(hkeyComponents, szRegName, &hkeyComp);
630     if( r != ERROR_SUCCESS )
631         goto end;
632
633     sz = GUID_SIZE;
634     r = RegEnumValueW(hkeyComp, index, szValName, &sz, NULL, NULL, NULL, NULL);
635     if( r != ERROR_SUCCESS )
636         goto end;
637
638     unsquash_guid(szValName, szProduct);
639
640 end:
641     if( hkeyComp )
642         RegCloseKey(hkeyComp);
643     if( hkeyComponents )
644         RegCloseKey(hkeyComponents);
645     if( hkey )
646         RegCloseKey(hkey);
647
648     return r;
649 }
650
651 UINT WINAPI MsiEnumComponentQualifiersA(
652     LPSTR szComponent, DWORD iIndex, LPSTR lpQualifierBuf, DWORD* pcchQualifierBuf, LPSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf)
653 {
654 FIXME("%s 0x%08lx %p %p %p %p\n", debugstr_a(szComponent), iIndex, lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf, pcchApplicationDataBuf);
655     return ERROR_CALL_NOT_IMPLEMENTED;
656 }
657
658 UINT WINAPI MsiEnumComponentQualifiersW(
659     LPWSTR szComponent, DWORD iIndex, LPWSTR lpQualifierBuf, DWORD* pcchQualifierBuf, LPWSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf)
660 {
661 FIXME("%s 0x%08lx %p %p %p %p\n", debugstr_w(szComponent), iIndex, lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf, pcchApplicationDataBuf);
662     return ERROR_CALL_NOT_IMPLEMENTED;
663 }
664
665 UINT WINAPI MsiProvideAssemblyA(
666     LPCSTR szAssemblyName, LPCSTR szAppContext, DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf, DWORD* pcchPathBuf) 
667 {
668     FIXME("%s %s 0x%08lx 0x%08lx %p %p\n", 
669         debugstr_a(szAssemblyName),  debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf, pcchPathBuf);
670     return ERROR_CALL_NOT_IMPLEMENTED;
671 }
672
673 UINT WINAPI MsiProvideAssemblyW(
674     LPCWSTR szAssemblyName, LPCWSTR szAppContext, DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf, DWORD* pcchPathBuf) 
675 {
676     FIXME("%s %s 0x%08lx 0x%08lx %p %p\n", 
677         debugstr_w(szAssemblyName),  debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf, pcchPathBuf);
678     return ERROR_CALL_NOT_IMPLEMENTED;
679 }
680
681 UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor, LPSTR szPath, DWORD *pcchPath, DWORD *pcchArgs )
682 {
683     FIXME("%s %p %p %p\n", debugstr_a(szDescriptor), szPath, pcchPath, pcchArgs );
684     return ERROR_CALL_NOT_IMPLEMENTED;
685 }
686
687 UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor, LPWSTR szPath, DWORD *pcchPath, DWORD *pcchArgs )
688 {
689     FIXME("%s %p %p %p\n", debugstr_w(szDescriptor), szPath, pcchPath, pcchArgs );
690     return ERROR_CALL_NOT_IMPLEMENTED;
691 }
692
693 HRESULT WINAPI MsiGetFileSignatureInformationA(
694   LPCSTR szSignedObjectPath, DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData, DWORD* pcbHashData)
695 {
696     FIXME("%s 0x%08lx %p %p %p\n", debugstr_a(szSignedObjectPath), dwFlags, ppcCertContext, pbHashData, pcbHashData);
697     return ERROR_CALL_NOT_IMPLEMENTED;
698 }
699
700 HRESULT WINAPI MsiGetFileSignatureInformationW(
701   LPCWSTR szSignedObjectPath, DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData, DWORD* pcbHashData)
702 {
703     FIXME("%s 0x%08lx %p %p %p\n", debugstr_w(szSignedObjectPath), dwFlags, ppcCertContext, pbHashData, pcbHashData);
704     return ERROR_CALL_NOT_IMPLEMENTED;
705 }
706
707 HRESULT WINAPI MSI_DllGetVersion(DLLVERSIONINFO *pdvi)
708 {
709     TRACE("%p\n",pdvi);
710
711     if (pdvi->cbSize != sizeof(DLLVERSIONINFO))
712         return E_INVALIDARG;
713
714     pdvi->dwMajorVersion = MSI_MAJORVERSION;
715     pdvi->dwMinorVersion = MSI_MINORVERSION;
716     pdvi->dwBuildNumber = MSI_BUILDNUMBER;
717     pdvi->dwPlatformID = 1;
718
719     return S_OK;
720 }
721
722 BOOL WINAPI MSI_DllCanUnloadNow(void)
723 {
724     return FALSE;
725 }