d3dx8: Add a few tests for MatrixStack.
[wine] / dlls / msi / msi.c
1 /*
2  * Implementation of the Microsoft Installer (msi.dll)
3  *
4  * Copyright 2002,2003,2004,2005 Mike McCormack for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <stdarg.h>
22
23 #define COBJMACROS
24 #define NONAMELESSUNION
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "winnls.h"
30 #include "shlwapi.h"
31 #include "wine/debug.h"
32 #include "msi.h"
33 #include "msidefs.h"
34 #include "msiquery.h"
35 #include "msipriv.h"
36 #include "wincrypt.h"
37 #include "winver.h"
38 #include "winuser.h"
39 #include "shlobj.h"
40 #include "shobjidl.h"
41 #include "objidl.h"
42 #include "wine/unicode.h"
43
44 WINE_DEFAULT_DEBUG_CHANNEL(msi);
45
46 static const WCHAR installerW[] = {'\\','I','n','s','t','a','l','l','e','r',0};
47
48 static UINT msi_locate_product(LPCWSTR szProduct, MSIINSTALLCONTEXT *context)
49 {
50     HKEY hkey = NULL;
51
52     *context = MSIINSTALLCONTEXT_NONE;
53
54     if (MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
55                               &hkey, FALSE) == ERROR_SUCCESS)
56         *context = MSIINSTALLCONTEXT_USERMANAGED;
57     else if (MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
58                                    &hkey, FALSE) == ERROR_SUCCESS)
59         *context = MSIINSTALLCONTEXT_MACHINE;
60     else if (MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
61                                    &hkey, FALSE) == ERROR_SUCCESS)
62         *context = MSIINSTALLCONTEXT_USERUNMANAGED;
63
64     RegCloseKey(hkey);
65
66     if (*context == MSIINSTALLCONTEXT_NONE)
67         return ERROR_UNKNOWN_PRODUCT;
68
69     return ERROR_SUCCESS;
70 }
71
72 UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct)
73 {
74     UINT r;
75     LPWSTR szwProd = NULL;
76
77     TRACE("%s %p\n",debugstr_a(szProduct), phProduct);
78
79     if( szProduct )
80     {
81         szwProd = strdupAtoW( szProduct );
82         if( !szwProd )
83             return ERROR_OUTOFMEMORY;
84     }
85
86     r = MsiOpenProductW( szwProd, phProduct );
87
88     msi_free( szwProd );
89
90     return r;
91 }
92
93 static UINT MSI_OpenProductW(LPCWSTR szProduct, MSIPACKAGE **package)
94 {
95     UINT r;
96     HKEY props;
97     LPWSTR path;
98     MSIINSTALLCONTEXT context;
99
100     static const WCHAR managed[] = {
101         'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0};
102     static const WCHAR local[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0};
103
104     TRACE("%s %p\n", debugstr_w(szProduct), package);
105
106     r = msi_locate_product(szProduct, &context);
107     if (r != ERROR_SUCCESS)
108         return r;
109
110     if (context == MSIINSTALLCONTEXT_MACHINE)
111         r = MSIREG_OpenLocalSystemInstallProps(szProduct, &props, FALSE);
112     else if (context == MSIINSTALLCONTEXT_USERMANAGED ||
113              context == MSIINSTALLCONTEXT_USERUNMANAGED)
114         r = MSIREG_OpenCurrentUserInstallProps(szProduct, &props, FALSE);
115
116     if (r != ERROR_SUCCESS)
117         return ERROR_UNKNOWN_PRODUCT;
118
119     if (context == MSIINSTALLCONTEXT_USERMANAGED)
120         path = msi_reg_get_val_str(props, managed);
121     else
122         path = msi_reg_get_val_str(props, local);
123
124     r = ERROR_UNKNOWN_PRODUCT;
125
126     if (!path || GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES)
127         goto done;
128
129     if (PathIsRelativeW(path))
130     {
131         r = ERROR_INSTALL_PACKAGE_OPEN_FAILED;
132         goto done;
133     }
134
135     r = MSI_OpenPackageW(path, package);
136
137 done:
138     RegCloseKey(props);
139     msi_free(path);
140     return r;
141 }
142
143 UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct)
144 {
145     MSIPACKAGE *package = NULL;
146     WCHAR squished_pc[GUID_SIZE];
147     UINT r;
148
149     if (!szProduct || !squash_guid(szProduct, squished_pc))
150         return ERROR_INVALID_PARAMETER;
151
152     if (!phProduct)
153         return ERROR_INVALID_PARAMETER;
154
155     r = MSI_OpenProductW(szProduct, &package);
156     if (r != ERROR_SUCCESS)
157         return r;
158
159     *phProduct = alloc_msihandle(&package->hdr);
160     if (!*phProduct)
161         r = ERROR_NOT_ENOUGH_MEMORY;
162
163     msiobj_release(&package->hdr);
164     return r;
165 }
166
167 UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
168                 LPCSTR szTransforms, LANGID lgidLanguage)
169 {
170     FIXME("%s %s %s %08x\n",debugstr_a(szPackagePath),
171           debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage);
172     return ERROR_CALL_NOT_IMPLEMENTED;
173 }
174
175 UINT WINAPI MsiAdvertiseProductW(LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
176                 LPCWSTR szTransforms, LANGID lgidLanguage)
177 {
178     FIXME("%s %s %s %08x\n",debugstr_w(szPackagePath),
179           debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage);
180     return ERROR_CALL_NOT_IMPLEMENTED;
181 }
182
183 UINT WINAPI MsiAdvertiseProductExA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
184       LPCSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
185 {
186     FIXME("%s %s %s %08x %08x %08x\n", debugstr_a(szPackagePath),
187           debugstr_a(szScriptfilePath), debugstr_a(szTransforms),
188           lgidLanguage, dwPlatform, dwOptions);
189     return ERROR_CALL_NOT_IMPLEMENTED;
190 }
191
192 UINT WINAPI MsiAdvertiseProductExW( LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
193       LPCWSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
194 {
195     FIXME("%s %s %s %08x %08x %08x\n", debugstr_w(szPackagePath),
196           debugstr_w(szScriptfilePath), debugstr_w(szTransforms),
197           lgidLanguage, dwPlatform, dwOptions);
198     return ERROR_CALL_NOT_IMPLEMENTED;
199 }
200
201 UINT WINAPI MsiInstallProductA(LPCSTR szPackagePath, LPCSTR szCommandLine)
202 {
203     LPWSTR szwPath = NULL, szwCommand = NULL;
204     UINT r = ERROR_OUTOFMEMORY;
205
206     TRACE("%s %s\n",debugstr_a(szPackagePath), debugstr_a(szCommandLine));
207
208     if( szPackagePath )
209     {
210         szwPath = strdupAtoW( szPackagePath );
211         if( !szwPath )
212             goto end;
213     }
214
215     if( szCommandLine )
216     {
217         szwCommand = strdupAtoW( szCommandLine );
218         if( !szwCommand )
219             goto end;
220     }
221
222     r = MsiInstallProductW( szwPath, szwCommand );
223
224 end:
225     msi_free( szwPath );
226     msi_free( szwCommand );
227
228     return r;
229 }
230
231 UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
232 {
233     MSIPACKAGE *package = NULL;
234     UINT r;
235
236     TRACE("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
237
238     r = MSI_OpenPackageW( szPackagePath, &package );
239     if (r == ERROR_SUCCESS)
240     {
241         r = MSI_InstallPackage( package, szPackagePath, szCommandLine );
242         msiobj_release( &package->hdr );
243     }
244
245     return r;
246 }
247
248 UINT WINAPI MsiReinstallProductA(LPCSTR szProduct, DWORD dwReinstallMode)
249 {
250     FIXME("%s %08x\n", debugstr_a(szProduct), dwReinstallMode);
251     return ERROR_CALL_NOT_IMPLEMENTED;
252 }
253
254 UINT WINAPI MsiReinstallProductW(LPCWSTR szProduct, DWORD dwReinstallMode)
255 {
256     FIXME("%s %08x\n", debugstr_w(szProduct), dwReinstallMode);
257     return ERROR_CALL_NOT_IMPLEMENTED;
258 }
259
260 UINT WINAPI MsiApplyPatchA(LPCSTR szPatchPackage, LPCSTR szInstallPackage,
261         INSTALLTYPE eInstallType, LPCSTR szCommandLine)
262 {
263     LPWSTR patch_package = NULL;
264     LPWSTR install_package = NULL;
265     LPWSTR command_line = NULL;
266     UINT r = ERROR_OUTOFMEMORY;
267
268     TRACE("%s %s %d %s\n", debugstr_a(szPatchPackage), debugstr_a(szInstallPackage),
269           eInstallType, debugstr_a(szCommandLine));
270
271     if (szPatchPackage && !(patch_package = strdupAtoW(szPatchPackage)))
272         goto done;
273
274     if (szInstallPackage && !(install_package = strdupAtoW(szInstallPackage)))
275         goto done;
276
277     if (szCommandLine && !(command_line = strdupAtoW(szCommandLine)))
278         goto done;
279
280     r = MsiApplyPatchW(patch_package, install_package, eInstallType, command_line);
281
282 done:
283     msi_free(patch_package);
284     msi_free(install_package);
285     msi_free(command_line);
286
287     return r;
288 }
289
290 UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage,
291          INSTALLTYPE eInstallType, LPCWSTR szCommandLine)
292 {
293     MSIHANDLE patch, info;
294     UINT r, type;
295     DWORD size = 0;
296     LPCWSTR cmd_ptr = szCommandLine;
297     LPWSTR beg, end;
298     LPWSTR cmd = NULL, codes = NULL;
299
300     static const WCHAR space[] = {' ',0};
301     static const WCHAR patcheq[] = {'P','A','T','C','H','=',0};
302     static WCHAR empty[] = {0};
303
304     TRACE("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage),
305           eInstallType, debugstr_w(szCommandLine));
306
307     if (szInstallPackage || eInstallType == INSTALLTYPE_NETWORK_IMAGE ||
308         eInstallType == INSTALLTYPE_SINGLE_INSTANCE)
309     {
310         FIXME("Only reading target products from patch\n");
311         return ERROR_CALL_NOT_IMPLEMENTED;
312     }
313
314     r = MsiOpenDatabaseW(szPatchPackage, MSIDBOPEN_READONLY, &patch);
315     if (r != ERROR_SUCCESS)
316         return r;
317
318     r = MsiGetSummaryInformationW(patch, NULL, 0, &info);
319     if (r != ERROR_SUCCESS)
320         goto done;
321
322     r = MsiSummaryInfoGetPropertyW(info, PID_TEMPLATE, &type, NULL, NULL, empty, &size);
323     if (r != ERROR_MORE_DATA || !size || type != VT_LPSTR)
324     {
325         ERR("Failed to read product codes from patch\n");
326         goto done;
327     }
328
329     codes = msi_alloc(++size * sizeof(WCHAR));
330     if (!codes)
331     {
332         r = ERROR_OUTOFMEMORY;
333         goto done;
334     }
335
336     r = MsiSummaryInfoGetPropertyW(info, PID_TEMPLATE, &type, NULL, NULL, codes, &size);
337     if (r != ERROR_SUCCESS)
338         goto done;
339
340     if (!szCommandLine)
341         cmd_ptr = empty;
342
343     size = lstrlenW(cmd_ptr) + lstrlenW(patcheq) + lstrlenW(szPatchPackage) + 1;
344     cmd = msi_alloc(size * sizeof(WCHAR));
345     if (!cmd)
346     {
347         r = ERROR_OUTOFMEMORY;
348         goto done;
349     }
350
351     lstrcpyW(cmd, cmd_ptr);
352     if (szCommandLine) lstrcatW(cmd, space);
353     lstrcatW(cmd, patcheq);
354     lstrcatW(cmd, szPatchPackage);
355
356     beg = codes;
357     while ((end = strchrW(beg, '}')))
358     {
359         *(end + 1) = '\0';
360
361         r = MsiConfigureProductExW(beg, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd);
362         if (r != ERROR_SUCCESS)
363             goto done;
364
365         beg = end + 2;
366     }
367
368 done:
369     msi_free(cmd);
370     msi_free(codes);
371
372     MsiCloseHandle(info);
373     MsiCloseHandle(patch);
374
375     return r;
376 }
377
378 UINT WINAPI MsiDetermineApplicablePatchesA(LPCSTR szProductPackagePath,
379         DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOA pPatchInfo)
380 {
381     FIXME("(%s, %d, %p): stub!\n", debugstr_a(szProductPackagePath),
382           cPatchInfo, pPatchInfo);
383
384     return ERROR_CALL_NOT_IMPLEMENTED;
385 }
386
387 UINT WINAPI MsiDetermineApplicablePatchesW(LPCWSTR szProductPackagePath,
388         DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOW pPatchInfo)
389 {
390     FIXME("(%s, %d, %p): stub!\n", debugstr_w(szProductPackagePath),
391           cPatchInfo, pPatchInfo);
392
393     return ERROR_CALL_NOT_IMPLEMENTED;
394 }
395
396 static UINT msi_open_package(LPCWSTR product, MSIINSTALLCONTEXT context,
397                              MSIPACKAGE **package)
398 {
399     UINT r;
400     DWORD sz;
401     HKEY props;
402     LPWSTR localpack;
403     WCHAR sourcepath[MAX_PATH];
404     WCHAR filename[MAX_PATH];
405
406     static const WCHAR szLocalPackage[] = {
407         'L','o','c','a','l','P','a','c','k','a','g','e',0};
408
409     if (context == MSIINSTALLCONTEXT_MACHINE)
410         r = MSIREG_OpenLocalSystemInstallProps(product, &props, FALSE);
411     else
412         r = MSIREG_OpenCurrentUserInstallProps(product, &props, FALSE);
413
414     if (r != ERROR_SUCCESS)
415         return ERROR_BAD_CONFIGURATION;
416
417     localpack = msi_reg_get_val_str(props, szLocalPackage);
418     if (localpack)
419     {
420         lstrcpyW(sourcepath, localpack);
421         msi_free(localpack);
422     }
423
424     if (!localpack || GetFileAttributesW(sourcepath) == INVALID_FILE_ATTRIBUTES)
425     {
426         sz = sizeof(sourcepath);
427         MsiSourceListGetInfoW(product, NULL, context, MSICODE_PRODUCT,
428                               INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
429
430         sz = sizeof(filename);
431         MsiSourceListGetInfoW(product, NULL, context, MSICODE_PRODUCT,
432                               INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
433
434         lstrcatW(sourcepath, filename);
435     }
436
437     if (GetFileAttributesW(sourcepath) == INVALID_FILE_ATTRIBUTES)
438         return ERROR_INSTALL_SOURCE_ABSENT;
439
440     return MSI_OpenPackageW(sourcepath, package);
441 }
442
443 UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
444                         INSTALLSTATE eInstallState, LPCWSTR szCommandLine)
445 {
446     MSIPACKAGE* package = NULL;
447     MSIINSTALLCONTEXT context;
448     UINT r;
449     DWORD sz;
450     WCHAR sourcepath[MAX_PATH];
451     LPWSTR commandline;
452
453     static const WCHAR szInstalled[] = {
454         ' ','I','n','s','t','a','l','l','e','d','=','1',0};
455     static const WCHAR szRemoveAll[] = {
456         ' ','R','E','M','O','V','E','=','A','L','L',0};
457     static const WCHAR szMachine[] = {
458         ' ','A','L','L','U','S','E','R','S','=','1',0};
459
460     TRACE("%s %d %d %s\n",debugstr_w(szProduct), iInstallLevel, eInstallState,
461           debugstr_w(szCommandLine));
462
463     if (!szProduct || lstrlenW(szProduct) != GUID_SIZE - 1)
464         return ERROR_INVALID_PARAMETER;
465
466     if (eInstallState == INSTALLSTATE_ADVERTISED ||
467         eInstallState == INSTALLSTATE_SOURCE)
468     {
469         FIXME("State %d not implemented\n", eInstallState);
470         return ERROR_CALL_NOT_IMPLEMENTED;
471     }
472
473     r = msi_locate_product(szProduct, &context);
474     if (r != ERROR_SUCCESS)
475         return r;
476
477     r = msi_open_package(szProduct, context, &package);
478     if (r != ERROR_SUCCESS)
479         return r;
480
481     sz = lstrlenW(szInstalled) + 1;
482
483     if (szCommandLine)
484         sz += lstrlenW(szCommandLine);
485
486     if (eInstallState == INSTALLSTATE_ABSENT)
487         sz += lstrlenW(szRemoveAll);
488
489     if (context == MSIINSTALLCONTEXT_MACHINE)
490         sz += lstrlenW(szMachine);
491
492     commandline = msi_alloc(sz * sizeof(WCHAR));
493     if (!commandline)
494     {
495         r = ERROR_OUTOFMEMORY;
496         goto end;
497     }
498
499     commandline[0] = 0;
500     if (szCommandLine)
501         lstrcpyW(commandline,szCommandLine);
502
503     if (MsiQueryProductStateW(szProduct) != INSTALLSTATE_UNKNOWN)
504         lstrcatW(commandline,szInstalled);
505
506     if (eInstallState == INSTALLSTATE_ABSENT)
507         lstrcatW(commandline, szRemoveAll);
508
509     if (context == MSIINSTALLCONTEXT_MACHINE)
510         lstrcatW(commandline, szMachine);
511
512     r = MSI_InstallPackage( package, sourcepath, commandline );
513
514     msi_free(commandline);
515
516 end:
517     msiobj_release( &package->hdr );
518
519     return r;
520 }
521
522 UINT WINAPI MsiConfigureProductExA(LPCSTR szProduct, int iInstallLevel,
523                         INSTALLSTATE eInstallState, LPCSTR szCommandLine)
524 {
525     LPWSTR szwProduct = NULL;
526     LPWSTR szwCommandLine = NULL;
527     UINT r = ERROR_OUTOFMEMORY;
528
529     if( szProduct )
530     {
531         szwProduct = strdupAtoW( szProduct );
532         if( !szwProduct )
533             goto end;
534     }
535
536     if( szCommandLine)
537     {
538         szwCommandLine = strdupAtoW( szCommandLine );
539         if( !szwCommandLine)
540             goto end;
541     }
542
543     r = MsiConfigureProductExW( szwProduct, iInstallLevel, eInstallState,
544                                 szwCommandLine );
545 end:
546     msi_free( szwProduct );
547     msi_free( szwCommandLine);
548
549     return r;
550 }
551
552 UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel,
553                                  INSTALLSTATE eInstallState)
554 {
555     LPWSTR szwProduct = NULL;
556     UINT r;
557
558     TRACE("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState);
559
560     if( szProduct )
561     {
562         szwProduct = strdupAtoW( szProduct );
563         if( !szwProduct )
564             return ERROR_OUTOFMEMORY;
565     }
566
567     r = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState );
568     msi_free( szwProduct );
569
570     return r;
571 }
572
573 UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel,
574                                  INSTALLSTATE eInstallState)
575 {
576     return MsiConfigureProductExW(szProduct, iInstallLevel, eInstallState, NULL);
577 }
578
579 UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer)
580 {
581     LPWSTR szwComponent = NULL;
582     UINT r;
583     WCHAR szwBuffer[GUID_SIZE];
584
585     TRACE("%s %s\n",debugstr_a(szComponent), debugstr_a(szBuffer));
586
587     if( szComponent )
588     {
589         szwComponent = strdupAtoW( szComponent );
590         if( !szwComponent )
591             return ERROR_OUTOFMEMORY;
592     }
593
594     *szwBuffer = '\0';
595     r = MsiGetProductCodeW( szwComponent, szwBuffer );
596
597     if(*szwBuffer)
598         WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, GUID_SIZE, NULL, NULL);
599
600     msi_free( szwComponent );
601
602     return r;
603 }
604
605 UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer)
606 {
607     UINT rc, index;
608     HKEY compkey, prodkey;
609     WCHAR squished_comp[GUID_SIZE];
610     WCHAR squished_prod[GUID_SIZE];
611     DWORD sz = GUID_SIZE;
612
613     TRACE("%s %p\n", debugstr_w(szComponent), szBuffer);
614
615     if (!szComponent || !*szComponent)
616         return ERROR_INVALID_PARAMETER;
617
618     if (!squash_guid(szComponent, squished_comp))
619         return ERROR_INVALID_PARAMETER;
620
621     if (MSIREG_OpenUserDataComponentKey(szComponent, &compkey, FALSE) != ERROR_SUCCESS &&
622         MSIREG_OpenLocalSystemComponentKey(szComponent, &compkey, FALSE) != ERROR_SUCCESS)
623     {
624         return ERROR_UNKNOWN_COMPONENT;
625     }
626
627     rc = RegEnumValueW(compkey, 0, squished_prod, &sz, NULL, NULL, NULL, NULL);
628     if (rc != ERROR_SUCCESS)
629     {
630         RegCloseKey(compkey);
631         return ERROR_UNKNOWN_COMPONENT;
632     }
633
634     /* check simple case, only one product */
635     rc = RegEnumValueW(compkey, 1, squished_prod, &sz, NULL, NULL, NULL, NULL);
636     if (rc == ERROR_NO_MORE_ITEMS)
637     {
638         rc = ERROR_SUCCESS;
639         goto done;
640     }
641
642     index = 0;
643     while ((rc = RegEnumValueW(compkey, index, squished_prod, &sz,
644            NULL, NULL, NULL, NULL)) != ERROR_NO_MORE_ITEMS)
645     {
646         index++;
647         sz = GUID_SIZE;
648         unsquash_guid(squished_prod, szBuffer);
649
650         if (MSIREG_OpenProductKey(szBuffer, MSIINSTALLCONTEXT_USERMANAGED,
651                                   &prodkey, FALSE) == ERROR_SUCCESS ||
652             MSIREG_OpenProductKey(szBuffer, MSIINSTALLCONTEXT_USERUNMANAGED,
653                                   &prodkey, FALSE) == ERROR_SUCCESS ||
654             MSIREG_OpenProductKey(szBuffer, MSIINSTALLCONTEXT_MACHINE,
655                                   &prodkey, FALSE) == ERROR_SUCCESS)
656         {
657             RegCloseKey(prodkey);
658             rc = ERROR_SUCCESS;
659             goto done;
660         }
661     }
662
663     rc = ERROR_INSTALL_FAILURE;
664
665 done:
666     RegCloseKey(compkey);
667     unsquash_guid(squished_prod, szBuffer);
668     return rc;
669 }
670
671 static LPWSTR msi_reg_get_value(HKEY hkey, LPCWSTR name, DWORD *type)
672 {
673     DWORD dval;
674     LONG res;
675     WCHAR temp[20];
676
677     static const WCHAR format[] = {'%','d',0};
678
679     res = RegQueryValueExW(hkey, name, NULL, type, NULL, NULL);
680     if (res != ERROR_SUCCESS)
681         return NULL;
682
683     if (*type == REG_SZ)
684         return msi_reg_get_val_str(hkey, name);
685
686     if (!msi_reg_get_val_dword(hkey, name, &dval))
687         return NULL;
688
689     sprintfW(temp, format, dval);
690     return strdupW(temp);
691 }
692
693 static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
694                                awstring *szValue, LPDWORD pcchValueBuf)
695 {
696     UINT r = ERROR_UNKNOWN_PROPERTY;
697     HKEY prodkey, userdata, source;
698     LPWSTR val = NULL;
699     WCHAR squished_pc[GUID_SIZE];
700     WCHAR packagecode[GUID_SIZE];
701     BOOL classes = FALSE;
702     BOOL badconfig = FALSE;
703     LONG res;
704     DWORD save, type = REG_NONE;
705
706     static WCHAR empty[] = {0};
707     static const WCHAR sourcelist[] = {
708         'S','o','u','r','c','e','L','i','s','t',0};
709     static const WCHAR display_name[] = {
710         'D','i','s','p','l','a','y','N','a','m','e',0};
711     static const WCHAR display_version[] = {
712         'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
713     static const WCHAR assignment[] = {
714         'A','s','s','i','g','n','m','e','n','t',0};
715
716     TRACE("%s %s %p %p\n", debugstr_w(szProduct),
717           debugstr_w(szAttribute), szValue, pcchValueBuf);
718
719     if ((szValue->str.w && !pcchValueBuf) || !szProduct || !szAttribute)
720         return ERROR_INVALID_PARAMETER;
721
722     if (!squash_guid(szProduct, squished_pc))
723         return ERROR_INVALID_PARAMETER;
724
725     if ((r = MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
726                                    &prodkey, FALSE)) != ERROR_SUCCESS &&
727         (r = MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
728                                    &prodkey, FALSE)) != ERROR_SUCCESS &&
729         (r = MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
730                                       &prodkey, FALSE)) == ERROR_SUCCESS)
731     {
732         classes = TRUE;
733     }
734
735     if (classes)
736         MSIREG_OpenLocalSystemProductKey(szProduct, &userdata, FALSE);
737     else
738         MSIREG_OpenCurrentUserInstallProps(szProduct, &userdata, FALSE);
739
740     if (!lstrcmpW(szAttribute, INSTALLPROPERTY_HELPLINKW) ||
741         !lstrcmpW(szAttribute, INSTALLPROPERTY_HELPTELEPHONEW) ||
742         !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLDATEW) ||
743         !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW) ||
744         !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLLOCATIONW) ||
745         !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLSOURCEW) ||
746         !lstrcmpW(szAttribute, INSTALLPROPERTY_LOCALPACKAGEW) ||
747         !lstrcmpW(szAttribute, INSTALLPROPERTY_PUBLISHERW) ||
748         !lstrcmpW(szAttribute, INSTALLPROPERTY_URLINFOABOUTW) ||
749         !lstrcmpW(szAttribute, INSTALLPROPERTY_URLUPDATEINFOW) ||
750         !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONMINORW) ||
751         !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONMAJORW) ||
752         !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW) ||
753         !lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTIDW) ||
754         !lstrcmpW(szAttribute, INSTALLPROPERTY_REGCOMPANYW) ||
755         !lstrcmpW(szAttribute, INSTALLPROPERTY_REGOWNERW))
756     {
757         if (!prodkey)
758         {
759             r = ERROR_UNKNOWN_PRODUCT;
760             goto done;
761         }
762
763         if (!userdata)
764             return ERROR_UNKNOWN_PROPERTY;
765
766         if (!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW))
767             szAttribute = display_name;
768         else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW))
769             szAttribute = display_version;
770
771         val = msi_reg_get_value(userdata, szAttribute, &type);
772         if (!val)
773             val = empty;
774     }
775     else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTANCETYPEW) ||
776              !lstrcmpW(szAttribute, INSTALLPROPERTY_TRANSFORMSW) ||
777              !lstrcmpW(szAttribute, INSTALLPROPERTY_LANGUAGEW) ||
778              !lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTNAMEW) ||
779              !lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW) ||
780              !lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW) ||
781              !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONW) ||
782              !lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTICONW) ||
783              !lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGENAMEW) ||
784              !lstrcmpW(szAttribute, INSTALLPROPERTY_AUTHORIZED_LUA_APPW))
785     {
786         if (!prodkey)
787         {
788             r = ERROR_UNKNOWN_PRODUCT;
789             goto done;
790         }
791
792         if (!lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW))
793             szAttribute = assignment;
794
795         if (!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGENAMEW))
796         {
797             res = RegOpenKeyW(prodkey, sourcelist, &source);
798             if (res == ERROR_SUCCESS)
799                 val = msi_reg_get_value(source, szAttribute, &type);
800
801             RegCloseKey(source);
802         }
803         else
804         {
805             val = msi_reg_get_value(prodkey, szAttribute, &type);
806             if (!val)
807                 val = empty;
808         }
809
810         if (val != empty && type != REG_DWORD &&
811             !lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW))
812         {
813             if (lstrlenW(val) != SQUISH_GUID_SIZE - 1)
814                 badconfig = TRUE;
815             else
816             {
817                 unsquash_guid(val, packagecode);
818                 msi_free(val);
819                 val = strdupW(packagecode);
820             }
821         }
822     }
823
824     if (!val)
825     {
826         r = ERROR_UNKNOWN_PROPERTY;
827         goto done;
828     }
829
830     if (pcchValueBuf)
831     {
832         save = *pcchValueBuf;
833
834         if (strlenW(val) < *pcchValueBuf)
835             r = msi_strcpy_to_awstring(val, szValue, pcchValueBuf);
836         else if (szValue->str.a || szValue->str.w)
837             r = ERROR_MORE_DATA;
838
839         if (!badconfig)
840             *pcchValueBuf = lstrlenW(val);
841         else if (r == ERROR_SUCCESS)
842         {
843             *pcchValueBuf = save;
844             r = ERROR_BAD_CONFIGURATION;
845         }
846     }
847     else if (badconfig)
848         r = ERROR_BAD_CONFIGURATION;
849
850     if (val != empty)
851         msi_free(val);
852
853 done:
854     RegCloseKey(prodkey);
855     RegCloseKey(userdata);
856     return r;
857 }
858
859 UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute,
860                                LPSTR szBuffer, LPDWORD pcchValueBuf)
861 {
862     LPWSTR szwProduct, szwAttribute = NULL;
863     UINT r = ERROR_OUTOFMEMORY;
864     awstring buffer;
865
866     TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szAttribute),
867           szBuffer, pcchValueBuf);
868
869     szwProduct = strdupAtoW( szProduct );
870     if( szProduct && !szwProduct )
871         goto end;
872
873     szwAttribute = strdupAtoW( szAttribute );
874     if( szAttribute && !szwAttribute )
875         goto end;
876
877     buffer.unicode = FALSE;
878     buffer.str.a = szBuffer;
879
880     r = MSI_GetProductInfo( szwProduct, szwAttribute,
881                             &buffer, pcchValueBuf );
882
883 end:
884     msi_free( szwProduct );
885     msi_free( szwAttribute );
886
887     return r;
888 }
889
890 UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
891                                LPWSTR szBuffer, LPDWORD pcchValueBuf)
892 {
893     awstring buffer;
894
895     TRACE("%s %s %p %p\n", debugstr_w(szProduct), debugstr_w(szAttribute),
896           szBuffer, pcchValueBuf);
897
898     buffer.unicode = TRUE;
899     buffer.str.w = szBuffer;
900
901     return MSI_GetProductInfo( szProduct, szAttribute,
902                                &buffer, pcchValueBuf );
903 }
904
905 UINT WINAPI MsiGetProductInfoExA(LPCSTR szProductCode, LPCSTR szUserSid,
906                                  MSIINSTALLCONTEXT dwContext, LPCSTR szProperty,
907                                  LPSTR szValue, LPDWORD pcchValue)
908 {
909     LPWSTR product = NULL;
910     LPWSTR usersid = NULL;
911     LPWSTR property = NULL;
912     LPWSTR value = NULL;
913     DWORD len = 0;
914     UINT r;
915
916     TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_a(szProductCode),
917           debugstr_a(szUserSid), dwContext, debugstr_a(szProperty),
918            szValue, pcchValue);
919
920     if (szValue && !pcchValue)
921         return ERROR_INVALID_PARAMETER;
922
923     if (szProductCode) product = strdupAtoW(szProductCode);
924     if (szUserSid) usersid = strdupAtoW(szUserSid);
925     if (szProperty) property = strdupAtoW(szProperty);
926
927     r = MsiGetProductInfoExW(product, usersid, dwContext, property,
928                              NULL, &len);
929     if (r != ERROR_SUCCESS)
930         goto done;
931
932     value = msi_alloc(++len * sizeof(WCHAR));
933     if (!value)
934     {
935         r = ERROR_OUTOFMEMORY;
936         goto done;
937     }
938
939     r = MsiGetProductInfoExW(product, usersid, dwContext, property,
940                              value, &len);
941     if (r != ERROR_SUCCESS)
942         goto done;
943
944     if (!pcchValue)
945         goto done;
946
947     len = WideCharToMultiByte(CP_ACP, 0, value, -1, NULL, 0, NULL, NULL);
948     if (*pcchValue >= len)
949         WideCharToMultiByte(CP_ACP, 0, value, -1, szValue, len, NULL, NULL);
950     else if (szValue)
951     {
952         r = ERROR_MORE_DATA;
953         if (*pcchValue > 0)
954             *szValue = '\0';
955     }
956
957     if (*pcchValue <= len || !szValue)
958         len = len * sizeof(WCHAR) - 1;
959
960     *pcchValue = len - 1;
961
962 done:
963     msi_free(product);
964     msi_free(usersid);
965     msi_free(property);
966     msi_free(value);
967
968     return r;
969 }
970
971 static UINT msi_copy_outval(LPWSTR val, LPWSTR out, LPDWORD size)
972 {
973     UINT r;
974
975     if (!val)
976         return ERROR_UNKNOWN_PROPERTY;
977
978     if (out)
979     {
980         if (strlenW(val) >= *size)
981         {
982             r = ERROR_MORE_DATA;
983             if (*size > 0)
984                 *out = '\0';
985         }
986         else
987             lstrcpyW(out, val);
988     }
989
990     if (size)
991         *size = lstrlenW(val);
992
993     return ERROR_SUCCESS;
994 }
995
996 UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
997                                  MSIINSTALLCONTEXT dwContext, LPCWSTR szProperty,
998                                  LPWSTR szValue, LPDWORD pcchValue)
999 {
1000     WCHAR squished_pc[GUID_SIZE];
1001     LPWSTR val = NULL;
1002     LPCWSTR package = NULL;
1003     HKEY props = NULL, prod;
1004     HKEY classes = NULL, managed;
1005     HKEY hkey = NULL;
1006     DWORD type;
1007     UINT r = ERROR_UNKNOWN_PRODUCT;
1008
1009     static const WCHAR one[] = {'1',0};
1010     static const WCHAR five[] = {'5',0};
1011     static const WCHAR empty[] = {0};
1012     static const WCHAR displayname[] = {
1013         'D','i','s','p','l','a','y','N','a','m','e',0};
1014     static const WCHAR displayversion[] = {
1015         'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
1016     static const WCHAR managed_local_package[] = {
1017         'M','a','n','a','g','e','d','L','o','c','a','l',
1018         'P','a','c','k','a','g','e',0};
1019
1020     TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_w(szProductCode),
1021           debugstr_w(szUserSid), dwContext, debugstr_w(szProperty),
1022            szValue, pcchValue);
1023
1024     if (!szProductCode || !squash_guid(szProductCode, squished_pc))
1025         return ERROR_INVALID_PARAMETER;
1026
1027     if (szValue && !pcchValue)
1028         return ERROR_INVALID_PARAMETER;
1029
1030     if (dwContext != MSIINSTALLCONTEXT_USERUNMANAGED &&
1031         dwContext != MSIINSTALLCONTEXT_USERMANAGED &&
1032         dwContext != MSIINSTALLCONTEXT_MACHINE)
1033         return ERROR_INVALID_PARAMETER;
1034
1035     if (!szProperty || !*szProperty)
1036         return ERROR_INVALID_PARAMETER;
1037
1038     if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
1039         return ERROR_INVALID_PARAMETER;
1040
1041     MSIREG_OpenProductKey(szProductCode, MSIINSTALLCONTEXT_USERMANAGED,
1042                           &managed, FALSE);
1043     MSIREG_OpenProductKey(szProductCode, MSIINSTALLCONTEXT_USERUNMANAGED,
1044                           &prod, FALSE);
1045
1046     if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
1047     {
1048         package = INSTALLPROPERTY_LOCALPACKAGEW;
1049         MSIREG_OpenCurrentUserInstallProps(szProductCode, &props, FALSE);
1050
1051         if (!props && !prod)
1052             goto done;
1053     }
1054     else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1055     {
1056         package = managed_local_package;
1057         MSIREG_OpenCurrentUserInstallProps(szProductCode, &props, FALSE);
1058
1059         if (!props && !managed)
1060             goto done;
1061     }
1062     else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1063     {
1064         package = INSTALLPROPERTY_LOCALPACKAGEW;
1065         MSIREG_OpenLocalSystemProductKey(szProductCode, &props, FALSE);
1066         MSIREG_OpenProductKey(szProductCode, dwContext, &classes, FALSE);
1067
1068         if (!props && !classes)
1069             goto done;
1070     }
1071
1072     if (!lstrcmpW(szProperty, INSTALLPROPERTY_HELPLINKW) ||
1073         !lstrcmpW(szProperty, INSTALLPROPERTY_HELPTELEPHONEW) ||
1074         !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLDATEW) ||
1075         !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW) ||
1076         !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLLOCATIONW) ||
1077         !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLSOURCEW) ||
1078         !lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW) ||
1079         !lstrcmpW(szProperty, INSTALLPROPERTY_PUBLISHERW) ||
1080         !lstrcmpW(szProperty, INSTALLPROPERTY_URLINFOABOUTW) ||
1081         !lstrcmpW(szProperty, INSTALLPROPERTY_URLUPDATEINFOW) ||
1082         !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONMINORW) ||
1083         !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONMAJORW) ||
1084         !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONSTRINGW) ||
1085         !lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTIDW) ||
1086         !lstrcmpW(szProperty, INSTALLPROPERTY_REGCOMPANYW) ||
1087         !lstrcmpW(szProperty, INSTALLPROPERTY_REGOWNERW) ||
1088         !lstrcmpW(szProperty, INSTALLPROPERTY_INSTANCETYPEW))
1089     {
1090         val = msi_reg_get_value(props, package, &type);
1091         if (!val)
1092         {
1093             if (prod || classes)
1094                 r = ERROR_UNKNOWN_PROPERTY;
1095
1096             goto done;
1097         }
1098
1099         msi_free(val);
1100
1101         if (!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW))
1102             szProperty = displayname;
1103         else if (!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONSTRINGW))
1104             szProperty = displayversion;
1105
1106         val = msi_reg_get_value(props, szProperty, &type);
1107         if (!val)
1108             val = strdupW(empty);
1109
1110         r = msi_copy_outval(val, szValue, pcchValue);
1111     }
1112     else if (!lstrcmpW(szProperty, INSTALLPROPERTY_TRANSFORMSW) ||
1113              !lstrcmpW(szProperty, INSTALLPROPERTY_LANGUAGEW) ||
1114              !lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTNAMEW) ||
1115              !lstrcmpW(szProperty, INSTALLPROPERTY_PACKAGECODEW) ||
1116              !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONW) ||
1117              !lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTICONW) ||
1118              !lstrcmpW(szProperty, INSTALLPROPERTY_PACKAGENAMEW) ||
1119              !lstrcmpW(szProperty, INSTALLPROPERTY_AUTHORIZED_LUA_APPW))
1120     {
1121         if (!prod && !classes)
1122             goto done;
1123
1124         if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
1125             hkey = prod;
1126         else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1127             hkey = managed;
1128         else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1129             hkey = classes;
1130
1131         val = msi_reg_get_value(hkey, szProperty, &type);
1132         if (!val)
1133             val = strdupW(empty);
1134
1135         r = msi_copy_outval(val, szValue, pcchValue);
1136     }
1137     else if (!lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTSTATEW))
1138     {
1139         if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1140         {
1141             if (props)
1142             {
1143                 val = msi_reg_get_value(props, package, &type);
1144                 if (!val)
1145                     goto done;
1146
1147                 msi_free(val);
1148                 val = strdupW(five);
1149             }
1150             else
1151                 val = strdupW(one);
1152
1153             r = msi_copy_outval(val, szValue, pcchValue);
1154             goto done;
1155         }
1156         else if (props && (val = msi_reg_get_value(props, package, &type)))
1157         {
1158             msi_free(val);
1159             val = strdupW(five);
1160             r = msi_copy_outval(val, szValue, pcchValue);
1161             goto done;
1162         }
1163
1164         if (prod || managed)
1165             val = strdupW(one);
1166         else
1167             goto done;
1168
1169         r = msi_copy_outval(val, szValue, pcchValue);
1170     }
1171     else if (!lstrcmpW(szProperty, INSTALLPROPERTY_ASSIGNMENTTYPEW))
1172     {
1173         if (!prod && !classes)
1174             goto done;
1175
1176         /* FIXME */
1177         val = strdupW(empty);
1178         r = msi_copy_outval(val, szValue, pcchValue);
1179     }
1180     else
1181         r = ERROR_UNKNOWN_PROPERTY;
1182
1183 done:
1184     RegCloseKey(props);
1185     RegCloseKey(prod);
1186     RegCloseKey(managed);
1187     RegCloseKey(classes);
1188     msi_free(val);
1189
1190     return r;
1191 }
1192
1193 UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes)
1194 {
1195     LPWSTR szwLogFile = NULL;
1196     UINT r;
1197
1198     TRACE("%08x %s %08x\n", dwLogMode, debugstr_a(szLogFile), attributes);
1199
1200     if( szLogFile )
1201     {
1202         szwLogFile = strdupAtoW( szLogFile );
1203         if( !szwLogFile )
1204             return ERROR_OUTOFMEMORY;
1205     }
1206     r = MsiEnableLogW( dwLogMode, szwLogFile, attributes );
1207     msi_free( szwLogFile );
1208     return r;
1209 }
1210
1211 UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes)
1212 {
1213     HANDLE file = INVALID_HANDLE_VALUE;
1214
1215     TRACE("%08x %s %08x\n", dwLogMode, debugstr_w(szLogFile), attributes);
1216
1217     if (szLogFile)
1218     {
1219         lstrcpyW(gszLogFile,szLogFile);
1220         if (!(attributes & INSTALLLOGATTRIBUTES_APPEND))
1221             DeleteFileW(szLogFile);
1222         file = CreateFileW(szLogFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
1223                                FILE_ATTRIBUTE_NORMAL, NULL);
1224         if (file != INVALID_HANDLE_VALUE)
1225             CloseHandle(file);
1226         else
1227             ERR("Unable to enable log %s\n",debugstr_w(szLogFile));
1228     }
1229     else
1230         gszLogFile[0] = '\0';
1231
1232     return ERROR_SUCCESS;
1233 }
1234
1235 UINT WINAPI MsiEnumComponentCostsW(MSIHANDLE hInstall, LPCWSTR szComponent,
1236                                    DWORD dwIndex, INSTALLSTATE iState,
1237                                    LPWSTR lpDriveBuf, DWORD *pcchDriveBuf,
1238                                    int *piCost, int *pTempCost)
1239 {
1240     FIXME("(%ld, %s, %d, %d, %p, %p, %p %p): stub!\n", hInstall,
1241           debugstr_w(szComponent), dwIndex, iState, lpDriveBuf,
1242           pcchDriveBuf, piCost, pTempCost);
1243
1244     return ERROR_NO_MORE_ITEMS;
1245 }
1246
1247 UINT WINAPI MsiQueryComponentStateA(LPCSTR szProductCode,
1248                                     LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1249                                     LPCSTR szComponent, INSTALLSTATE *pdwState)
1250 {
1251     LPWSTR prodcode = NULL, usersid = NULL, comp = NULL;
1252     UINT r;
1253
1254     TRACE("(%s, %s, %d, %s, %p)\n", debugstr_a(szProductCode),
1255           debugstr_a(szUserSid), dwContext, debugstr_a(szComponent), pdwState);
1256
1257     if (szProductCode && !(prodcode = strdupAtoW(szProductCode)))
1258         return ERROR_OUTOFMEMORY;
1259
1260     if (szUserSid && !(usersid = strdupAtoW(szUserSid)))
1261             return ERROR_OUTOFMEMORY;
1262
1263     if (szComponent && !(comp = strdupAtoW(szComponent)))
1264             return ERROR_OUTOFMEMORY;
1265
1266     r = MsiQueryComponentStateW(prodcode, usersid, dwContext, comp, pdwState);
1267
1268     msi_free(prodcode);
1269     msi_free(usersid);
1270     msi_free(comp);
1271
1272     return r;
1273 }
1274
1275 static BOOL msi_comp_find_prod_key(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
1276 {
1277     UINT r;
1278     HKEY hkey;
1279
1280     r = MSIREG_OpenProductKey(prodcode, context, &hkey, FALSE);
1281     RegCloseKey(hkey);
1282     return (r == ERROR_SUCCESS);
1283 }
1284
1285 static BOOL msi_comp_find_package(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
1286 {
1287     LPCWSTR package;
1288     HKEY hkey;
1289     DWORD sz;
1290     LONG res;
1291     UINT r;
1292
1293     static const WCHAR local_package[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0};
1294     static const WCHAR managed_local_package[] = {
1295         'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0
1296     };
1297
1298     if (context == MSIINSTALLCONTEXT_MACHINE)
1299         r = MSIREG_OpenLocalSystemProductKey(prodcode, &hkey, FALSE);
1300     else
1301         r = MSIREG_OpenCurrentUserInstallProps(prodcode, &hkey, FALSE);
1302
1303     if (r != ERROR_SUCCESS)
1304         return FALSE;
1305
1306     if (context == MSIINSTALLCONTEXT_USERMANAGED)
1307         package = managed_local_package;
1308     else
1309         package = local_package;
1310
1311     sz = 0;
1312     res = RegQueryValueExW(hkey, package, NULL, NULL, NULL, &sz);
1313     RegCloseKey(hkey);
1314
1315     return (res == ERROR_SUCCESS);
1316 }
1317
1318 static BOOL msi_comp_find_prodcode(LPWSTR squished_pc,
1319                                    MSIINSTALLCONTEXT context,
1320                                    LPCWSTR comp, LPWSTR val, DWORD *sz)
1321 {
1322     HKEY hkey;
1323     LONG res;
1324     UINT r;
1325
1326     if (context == MSIINSTALLCONTEXT_MACHINE)
1327         r = MSIREG_OpenLocalSystemComponentKey(comp, &hkey, FALSE);
1328     else
1329         r = MSIREG_OpenUserDataComponentKey(comp, &hkey, FALSE);
1330
1331     if (r != ERROR_SUCCESS)
1332         return FALSE;
1333
1334     res = RegQueryValueExW(hkey, squished_pc, NULL, NULL, (BYTE *)val, sz);
1335     if (res != ERROR_SUCCESS)
1336         return FALSE;
1337
1338     RegCloseKey(hkey);
1339     return TRUE;
1340 }
1341
1342 UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode,
1343                                     LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1344                                     LPCWSTR szComponent, INSTALLSTATE *pdwState)
1345 {
1346     WCHAR squished_pc[GUID_SIZE];
1347     WCHAR val[MAX_PATH];
1348     BOOL found;
1349     DWORD sz;
1350
1351     TRACE("(%s, %s, %d, %s, %p)\n", debugstr_w(szProductCode),
1352           debugstr_w(szUserSid), dwContext, debugstr_w(szComponent), pdwState);
1353
1354     if (!pdwState)
1355         return ERROR_INVALID_PARAMETER;
1356
1357     if (!szProductCode || !*szProductCode || lstrlenW(szProductCode) != GUID_SIZE - 1)
1358         return ERROR_INVALID_PARAMETER;
1359
1360     if (!squash_guid(szProductCode, squished_pc))
1361         return ERROR_INVALID_PARAMETER;
1362
1363     found = msi_comp_find_prod_key(szProductCode, dwContext);
1364
1365     if (!msi_comp_find_package(szProductCode, dwContext))
1366     {
1367         if (found)
1368         {
1369             *pdwState = INSTALLSTATE_UNKNOWN;
1370             return ERROR_UNKNOWN_COMPONENT;
1371         }
1372
1373         return ERROR_UNKNOWN_PRODUCT;
1374     }
1375
1376     *pdwState = INSTALLSTATE_UNKNOWN;
1377
1378     sz = MAX_PATH;
1379     if (!msi_comp_find_prodcode(squished_pc, dwContext, szComponent, val, &sz))
1380         return ERROR_UNKNOWN_COMPONENT;
1381
1382     if (sz == 0)
1383         *pdwState = INSTALLSTATE_NOTUSED;
1384     else
1385     {
1386         if (lstrlenW(val) > 2 &&
1387             val[0] >= '0' && val[0] <= '9' && val[1] >= '0' && val[1] <= '9')
1388         {
1389             *pdwState = INSTALLSTATE_SOURCE;
1390         }
1391         else
1392             *pdwState = INSTALLSTATE_LOCAL;
1393     }
1394
1395     return ERROR_SUCCESS;
1396 }
1397
1398 INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct)
1399 {
1400     LPWSTR szwProduct = NULL;
1401     INSTALLSTATE r;
1402
1403     if( szProduct )
1404     {
1405          szwProduct = strdupAtoW( szProduct );
1406          if( !szwProduct )
1407              return ERROR_OUTOFMEMORY;
1408     }
1409     r = MsiQueryProductStateW( szwProduct );
1410     msi_free( szwProduct );
1411     return r;
1412 }
1413
1414 INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct)
1415 {
1416     INSTALLSTATE state = INSTALLSTATE_ADVERTISED;
1417     HKEY prodkey = 0, userdata = 0;
1418     BOOL user = TRUE;
1419     DWORD val;
1420     UINT r;
1421
1422     static const WCHAR szWindowsInstaller[] = {
1423         'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
1424
1425     TRACE("%s\n", debugstr_w(szProduct));
1426
1427     if (!szProduct || !*szProduct)
1428         return INSTALLSTATE_INVALIDARG;
1429
1430     if (lstrlenW(szProduct) != GUID_SIZE - 1)
1431         return INSTALLSTATE_INVALIDARG;
1432
1433     if (MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
1434                               &prodkey, FALSE) != ERROR_SUCCESS &&
1435         MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
1436                               &prodkey, FALSE) != ERROR_SUCCESS &&
1437         MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
1438                               &prodkey, FALSE) == ERROR_SUCCESS)
1439     {
1440         user = FALSE;
1441     }
1442
1443     if (user)
1444     {
1445         r = MSIREG_OpenCurrentUserInstallProps(szProduct, &userdata, FALSE);
1446         if (r != ERROR_SUCCESS)
1447             goto done;
1448     }
1449     else
1450     {
1451         r = MSIREG_OpenLocalSystemInstallProps(szProduct, &userdata, FALSE);
1452         if (r != ERROR_SUCCESS)
1453             goto done;
1454     }
1455
1456     if (!msi_reg_get_val_dword(userdata, szWindowsInstaller, &val))
1457         goto done;
1458
1459     if (val)
1460         state = INSTALLSTATE_DEFAULT;
1461     else
1462         state = INSTALLSTATE_UNKNOWN;
1463
1464 done:
1465     if (!prodkey)
1466     {
1467         state = INSTALLSTATE_UNKNOWN;
1468
1469         if (userdata)
1470             state = INSTALLSTATE_ABSENT;
1471     }
1472
1473     RegCloseKey(prodkey);
1474     RegCloseKey(userdata);
1475     return state;
1476 }
1477
1478 INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd)
1479 {
1480     INSTALLUILEVEL old = gUILevel;
1481     HWND oldwnd = gUIhwnd;
1482
1483     TRACE("%08x %p\n", dwUILevel, phWnd);
1484
1485     gUILevel = dwUILevel;
1486     if (phWnd)
1487     {
1488         gUIhwnd = *phWnd;
1489         *phWnd = oldwnd;
1490     }
1491     return old;
1492 }
1493
1494 INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler,
1495                                   DWORD dwMessageFilter, LPVOID pvContext)
1496 {
1497     INSTALLUI_HANDLERA prev = gUIHandlerA;
1498
1499     TRACE("%p %x %p\n",puiHandler, dwMessageFilter,pvContext);
1500     gUIHandlerA = puiHandler;
1501     gUIFilter = dwMessageFilter;
1502     gUIContext = pvContext;
1503
1504     return prev;
1505 }
1506
1507 INSTALLUI_HANDLERW WINAPI MsiSetExternalUIW(INSTALLUI_HANDLERW puiHandler,
1508                                   DWORD dwMessageFilter, LPVOID pvContext)
1509 {
1510     INSTALLUI_HANDLERW prev = gUIHandlerW;
1511
1512     TRACE("%p %x %p\n",puiHandler,dwMessageFilter,pvContext);
1513     gUIHandlerW = puiHandler;
1514     gUIFilter = dwMessageFilter;
1515     gUIContext = pvContext;
1516
1517     return prev;
1518 }
1519
1520 /******************************************************************
1521  *  MsiLoadStringW            [MSI.@]
1522  *
1523  * Loads a string from MSI's string resources.
1524  *
1525  * PARAMS
1526  *
1527  *   handle        [I]  only -1 is handled currently
1528  *   id            [I]  id of the string to be loaded
1529  *   lpBuffer      [O]  buffer for the string to be written to
1530  *   nBufferMax    [I]  maximum size of the buffer in characters
1531  *   lang          [I]  the preferred language for the string
1532  *
1533  * RETURNS
1534  *
1535  *   If successful, this function returns the language id of the string loaded
1536  *   If the function fails, the function returns zero.
1537  *
1538  * NOTES
1539  *
1540  *   The type of the first parameter is unknown.  LoadString's prototype
1541  *  suggests that it might be a module handle.  I have made it an MSI handle
1542  *  for starters, as -1 is an invalid MSI handle, but not an invalid module
1543  *  handle.  Maybe strings can be stored in an MSI database somehow.
1544  */
1545 LANGID WINAPI MsiLoadStringW( MSIHANDLE handle, UINT id, LPWSTR lpBuffer,
1546                 int nBufferMax, LANGID lang )
1547 {
1548     HRSRC hres;
1549     HGLOBAL hResData;
1550     LPWSTR p;
1551     DWORD i, len;
1552
1553     TRACE("%ld %u %p %d %d\n", handle, id, lpBuffer, nBufferMax, lang);
1554
1555     if( handle != -1 )
1556         FIXME("don't know how to deal with handle = %08lx\n", handle);
1557
1558     if( !lang )
1559         lang = GetUserDefaultLangID();
1560
1561     hres = FindResourceExW( msi_hInstance, (LPCWSTR) RT_STRING,
1562                             (LPWSTR)1, lang );
1563     if( !hres )
1564         return 0;
1565     hResData = LoadResource( msi_hInstance, hres );
1566     if( !hResData )
1567         return 0;
1568     p = LockResource( hResData );
1569     if( !p )
1570         return 0;
1571
1572     for (i = 0; i < (id&0xf); i++)
1573         p += *p + 1;
1574     len = *p;
1575
1576     if( nBufferMax <= len )
1577         return 0;
1578
1579     memcpy( lpBuffer, p+1, len * sizeof(WCHAR));
1580     lpBuffer[ len ] = 0;
1581
1582     TRACE("found -> %s\n", debugstr_w(lpBuffer));
1583
1584     return lang;
1585 }
1586
1587 LANGID WINAPI MsiLoadStringA( MSIHANDLE handle, UINT id, LPSTR lpBuffer,
1588                 int nBufferMax, LANGID lang )
1589 {
1590     LPWSTR bufW;
1591     LANGID r;
1592     INT len;
1593
1594     bufW = msi_alloc(nBufferMax*sizeof(WCHAR));
1595     r = MsiLoadStringW(handle, id, bufW, nBufferMax, lang);
1596     if( r )
1597     {
1598         len = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL );
1599         if( len <= nBufferMax )
1600             WideCharToMultiByte( CP_ACP, 0, bufW, -1,
1601                                  lpBuffer, nBufferMax, NULL, NULL );
1602         else
1603             r = 0;
1604     }
1605     msi_free(bufW);
1606     return r;
1607 }
1608
1609 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf,
1610                 LPDWORD pcchBuf)
1611 {
1612     char szProduct[GUID_SIZE];
1613
1614     TRACE("%s %p %p\n", debugstr_a(szComponent), lpPathBuf, pcchBuf);
1615
1616     if (MsiGetProductCodeA( szComponent, szProduct ) != ERROR_SUCCESS)
1617         return INSTALLSTATE_UNKNOWN;
1618
1619     return MsiGetComponentPathA( szProduct, szComponent, lpPathBuf, pcchBuf );
1620 }
1621
1622 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPWSTR lpPathBuf,
1623                 LPDWORD pcchBuf)
1624 {
1625     WCHAR szProduct[GUID_SIZE];
1626
1627     TRACE("%s %p %p\n", debugstr_w(szComponent), lpPathBuf, pcchBuf);
1628
1629     if (MsiGetProductCodeW( szComponent, szProduct ) != ERROR_SUCCESS)
1630         return INSTALLSTATE_UNKNOWN;
1631
1632     return MsiGetComponentPathW( szProduct, szComponent, lpPathBuf, pcchBuf );
1633 }
1634
1635 UINT WINAPI MsiMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType,
1636                 WORD wLanguageId, DWORD f)
1637 {
1638     FIXME("%p %s %s %u %08x %08x\n", hWnd, debugstr_a(lpText), debugstr_a(lpCaption),
1639           uType, wLanguageId, f);
1640     return MessageBoxExA(hWnd,lpText,lpCaption,uType,wLanguageId); 
1641 }
1642
1643 UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType,
1644                 WORD wLanguageId, DWORD f)
1645 {
1646     FIXME("%p %s %s %u %08x %08x\n", hWnd, debugstr_w(lpText), debugstr_w(lpCaption),
1647           uType, wLanguageId, f);
1648     return MessageBoxExW(hWnd,lpText,lpCaption,uType,wLanguageId); 
1649 }
1650
1651 UINT WINAPI MsiProvideAssemblyA( LPCSTR szAssemblyName, LPCSTR szAppContext,
1652                 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf,
1653                 LPDWORD pcchPathBuf )
1654 {
1655     FIXME("%s %s %08x %08x %p %p\n", debugstr_a(szAssemblyName),
1656           debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
1657           pcchPathBuf);
1658     return ERROR_CALL_NOT_IMPLEMENTED;
1659 }
1660
1661 UINT WINAPI MsiProvideAssemblyW( LPCWSTR szAssemblyName, LPCWSTR szAppContext,
1662                 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf,
1663                 LPDWORD pcchPathBuf )
1664 {
1665     FIXME("%s %s %08x %08x %p %p\n", debugstr_w(szAssemblyName),
1666           debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
1667           pcchPathBuf);
1668     return ERROR_CALL_NOT_IMPLEMENTED;
1669 }
1670
1671 UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor,
1672                 LPSTR szPath, LPDWORD pcchPath, LPDWORD pcchArgs )
1673 {
1674     FIXME("%s %p %p %p\n", debugstr_a(szDescriptor), szPath, pcchPath, pcchArgs );
1675     return ERROR_CALL_NOT_IMPLEMENTED;
1676 }
1677
1678 UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor,
1679                 LPWSTR szPath, LPDWORD pcchPath, LPDWORD pcchArgs )
1680 {
1681     FIXME("%s %p %p %p\n", debugstr_w(szDescriptor), szPath, pcchPath, pcchArgs );
1682     return ERROR_CALL_NOT_IMPLEMENTED;
1683 }
1684
1685 HRESULT WINAPI MsiGetFileSignatureInformationA( LPCSTR szSignedObjectPath,
1686                 DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, LPBYTE pbHashData,
1687                 LPDWORD pcbHashData)
1688 {
1689     FIXME("%s %08x %p %p %p\n", debugstr_a(szSignedObjectPath), dwFlags,
1690           ppcCertContext, pbHashData, pcbHashData);
1691     return ERROR_CALL_NOT_IMPLEMENTED;
1692 }
1693
1694 HRESULT WINAPI MsiGetFileSignatureInformationW( LPCWSTR szSignedObjectPath,
1695                 DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, LPBYTE pbHashData,
1696                 LPDWORD pcbHashData)
1697 {
1698     FIXME("%s %08x %p %p %p\n", debugstr_w(szSignedObjectPath), dwFlags,
1699           ppcCertContext, pbHashData, pcbHashData);
1700     return ERROR_CALL_NOT_IMPLEMENTED;
1701 }
1702
1703 UINT WINAPI MsiGetProductPropertyA( MSIHANDLE hProduct, LPCSTR szProperty,
1704                                     LPSTR szValue, LPDWORD pccbValue )
1705 {
1706     FIXME("%ld %s %p %p\n", hProduct, debugstr_a(szProperty), szValue, pccbValue);
1707     return ERROR_CALL_NOT_IMPLEMENTED;
1708 }
1709
1710 UINT WINAPI MsiGetProductPropertyW( MSIHANDLE hProduct, LPCWSTR szProperty,
1711                                     LPWSTR szValue, LPDWORD pccbValue )
1712 {
1713     FIXME("%ld %s %p %p\n", hProduct, debugstr_w(szProperty), szValue, pccbValue);
1714     return ERROR_CALL_NOT_IMPLEMENTED;
1715 }
1716
1717 UINT WINAPI MsiVerifyPackageA( LPCSTR szPackage )
1718 {
1719     UINT r;
1720     LPWSTR szPack = NULL;
1721
1722     TRACE("%s\n", debugstr_a(szPackage) );
1723
1724     if( szPackage )
1725     {
1726         szPack = strdupAtoW( szPackage );
1727         if( !szPack )
1728             return ERROR_OUTOFMEMORY;
1729     }
1730
1731     r = MsiVerifyPackageW( szPack );
1732
1733     msi_free( szPack );
1734
1735     return r;
1736 }
1737
1738 UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage )
1739 {
1740     MSIHANDLE handle;
1741     UINT r;
1742
1743     TRACE("%s\n", debugstr_w(szPackage) );
1744
1745     r = MsiOpenDatabaseW( szPackage, MSIDBOPEN_READONLY, &handle );
1746     MsiCloseHandle( handle );
1747
1748     return r;
1749 }
1750
1751 static INSTALLSTATE MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent,
1752                                          awstring* lpPathBuf, LPDWORD pcchBuf)
1753 {
1754     WCHAR squished_pc[GUID_SIZE];
1755     WCHAR squished_comp[GUID_SIZE];
1756     HKEY hkey;
1757     LPWSTR path = NULL;
1758     INSTALLSTATE state;
1759     DWORD version;
1760
1761     static const WCHAR wininstaller[] = {
1762         'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
1763
1764     TRACE("%s %s %p %p\n", debugstr_w(szProduct),
1765            debugstr_w(szComponent), lpPathBuf->str.w, pcchBuf);
1766
1767     if (!szProduct || !szComponent)
1768         return INSTALLSTATE_INVALIDARG;
1769
1770     if (lpPathBuf->str.w && !pcchBuf)
1771         return INSTALLSTATE_INVALIDARG;
1772
1773     if (!squash_guid(szProduct, squished_pc) ||
1774         !squash_guid(szComponent, squished_comp))
1775         return INSTALLSTATE_INVALIDARG;
1776
1777     state = INSTALLSTATE_UNKNOWN;
1778
1779     if (MSIREG_OpenLocalSystemComponentKey(szComponent, &hkey, FALSE) == ERROR_SUCCESS ||
1780         MSIREG_OpenUserDataComponentKey(szComponent, &hkey, FALSE) == ERROR_SUCCESS)
1781     {
1782         path = msi_reg_get_val_str(hkey, squished_pc);
1783         RegCloseKey(hkey);
1784
1785         state = INSTALLSTATE_ABSENT;
1786
1787         if ((MSIREG_OpenLocalSystemProductKey(szProduct, &hkey, FALSE) == ERROR_SUCCESS ||
1788             MSIREG_OpenUserDataProductKey(szProduct, &hkey, FALSE) == ERROR_SUCCESS) &&
1789             msi_reg_get_val_dword(hkey, wininstaller, &version) &&
1790             GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
1791         {
1792             RegCloseKey(hkey);
1793             state = INSTALLSTATE_LOCAL;
1794         }
1795     }
1796
1797     if (state != INSTALLSTATE_LOCAL &&
1798         (MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
1799                                &hkey, FALSE) == ERROR_SUCCESS ||
1800          MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
1801                                &hkey, FALSE) == ERROR_SUCCESS))
1802     {
1803         RegCloseKey(hkey);
1804
1805         if (MSIREG_OpenLocalSystemComponentKey(szComponent, &hkey, FALSE) == ERROR_SUCCESS ||
1806             MSIREG_OpenUserDataComponentKey(szComponent, &hkey, FALSE) == ERROR_SUCCESS)
1807         {
1808             msi_free(path);
1809             path = msi_reg_get_val_str(hkey, squished_pc);
1810             RegCloseKey(hkey);
1811
1812             state = INSTALLSTATE_ABSENT;
1813
1814             if (GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
1815                 state = INSTALLSTATE_LOCAL;
1816         }
1817     }
1818
1819     if (!path)
1820         return INSTALLSTATE_UNKNOWN;
1821
1822     if (state == INSTALLSTATE_LOCAL && !*path)
1823         state = INSTALLSTATE_NOTUSED;
1824
1825     msi_strcpy_to_awstring(path, lpPathBuf, pcchBuf);
1826     msi_free(path);
1827     return state;
1828 }
1829
1830 /******************************************************************
1831  * MsiGetComponentPathW      [MSI.@]
1832  */
1833 INSTALLSTATE WINAPI MsiGetComponentPathW(LPCWSTR szProduct, LPCWSTR szComponent,
1834                                          LPWSTR lpPathBuf, LPDWORD pcchBuf)
1835 {
1836     awstring path;
1837
1838     path.unicode = TRUE;
1839     path.str.w = lpPathBuf;
1840
1841     return MSI_GetComponentPath( szProduct, szComponent, &path, pcchBuf );
1842 }
1843
1844 /******************************************************************
1845  * MsiGetComponentPathA      [MSI.@]
1846  */
1847 INSTALLSTATE WINAPI MsiGetComponentPathA(LPCSTR szProduct, LPCSTR szComponent,
1848                                          LPSTR lpPathBuf, LPDWORD pcchBuf)
1849 {
1850     LPWSTR szwProduct, szwComponent = NULL;
1851     INSTALLSTATE r = INSTALLSTATE_UNKNOWN;
1852     awstring path;
1853
1854     szwProduct = strdupAtoW( szProduct );
1855     if( szProduct && !szwProduct)
1856         goto end;
1857
1858     szwComponent = strdupAtoW( szComponent );
1859     if( szComponent && !szwComponent )
1860         goto end;
1861
1862     path.unicode = FALSE;
1863     path.str.a = lpPathBuf;
1864
1865     r = MSI_GetComponentPath( szwProduct, szwComponent, &path, pcchBuf );
1866
1867 end:
1868     msi_free( szwProduct );
1869     msi_free( szwComponent );
1870
1871     return r;
1872 }
1873
1874 /******************************************************************
1875  * MsiQueryFeatureStateA      [MSI.@]
1876  */
1877 INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature)
1878 {
1879     LPWSTR szwProduct = NULL, szwFeature= NULL;
1880     INSTALLSTATE rc = INSTALLSTATE_UNKNOWN;
1881
1882     szwProduct = strdupAtoW( szProduct );
1883     if ( szProduct && !szwProduct )
1884         goto end;
1885
1886     szwFeature = strdupAtoW( szFeature );
1887     if ( szFeature && !szwFeature )
1888         goto end;
1889
1890     rc = MsiQueryFeatureStateW(szwProduct, szwFeature);
1891
1892 end:
1893     msi_free( szwProduct);
1894     msi_free( szwFeature);
1895
1896     return rc;
1897 }
1898
1899 /******************************************************************
1900  * MsiQueryFeatureStateW      [MSI.@]
1901  *
1902  * Checks the state of a feature
1903  *
1904  * PARAMS
1905  *   szProduct     [I]  Product's GUID string
1906  *   szFeature     [I]  Feature's GUID string
1907  *
1908  * RETURNS
1909  *   INSTALLSTATE_LOCAL        Feature is installed and usable
1910  *   INSTALLSTATE_ABSENT       Feature is absent
1911  *   INSTALLSTATE_ADVERTISED   Feature should be installed on demand
1912  *   INSTALLSTATE_UNKNOWN      An error occurred
1913  *   INSTALLSTATE_INVALIDARG   One of the GUIDs was invalid
1914  *
1915  */
1916 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
1917 {
1918     WCHAR squishProduct[33], comp[GUID_SIZE];
1919     GUID guid;
1920     LPWSTR components, p, parent_feature, path;
1921     UINT rc;
1922     HKEY hkey;
1923     INSTALLSTATE r;
1924     BOOL missing = FALSE;
1925     BOOL machine = FALSE;
1926     BOOL source = FALSE;
1927
1928     TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature));
1929
1930     if (!szProduct || !szFeature)
1931         return INSTALLSTATE_INVALIDARG;
1932
1933     if (!squash_guid( szProduct, squishProduct ))
1934         return INSTALLSTATE_INVALIDARG;
1935
1936     if (MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
1937                                &hkey, FALSE) != ERROR_SUCCESS &&
1938         MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
1939                                &hkey, FALSE) != ERROR_SUCCESS)
1940     {
1941         rc = MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
1942                                     &hkey, FALSE);
1943         if (rc != ERROR_SUCCESS)
1944             return INSTALLSTATE_UNKNOWN;
1945
1946         machine = TRUE;
1947     }
1948
1949     parent_feature = msi_reg_get_val_str( hkey, szFeature );
1950     RegCloseKey(hkey);
1951
1952     if (!parent_feature)
1953         return INSTALLSTATE_UNKNOWN;
1954
1955     r = (parent_feature[0] == 6) ? INSTALLSTATE_ABSENT : INSTALLSTATE_LOCAL;
1956     msi_free(parent_feature);
1957     if (r == INSTALLSTATE_ABSENT)
1958         return r;
1959
1960     if (machine)
1961         rc = MSIREG_OpenUserDataFeaturesKey(szProduct,
1962                                             MSIINSTALLCONTEXT_MACHINE,
1963                                             &hkey, FALSE);
1964     else
1965         rc = MSIREG_OpenUserDataFeaturesKey(szProduct,
1966                                             MSIINSTALLCONTEXT_USERUNMANAGED,
1967                                             &hkey, FALSE);
1968
1969     if (rc != ERROR_SUCCESS)
1970         return INSTALLSTATE_ADVERTISED;
1971
1972     components = msi_reg_get_val_str( hkey, szFeature );
1973     RegCloseKey(hkey);
1974
1975     TRACE("rc = %d buffer = %s\n", rc, debugstr_w(components));
1976
1977     if (!components)
1978         return INSTALLSTATE_ADVERTISED;
1979
1980     for( p = components; *p && *p != 2 ; p += 20)
1981     {
1982         if (!decode_base85_guid( p, &guid ))
1983         {
1984             if (p != components)
1985                 break;
1986
1987             msi_free(components);
1988             return INSTALLSTATE_BADCONFIG;
1989         }
1990
1991         StringFromGUID2(&guid, comp, GUID_SIZE);
1992
1993         if (machine)
1994             rc = MSIREG_OpenLocalUserDataComponentKey(comp, &hkey, FALSE);
1995         else
1996             rc = MSIREG_OpenUserDataComponentKey(comp, &hkey, FALSE);
1997
1998         if (rc != ERROR_SUCCESS)
1999         {
2000             msi_free(components);
2001             return INSTALLSTATE_ADVERTISED;
2002         }
2003
2004         path = msi_reg_get_val_str(hkey, squishProduct);
2005         if (!path)
2006             missing = TRUE;
2007         else if (lstrlenW(path) > 2 &&
2008                  path[0] >= '0' && path[0] <= '9' &&
2009                  path[1] >= '0' && path[1] <= '9')
2010         {
2011             source = TRUE;
2012         }
2013
2014         msi_free(path);
2015     }
2016
2017     TRACE("%s %s -> %d\n", debugstr_w(szProduct), debugstr_w(szFeature), r);
2018     msi_free(components);
2019
2020     if (missing)
2021         return INSTALLSTATE_ADVERTISED;
2022
2023     if (source)
2024         return INSTALLSTATE_SOURCE;
2025
2026     return INSTALLSTATE_LOCAL;
2027 }
2028
2029 /******************************************************************
2030  * MsiGetFileVersionA         [MSI.@]
2031  */
2032 UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf,
2033                 LPDWORD pcchVersionBuf, LPSTR lpLangBuf, LPDWORD pcchLangBuf)
2034 {
2035     LPWSTR szwFilePath = NULL, lpwVersionBuff = NULL, lpwLangBuff = NULL;
2036     UINT ret = ERROR_OUTOFMEMORY;
2037
2038     if ((lpVersionBuf && !pcchVersionBuf) ||
2039         (lpLangBuf && !pcchLangBuf))
2040         return ERROR_INVALID_PARAMETER;
2041
2042     if( szFilePath )
2043     {
2044         szwFilePath = strdupAtoW( szFilePath );
2045         if( !szwFilePath )
2046             goto end;
2047     }
2048
2049     if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf )
2050     {
2051         lpwVersionBuff = msi_alloc(*pcchVersionBuf*sizeof(WCHAR));
2052         if( !lpwVersionBuff )
2053             goto end;
2054     }
2055
2056     if( lpLangBuf && pcchLangBuf && *pcchLangBuf )
2057     {
2058         lpwLangBuff = msi_alloc(*pcchLangBuf*sizeof(WCHAR));
2059         if( !lpwLangBuff )
2060             goto end;
2061     }
2062
2063     ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf,
2064                              lpwLangBuff, pcchLangBuf);
2065
2066     if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwVersionBuff )
2067         WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1,
2068                             lpVersionBuf, *pcchVersionBuf + 1, NULL, NULL);
2069     if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwLangBuff )
2070         WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1,
2071                             lpLangBuf, *pcchLangBuf + 1, NULL, NULL);
2072
2073 end:
2074     msi_free(szwFilePath);
2075     msi_free(lpwVersionBuff);
2076     msi_free(lpwLangBuff);
2077
2078     return ret;
2079 }
2080
2081 /******************************************************************
2082  * MsiGetFileVersionW         [MSI.@]
2083  */
2084 UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf,
2085                 LPDWORD pcchVersionBuf, LPWSTR lpLangBuf, LPDWORD pcchLangBuf)
2086 {
2087     static const WCHAR szVersionResource[] = {'\\',0};
2088     static const WCHAR szVersionFormat[] = {
2089         '%','d','.','%','d','.','%','d','.','%','d',0};
2090     static const WCHAR szLangResource[] = {
2091         '\\','V','a','r','F','i','l','e','I','n','f','o','\\',
2092         'T','r','a','n','s','l','a','t','i','o','n',0};
2093     static const WCHAR szLangFormat[] = {'%','d',0};
2094     UINT ret = 0;
2095     DWORD dwVerLen, gle;
2096     LPVOID lpVer = NULL;
2097     VS_FIXEDFILEINFO *ffi;
2098     USHORT *lang;
2099     UINT puLen;
2100     WCHAR tmp[32];
2101
2102     TRACE("%s %p %d %p %d\n", debugstr_w(szFilePath),
2103           lpVersionBuf, pcchVersionBuf?*pcchVersionBuf:0,
2104           lpLangBuf, pcchLangBuf?*pcchLangBuf:0);
2105
2106     if ((lpVersionBuf && !pcchVersionBuf) ||
2107         (lpLangBuf && !pcchLangBuf))
2108         return ERROR_INVALID_PARAMETER;
2109
2110     dwVerLen = GetFileVersionInfoSizeW(szFilePath, NULL);
2111     if( !dwVerLen )
2112     {
2113         gle = GetLastError();
2114         if (gle == ERROR_BAD_PATHNAME)
2115             return ERROR_FILE_NOT_FOUND;
2116         else if (gle == ERROR_RESOURCE_DATA_NOT_FOUND)
2117             return ERROR_FILE_INVALID;
2118
2119         return gle;
2120     }
2121
2122     lpVer = msi_alloc(dwVerLen);
2123     if( !lpVer )
2124     {
2125         ret = ERROR_OUTOFMEMORY;
2126         goto end;
2127     }
2128
2129     if( !GetFileVersionInfoW(szFilePath, 0, dwVerLen, lpVer) )
2130     {
2131         ret = GetLastError();
2132         goto end;
2133     }
2134
2135     if (pcchVersionBuf)
2136     {
2137         if( VerQueryValueW(lpVer, szVersionResource, (LPVOID*)&ffi, &puLen) &&
2138             (puLen > 0) )
2139         {
2140             wsprintfW(tmp, szVersionFormat,
2141                   HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS),
2142                   HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS));
2143             if (lpVersionBuf) lstrcpynW(lpVersionBuf, tmp, *pcchVersionBuf);
2144
2145             if (strlenW(tmp) >= *pcchVersionBuf)
2146                 ret = ERROR_MORE_DATA;
2147
2148             *pcchVersionBuf = lstrlenW(tmp);
2149         }
2150         else
2151         {
2152             if (lpVersionBuf) *lpVersionBuf = 0;
2153             *pcchVersionBuf = 0;
2154         }
2155     }
2156
2157     if (pcchLangBuf)
2158     {
2159         if (VerQueryValueW(lpVer, szLangResource, (LPVOID*)&lang, &puLen) &&
2160             (puLen > 0))
2161         {
2162             wsprintfW(tmp, szLangFormat, *lang);
2163             if (lpLangBuf) lstrcpynW(lpLangBuf, tmp, *pcchLangBuf);
2164
2165             if (strlenW(tmp) >= *pcchLangBuf)
2166                 ret = ERROR_MORE_DATA;
2167
2168             *pcchLangBuf = lstrlenW(tmp);
2169         }
2170         else
2171         {
2172             if (lpLangBuf) *lpLangBuf = 0;
2173             *pcchLangBuf = 0;
2174         }
2175     }
2176
2177 end:
2178     msi_free(lpVer);
2179     return ret;
2180 }
2181
2182 /***********************************************************************
2183  * MsiGetFeatureUsageW           [MSI.@]
2184  */
2185 UINT WINAPI MsiGetFeatureUsageW( LPCWSTR szProduct, LPCWSTR szFeature,
2186                                  LPDWORD pdwUseCount, LPWORD pwDateUsed )
2187 {
2188     FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szFeature),
2189           pdwUseCount, pwDateUsed);
2190     return ERROR_CALL_NOT_IMPLEMENTED;
2191 }
2192
2193 /***********************************************************************
2194  * MsiGetFeatureUsageA           [MSI.@]
2195  */
2196 UINT WINAPI MsiGetFeatureUsageA( LPCSTR szProduct, LPCSTR szFeature,
2197                                  LPDWORD pdwUseCount, LPWORD pwDateUsed )
2198 {
2199     LPWSTR prod = NULL, feat = NULL;
2200     UINT ret = ERROR_OUTOFMEMORY;
2201
2202     TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szFeature),
2203           pdwUseCount, pwDateUsed);
2204
2205     prod = strdupAtoW( szProduct );
2206     if (szProduct && !prod)
2207         goto end;
2208
2209     feat = strdupAtoW( szFeature );
2210     if (szFeature && !feat)
2211         goto end;
2212
2213     ret = MsiGetFeatureUsageW( prod, feat, pdwUseCount, pwDateUsed );
2214
2215 end:
2216     msi_free( prod );
2217     msi_free( feat );
2218
2219     return ret;
2220 }
2221
2222 /***********************************************************************
2223  * MsiUseFeatureExW           [MSI.@]
2224  */
2225 INSTALLSTATE WINAPI MsiUseFeatureExW( LPCWSTR szProduct, LPCWSTR szFeature,
2226                                       DWORD dwInstallMode, DWORD dwReserved )
2227 {
2228     INSTALLSTATE state;
2229
2230     TRACE("%s %s %i %i\n", debugstr_w(szProduct), debugstr_w(szFeature),
2231           dwInstallMode, dwReserved);
2232
2233     state = MsiQueryFeatureStateW( szProduct, szFeature );
2234
2235     if (dwReserved)
2236         return INSTALLSTATE_INVALIDARG;
2237
2238     if (state == INSTALLSTATE_LOCAL && dwInstallMode != INSTALLMODE_NODETECTION)
2239     {
2240         FIXME("mark product %s feature %s as used\n",
2241               debugstr_w(szProduct), debugstr_w(szFeature) );
2242     }
2243
2244     return state;
2245 }
2246
2247 /***********************************************************************
2248  * MsiUseFeatureExA           [MSI.@]
2249  */
2250 INSTALLSTATE WINAPI MsiUseFeatureExA( LPCSTR szProduct, LPCSTR szFeature,
2251                                       DWORD dwInstallMode, DWORD dwReserved )
2252 {
2253     INSTALLSTATE ret = INSTALLSTATE_UNKNOWN;
2254     LPWSTR prod = NULL, feat = NULL;
2255
2256     TRACE("%s %s %i %i\n", debugstr_a(szProduct), debugstr_a(szFeature),
2257           dwInstallMode, dwReserved);
2258
2259     prod = strdupAtoW( szProduct );
2260     if (szProduct && !prod)
2261         goto end;
2262
2263     feat = strdupAtoW( szFeature );
2264     if (szFeature && !feat)
2265         goto end;
2266
2267     ret = MsiUseFeatureExW( prod, feat, dwInstallMode, dwReserved );
2268
2269 end:
2270     msi_free( prod );
2271     msi_free( feat );
2272
2273     return ret;
2274 }
2275
2276 /***********************************************************************
2277  * MsiUseFeatureW             [MSI.@]
2278  */
2279 INSTALLSTATE WINAPI MsiUseFeatureW( LPCWSTR szProduct, LPCWSTR szFeature )
2280 {
2281     return MsiUseFeatureExW(szProduct, szFeature, 0, 0);
2282 }
2283
2284 /***********************************************************************
2285  * MsiUseFeatureA             [MSI.@]
2286  */
2287 INSTALLSTATE WINAPI MsiUseFeatureA( LPCSTR szProduct, LPCSTR szFeature )
2288 {
2289     return MsiUseFeatureExA(szProduct, szFeature, 0, 0);
2290 }
2291
2292 /***********************************************************************
2293  * MSI_ProvideQualifiedComponentEx [internal]
2294  */
2295 static UINT MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent,
2296                 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct,
2297                 DWORD Unused1, DWORD Unused2, awstring *lpPathBuf,
2298                 LPDWORD pcchPathBuf)
2299 {
2300     WCHAR product[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1],
2301           feature[MAX_FEATURE_CHARS+1];
2302     LPWSTR info;
2303     HKEY hkey;
2304     DWORD sz;
2305     UINT rc;
2306
2307     TRACE("%s %s %i %s %i %i %p %p\n", debugstr_w(szComponent),
2308           debugstr_w(szQualifier), dwInstallMode, debugstr_w(szProduct),
2309           Unused1, Unused2, lpPathBuf, pcchPathBuf);
2310
2311     rc = MSIREG_OpenUserComponentsKey(szComponent, &hkey, FALSE);
2312     if (rc != ERROR_SUCCESS)
2313         return ERROR_INDEX_ABSENT;
2314
2315     info = msi_reg_get_val_str( hkey, szQualifier );
2316     RegCloseKey(hkey);
2317
2318     if (!info)
2319         return ERROR_INDEX_ABSENT;
2320
2321     MsiDecomposeDescriptorW(info, product, feature, component, &sz);
2322
2323     if (!szProduct)
2324         rc = MSI_GetComponentPath(product, component, lpPathBuf, pcchPathBuf);
2325     else
2326         rc = MSI_GetComponentPath(szProduct, component, lpPathBuf, pcchPathBuf);
2327
2328     msi_free( info );
2329
2330     if (rc != INSTALLSTATE_LOCAL)
2331         return ERROR_FILE_NOT_FOUND;
2332
2333     return ERROR_SUCCESS;
2334 }
2335
2336 /***********************************************************************
2337  * MsiProvideQualifiedComponentExW [MSI.@]
2338  */
2339 UINT WINAPI MsiProvideQualifiedComponentExW(LPCWSTR szComponent,
2340                 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct,
2341                 DWORD Unused1, DWORD Unused2, LPWSTR lpPathBuf,
2342                 LPDWORD pcchPathBuf)
2343 {
2344     awstring path;
2345
2346     path.unicode = TRUE;
2347     path.str.w = lpPathBuf;
2348
2349     return MSI_ProvideQualifiedComponentEx(szComponent, szQualifier,
2350             dwInstallMode, szProduct, Unused1, Unused2, &path, pcchPathBuf);
2351 }
2352
2353 /***********************************************************************
2354  * MsiProvideQualifiedComponentExA [MSI.@]
2355  */
2356 UINT WINAPI MsiProvideQualifiedComponentExA(LPCSTR szComponent,
2357                 LPCSTR szQualifier, DWORD dwInstallMode, LPCSTR szProduct,
2358                 DWORD Unused1, DWORD Unused2, LPSTR lpPathBuf,
2359                 LPDWORD pcchPathBuf)
2360 {
2361     LPWSTR szwComponent, szwQualifier = NULL, szwProduct = NULL;
2362     UINT r = ERROR_OUTOFMEMORY;
2363     awstring path;
2364
2365     TRACE("%s %s %u %s %u %u %p %p\n", debugstr_a(szComponent),
2366           debugstr_a(szQualifier), dwInstallMode, debugstr_a(szProduct),
2367           Unused1, Unused2, lpPathBuf, pcchPathBuf);
2368
2369     szwComponent = strdupAtoW( szComponent );
2370     if (szComponent && !szwComponent)
2371         goto end;
2372
2373     szwQualifier = strdupAtoW( szQualifier );
2374     if (szQualifier && !szwQualifier)
2375         goto end;
2376
2377     szwProduct = strdupAtoW( szProduct );
2378     if (szProduct && !szwProduct)
2379         goto end;
2380
2381     path.unicode = FALSE;
2382     path.str.a = lpPathBuf;
2383
2384     r = MSI_ProvideQualifiedComponentEx(szwComponent, szwQualifier,
2385                               dwInstallMode, szwProduct, Unused1,
2386                               Unused2, &path, pcchPathBuf);
2387 end:
2388     msi_free(szwProduct);
2389     msi_free(szwComponent);
2390     msi_free(szwQualifier);
2391
2392     return r;
2393 }
2394
2395 /***********************************************************************
2396  * MsiProvideQualifiedComponentW [MSI.@]
2397  */
2398 UINT WINAPI MsiProvideQualifiedComponentW( LPCWSTR szComponent,
2399                 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR lpPathBuf,
2400                 LPDWORD pcchPathBuf)
2401 {
2402     return MsiProvideQualifiedComponentExW(szComponent, szQualifier, 
2403                     dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
2404 }
2405
2406 /***********************************************************************
2407  * MsiProvideQualifiedComponentA [MSI.@]
2408  */
2409 UINT WINAPI MsiProvideQualifiedComponentA( LPCSTR szComponent,
2410                 LPCSTR szQualifier, DWORD dwInstallMode, LPSTR lpPathBuf,
2411                 LPDWORD pcchPathBuf)
2412 {
2413     return MsiProvideQualifiedComponentExA(szComponent, szQualifier,
2414                               dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
2415 }
2416
2417 /***********************************************************************
2418  * MSI_GetUserInfo [internal]
2419  */
2420 static USERINFOSTATE MSI_GetUserInfo(LPCWSTR szProduct,
2421                 awstring *lpUserNameBuf, LPDWORD pcchUserNameBuf,
2422                 awstring *lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
2423                 awstring *lpSerialBuf, LPDWORD pcchSerialBuf)
2424 {
2425     WCHAR squished_pc[SQUISH_GUID_SIZE];
2426     LPWSTR user, org, serial;
2427     USERINFOSTATE state;
2428     HKEY hkey, props;
2429     LPCWSTR orgptr;
2430     UINT r;
2431
2432     static const WCHAR szEmpty[] = {0};
2433
2434     TRACE("%s %p %p %p %p %p %p\n", debugstr_w(szProduct), lpUserNameBuf,
2435           pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf,
2436           pcchSerialBuf);
2437
2438     if (!szProduct || !squash_guid(szProduct, squished_pc))
2439         return USERINFOSTATE_INVALIDARG;
2440
2441     if (MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
2442                               &hkey, FALSE) != ERROR_SUCCESS &&
2443         MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
2444                               &hkey, FALSE) != ERROR_SUCCESS &&
2445         MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
2446                               &hkey, FALSE) != ERROR_SUCCESS)
2447     {
2448         return USERINFOSTATE_UNKNOWN;
2449     }
2450
2451     if (MSIREG_OpenCurrentUserInstallProps(szProduct, &props, FALSE) != ERROR_SUCCESS &&
2452         MSIREG_OpenLocalSystemInstallProps(szProduct, &props, FALSE) != ERROR_SUCCESS)
2453     {
2454         RegCloseKey(hkey);
2455         return USERINFOSTATE_ABSENT;
2456     }
2457
2458     user = msi_reg_get_val_str(props, INSTALLPROPERTY_REGOWNERW);
2459     org = msi_reg_get_val_str(props, INSTALLPROPERTY_REGCOMPANYW);
2460     serial = msi_reg_get_val_str(props, INSTALLPROPERTY_PRODUCTIDW);
2461     state = USERINFOSTATE_ABSENT;
2462
2463     RegCloseKey(hkey);
2464     RegCloseKey(props);
2465
2466     if (user && serial)
2467         state = USERINFOSTATE_PRESENT;
2468
2469     if (pcchUserNameBuf)
2470     {
2471         if (lpUserNameBuf && !user)
2472         {
2473             (*pcchUserNameBuf)--;
2474             goto done;
2475         }
2476
2477         r = msi_strcpy_to_awstring(user, lpUserNameBuf, pcchUserNameBuf);
2478         if (r == ERROR_MORE_DATA)
2479         {
2480             state = USERINFOSTATE_MOREDATA;
2481             goto done;
2482         }
2483     }
2484
2485     if (pcchOrgNameBuf)
2486     {
2487         orgptr = org;
2488         if (!orgptr) orgptr = szEmpty;
2489
2490         r = msi_strcpy_to_awstring(orgptr, lpOrgNameBuf, pcchOrgNameBuf);
2491         if (r == ERROR_MORE_DATA)
2492         {
2493             state = USERINFOSTATE_MOREDATA;
2494             goto done;
2495         }
2496     }
2497
2498     if (pcchSerialBuf)
2499     {
2500         if (!serial)
2501         {
2502             (*pcchSerialBuf)--;
2503             goto done;
2504         }
2505
2506         r = msi_strcpy_to_awstring(serial, lpSerialBuf, pcchSerialBuf);
2507         if (r == ERROR_MORE_DATA)
2508             state = USERINFOSTATE_MOREDATA;
2509     }
2510
2511 done:
2512     msi_free(user);
2513     msi_free(org);
2514     msi_free(serial);
2515
2516     return state;
2517 }
2518
2519 /***********************************************************************
2520  * MsiGetUserInfoW [MSI.@]
2521  */
2522 USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct,
2523                 LPWSTR lpUserNameBuf, LPDWORD pcchUserNameBuf,
2524                 LPWSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
2525                 LPWSTR lpSerialBuf, LPDWORD pcchSerialBuf)
2526 {
2527     awstring user, org, serial;
2528
2529     if ((lpUserNameBuf && !pcchUserNameBuf) ||
2530         (lpOrgNameBuf && !pcchOrgNameBuf) ||
2531         (lpSerialBuf && !pcchSerialBuf))
2532         return USERINFOSTATE_INVALIDARG;
2533
2534     user.unicode = TRUE;
2535     user.str.w = lpUserNameBuf;
2536     org.unicode = TRUE;
2537     org.str.w = lpOrgNameBuf;
2538     serial.unicode = TRUE;
2539     serial.str.w = lpSerialBuf;
2540
2541     return MSI_GetUserInfo( szProduct, &user, pcchUserNameBuf,
2542                             &org, pcchOrgNameBuf,
2543                             &serial, pcchSerialBuf );
2544 }
2545
2546 USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR szProduct,
2547                 LPSTR lpUserNameBuf, LPDWORD pcchUserNameBuf,
2548                 LPSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
2549                 LPSTR lpSerialBuf, LPDWORD pcchSerialBuf)
2550 {
2551     awstring user, org, serial;
2552     LPWSTR prod;
2553     UINT r;
2554
2555     if ((lpUserNameBuf && !pcchUserNameBuf) ||
2556         (lpOrgNameBuf && !pcchOrgNameBuf) ||
2557         (lpSerialBuf && !pcchSerialBuf))
2558         return USERINFOSTATE_INVALIDARG;
2559
2560     prod = strdupAtoW( szProduct );
2561     if (szProduct && !prod)
2562         return ERROR_OUTOFMEMORY;
2563
2564     user.unicode = FALSE;
2565     user.str.a = lpUserNameBuf;
2566     org.unicode = FALSE;
2567     org.str.a = lpOrgNameBuf;
2568     serial.unicode = FALSE;
2569     serial.str.a = lpSerialBuf;
2570
2571     r = MSI_GetUserInfo( prod, &user, pcchUserNameBuf,
2572                          &org, pcchOrgNameBuf,
2573                          &serial, pcchSerialBuf );
2574
2575     msi_free( prod );
2576
2577     return r;
2578 }
2579
2580 UINT WINAPI MsiCollectUserInfoW(LPCWSTR szProduct)
2581 {
2582     MSIHANDLE handle;
2583     UINT rc;
2584     MSIPACKAGE *package;
2585     static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
2586
2587     TRACE("(%s)\n",debugstr_w(szProduct));
2588
2589     rc = MsiOpenProductW(szProduct,&handle);
2590     if (rc != ERROR_SUCCESS)
2591         return ERROR_INVALID_PARAMETER;
2592
2593     package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
2594     rc = ACTION_PerformUIAction(package, szFirstRun, -1);
2595     msiobj_release( &package->hdr );
2596
2597     MsiCloseHandle(handle);
2598
2599     return rc;
2600 }
2601
2602 UINT WINAPI MsiCollectUserInfoA(LPCSTR szProduct)
2603 {
2604     MSIHANDLE handle;
2605     UINT rc;
2606     MSIPACKAGE *package;
2607     static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
2608
2609     TRACE("(%s)\n",debugstr_a(szProduct));
2610
2611     rc = MsiOpenProductA(szProduct,&handle);
2612     if (rc != ERROR_SUCCESS)
2613         return ERROR_INVALID_PARAMETER;
2614
2615     package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
2616     rc = ACTION_PerformUIAction(package, szFirstRun, -1);
2617     msiobj_release( &package->hdr );
2618
2619     MsiCloseHandle(handle);
2620
2621     return rc;
2622 }
2623
2624 /***********************************************************************
2625  * MsiConfigureFeatureA            [MSI.@]
2626  */
2627 UINT WINAPI MsiConfigureFeatureA(LPCSTR szProduct, LPCSTR szFeature, INSTALLSTATE eInstallState)
2628 {
2629     LPWSTR prod, feat = NULL;
2630     UINT r = ERROR_OUTOFMEMORY;
2631
2632     TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature), eInstallState);
2633
2634     prod = strdupAtoW( szProduct );
2635     if (szProduct && !prod)
2636         goto end;
2637
2638     feat = strdupAtoW( szFeature );
2639     if (szFeature && !feat)
2640         goto end;
2641
2642     r = MsiConfigureFeatureW(prod, feat, eInstallState);
2643
2644 end:
2645     msi_free(feat);
2646     msi_free(prod);
2647
2648     return r;
2649 }
2650
2651 /***********************************************************************
2652  * MsiConfigureFeatureW            [MSI.@]
2653  */
2654 UINT WINAPI MsiConfigureFeatureW(LPCWSTR szProduct, LPCWSTR szFeature, INSTALLSTATE eInstallState)
2655 {
2656     static const WCHAR szCostInit[] = { 'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0 };
2657     MSIPACKAGE *package = NULL;
2658     UINT r;
2659     WCHAR sourcepath[MAX_PATH], filename[MAX_PATH];
2660     DWORD sz;
2661
2662     TRACE("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature), eInstallState);
2663
2664     if (!szProduct || !szFeature)
2665         return ERROR_INVALID_PARAMETER;
2666
2667     switch (eInstallState)
2668     {
2669     case INSTALLSTATE_DEFAULT:
2670         /* FIXME: how do we figure out the default location? */
2671         eInstallState = INSTALLSTATE_LOCAL;
2672         break;
2673     case INSTALLSTATE_LOCAL:
2674     case INSTALLSTATE_SOURCE:
2675     case INSTALLSTATE_ABSENT:
2676     case INSTALLSTATE_ADVERTISED:
2677         break;
2678     default:
2679         return ERROR_INVALID_PARAMETER;
2680     }
2681
2682     r = MSI_OpenProductW( szProduct, &package );
2683     if (r != ERROR_SUCCESS)
2684         return r;
2685
2686     sz = sizeof(sourcepath);
2687     MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2688                 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
2689
2690     sz = sizeof(filename);
2691     MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2692                 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
2693
2694     lstrcatW( sourcepath, filename );
2695
2696     MsiSetInternalUI( INSTALLUILEVEL_BASIC, NULL );
2697
2698     r = ACTION_PerformUIAction( package, szCostInit, -1 );
2699     if (r != ERROR_SUCCESS)
2700         goto end;
2701
2702     r = MSI_SetFeatureStateW( package, szFeature, eInstallState);
2703     if (r != ERROR_SUCCESS)
2704         goto end;
2705
2706     r = MSI_InstallPackage( package, sourcepath, NULL );
2707
2708 end:
2709     msiobj_release( &package->hdr );
2710
2711     return r;
2712 }
2713
2714 /***********************************************************************
2715  * MsiCreateAndVerifyInstallerDirectory [MSI.@]
2716  *
2717  * Notes: undocumented
2718  */
2719 UINT WINAPI MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved)
2720 {
2721     WCHAR path[MAX_PATH];
2722
2723     TRACE("%d\n", dwReserved);
2724
2725     if (dwReserved)
2726     {
2727         FIXME("dwReserved=%d\n", dwReserved);
2728         return ERROR_INVALID_PARAMETER;
2729     }
2730
2731     if (!GetWindowsDirectoryW(path, MAX_PATH))
2732         return ERROR_FUNCTION_FAILED;
2733
2734     lstrcatW(path, installerW);
2735
2736     if (!CreateDirectoryW(path, NULL))
2737         return ERROR_FUNCTION_FAILED;
2738
2739     return ERROR_SUCCESS;
2740 }
2741
2742 /***********************************************************************
2743  * MsiGetShortcutTargetA           [MSI.@]
2744  */
2745 UINT WINAPI MsiGetShortcutTargetA( LPCSTR szShortcutTarget,
2746                                    LPSTR szProductCode, LPSTR szFeatureId,
2747                                    LPSTR szComponentCode )
2748 {
2749     LPWSTR target;
2750     const int len = MAX_FEATURE_CHARS+1;
2751     WCHAR product[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1];
2752     UINT r;
2753
2754     target = strdupAtoW( szShortcutTarget );
2755     if (szShortcutTarget && !target )
2756         return ERROR_OUTOFMEMORY;
2757     product[0] = 0;
2758     feature[0] = 0;
2759     component[0] = 0;
2760     r = MsiGetShortcutTargetW( target, product, feature, component );
2761     msi_free( target );
2762     if (r == ERROR_SUCCESS)
2763     {
2764         WideCharToMultiByte( CP_ACP, 0, product, -1, szProductCode, len, NULL, NULL );
2765         WideCharToMultiByte( CP_ACP, 0, feature, -1, szFeatureId, len, NULL, NULL );
2766         WideCharToMultiByte( CP_ACP, 0, component, -1, szComponentCode, len, NULL, NULL );
2767     }
2768     return r;
2769 }
2770
2771 /***********************************************************************
2772  * MsiGetShortcutTargetW           [MSI.@]
2773  */
2774 UINT WINAPI MsiGetShortcutTargetW( LPCWSTR szShortcutTarget,
2775                                    LPWSTR szProductCode, LPWSTR szFeatureId,
2776                                    LPWSTR szComponentCode )
2777 {
2778     IShellLinkDataList *dl = NULL;
2779     IPersistFile *pf = NULL;
2780     LPEXP_DARWIN_LINK darwin = NULL;
2781     HRESULT r, init;
2782
2783     TRACE("%s %p %p %p\n", debugstr_w(szShortcutTarget),
2784           szProductCode, szFeatureId, szComponentCode );
2785
2786     init = CoInitialize(NULL);
2787
2788     r = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
2789                           &IID_IPersistFile, (LPVOID*) &pf );
2790     if( SUCCEEDED( r ) )
2791     {
2792         r = IPersistFile_Load( pf, szShortcutTarget,
2793                                STGM_READ | STGM_SHARE_DENY_WRITE );
2794         if( SUCCEEDED( r ) )
2795         {
2796             r = IPersistFile_QueryInterface( pf, &IID_IShellLinkDataList,
2797                                              (LPVOID*) &dl );
2798             if( SUCCEEDED( r ) )
2799             {
2800                 IShellLinkDataList_CopyDataBlock( dl, EXP_DARWIN_ID_SIG,
2801                                                   (LPVOID) &darwin );
2802                 IShellLinkDataList_Release( dl );
2803             }
2804         }
2805         IPersistFile_Release( pf );
2806     }
2807
2808     if (SUCCEEDED(init))
2809         CoUninitialize();
2810
2811     TRACE("darwin = %p\n", darwin);
2812
2813     if (darwin)
2814     {
2815         DWORD sz;
2816         UINT ret;
2817
2818         ret = MsiDecomposeDescriptorW( darwin->szwDarwinID,
2819                   szProductCode, szFeatureId, szComponentCode, &sz );
2820         LocalFree( darwin );
2821         return ret;
2822     }
2823
2824     return ERROR_FUNCTION_FAILED;
2825 }
2826
2827 UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature,
2828                                   DWORD dwReinstallMode )
2829 {
2830     MSIPACKAGE* package = NULL;
2831     UINT r;
2832     WCHAR sourcepath[MAX_PATH];
2833     WCHAR filename[MAX_PATH];
2834     static const WCHAR szLogVerbose[] = {
2835         ' ','L','O','G','V','E','R','B','O','S','E',0 };
2836     static const WCHAR szInstalled[] = { 'I','n','s','t','a','l','l','e','d',0};
2837     static const WCHAR szReinstall[] = {'R','E','I','N','S','T','A','L','L',0};
2838     static const WCHAR szReinstallMode[] = {'R','E','I','N','S','T','A','L','L','M','O','D','E',0};
2839     static const WCHAR szOne[] = {'1',0};
2840     WCHAR reinstallmode[11];
2841     LPWSTR ptr;
2842     DWORD sz;
2843
2844     FIXME("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature),
2845                            dwReinstallMode);
2846
2847     ptr = reinstallmode;
2848
2849     if (dwReinstallMode & REINSTALLMODE_FILEMISSING)
2850         *ptr++ = 'p';
2851     if (dwReinstallMode & REINSTALLMODE_FILEOLDERVERSION)
2852         *ptr++ = 'o';
2853     if (dwReinstallMode & REINSTALLMODE_FILEEQUALVERSION)
2854         *ptr++ = 'w';
2855     if (dwReinstallMode & REINSTALLMODE_FILEEXACT)
2856         *ptr++ = 'd';
2857     if (dwReinstallMode & REINSTALLMODE_FILEVERIFY)
2858         *ptr++ = 'c';
2859     if (dwReinstallMode & REINSTALLMODE_FILEREPLACE)
2860         *ptr++ = 'a';
2861     if (dwReinstallMode & REINSTALLMODE_USERDATA)
2862         *ptr++ = 'u';
2863     if (dwReinstallMode & REINSTALLMODE_MACHINEDATA)
2864         *ptr++ = 'm';
2865     if (dwReinstallMode & REINSTALLMODE_SHORTCUT)
2866         *ptr++ = 's';
2867     if (dwReinstallMode & REINSTALLMODE_PACKAGE)
2868         *ptr++ = 'v';
2869     *ptr = 0;
2870     
2871     sz = sizeof(sourcepath);
2872     MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2873             MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
2874
2875     sz = sizeof(filename);
2876     MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2877             MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
2878
2879     lstrcatW( sourcepath, filename );
2880
2881     if (dwReinstallMode & REINSTALLMODE_PACKAGE)
2882         r = MSI_OpenPackageW( sourcepath, &package );
2883     else
2884         r = MSI_OpenProductW( szProduct, &package );
2885
2886     if (r != ERROR_SUCCESS)
2887         return r;
2888
2889     MSI_SetPropertyW( package, szReinstallMode, reinstallmode );
2890     MSI_SetPropertyW( package, szInstalled, szOne );
2891     MSI_SetPropertyW( package, szLogVerbose, szOne );
2892     MSI_SetPropertyW( package, szReinstall, szFeature );
2893
2894     r = MSI_InstallPackage( package, sourcepath, NULL );
2895
2896     msiobj_release( &package->hdr );
2897
2898     return r;
2899 }
2900
2901 UINT WINAPI MsiReinstallFeatureA( LPCSTR szProduct, LPCSTR szFeature,
2902                                   DWORD dwReinstallMode )
2903 {
2904     LPWSTR wszProduct;
2905     LPWSTR wszFeature;
2906     UINT rc;
2907
2908     TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature),
2909                            dwReinstallMode);
2910
2911     wszProduct = strdupAtoW(szProduct);
2912     wszFeature = strdupAtoW(szFeature);
2913
2914     rc = MsiReinstallFeatureW(wszProduct, wszFeature, dwReinstallMode);
2915
2916     msi_free(wszProduct);
2917     msi_free(wszFeature);
2918     return rc;
2919 }
2920
2921 typedef struct
2922 {
2923     unsigned int i[2];
2924     unsigned int buf[4];
2925     unsigned char in[64];
2926     unsigned char digest[16];
2927 } MD5_CTX;
2928
2929 extern VOID WINAPI MD5Init( MD5_CTX *);
2930 extern VOID WINAPI MD5Update( MD5_CTX *, const unsigned char *, unsigned int );
2931 extern VOID WINAPI MD5Final( MD5_CTX *);
2932
2933 /***********************************************************************
2934  * MsiGetFileHashW            [MSI.@]
2935  */
2936 UINT WINAPI MsiGetFileHashW( LPCWSTR szFilePath, DWORD dwOptions,
2937                              PMSIFILEHASHINFO pHash )
2938 {
2939     HANDLE handle, mapping;
2940     void *p;
2941     DWORD length;
2942     UINT r = ERROR_FUNCTION_FAILED;
2943
2944     TRACE("%s %08x %p\n", debugstr_w(szFilePath), dwOptions, pHash );
2945
2946     if (!szFilePath)
2947         return ERROR_INVALID_PARAMETER;
2948
2949     if (!*szFilePath)
2950         return ERROR_PATH_NOT_FOUND;
2951
2952     if (dwOptions)
2953         return ERROR_INVALID_PARAMETER;
2954     if (!pHash)
2955         return ERROR_INVALID_PARAMETER;
2956     if (pHash->dwFileHashInfoSize < sizeof *pHash)
2957         return ERROR_INVALID_PARAMETER;
2958
2959     handle = CreateFileW( szFilePath, GENERIC_READ,
2960                           FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL );
2961     if (handle == INVALID_HANDLE_VALUE)
2962         return ERROR_FILE_NOT_FOUND;
2963
2964     length = GetFileSize( handle, NULL );
2965
2966     mapping = CreateFileMappingW( handle, NULL, PAGE_READONLY, 0, 0, NULL );
2967     if (mapping)
2968     {
2969         p = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, length );
2970         if (p)
2971         {
2972             MD5_CTX ctx;
2973
2974             MD5Init( &ctx );
2975             MD5Update( &ctx, p, length );
2976             MD5Final( &ctx );
2977             UnmapViewOfFile( p );
2978
2979             memcpy( pHash->dwData, ctx.digest, sizeof pHash->dwData );
2980             r = ERROR_SUCCESS;
2981         }
2982         CloseHandle( mapping );
2983     }
2984     CloseHandle( handle );
2985
2986     return r;
2987 }
2988
2989 /***********************************************************************
2990  * MsiGetFileHashA            [MSI.@]
2991  */
2992 UINT WINAPI MsiGetFileHashA( LPCSTR szFilePath, DWORD dwOptions,
2993                              PMSIFILEHASHINFO pHash )
2994 {
2995     LPWSTR file;
2996     UINT r;
2997
2998     TRACE("%s %08x %p\n", debugstr_a(szFilePath), dwOptions, pHash );
2999
3000     file = strdupAtoW( szFilePath );
3001     if (szFilePath && !file)
3002         return ERROR_OUTOFMEMORY;
3003
3004     r = MsiGetFileHashW( file, dwOptions, pHash );
3005     msi_free( file );
3006     return r;
3007 }
3008
3009 /***********************************************************************
3010  * MsiAdvertiseScriptW        [MSI.@]
3011  */
3012 UINT WINAPI MsiAdvertiseScriptW( LPCWSTR szScriptFile, DWORD dwFlags,
3013                                  PHKEY phRegData, BOOL fRemoveItems )
3014 {
3015     FIXME("%s %08x %p %d\n",
3016           debugstr_w( szScriptFile ), dwFlags, phRegData, fRemoveItems );
3017     return ERROR_CALL_NOT_IMPLEMENTED;
3018 }
3019
3020 /***********************************************************************
3021  * MsiAdvertiseScriptA        [MSI.@]
3022  */
3023 UINT WINAPI MsiAdvertiseScriptA( LPCSTR szScriptFile, DWORD dwFlags,
3024                                  PHKEY phRegData, BOOL fRemoveItems )
3025 {
3026     FIXME("%s %08x %p %d\n",
3027           debugstr_a( szScriptFile ), dwFlags, phRegData, fRemoveItems );
3028     return ERROR_CALL_NOT_IMPLEMENTED;
3029 }
3030
3031 /***********************************************************************
3032  * MsiIsProductElevatedW        [MSI.@]
3033  */
3034 UINT WINAPI MsiIsProductElevatedW( LPCWSTR szProduct, BOOL *pfElevated )
3035 {
3036     FIXME("%s %p - stub\n",
3037           debugstr_w( szProduct ), pfElevated );
3038     *pfElevated = TRUE;
3039     return ERROR_SUCCESS;
3040 }
3041
3042 /***********************************************************************
3043  * MsiIsProductElevatedA        [MSI.@]
3044  */
3045 UINT WINAPI MsiIsProductElevatedA( LPCSTR szProduct, BOOL *pfElevated )
3046 {
3047     FIXME("%s %p - stub\n",
3048           debugstr_a( szProduct ), pfElevated );
3049     *pfElevated = TRUE;
3050     return ERROR_SUCCESS;
3051 }
3052
3053 /***********************************************************************
3054  * MsiSetExternalUIRecord     [MSI.@]
3055  */
3056 UINT WINAPI MsiSetExternalUIRecord( INSTALLUI_HANDLER_RECORD puiHandler,
3057                                     DWORD dwMessageFilter, LPVOID pvContext,
3058                                     PINSTALLUI_HANDLER_RECORD ppuiPrevHandler)
3059 {
3060     FIXME("%p %08x %p %p\n", puiHandler, dwMessageFilter ,pvContext,
3061                              ppuiPrevHandler);
3062     return ERROR_CALL_NOT_IMPLEMENTED;
3063 }
3064
3065 /***********************************************************************
3066  * MsiInstallMissingComponentW     [MSI.@]
3067  */
3068 UINT WINAPI MsiInstallMissingComponentW(LPCWSTR szProduct, LPCWSTR szComponent, INSTALLSTATE eInstallState)
3069 {
3070     FIXME("(%s %s %d\n", debugstr_w(szProduct), debugstr_w(szComponent), eInstallState);
3071     return ERROR_SUCCESS;
3072 }