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