xref: /reactos/modules/rostests/winetests/msi/msi.c (revision d7c30ed1)
1 /*
2  * tests for Microsoft Installer functionality
3  *
4  * Copyright 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 #define _WIN32_MSI 300
22 #define COBJMACROS
23 
24 #include <stdio.h>
25 #include <windows.h>
26 #include <msi.h>
27 #include <msiquery.h>
28 #include <msidefs.h>
29 #include <sddl.h>
30 #include <fci.h>
31 #include <shellapi.h>
32 #include <objidl.h>
33 
34 #include "wine/test.h"
35 #include "utils.h"
36 
37 #define GUID_SIZE (39)
38 #define SQUASHED_GUID_SIZE (33)
39 
40 static BOOL is_wow64;
41 static const char msifile[] = "winetest.msi";
42 static const WCHAR msifileW[] = {'w','i','n','e','t','e','s','t','.','m','s','i',0};
43 
44 static LONG (WINAPI *pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD);
45 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
46 
47 static INSTALLSTATE (WINAPI *pMsiGetComponentPathA)
48     (LPCSTR, LPCSTR, LPSTR, DWORD*);
49 static INSTALLSTATE (WINAPI *pMsiGetComponentPathExA)
50     (LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPSTR, LPDWORD);
51 static INSTALLSTATE (WINAPI *pMsiProvideComponentA)
52     (LPCSTR, LPCSTR, LPCSTR, DWORD, LPSTR, LPDWORD);
53 static INSTALLSTATE (WINAPI *pMsiProvideComponentW)
54     (LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPWSTR, LPDWORD);
55 static UINT (WINAPI *pMsiGetFileHashA)
56     (LPCSTR, DWORD, PMSIFILEHASHINFO);
57 static UINT (WINAPI *pMsiGetProductInfoExA)
58     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, LPSTR, LPDWORD);
59 static UINT (WINAPI *pMsiOpenPackageExA)
60     (LPCSTR, DWORD, MSIHANDLE*);
61 static UINT (WINAPI *pMsiOpenPackageExW)
62     (LPCWSTR, DWORD, MSIHANDLE*);
63 static UINT (WINAPI *pMsiEnumPatchesExA)
64     (LPCSTR, LPCSTR, DWORD, DWORD, DWORD, LPSTR, LPSTR,
65     MSIINSTALLCONTEXT*, LPSTR, LPDWORD);
66 static UINT (WINAPI *pMsiQueryComponentStateA)
67     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, INSTALLSTATE*);
68 static INSTALLSTATE (WINAPI *pMsiUseFeatureExA)
69     (LPCSTR, LPCSTR ,DWORD, DWORD);
70 static UINT (WINAPI *pMsiGetPatchInfoExA)
71     (LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, LPSTR, DWORD *);
72 static UINT (WINAPI *pMsiEnumProductsExA)
73     (LPCSTR, LPCSTR, DWORD, DWORD, CHAR[39], MSIINSTALLCONTEXT *, LPSTR, LPDWORD);
74 static UINT (WINAPI *pMsiEnumComponentsExA)
75     (LPCSTR, DWORD, DWORD, CHAR[39], MSIINSTALLCONTEXT *, LPSTR, LPDWORD);
76 static UINT (WINAPI *pMsiSetExternalUIRecord)
77     (INSTALLUI_HANDLER_RECORD, DWORD, LPVOID, PINSTALLUI_HANDLER_RECORD);
78 static UINT (WINAPI *pMsiSourceListGetInfoA)
79     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, LPSTR, LPDWORD);
80 
81 static void init_functionpointers(void)
82 {
83     HMODULE hmsi = GetModuleHandleA("msi.dll");
84     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
85     HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
86 
87 #define GET_PROC(dll, func) \
88     p ## func = (void *)GetProcAddress(dll, #func); \
89     if(!p ## func) \
90       trace("GetProcAddress(%s) failed\n", #func);
91 
92     GET_PROC(hmsi, MsiGetComponentPathA)
93     GET_PROC(hmsi, MsiGetComponentPathExA);
94     GET_PROC(hmsi, MsiProvideComponentA)
95     GET_PROC(hmsi, MsiProvideComponentW)
96     GET_PROC(hmsi, MsiGetFileHashA)
97     GET_PROC(hmsi, MsiGetProductInfoExA)
98     GET_PROC(hmsi, MsiOpenPackageExA)
99     GET_PROC(hmsi, MsiOpenPackageExW)
100     GET_PROC(hmsi, MsiEnumPatchesExA)
101     GET_PROC(hmsi, MsiQueryComponentStateA)
102     GET_PROC(hmsi, MsiSetExternalUIRecord)
103     GET_PROC(hmsi, MsiUseFeatureExA)
104     GET_PROC(hmsi, MsiGetPatchInfoExA)
105     GET_PROC(hmsi, MsiEnumProductsExA)
106     GET_PROC(hmsi, MsiEnumComponentsExA)
107     GET_PROC(hmsi, MsiSourceListGetInfoA)
108 
109     GET_PROC(hadvapi32, RegDeleteKeyExA)
110     GET_PROC(hkernel32, IsWow64Process)
111 
112 #undef GET_PROC
113 }
114 
115 /* cabinet definitions */
116 
117 /* make the max size large so there is only one cab file */
118 #define MEDIA_SIZE          0x7FFFFFFF
119 #define FOLDER_THRESHOLD    900000
120 
121 static BOOL add_cabinet_storage(LPCSTR db, LPCSTR cabinet)
122 {
123     WCHAR dbW[MAX_PATH], cabinetW[MAX_PATH];
124     IStorage *stg;
125     IStream *stm;
126     HRESULT hr;
127     HANDLE handle;
128 
129     MultiByteToWideChar(CP_ACP, 0, db, -1, dbW, MAX_PATH);
130     hr = StgOpenStorage(dbW, NULL, STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
131     if (FAILED(hr))
132         return FALSE;
133 
134     MultiByteToWideChar(CP_ACP, 0, cabinet, -1, cabinetW, MAX_PATH);
135     hr = IStorage_CreateStream(stg, cabinetW, STGM_WRITE|STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
136     if (FAILED(hr))
137     {
138         IStorage_Release(stg);
139         return FALSE;
140     }
141 
142     handle = CreateFileW(cabinetW, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
143     if (handle != INVALID_HANDLE_VALUE)
144     {
145         DWORD count;
146         char buffer[1024];
147         if (ReadFile(handle, buffer, sizeof(buffer), &count, NULL))
148             IStream_Write(stm, buffer, count, &count);
149         CloseHandle(handle);
150     }
151 
152     IStream_Release(stm);
153     IStorage_Release(stg);
154 
155     return TRUE;
156 }
157 
158 /* msi database data */
159 
160 static const char directory_dat[] =
161     "Directory\tDirectory_Parent\tDefaultDir\n"
162     "s72\tS72\tl255\n"
163     "Directory\tDirectory\n"
164     "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
165     "ProgramFilesFolder\tTARGETDIR\t.\n"
166     "TARGETDIR\t\tSourceDir";
167 
168 static const char component_dat[] =
169     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
170     "s72\tS38\ts72\ti2\tS255\tS72\n"
171     "Component\tComponent\n"
172     "One\t{8F5BAEEF-DD92-40AC-9397-BE3CF9F97C81}\tMSITESTDIR\t2\tNOT REINSTALL\tone.txt\n";
173 
174 static const char feature_dat[] =
175     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
176     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
177     "Feature\tFeature\n"
178     "One\t\tOne\tOne\t1\t3\tMSITESTDIR\t0\n"
179     "Two\t\t\t\t2\t1\tTARGETDIR\t0\n";
180 
181 static const char feature_comp_dat[] =
182     "Feature_\tComponent_\n"
183     "s38\ts72\n"
184     "FeatureComponents\tFeature_\tComponent_\n"
185     "One\tOne\n";
186 
187 static const char file_dat[] =
188     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
189     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
190     "File\tFile\n"
191     "one.txt\tOne\tone.txt\t1000\t\t\t0\t1\n";
192 
193 static const char install_exec_seq_dat[] =
194     "Action\tCondition\tSequence\n"
195     "s72\tS255\tI2\n"
196     "InstallExecuteSequence\tAction\n"
197     "ValidateProductID\t\t700\n"
198     "CostInitialize\t\t800\n"
199     "FileCost\t\t900\n"
200     "CostFinalize\t\t1000\n"
201     "InstallValidate\t\t1400\n"
202     "InstallInitialize\t\t1500\n"
203     "ProcessComponents\t\t1600\n"
204     "UnpublishFeatures\t\t1800\n"
205     "RemoveFiles\t\t3500\n"
206     "InstallFiles\t\t4000\n"
207     "RegisterProduct\t\t6100\n"
208     "PublishFeatures\t\t6300\n"
209     "PublishProduct\t\t6400\n"
210     "InstallFinalize\t\t6600";
211 
212 static const char media_dat[] =
213     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
214     "i2\ti4\tL64\tS255\tS32\tS72\n"
215     "Media\tDiskId\n"
216     "1\t1\t\t\tDISK1\t\n";
217 
218 static const char property_dat[] =
219     "Property\tValue\n"
220     "s72\tl0\n"
221     "Property\tProperty\n"
222     "INSTALLLEVEL\t3\n"
223     "Manufacturer\tWine\n"
224     "ProductCode\t{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}\n"
225     "ProductName\tMSITEST\n"
226     "ProductVersion\t1.1.1\n"
227     "UpgradeCode\t{9574448F-9B86-4E07-B6F6-8D199DA12127}\n"
228     "MSIFASTINSTALL\t1\n";
229 
230 static const char ci2_property_dat[] =
231     "Property\tValue\n"
232     "s72\tl0\n"
233     "Property\tProperty\n"
234     "INSTALLLEVEL\t3\n"
235     "Manufacturer\tWine\n"
236     "ProductCode\t{FF4AFE9C-6AC2-44F9-A060-9EA6BD16C75E}\n"
237     "ProductName\tMSITEST2\n"
238     "ProductVersion\t1.1.1\n"
239     "UpgradeCode\t{6B60C3CA-B8CA-4FB7-A395-092D98FF5D2A}\n"
240     "MSIFASTINSTALL\t1\n";
241 
242 static const char mcp_component_dat[] =
243     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
244     "s72\tS38\ts72\ti2\tS255\tS72\n"
245     "Component\tComponent\n"
246     "hydrogen\t{C844BD1E-1907-4C00-8BC9-150BD70DF0A1}\tMSITESTDIR\t2\t\thydrogen\n"
247     "helium\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t2\t\thelium\n"
248     "lithium\t{4AF28FFC-71C7-4307-BDE4-B77C5338F56F}\tMSITESTDIR\t2\tPROPVAR=42\tlithium\n";
249 
250 static const char mcp_feature_dat[] =
251     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
252     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
253     "Feature\tFeature\n"
254     "hydroxyl\t\thydroxyl\thydroxyl\t2\t1\tTARGETDIR\t0\n"
255     "heliox\t\theliox\theliox\t2\t5\tTARGETDIR\t0\n"
256     "lithia\t\tlithia\tlithia\t2\t10\tTARGETDIR\t0";
257 
258 static const char mcp_feature_comp_dat[] =
259     "Feature_\tComponent_\n"
260     "s38\ts72\n"
261     "FeatureComponents\tFeature_\tComponent_\n"
262     "hydroxyl\thydrogen\n"
263     "heliox\thelium\n"
264     "lithia\tlithium";
265 
266 static const char mcp_file_dat[] =
267     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
268     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
269     "File\tFile\n"
270     "hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n"
271     "helium\thelium\thelium\t0\t\t\t8192\t1\n"
272     "lithium\tlithium\tlithium\t0\t\t\t8192\t1";
273 
274 static const char lus_component_dat[] =
275     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
276     "s72\tS38\ts72\ti2\tS255\tS72\n"
277     "Component\tComponent\n"
278     "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
279 
280 static const char lus_feature_dat[] =
281     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
282     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
283     "Feature\tFeature\n"
284     "feature\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0\n"
285     "montecristo\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0";
286 
287 static const char lus_file_dat[] =
288     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
289     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
290     "File\tFile\n"
291     "maximus\tmaximus\tmaximus\t500\t\t\t8192\t1";
292 
293 static const char lus_feature_comp_dat[] =
294     "Feature_\tComponent_\n"
295     "s38\ts72\n"
296     "FeatureComponents\tFeature_\tComponent_\n"
297     "feature\tmaximus\n"
298     "montecristo\tmaximus";
299 
300 static const char lus_install_exec_seq_dat[] =
301     "Action\tCondition\tSequence\n"
302     "s72\tS255\tI2\n"
303     "InstallExecuteSequence\tAction\n"
304     "ValidateProductID\t\t700\n"
305     "CostInitialize\t\t800\n"
306     "FileCost\t\t900\n"
307     "CostFinalize\t\t1000\n"
308     "InstallValidate\t\t1400\n"
309     "InstallInitialize\t\t1500\n"
310     "ProcessComponents\tPROCESS_COMPONENTS=1 Or FULL=1\t1600\n"
311     "UnpublishFeatures\tUNPUBLISH_FEATURES=1 Or FULL=1\t1800\n"
312     "RemoveFiles\t\t3500\n"
313     "InstallFiles\t\t4000\n"
314     "RegisterUser\tREGISTER_USER=1 Or FULL=1\t6000\n"
315     "RegisterProduct\tREGISTER_PRODUCT=1 Or FULL=1\t6100\n"
316     "PublishFeatures\tPUBLISH_FEATURES=1 Or FULL=1\t6300\n"
317     "PublishProduct\tPUBLISH_PRODUCT=1 Or FULL=1\t6400\n"
318     "InstallFinalize\t\t6600";
319 
320 static const char lus0_media_dat[] =
321     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
322     "i2\ti4\tL64\tS255\tS32\tS72\n"
323     "Media\tDiskId\n"
324     "1\t1\t\t\tDISK1\t\n";
325 
326 static const char lus1_media_dat[] =
327     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
328     "i2\ti4\tL64\tS255\tS32\tS72\n"
329     "Media\tDiskId\n"
330     "1\t1\t\ttest1.cab\tDISK1\t\n";
331 
332 static const char lus2_media_dat[] =
333     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
334     "i2\ti4\tL64\tS255\tS32\tS72\n"
335     "Media\tDiskId\n"
336     "1\t1\t\t#test1.cab\tDISK1\t\n";
337 
338 static const char spf_custom_action_dat[] =
339     "Action\tType\tSource\tTarget\tISComments\n"
340     "s72\ti2\tS64\tS0\tS255\n"
341     "CustomAction\tAction\n"
342     "SetFolderProp\t51\tMSITESTDIR\t[ProgramFilesFolder]\\msitest\\added\t\n"
343     "SetFolderProp2\t51\tMSITESTDIR\t[ProgramFilesFolder]\\msitest\\added\\added2\t\n";
344 
345 static const char spf_install_exec_seq_dat[] =
346     "Action\tCondition\tSequence\n"
347     "s72\tS255\tI2\n"
348     "InstallExecuteSequence\tAction\n"
349     "CostInitialize\t\t800\n"
350     "FileCost\t\t900\n"
351     "SetFolderProp\t\t950\n"
352     "SetFolderProp2\t\t960\n"
353     "CostFinalize\t\t1000\n"
354     "InstallValidate\t\t1400\n"
355     "InstallInitialize\t\t1500\n"
356     "InstallFiles\t\t4000\n"
357     "InstallServices\t\t5000\n"
358     "InstallFinalize\t\t6600\n";
359 
360 static const char spf_install_ui_seq_dat[] =
361     "Action\tCondition\tSequence\n"
362     "s72\tS255\tI2\n"
363     "InstallUISequence\tAction\n"
364     "CostInitialize\t\t800\n"
365     "FileCost\t\t900\n"
366     "CostFinalize\t\t1000\n"
367     "ExecuteAction\t\t1100\n";
368 
369 static const char spf_directory_dat[] =
370     "Directory\tDirectory_Parent\tDefaultDir\n"
371     "s72\tS72\tl255\n"
372     "Directory\tDirectory\n"
373     "PARENTDIR\tTARGETDIR\tparent\n"
374     "CHILDDIR\tPARENTDIR\tchild\n"
375     "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
376     "ProgramFilesFolder\tTARGETDIR\t.\n"
377     "TARGETDIR\t\tSourceDir";
378 
379 static const char spf_component_dat[] =
380     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
381     "s72\tS38\ts72\ti2\tS255\tS72\n"
382     "Component\tComponent\n"
383     "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
384 
385 static const char spf2_install_exec_seq_dat[] =
386     "Action\tCondition\tSequence\n"
387     "s72\tS255\tI2\n"
388     "InstallExecuteSequence\tAction\n"
389     "CostInitialize\t\t800\n"
390     "FileCost\t\t900\n"
391     "FormatParentFolderCheck\t\t910\n"
392     "FormatChildFolderCheck\t\t920\n"
393     "CheckParentFolder\tNOT PARENTDIR=PARENTDIRCHECK\t930\n"
394     "CheckChildFolder\tNOT CHILDDIR=CHILDDIRCHECK\t940\n"
395     "FormatParentFolderCheck2\t\t945\n"
396     "SetParentFolder\t\t950\n"
397     "CheckParentFolder2\tNOT PARENTDIR=PARENTDIRCHECK\t960\n"
398     "CheckChildFolder2\tNOT CHILDDIR=CHILDDIRCHECK\t970\n"
399     "CostFinalize\t\t1000\n"
400     "FormatParentFolderCheck3\t\t1005\n"
401     "CheckParentFolder3\tNOT PARENTDIR=PARENTDIRCHECK\t1010\n"
402     "CheckChildFolder3\tNOT CHILDDIR=CHILDDIRCHECK\t1020\n"
403     "InstallValidate\t\t1400\n"
404     "InstallInitialize\t\t1500\n"
405     "InstallFiles\t\t4000\n"
406     "CreateShortcuts\t\t4100\n"
407     "InstallFinalize\t\t6600\n";
408 
409 static const char spf2_custom_action_dat[] =
410     "Action\tType\tSource\tTarget\tISComments\n"
411     "s72\ti2\tS64\tS0\tS255\n"
412     "CustomAction\tAction\n"
413     "FormatParentFolderCheck\t51\tPARENTDIRCHECK\t[TARGETDIR]parent\\\t\n"
414     "FormatChildFolderCheck\t51\tCHILDDIRCHECK\t[TARGETDIR]parent\\child\\\t\n"
415     "CheckParentFolder\t19\tPARENTDIR\tparent prop wrong before set: [PARENTDIR]\t\n"
416     "CheckChildFolder\t19\tCHILDDIR\tchild prop wrong before set: [CHILDDIR]\t\n"
417     "FormatParentFolderCheck2\t51\tPARENTDIRCHECK\t[ProgramFilesFolder]msitest\\parent\t\n"
418     "SetParentFolder\t51\tPARENTDIR\t[PARENTDIRCHECK]\t\n"
419     "CheckParentFolder2\t19\tPARENTDIR\tparent prop wrong after set: [PARENTDIR]\t\n"
420     "CheckChildFolder2\t19\tCHILDDIR\tchild prop wrong after set: [CHILDDIR]\t\n"
421     "FormatParentFolderCheck3\t51\tPARENTDIRCHECK\t[ProgramFilesFolder]msitest\\parent\\\t\n"
422     "CheckParentFolder3\t19\tPARENTDIR\tparent prop wrong after CostFinalize: [PARENTDIR]\t\n"
423     "CheckChildFolder3\t19\tCHILDDIR\tchild prop wrong after CostFinalize: [CHILDDIR]\t\n";
424 
425 static const char shortcut_dat[] =
426     "Shortcut\tDirectory_\tName\tComponent_\tTarget\tArguments\tDescription\tHotkey\tIcon_\tIconIndex\tShowCmd\tWkDir\n"
427     "s72\ts72\tl128\ts72\ts72\tS255\tL255\tI2\tS72\tI2\tI2\tS72\n"
428     "Shortcut\tShortcut\n"
429     "Shortcut\tCHILDDIR\tShortcut\tmaximus\t[#maximus]\t\tShortcut\t\t\t\t\tMSITESTDIR\n";
430 
431 static const char sd_file_dat[] =
432     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
433     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
434     "File\tFile\n"
435     "sourcedir.txt\tsourcedir\tsourcedir.txt\t1000\t\t\t8192\t1\n";
436 
437 static const char sd_feature_dat[] =
438     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
439     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
440     "Feature\tFeature\n"
441     "sourcedir\t\t\tsourcedir feature\t1\t2\tMSITESTDIR\t0\n";
442 
443 static const char sd_feature_comp_dat[] =
444     "Feature_\tComponent_\n"
445     "s38\ts72\n"
446     "FeatureComponents\tFeature_\tComponent_\n"
447     "sourcedir\tsourcedir\n";
448 
449 static const char sd_component_dat[] =
450     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
451     "s72\tS38\ts72\ti2\tS255\tS72\n"
452     "Component\tComponent\n"
453     "sourcedir\t{DD422F92-3ED8-49B5-A0B7-F266F98357DF}\tMSITESTDIR\t0\t\tsourcedir.txt\n";
454 
455 static const char sd_install_ui_seq_dat[] =
456     "Action\tCondition\tSequence\n"
457     "s72\tS255\tI2\n"
458     "InstallUISequence\tAction\n"
459     "TestSourceDirProp1\tnot SourceDir and not SOURCEDIR and not Installed\t99\n"
460     "AppSearch\t\t100\n"
461     "TestSourceDirProp2\tnot SourceDir and not SOURCEDIR and not Installed\t101\n"
462     "LaunchConditions\tnot Installed \t110\n"
463     "TestSourceDirProp3\tnot SourceDir and not SOURCEDIR and not Installed\t111\n"
464     "FindRelatedProducts\t\t120\n"
465     "TestSourceDirProp4\tnot SourceDir and not SOURCEDIR and not Installed\t121\n"
466     "CCPSearch\t\t130\n"
467     "TestSourceDirProp5\tnot SourceDir and not SOURCEDIR and not Installed\t131\n"
468     "RMCCPSearch\t\t140\n"
469     "TestSourceDirProp6\tnot SourceDir and not SOURCEDIR and not Installed\t141\n"
470     "ValidateProductID\t\t150\n"
471     "TestSourceDirProp7\tnot SourceDir and not SOURCEDIR and not Installed\t151\n"
472     "CostInitialize\t\t800\n"
473     "TestSourceDirProp8\tnot SourceDir and not SOURCEDIR and not Installed\t801\n"
474     "FileCost\t\t900\n"
475     "TestSourceDirProp9\tnot SourceDir and not SOURCEDIR and not Installed\t901\n"
476     "IsolateComponents\t\t1000\n"
477     "TestSourceDirProp10\tnot SourceDir and not SOURCEDIR and not Installed\t1001\n"
478     "CostFinalize\t\t1100\n"
479     "TestSourceDirProp11\tnot SourceDir and not SOURCEDIR and not Installed\t1101\n"
480     "MigrateFeatureStates\t\t1200\n"
481     "TestSourceDirProp12\tnot SourceDir and not SOURCEDIR and not Installed\t1201\n"
482     "ExecuteAction\t\t1300\n"
483     "TestSourceDirProp13\tnot SourceDir and not SOURCEDIR and not Installed\t1301\n";
484 
485 static const char sd_install_exec_seq_dat[] =
486     "Action\tCondition\tSequence\n"
487     "s72\tS255\tI2\n"
488     "InstallExecuteSequence\tAction\n"
489     "TestSourceDirProp14\tSourceDir and SOURCEDIR and not Installed\t99\n"
490     "LaunchConditions\t\t100\n"
491     "TestSourceDirProp15\tSourceDir and SOURCEDIR and not Installed\t101\n"
492     "ValidateProductID\t\t700\n"
493     "TestSourceDirProp16\tSourceDir and SOURCEDIR and not Installed\t701\n"
494     "CostInitialize\t\t800\n"
495     "TestSourceDirProp17\tSourceDir and SOURCEDIR and not Installed\t801\n"
496     "ResolveSource\tResolveSource and not Installed\t850\n"
497     "TestSourceDirProp18\tResolveSource and not SourceDir and not SOURCEDIR and not Installed\t851\n"
498     "TestSourceDirProp19\tnot ResolveSource and SourceDir and SOURCEDIR and not Installed\t852\n"
499     "FileCost\t\t900\n"
500     "TestSourceDirProp20\tSourceDir and SOURCEDIR and not Installed\t901\n"
501     "IsolateComponents\t\t1000\n"
502     "TestSourceDirProp21\tSourceDir and SOURCEDIR and not Installed\t1001\n"
503     "CostFinalize\t\t1100\n"
504     "TestSourceDirProp22\tSourceDir and SOURCEDIR and not Installed\t1101\n"
505     "MigrateFeatureStates\t\t1200\n"
506     "TestSourceDirProp23\tSourceDir and SOURCEDIR and not Installed\t1201\n"
507     "InstallValidate\t\t1400\n"
508     "TestSourceDirProp24\tSourceDir and SOURCEDIR and not Installed\t1401\n"
509     "InstallInitialize\t\t1500\n"
510     "TestSourceDirProp25\tSourceDir and SOURCEDIR and not Installed\t1501\n"
511     "ProcessComponents\t\t1600\n"
512     "TestSourceDirProp26\tnot SourceDir and not SOURCEDIR and not Installed\t1601\n"
513     "UnpublishFeatures\t\t1800\n"
514     "TestSourceDirProp27\tnot SourceDir and not SOURCEDIR and not Installed\t1801\n"
515     "RemoveFiles\t\t3500\n"
516     "TestSourceDirProp28\tnot SourceDir and not SOURCEDIR and not Installed\t3501\n"
517     "InstallFiles\t\t4000\n"
518     "TestSourceDirProp29\tnot SourceDir and not SOURCEDIR and not Installed\t4001\n"
519     "RegisterUser\t\t6000\n"
520     "TestSourceDirProp30\tnot SourceDir and not SOURCEDIR and not Installed\t6001\n"
521     "RegisterProduct\t\t6100\n"
522     "TestSourceDirProp31\tnot SourceDir and not SOURCEDIR and not Installed\t6101\n"
523     "PublishFeatures\t\t6300\n"
524     "TestSourceDirProp32\tnot SourceDir and not SOURCEDIR and not Installed\t6301\n"
525     "PublishProduct\t\t6400\n"
526     "TestSourceDirProp33\tnot SourceDir and not SOURCEDIR and not Installed\t6401\n"
527     "InstallExecute\t\t6500\n"
528     "TestSourceDirProp34\tnot SourceDir and not SOURCEDIR and not Installed\t6501\n"
529     "InstallFinalize\t\t6600\n"
530     "TestSourceDirProp35\tnot SourceDir and not SOURCEDIR and not Installed\t6601\n";
531 
532 static const char sd_custom_action_dat[] =
533     "Action\tType\tSource\tTarget\tISComments\n"
534     "s72\ti2\tS64\tS0\tS255\n"
535     "CustomAction\tAction\n"
536     "TestSourceDirProp1\t19\t\tTest 1 failed\t\n"
537     "TestSourceDirProp2\t19\t\tTest 2 failed\t\n"
538     "TestSourceDirProp3\t19\t\tTest 3 failed\t\n"
539     "TestSourceDirProp4\t19\t\tTest 4 failed\t\n"
540     "TestSourceDirProp5\t19\t\tTest 5 failed\t\n"
541     "TestSourceDirProp6\t19\t\tTest 6 failed\t\n"
542     "TestSourceDirProp7\t19\t\tTest 7 failed\t\n"
543     "TestSourceDirProp8\t19\t\tTest 8 failed\t\n"
544     "TestSourceDirProp9\t19\t\tTest 9 failed\t\n"
545     "TestSourceDirProp10\t19\t\tTest 10 failed\t\n"
546     "TestSourceDirProp11\t19\t\tTest 11 failed\t\n"
547     "TestSourceDirProp12\t19\t\tTest 12 failed\t\n"
548     "TestSourceDirProp13\t19\t\tTest 13 failed\t\n"
549     "TestSourceDirProp14\t19\t\tTest 14 failed\t\n"
550     "TestSourceDirProp15\t19\t\tTest 15 failed\t\n"
551     "TestSourceDirProp16\t19\t\tTest 16 failed\t\n"
552     "TestSourceDirProp17\t19\t\tTest 17 failed\t\n"
553     "TestSourceDirProp18\t19\t\tTest 18 failed\t\n"
554     "TestSourceDirProp19\t19\t\tTest 19 failed\t\n"
555     "TestSourceDirProp20\t19\t\tTest 20 failed\t\n"
556     "TestSourceDirProp21\t19\t\tTest 21 failed\t\n"
557     "TestSourceDirProp22\t19\t\tTest 22 failed\t\n"
558     "TestSourceDirProp23\t19\t\tTest 23 failed\t\n"
559     "TestSourceDirProp24\t19\t\tTest 24 failed\t\n"
560     "TestSourceDirProp25\t19\t\tTest 25 failed\t\n"
561     "TestSourceDirProp26\t19\t\tTest 26 failed\t\n"
562     "TestSourceDirProp27\t19\t\tTest 27 failed\t\n"
563     "TestSourceDirProp28\t19\t\tTest 28 failed\t\n"
564     "TestSourceDirProp29\t19\t\tTest 29 failed\t\n"
565     "TestSourceDirProp30\t19\t\tTest 30 failed\t\n"
566     "TestSourceDirProp31\t19\t\tTest 31 failed\t\n"
567     "TestSourceDirProp32\t19\t\tTest 32 failed\t\n"
568     "TestSourceDirProp33\t19\t\tTest 33 failed\t\n"
569     "TestSourceDirProp34\t19\t\tTest 34 failed\t\n"
570     "TestSourceDirProp35\t19\t\tTest 35 failed\t\n";
571 
572 static const char ci_install_exec_seq_dat[] =
573     "Action\tCondition\tSequence\n"
574     "s72\tS255\tI2\n"
575     "InstallExecuteSequence\tAction\n"
576     "CostInitialize\t\t800\n"
577     "FileCost\t\t900\n"
578     "CostFinalize\t\t1000\n"
579     "InstallValidate\t\t1400\n"
580     "InstallInitialize\t\t1500\n"
581     "RunInstall\tnot Installed\t1550\n"
582     "ProcessComponents\t\t1600\n"
583     "UnpublishFeatures\t\t1800\n"
584     "RemoveFiles\t\t3500\n"
585     "InstallFiles\t\t4000\n"
586     "RegisterProduct\t\t6100\n"
587     "PublishFeatures\t\t6300\n"
588     "PublishProduct\t\t6400\n"
589     "InstallFinalize\t\t6600\n";
590 
591 static const char ci_custom_action_dat[] =
592     "Action\tType\tSource\tTarget\tISComments\n"
593     "s72\ti2\tS64\tS0\tS255\n"
594     "CustomAction\tAction\n"
595     "RunInstall\t23\tmsitest\\concurrent.msi\tMYPROP=[UILevel]\t\n";
596 
597 static const char ci_component_dat[] =
598     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
599     "s72\tS38\ts72\ti2\tS255\tS72\n"
600     "Component\tComponent\n"
601     "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
602 
603 static const char ci2_component_dat[] =
604     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
605     "s72\tS38\ts72\ti2\tS255\tS72\n"
606     "Component\tComponent\n"
607     "augustus\t\tMSITESTDIR\t0\tUILevel=3 AND MYPROP=5\taugustus\n";
608 
609 static const char ci2_feature_comp_dat[] =
610     "Feature_\tComponent_\n"
611     "s38\ts72\n"
612     "FeatureComponents\tFeature_\tComponent_\n"
613     "feature\taugustus";
614 
615 static const char ci2_file_dat[] =
616     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
617     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
618     "File\tFile\n"
619     "augustus\taugustus\taugustus\t500\t\t\t8192\t1";
620 
621 static const char cl_custom_action_dat[] =
622     "Action\tType\tSource\tTarget\tISComments\n"
623     "s72\ti2\tS64\tS0\tS255\n"
624     "CustomAction\tAction\n"
625     "TestCommandlineProp\t19\t\tTest1\t\n";
626 
627 static const char cl_install_exec_seq_dat[] =
628     "Action\tCondition\tSequence\n"
629     "s72\tS255\tI2\n"
630     "InstallExecuteSequence\tAction\n"
631     "LaunchConditions\t\t100\n"
632     "ValidateProductID\t\t700\n"
633     "CostInitialize\t\t800\n"
634     "FileCost\t\t900\n"
635     "CostFinalize\t\t1000\n"
636     "TestCommandlineProp\tP=\"one\"\t1100\n"
637     "InstallInitialize\t\t1500\n"
638     "ProcessComponents\t\t1600\n"
639     "InstallValidate\t\t1400\n"
640     "InstallFinalize\t\t5000\n";
641 
642 static const msi_table tables[] =
643 {
644     ADD_TABLE(directory),
645     ADD_TABLE(component),
646     ADD_TABLE(feature),
647     ADD_TABLE(feature_comp),
648     ADD_TABLE(file),
649     ADD_TABLE(install_exec_seq),
650     ADD_TABLE(media),
651     ADD_TABLE(property),
652 };
653 
654 static const msi_table mcp_tables[] =
655 {
656     ADD_TABLE(directory),
657     ADD_TABLE(mcp_component),
658     ADD_TABLE(mcp_feature),
659     ADD_TABLE(mcp_feature_comp),
660     ADD_TABLE(mcp_file),
661     ADD_TABLE(install_exec_seq),
662     ADD_TABLE(media),
663     ADD_TABLE(property)
664 };
665 
666 static const msi_table lus0_tables[] =
667 {
668     ADD_TABLE(lus_component),
669     ADD_TABLE(directory),
670     ADD_TABLE(lus_feature),
671     ADD_TABLE(lus_feature_comp),
672     ADD_TABLE(lus_file),
673     ADD_TABLE(lus_install_exec_seq),
674     ADD_TABLE(lus0_media),
675     ADD_TABLE(property)
676 };
677 
678 static const msi_table lus1_tables[] =
679 {
680     ADD_TABLE(lus_component),
681     ADD_TABLE(directory),
682     ADD_TABLE(lus_feature),
683     ADD_TABLE(lus_feature_comp),
684     ADD_TABLE(lus_file),
685     ADD_TABLE(lus_install_exec_seq),
686     ADD_TABLE(lus1_media),
687     ADD_TABLE(property)
688 };
689 
690 static const msi_table lus2_tables[] =
691 {
692     ADD_TABLE(lus_component),
693     ADD_TABLE(directory),
694     ADD_TABLE(lus_feature),
695     ADD_TABLE(lus_feature_comp),
696     ADD_TABLE(lus_file),
697     ADD_TABLE(lus_install_exec_seq),
698     ADD_TABLE(lus2_media),
699     ADD_TABLE(property)
700 };
701 
702 static const msi_table spf_tables[] =
703 {
704     ADD_TABLE(lus_component),
705     ADD_TABLE(directory),
706     ADD_TABLE(lus_feature),
707     ADD_TABLE(lus_feature_comp),
708     ADD_TABLE(lus_file),
709     ADD_TABLE(lus0_media),
710     ADD_TABLE(property),
711     ADD_TABLE(spf_custom_action),
712     ADD_TABLE(spf_install_exec_seq),
713     ADD_TABLE(spf_install_ui_seq)
714 };
715 
716 static const msi_table spf2_tables[] =
717 {
718     ADD_TABLE(spf_component),
719     ADD_TABLE(spf_directory),
720     ADD_TABLE(lus_feature),
721     ADD_TABLE(lus_feature_comp),
722     ADD_TABLE(lus_file),
723     ADD_TABLE(lus0_media),
724     ADD_TABLE(property),
725     ADD_TABLE(spf2_custom_action),
726     ADD_TABLE(spf2_install_exec_seq),
727     ADD_TABLE(spf_install_ui_seq),
728     ADD_TABLE(shortcut)
729 };
730 
731 static const msi_table sd_tables[] =
732 {
733     ADD_TABLE(directory),
734     ADD_TABLE(sd_component),
735     ADD_TABLE(sd_feature),
736     ADD_TABLE(sd_feature_comp),
737     ADD_TABLE(sd_file),
738     ADD_TABLE(sd_install_exec_seq),
739     ADD_TABLE(sd_install_ui_seq),
740     ADD_TABLE(sd_custom_action),
741     ADD_TABLE(media),
742     ADD_TABLE(property)
743 };
744 
745 static const msi_table ci_tables[] =
746 {
747     ADD_TABLE(ci_component),
748     ADD_TABLE(directory),
749     ADD_TABLE(lus_feature),
750     ADD_TABLE(lus_feature_comp),
751     ADD_TABLE(lus_file),
752     ADD_TABLE(ci_install_exec_seq),
753     ADD_TABLE(lus0_media),
754     ADD_TABLE(property),
755     ADD_TABLE(ci_custom_action),
756 };
757 
758 static const msi_table ci2_tables[] =
759 {
760     ADD_TABLE(ci2_component),
761     ADD_TABLE(directory),
762     ADD_TABLE(lus_feature),
763     ADD_TABLE(ci2_feature_comp),
764     ADD_TABLE(ci2_file),
765     ADD_TABLE(install_exec_seq),
766     ADD_TABLE(lus0_media),
767     ADD_TABLE(ci2_property),
768 };
769 
770 static const msi_table cl_tables[] =
771 {
772     ADD_TABLE(component),
773     ADD_TABLE(directory),
774     ADD_TABLE(feature),
775     ADD_TABLE(feature_comp),
776     ADD_TABLE(file),
777     ADD_TABLE(cl_custom_action),
778     ADD_TABLE(cl_install_exec_seq),
779     ADD_TABLE(media),
780     ADD_TABLE(property)
781 };
782 
783 static UINT set_summary_info(MSIHANDLE hdb, LPSTR prodcode)
784 {
785     UINT res;
786     MSIHANDLE suminfo;
787 
788     /* build summary info */
789     res = MsiGetSummaryInformationA(hdb, NULL, 7, &suminfo);
790     ok(res == ERROR_SUCCESS, "Failed to open summaryinfo\n");
791 
792     res = MsiSummaryInfoSetPropertyA(suminfo, 2, VT_LPSTR, 0, NULL,
793                                     "Installation Database");
794     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
795 
796     res = MsiSummaryInfoSetPropertyA(suminfo, 3, VT_LPSTR, 0, NULL,
797                                     "Installation Database");
798     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
799 
800     res = MsiSummaryInfoSetPropertyA(suminfo, 4, VT_LPSTR, 0, NULL,
801                                     "Wine Hackers");
802     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
803 
804     res = MsiSummaryInfoSetPropertyA(suminfo, 7, VT_LPSTR, 0, NULL,
805                                     ";1033");
806     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
807 
808     res = MsiSummaryInfoSetPropertyA(suminfo, PID_REVNUMBER, VT_LPSTR, 0, NULL,
809                                     "{A2078D65-94D6-4205-8DEE-F68D6FD622AA}");
810     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
811 
812     res = MsiSummaryInfoSetPropertyA(suminfo, 14, VT_I4, 100, NULL, NULL);
813     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
814 
815     res = MsiSummaryInfoSetPropertyA(suminfo, 15, VT_I4, 0, NULL, NULL);
816     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
817 
818     res = MsiSummaryInfoPersist(suminfo);
819     ok(res == ERROR_SUCCESS, "Failed to make summary info persist\n");
820 
821     res = MsiCloseHandle(suminfo);
822     ok(res == ERROR_SUCCESS, "Failed to close suminfo\n");
823 
824     return res;
825 }
826 
827 static MSIHANDLE create_package_db(LPSTR prodcode)
828 {
829     MSIHANDLE hdb = 0;
830     CHAR query[MAX_PATH];
831     UINT res;
832 
833     DeleteFileA(msifile);
834 
835     /* create an empty database */
836     res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
837     ok( res == ERROR_SUCCESS , "Failed to create database\n" );
838     if (res != ERROR_SUCCESS)
839         return hdb;
840 
841     res = MsiDatabaseCommit(hdb);
842     ok(res == ERROR_SUCCESS, "Failed to commit database\n");
843 
844     set_summary_info(hdb, prodcode);
845 
846     res = run_query(hdb, 0,
847             "CREATE TABLE `Directory` ( "
848             "`Directory` CHAR(255) NOT NULL, "
849             "`Directory_Parent` CHAR(255), "
850             "`DefaultDir` CHAR(255) NOT NULL "
851             "PRIMARY KEY `Directory`)");
852     ok(res == ERROR_SUCCESS , "Failed to create directory table\n");
853 
854     res = run_query(hdb, 0,
855             "CREATE TABLE `Property` ( "
856             "`Property` CHAR(72) NOT NULL, "
857             "`Value` CHAR(255) "
858             "PRIMARY KEY `Property`)");
859     ok(res == ERROR_SUCCESS , "Failed to create directory table\n");
860 
861     sprintf(query, "INSERT INTO `Property` "
862             "(`Property`, `Value`) "
863             "VALUES( 'ProductCode', '%s' )", prodcode);
864     res = run_query(hdb, 0, query);
865     ok(res == ERROR_SUCCESS , "Failed\n");
866 
867     res = MsiDatabaseCommit(hdb);
868     ok(res == ERROR_SUCCESS, "Failed to commit database\n");
869 
870     return hdb;
871 }
872 
873 static void test_usefeature(void)
874 {
875     INSTALLSTATE r;
876 
877     if (!pMsiUseFeatureExA)
878     {
879         win_skip("MsiUseFeatureExA not implemented\n");
880         return;
881     }
882 
883     r = MsiQueryFeatureStateA(NULL, NULL);
884     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
885 
886     r = MsiQueryFeatureStateA("{9085040-6000-11d3-8cfe-0150048383c9}" ,NULL);
887     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
888 
889     r = pMsiUseFeatureExA(NULL,NULL,0,0);
890     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
891 
892     r = pMsiUseFeatureExA(NULL, "WORDVIEWFiles", -2, 1 );
893     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
894 
895     r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}",
896                          NULL, -2, 0 );
897     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
898 
899     r = pMsiUseFeatureExA("{9085040-6000-11d3-8cfe-0150048383c9}",
900                          "WORDVIEWFiles", -2, 0 );
901     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
902 
903     r = pMsiUseFeatureExA("{0085040-6000-11d3-8cfe-0150048383c9}",
904                          "WORDVIEWFiles", -2, 0 );
905     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
906 
907     r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}",
908                          "WORDVIEWFiles", -2, 1 );
909     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
910 }
911 
912 static LONG delete_key( HKEY key, LPCSTR subkey, REGSAM access )
913 {
914     if (pRegDeleteKeyExA)
915         return pRegDeleteKeyExA( key, subkey, access, 0 );
916     return RegDeleteKeyA( key, subkey );
917 }
918 
919 static void test_null(void)
920 {
921     MSIHANDLE hpkg;
922     UINT r;
923     HKEY hkey;
924     DWORD dwType, cbData;
925     LPBYTE lpData = NULL;
926     INSTALLSTATE state;
927     REGSAM access = KEY_ALL_ACCESS;
928 
929     if (is_wow64)
930         access |= KEY_WOW64_64KEY;
931 
932     r = pMsiOpenPackageExW(NULL, 0, &hpkg);
933     ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
934 
935     state = MsiQueryProductStateW(NULL);
936     ok( state == INSTALLSTATE_INVALIDARG, "wrong return\n");
937 
938     r = MsiEnumFeaturesW(NULL,0,NULL,NULL);
939     ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
940 
941     r = MsiConfigureFeatureW(NULL, NULL, 0);
942     ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
943 
944     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", NULL, 0);
945     ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
946 
947     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000001}", "foo", 0);
948     ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
949 
950     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000002}", "foo", INSTALLSTATE_DEFAULT);
951     ok( r == ERROR_UNKNOWN_PRODUCT, "wrong error %d\n", r);
952 
953     /* make sure empty string to MsiGetProductInfo is not a handle to default registry value, saving and restoring the
954      * necessary registry values */
955 
956     /* empty product string */
957     r = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", 0, access, &hkey);
958     if (r == ERROR_ACCESS_DENIED)
959     {
960         skip("Not enough rights to perform tests\n");
961         return;
962     }
963     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
964 
965     r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
966     ok ( r == ERROR_SUCCESS || r == ERROR_FILE_NOT_FOUND, "wrong error %d\n", r);
967     if ( r == ERROR_SUCCESS )
968     {
969         lpData = HeapAlloc(GetProcessHeap(), 0, cbData);
970         if (!lpData)
971             skip("Out of memory\n");
972         else
973         {
974             r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
975             ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
976         }
977     }
978 
979     r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
980     if (r == ERROR_ACCESS_DENIED)
981     {
982         skip("Not enough rights to perform tests\n");
983         HeapFree(GetProcessHeap(), 0, lpData);
984         RegCloseKey(hkey);
985         return;
986     }
987     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
988 
989     r = MsiGetProductInfoA("", "", NULL, NULL);
990     ok ( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
991 
992     if (lpData)
993     {
994         r = RegSetValueExA(hkey, NULL, 0, dwType, lpData, cbData);
995         ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
996 
997         HeapFree(GetProcessHeap(), 0, lpData);
998     }
999     else
1000     {
1001         r = RegDeleteValueA(hkey, NULL);
1002         ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
1003     }
1004 
1005     r = RegCloseKey(hkey);
1006     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1007 
1008     /* empty attribute */
1009     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}",
1010                         0, NULL, 0, access, NULL, &hkey, NULL);
1011     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1012 
1013     r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
1014     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1015 
1016     r = MsiGetProductInfoA("{F1C3AF50-8B56-4A69-A00C-00773FE42F30}", "", NULL, NULL);
1017     ok ( r == ERROR_UNKNOWN_PROPERTY, "wrong error %d\n", r);
1018 
1019     r = RegCloseKey(hkey);
1020     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1021 
1022     r = delete_key(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}",
1023                    access & KEY_WOW64_64KEY);
1024     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1025 }
1026 
1027 static void test_getcomponentpath(void)
1028 {
1029     INSTALLSTATE r;
1030     char buffer[0x100];
1031     DWORD sz;
1032 
1033     if(!pMsiGetComponentPathA)
1034         return;
1035 
1036     r = pMsiGetComponentPathA( NULL, NULL, NULL, NULL );
1037     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1038 
1039     r = pMsiGetComponentPathA( "bogus", "bogus", NULL, NULL );
1040     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1041 
1042     r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", NULL, NULL );
1043     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1044 
1045     sz = sizeof buffer;
1046     buffer[0]=0;
1047     r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", buffer, &sz );
1048     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1049 
1050     r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C998E7}",
1051         "{00000000-0000-0000-0000-000000000000}", buffer, &sz );
1052     ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
1053 
1054     r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
1055         "{00000000-0000-0000-0000-00000000}", buffer, &sz );
1056     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1057 
1058     r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
1059         "{029E403D-A86A-1D11-5B5B0006799C897E}", buffer, &sz );
1060     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1061 
1062     r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C9987e}",
1063                             "{00000000-A68A-11d1-5B5B-0006799C897E}", buffer, &sz );
1064     ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
1065 }
1066 
1067 static void create_test_files(void)
1068 {
1069     CreateDirectoryA("msitest", NULL);
1070     create_file("msitest\\one.txt", 100);
1071     CreateDirectoryA("msitest\\first", NULL);
1072     create_file("msitest\\first\\two.txt", 100);
1073     CreateDirectoryA("msitest\\second", NULL);
1074     create_file("msitest\\second\\three.txt", 100);
1075 
1076     create_file("four.txt", 100);
1077     create_file("five.txt", 100);
1078     create_cab_file("msitest.cab", MEDIA_SIZE, "four.txt\0five.txt\0");
1079 
1080     create_file("msitest\\filename", 100);
1081     create_file("msitest\\service.exe", 100);
1082 
1083     DeleteFileA("four.txt");
1084     DeleteFileA("five.txt");
1085 }
1086 
1087 static void delete_test_files(void)
1088 {
1089     DeleteFileA("msitest.msi");
1090     DeleteFileA("msitest.cab");
1091     DeleteFileA("msitest\\second\\three.txt");
1092     DeleteFileA("msitest\\first\\two.txt");
1093     DeleteFileA("msitest\\one.txt");
1094     DeleteFileA("msitest\\service.exe");
1095     DeleteFileA("msitest\\filename");
1096     RemoveDirectoryA("msitest\\second");
1097     RemoveDirectoryA("msitest\\first");
1098     RemoveDirectoryA("msitest");
1099 }
1100 
1101 #define HASHSIZE sizeof(MSIFILEHASHINFO)
1102 
1103 static const struct
1104 {
1105     LPCSTR data;
1106     DWORD size;
1107     MSIFILEHASHINFO hash;
1108 } hash_data[] =
1109 {
1110     { "", 0,
1111       { HASHSIZE,
1112         { 0, 0, 0, 0 },
1113       },
1114     },
1115 
1116     { "abc", 0,
1117       { HASHSIZE,
1118         { 0x98500190, 0xb04fd23c, 0x7d3f96d6, 0x727fe128 },
1119       },
1120     },
1121 
1122     { "C:\\Program Files\\msitest\\caesar\n", 0,
1123       { HASHSIZE,
1124         { 0x2b566794, 0xfd42181b, 0x2514d6e4, 0x5768b4e2 },
1125       },
1126     },
1127 
1128     { "C:\\Program Files\\msitest\\caesar\n", 500,
1129       { HASHSIZE,
1130         { 0x58095058, 0x805efeff, 0x10f3483e, 0x0147d653 },
1131       },
1132     },
1133 };
1134 
1135 static void test_MsiGetFileHash(void)
1136 {
1137     const char name[] = "msitest.bin";
1138     UINT r;
1139     MSIFILEHASHINFO hash;
1140     DWORD i;
1141 
1142     if (!pMsiGetFileHashA)
1143     {
1144         win_skip("MsiGetFileHash not implemented\n");
1145         return;
1146     }
1147 
1148     hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
1149 
1150     /* szFilePath is NULL */
1151     r = pMsiGetFileHashA(NULL, 0, &hash);
1152     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1153 
1154     /* szFilePath is empty */
1155     r = pMsiGetFileHashA("", 0, &hash);
1156     ok(r == ERROR_PATH_NOT_FOUND || r == ERROR_BAD_PATHNAME,
1157        "Expected ERROR_PATH_NOT_FOUND or ERROR_BAD_PATHNAME, got %d\n", r);
1158 
1159     /* szFilePath is nonexistent */
1160     r = pMsiGetFileHashA(name, 0, &hash);
1161     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
1162 
1163     /* dwOptions is non-zero */
1164     r = pMsiGetFileHashA(name, 1, &hash);
1165     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1166 
1167     /* pHash.dwFileHashInfoSize is not correct */
1168     hash.dwFileHashInfoSize = 0;
1169     r = pMsiGetFileHashA(name, 0, &hash);
1170     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1171 
1172     /* pHash is NULL */
1173     r = pMsiGetFileHashA(name, 0, NULL);
1174     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1175 
1176     for (i = 0; i < ARRAY_SIZE(hash_data); i++)
1177     {
1178         int ret;
1179 
1180         create_file_data(name, hash_data[i].data, hash_data[i].size);
1181 
1182         memset(&hash, 0, sizeof(MSIFILEHASHINFO));
1183         hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
1184 
1185         r = pMsiGetFileHashA(name, 0, &hash);
1186         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1187 
1188         ret = memcmp(&hash, &hash_data[i].hash, HASHSIZE);
1189         ok(!ret, "Hash incorrect\n");
1190 
1191         DeleteFileA(name);
1192     }
1193 }
1194 
1195 /* copied from dlls/msi/registry.c */
1196 static BOOL squash_guid(LPCWSTR in, LPWSTR out)
1197 {
1198     DWORD i,n=1;
1199     GUID guid;
1200 
1201     if (FAILED(CLSIDFromString((LPCOLESTR)in, &guid)))
1202         return FALSE;
1203 
1204     for(i=0; i<8; i++)
1205         out[7-i] = in[n++];
1206     n++;
1207     for(i=0; i<4; i++)
1208         out[11-i] = in[n++];
1209     n++;
1210     for(i=0; i<4; i++)
1211         out[15-i] = in[n++];
1212     n++;
1213     for(i=0; i<2; i++)
1214     {
1215         out[17+i*2] = in[n++];
1216         out[16+i*2] = in[n++];
1217     }
1218     n++;
1219     for( ; i<8; i++)
1220     {
1221         out[17+i*2] = in[n++];
1222         out[16+i*2] = in[n++];
1223     }
1224     out[32]=0;
1225     return TRUE;
1226 }
1227 
1228 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
1229 {
1230     WCHAR guidW[GUID_SIZE];
1231     WCHAR squashedW[SQUASHED_GUID_SIZE];
1232     GUID guid;
1233     HRESULT hr;
1234     int size;
1235 
1236     hr = CoCreateGuid(&guid);
1237     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
1238 
1239     size = StringFromGUID2(&guid, guidW, ARRAY_SIZE(guidW));
1240     ok(size == GUID_SIZE, "Expected %d, got %d.\n", GUID_SIZE, size);
1241 
1242     WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, GUID_SIZE, NULL, NULL);
1243     if (squashed)
1244     {
1245         squash_guid(guidW, squashedW);
1246         WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, SQUASHED_GUID_SIZE, NULL, NULL);
1247     }
1248 }
1249 
1250 static char *get_user_sid(void)
1251 {
1252     HANDLE token;
1253     DWORD size = 0;
1254     TOKEN_USER *user;
1255     char *usersid = NULL;
1256 
1257     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
1258     GetTokenInformation(token, TokenUser, NULL, size, &size);
1259 
1260     user = HeapAlloc(GetProcessHeap(), 0, size);
1261     GetTokenInformation(token, TokenUser, user, size, &size);
1262     ConvertSidToStringSidA(user->User.Sid, &usersid);
1263     HeapFree(GetProcessHeap(), 0, user);
1264 
1265     CloseHandle(token);
1266     return usersid;
1267 }
1268 
1269 static void test_MsiQueryProductState(void)
1270 {
1271     CHAR prodcode[MAX_PATH];
1272     CHAR prod_squashed[MAX_PATH];
1273     CHAR keypath[MAX_PATH*2];
1274     LPSTR usersid;
1275     INSTALLSTATE state;
1276     LONG res;
1277     HKEY userkey, localkey, props;
1278     HKEY prodkey;
1279     DWORD data, error;
1280     REGSAM access = KEY_ALL_ACCESS;
1281 
1282     create_test_guid(prodcode, prod_squashed);
1283     usersid = get_user_sid();
1284 
1285     if (is_wow64)
1286         access |= KEY_WOW64_64KEY;
1287 
1288     /* NULL prodcode */
1289     SetLastError(0xdeadbeef);
1290     state = MsiQueryProductStateA(NULL);
1291     error = GetLastError();
1292     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1293     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1294 
1295     /* empty prodcode */
1296     SetLastError(0xdeadbeef);
1297     state = MsiQueryProductStateA("");
1298     error = GetLastError();
1299     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1300     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1301 
1302     /* garbage prodcode */
1303     SetLastError(0xdeadbeef);
1304     state = MsiQueryProductStateA("garbage");
1305     error = GetLastError();
1306     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1307     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1308 
1309     /* guid without brackets */
1310     SetLastError(0xdeadbeef);
1311     state = MsiQueryProductStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D");
1312     error = GetLastError();
1313     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1314     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1315 
1316     /* guid with brackets */
1317     SetLastError(0xdeadbeef);
1318     state = MsiQueryProductStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}");
1319     error = GetLastError();
1320     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1321     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1322        "expected ERROR_SUCCESS, got %u\n", error);
1323 
1324     /* same length as guid, but random */
1325     SetLastError(0xdeadbeef);
1326     state = MsiQueryProductStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93");
1327     error = GetLastError();
1328     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1329     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1330 
1331     /* MSIINSTALLCONTEXT_USERUNMANAGED */
1332 
1333     SetLastError(0xdeadbeef);
1334     state = MsiQueryProductStateA(prodcode);
1335     error = GetLastError();
1336     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1337     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1338        "expected ERROR_SUCCESS, got %u\n", error);
1339 
1340     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
1341     lstrcatA(keypath, prod_squashed);
1342 
1343     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
1344     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1345 
1346     /* user product key exists */
1347     SetLastError(0xdeadbeef);
1348     state = MsiQueryProductStateA(prodcode);
1349     error = GetLastError();
1350     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1351     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1352        "expected ERROR_SUCCESS, got %u\n", error);
1353 
1354     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
1355     lstrcatA(keypath, prodcode);
1356 
1357     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1358     if (res == ERROR_ACCESS_DENIED)
1359     {
1360         skip("Not enough rights to perform tests\n");
1361         RegDeleteKeyA(userkey, "");
1362         RegCloseKey(userkey);
1363         LocalFree(usersid);
1364         return;
1365     }
1366     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1367 
1368     /* local uninstall key exists */
1369     SetLastError(0xdeadbeef);
1370     state = MsiQueryProductStateA(prodcode);
1371     error = GetLastError();
1372     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1373     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1374        "expected ERROR_SUCCESS, got %u\n", error);
1375 
1376     data = 1;
1377     res = RegSetValueExA(localkey, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1378     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1379 
1380     /* WindowsInstaller value exists */
1381     SetLastError(0xdeadbeef);
1382     state = MsiQueryProductStateA(prodcode);
1383     error = GetLastError();
1384     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1385     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1386        "expected ERROR_SUCCESS, got %u\n", error);
1387 
1388     RegDeleteValueA(localkey, "WindowsInstaller");
1389     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1390 
1391     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1392     lstrcatA(keypath, usersid);
1393     lstrcatA(keypath, "\\Products\\");
1394     lstrcatA(keypath, prod_squashed);
1395 
1396     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1397     if (res == ERROR_ACCESS_DENIED)
1398     {
1399         skip("Not enough rights to perform tests\n");
1400         RegDeleteKeyA(userkey, "");
1401         RegCloseKey(userkey);
1402         LocalFree(usersid);
1403         return;
1404     }
1405     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1406 
1407     /* local product key exists */
1408     SetLastError(0xdeadbeef);
1409     state = MsiQueryProductStateA(prodcode);
1410     error = GetLastError();
1411     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1412     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1413        "expected ERROR_SUCCESS, got %u\n", error);
1414 
1415     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1416     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1417 
1418     /* install properties key exists */
1419     SetLastError(0xdeadbeef);
1420     state = MsiQueryProductStateA(prodcode);
1421     error = GetLastError();
1422     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1423     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1424        "expected ERROR_SUCCESS, got %u\n", error);
1425 
1426     data = 1;
1427     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1428     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1429 
1430     /* WindowsInstaller value exists */
1431     SetLastError(0xdeadbeef);
1432     state = MsiQueryProductStateA(prodcode);
1433     error = GetLastError();
1434     if (state == INSTALLSTATE_ADVERTISED)
1435     {
1436         win_skip("broken result\n");
1437         RegDeleteValueA(props, "WindowsInstaller");
1438         delete_key(props, "", access & KEY_WOW64_64KEY);
1439         RegCloseKey(props);
1440         delete_key(localkey, "", access & KEY_WOW64_64KEY);
1441         RegCloseKey(localkey);
1442         RegDeleteKeyA(userkey, "");
1443         RegCloseKey(userkey);
1444         LocalFree(usersid);
1445         return;
1446     }
1447     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1448     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1449        "expected ERROR_SUCCESS, got %u\n", error);
1450 
1451     data = 2;
1452     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1453     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1454 
1455     /* WindowsInstaller value is not 1 */
1456     SetLastError(0xdeadbeef);
1457     state = MsiQueryProductStateA(prodcode);
1458     error = GetLastError();
1459     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1460     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1461        "expected ERROR_SUCCESS, got %u\n", error);
1462 
1463     RegDeleteKeyA(userkey, "");
1464 
1465     /* user product key does not exist */
1466     SetLastError(0xdeadbeef);
1467     state = MsiQueryProductStateA(prodcode);
1468     error = GetLastError();
1469     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1470     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1471        "expected ERROR_SUCCESS, got %u\n", error);
1472 
1473     RegDeleteValueA(props, "WindowsInstaller");
1474     delete_key(props, "", access & KEY_WOW64_64KEY);
1475     RegCloseKey(props);
1476     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1477     RegCloseKey(localkey);
1478     RegDeleteKeyA(userkey, "");
1479     RegCloseKey(userkey);
1480 
1481     /* MSIINSTALLCONTEXT_USERMANAGED */
1482 
1483     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
1484     lstrcatA(keypath, usersid);
1485     lstrcatA(keypath, "\\Installer\\Products\\");
1486     lstrcatA(keypath, prod_squashed);
1487 
1488     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
1489     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1490 
1491     state = MsiQueryProductStateA(prodcode);
1492     ok(state == INSTALLSTATE_ADVERTISED,
1493        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1494 
1495     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1496     lstrcatA(keypath, usersid);
1497     lstrcatA(keypath, "\\Products\\");
1498     lstrcatA(keypath, prod_squashed);
1499 
1500     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1501     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1502 
1503     state = MsiQueryProductStateA(prodcode);
1504     ok(state == INSTALLSTATE_ADVERTISED,
1505        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1506 
1507     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1508     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1509 
1510     state = MsiQueryProductStateA(prodcode);
1511     ok(state == INSTALLSTATE_ADVERTISED,
1512        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1513 
1514     data = 1;
1515     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1516     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1517 
1518     /* WindowsInstaller value exists */
1519     state = MsiQueryProductStateA(prodcode);
1520     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1521 
1522     RegDeleteValueA(props, "WindowsInstaller");
1523     delete_key(props, "", access & KEY_WOW64_64KEY);
1524     RegCloseKey(props);
1525     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1526     RegCloseKey(localkey);
1527     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
1528     RegCloseKey(prodkey);
1529 
1530     /* MSIINSTALLCONTEXT_MACHINE */
1531 
1532     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
1533     lstrcatA(keypath, prod_squashed);
1534 
1535     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
1536     if (res == ERROR_ACCESS_DENIED)
1537     {
1538         skip( "insufficient rights\n" );
1539         LocalFree( usersid );
1540         return;
1541     }
1542     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1543 
1544     state = MsiQueryProductStateA(prodcode);
1545     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1546 
1547     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1548     lstrcatA(keypath, "S-1-5-18\\Products\\");
1549     lstrcatA(keypath, prod_squashed);
1550 
1551     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1552     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1553 
1554     state = MsiQueryProductStateA(prodcode);
1555     ok(state == INSTALLSTATE_ADVERTISED,
1556        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1557 
1558     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1559     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1560 
1561     state = MsiQueryProductStateA(prodcode);
1562     ok(state == INSTALLSTATE_ADVERTISED,
1563        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1564 
1565     data = 1;
1566     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1567     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1568 
1569     /* WindowsInstaller value exists */
1570     state = MsiQueryProductStateA(prodcode);
1571     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1572 
1573     RegDeleteValueA(props, "WindowsInstaller");
1574     delete_key(props, "", access & KEY_WOW64_64KEY);
1575     RegCloseKey(props);
1576     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1577     RegCloseKey(localkey);
1578     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
1579     RegCloseKey(prodkey);
1580 
1581     LocalFree(usersid);
1582 }
1583 
1584 static const char table_enc85[] =
1585 "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
1586 "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
1587 "yz{}~";
1588 
1589 /*
1590  *  Encodes a base85 guid given a GUID pointer
1591  *  Caller should provide a 21 character buffer for the encoded string.
1592  */
1593 static void encode_base85_guid( GUID *guid, LPWSTR str )
1594 {
1595     unsigned int x, *p, i;
1596 
1597     p = (unsigned int*) guid;
1598     for( i=0; i<4; i++ )
1599     {
1600         x = p[i];
1601         *str++ = table_enc85[x%85];
1602         x = x/85;
1603         *str++ = table_enc85[x%85];
1604         x = x/85;
1605         *str++ = table_enc85[x%85];
1606         x = x/85;
1607         *str++ = table_enc85[x%85];
1608         x = x/85;
1609         *str++ = table_enc85[x%85];
1610     }
1611     *str = 0;
1612 }
1613 
1614 static void compose_base85_guid(LPSTR component, LPSTR comp_base85, LPSTR squashed)
1615 {
1616     WCHAR guidW[MAX_PATH];
1617     WCHAR base85W[MAX_PATH];
1618     WCHAR squashedW[MAX_PATH];
1619     GUID guid;
1620     HRESULT hr;
1621     int size;
1622 
1623     hr = CoCreateGuid(&guid);
1624     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
1625 
1626     size = StringFromGUID2(&guid, guidW, MAX_PATH);
1627     ok(size == 39, "Expected 39, got %d\n", hr);
1628 
1629     WideCharToMultiByte(CP_ACP, 0, guidW, size, component, MAX_PATH, NULL, NULL);
1630     encode_base85_guid(&guid, base85W);
1631     WideCharToMultiByte(CP_ACP, 0, base85W, -1, comp_base85, MAX_PATH, NULL, NULL);
1632     squash_guid(guidW, squashedW);
1633     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
1634 }
1635 
1636 static void test_MsiQueryFeatureState(void)
1637 {
1638     HKEY userkey, localkey, compkey, compkey2;
1639     CHAR prodcode[MAX_PATH];
1640     CHAR prod_squashed[MAX_PATH];
1641     CHAR component[MAX_PATH];
1642     CHAR comp_base85[MAX_PATH];
1643     CHAR comp_squashed[MAX_PATH], comp_squashed2[MAX_PATH];
1644     CHAR keypath[MAX_PATH*2];
1645     INSTALLSTATE state;
1646     LPSTR usersid;
1647     LONG res;
1648     REGSAM access = KEY_ALL_ACCESS;
1649     DWORD error;
1650 
1651     create_test_guid(prodcode, prod_squashed);
1652     compose_base85_guid(component, comp_base85, comp_squashed);
1653     compose_base85_guid(component, comp_base85 + 20, comp_squashed2);
1654     usersid = get_user_sid();
1655 
1656     if (is_wow64)
1657         access |= KEY_WOW64_64KEY;
1658 
1659     /* NULL prodcode */
1660     SetLastError(0xdeadbeef);
1661     state = MsiQueryFeatureStateA(NULL, "feature");
1662     error = GetLastError();
1663     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1664     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1665 
1666     /* empty prodcode */
1667     SetLastError(0xdeadbeef);
1668     state = MsiQueryFeatureStateA("", "feature");
1669     error = GetLastError();
1670     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1671     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1672 
1673     /* garbage prodcode */
1674     SetLastError(0xdeadbeef);
1675     state = MsiQueryFeatureStateA("garbage", "feature");
1676     error = GetLastError();
1677     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1678     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1679 
1680     /* guid without brackets */
1681     SetLastError(0xdeadbeef);
1682     state = MsiQueryFeatureStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", "feature");
1683     error = GetLastError();
1684     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1685     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1686 
1687     /* guid with brackets */
1688     SetLastError(0xdeadbeef);
1689     state = MsiQueryFeatureStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", "feature");
1690     error = GetLastError();
1691     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1692     ok(error == ERROR_SUCCESS || broken(error == ERROR_ALREADY_EXISTS) /* win2k */,
1693        "expected ERROR_SUCCESS, got %u\n", error);
1694 
1695     /* same length as guid, but random */
1696     SetLastError(0xdeadbeef);
1697     state = MsiQueryFeatureStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", "feature");
1698     error = GetLastError();
1699     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1700     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1701 
1702     /* NULL szFeature */
1703     SetLastError(0xdeadbeef);
1704     state = MsiQueryFeatureStateA(prodcode, NULL);
1705     error = GetLastError();
1706     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1707     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1708 
1709     /* empty szFeature */
1710     SetLastError(0xdeadbeef);
1711     state = MsiQueryFeatureStateA(prodcode, "");
1712     error = GetLastError();
1713     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1714     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1715        "expected ERROR_SUCCESS, got %u\n", error);
1716 
1717     /* feature key does not exist yet */
1718     SetLastError(0xdeadbeef);
1719     state = MsiQueryFeatureStateA(prodcode, "feature");
1720     error = GetLastError();
1721     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1722     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1723        "expected ERROR_SUCCESS, got %u\n", error);
1724 
1725     /* MSIINSTALLCONTEXT_USERUNMANAGED */
1726 
1727     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Features\\");
1728     lstrcatA(keypath, prod_squashed);
1729 
1730     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
1731     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1732 
1733     /* feature key exists */
1734     SetLastError(0xdeadbeef);
1735     state = MsiQueryFeatureStateA(prodcode, "feature");
1736     error = GetLastError();
1737     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1738     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1739        "expected ERROR_SUCCESS, got %u\n", error);
1740 
1741     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 2);
1742     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1743 
1744     /* feature value exists */
1745     SetLastError(0xdeadbeef);
1746     state = MsiQueryFeatureStateA(prodcode, "feature");
1747     error = GetLastError();
1748     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1749     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1750        "expected ERROR_SUCCESS, got %u\n", error);
1751 
1752     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1753     lstrcatA(keypath, usersid);
1754     lstrcatA(keypath, "\\Products\\");
1755     lstrcatA(keypath, prod_squashed);
1756     lstrcatA(keypath, "\\Features");
1757 
1758     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1759     if (res == ERROR_ACCESS_DENIED)
1760     {
1761         skip("Not enough rights to perform tests\n");
1762         RegDeleteKeyA(userkey, "");
1763         RegCloseKey(userkey);
1764         LocalFree(usersid);
1765         return;
1766     }
1767     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1768 
1769     /* userdata features key exists */
1770     SetLastError(0xdeadbeef);
1771     state = MsiQueryFeatureStateA(prodcode, "feature");
1772     error = GetLastError();
1773     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1774     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1775        "expected ERROR_SUCCESS, got %u\n", error);
1776 
1777     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
1778     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1779 
1780     SetLastError(0xdeadbeef);
1781     state = MsiQueryFeatureStateA(prodcode, "feature");
1782     error = GetLastError();
1783     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
1784     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1785        "expected ERROR_SUCCESS, got %u\n", error);
1786 
1787     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
1788     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1789 
1790     SetLastError(0xdeadbeef);
1791     state = MsiQueryFeatureStateA(prodcode, "feature");
1792     error = GetLastError();
1793     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1794     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1795        "expected ERROR_SUCCESS, got %u\n", error);
1796 
1797     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
1798     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1799 
1800     SetLastError(0xdeadbeef);
1801     state = MsiQueryFeatureStateA(prodcode, "feature");
1802     error = GetLastError();
1803     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1804     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1805        "expected ERROR_SUCCESS, got %u\n", error);
1806 
1807     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
1808     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1809 
1810     SetLastError(0xdeadbeef);
1811     state = MsiQueryFeatureStateA(prodcode, "feature");
1812     error = GetLastError();
1813     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1814     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1815        "expected ERROR_SUCCESS, got %u\n", error);
1816 
1817     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1818     lstrcatA(keypath, usersid);
1819     lstrcatA(keypath, "\\Components\\");
1820     lstrcatA(keypath, comp_squashed);
1821 
1822     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
1823     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1824 
1825     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1826     lstrcatA(keypath, usersid);
1827     lstrcatA(keypath, "\\Components\\");
1828     lstrcatA(keypath, comp_squashed2);
1829 
1830     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
1831     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1832 
1833     SetLastError(0xdeadbeef);
1834     state = MsiQueryFeatureStateA(prodcode, "feature");
1835     error = GetLastError();
1836     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1837     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1838        "expected ERROR_SUCCESS, got %u\n", error);
1839 
1840     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
1841     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1842 
1843     SetLastError(0xdeadbeef);
1844     state = MsiQueryFeatureStateA(prodcode, "feature");
1845     error = GetLastError();
1846     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1847     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1848        "expected ERROR_SUCCESS, got %u\n", error);
1849 
1850     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
1851     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1852 
1853     SetLastError(0xdeadbeef);
1854     state = MsiQueryFeatureStateA(prodcode, "feature");
1855     error = GetLastError();
1856     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1857     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1858        "expected ERROR_SUCCESS, got %u\n", error);
1859 
1860     res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
1861     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1862 
1863     /* INSTALLSTATE_LOCAL */
1864     SetLastError(0xdeadbeef);
1865     state = MsiQueryFeatureStateA(prodcode, "feature");
1866     error = GetLastError();
1867     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1868     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1869        "expected ERROR_SUCCESS, got %u\n", error);
1870 
1871     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01\\", 4);
1872     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1873 
1874     /* INSTALLSTATE_SOURCE */
1875     SetLastError(0xdeadbeef);
1876     state = MsiQueryFeatureStateA(prodcode, "feature");
1877     error = GetLastError();
1878     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
1879     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1880        "expected ERROR_SUCCESS, got %u\n", error);
1881 
1882     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
1883     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1884 
1885     /* bad INSTALLSTATE_SOURCE */
1886     SetLastError(0xdeadbeef);
1887     state = MsiQueryFeatureStateA(prodcode, "feature");
1888     error = GetLastError();
1889     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1890     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1891        "expected ERROR_SUCCESS, got %u\n", error);
1892 
1893     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01a", 4);
1894     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1895 
1896     /* INSTALLSTATE_SOURCE */
1897     SetLastError(0xdeadbeef);
1898     state = MsiQueryFeatureStateA(prodcode, "feature");
1899     error = GetLastError();
1900     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
1901     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1902        "expected ERROR_SUCCESS, got %u\n", error);
1903 
1904     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
1905     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1906 
1907     /* bad INSTALLSTATE_SOURCE */
1908     SetLastError(0xdeadbeef);
1909     state = MsiQueryFeatureStateA(prodcode, "feature");
1910     error = GetLastError();
1911     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1912     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1913        "expected ERROR_SUCCESS, got %u\n", error);
1914 
1915     RegDeleteValueA(compkey, prod_squashed);
1916     RegDeleteValueA(compkey2, prod_squashed);
1917     delete_key(compkey, "", access & KEY_WOW64_64KEY);
1918     delete_key(compkey2, "", access & KEY_WOW64_64KEY);
1919     RegDeleteValueA(localkey, "feature");
1920     RegDeleteValueA(userkey, "feature");
1921     RegDeleteKeyA(userkey, "");
1922     RegCloseKey(compkey);
1923     RegCloseKey(compkey2);
1924     RegCloseKey(localkey);
1925     RegCloseKey(userkey);
1926 
1927     /* MSIINSTALLCONTEXT_USERMANAGED */
1928 
1929     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
1930     lstrcatA(keypath, usersid);
1931     lstrcatA(keypath, "\\Installer\\Features\\");
1932     lstrcatA(keypath, prod_squashed);
1933 
1934     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
1935     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1936 
1937     /* feature key exists */
1938     state = MsiQueryFeatureStateA(prodcode, "feature");
1939     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1940 
1941     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 1);
1942     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1943 
1944     /* feature value exists */
1945     state = MsiQueryFeatureStateA(prodcode, "feature");
1946     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1947 
1948     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1949     lstrcatA(keypath, usersid);
1950     lstrcatA(keypath, "\\Products\\");
1951     lstrcatA(keypath, prod_squashed);
1952     lstrcatA(keypath, "\\Features");
1953 
1954     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1955     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1956 
1957     /* userdata features key exists */
1958     state = MsiQueryFeatureStateA(prodcode, "feature");
1959     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1960 
1961     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
1962     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1963 
1964     state = MsiQueryFeatureStateA(prodcode, "feature");
1965     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
1966 
1967     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
1968     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1969 
1970     state = MsiQueryFeatureStateA(prodcode, "feature");
1971     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1972 
1973     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
1974     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1975 
1976     state = MsiQueryFeatureStateA(prodcode, "feature");
1977     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1978 
1979     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
1980     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1981 
1982     state = MsiQueryFeatureStateA(prodcode, "feature");
1983     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1984 
1985     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1986     lstrcatA(keypath, usersid);
1987     lstrcatA(keypath, "\\Components\\");
1988     lstrcatA(keypath, comp_squashed);
1989 
1990     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
1991     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1992 
1993     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1994     lstrcatA(keypath, usersid);
1995     lstrcatA(keypath, "\\Components\\");
1996     lstrcatA(keypath, comp_squashed2);
1997 
1998     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
1999     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2000 
2001     state = MsiQueryFeatureStateA(prodcode, "feature");
2002     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2003 
2004     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
2005     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2006 
2007     state = MsiQueryFeatureStateA(prodcode, "feature");
2008     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2009 
2010     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
2011     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2012 
2013     state = MsiQueryFeatureStateA(prodcode, "feature");
2014     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2015 
2016     res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
2017     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2018 
2019     state = MsiQueryFeatureStateA(prodcode, "feature");
2020     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2021 
2022     RegDeleteValueA(compkey, prod_squashed);
2023     RegDeleteValueA(compkey2, prod_squashed);
2024     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2025     delete_key(compkey2, "", access & KEY_WOW64_64KEY);
2026     RegDeleteValueA(localkey, "feature");
2027     RegDeleteValueA(userkey, "feature");
2028     delete_key(userkey, "", access & KEY_WOW64_64KEY);
2029     RegCloseKey(compkey);
2030     RegCloseKey(compkey2);
2031     RegCloseKey(localkey);
2032     RegCloseKey(userkey);
2033 
2034     /* MSIINSTALLCONTEXT_MACHINE */
2035 
2036     lstrcpyA(keypath, "Software\\Classes\\Installer\\Features\\");
2037     lstrcatA(keypath, prod_squashed);
2038 
2039     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
2040     if (res == ERROR_ACCESS_DENIED)
2041     {
2042         skip( "insufficient rights\n" );
2043         LocalFree( usersid );
2044         return;
2045     }
2046     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2047 
2048     /* feature key exists */
2049     state = MsiQueryFeatureStateA(prodcode, "feature");
2050     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2051 
2052     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 1);
2053     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2054 
2055     /* feature value exists */
2056     state = MsiQueryFeatureStateA(prodcode, "feature");
2057     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2058 
2059     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2060     lstrcatA(keypath, "S-1-5-18\\Products\\");
2061     lstrcatA(keypath, prod_squashed);
2062     lstrcatA(keypath, "\\Features");
2063 
2064     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
2065     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2066 
2067     /* userdata features key exists */
2068     state = MsiQueryFeatureStateA(prodcode, "feature");
2069     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2070 
2071     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
2072     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2073 
2074     state = MsiQueryFeatureStateA(prodcode, "feature");
2075     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
2076 
2077     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
2078     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2079 
2080     state = MsiQueryFeatureStateA(prodcode, "feature");
2081     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2082 
2083     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
2084     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2085 
2086     state = MsiQueryFeatureStateA(prodcode, "feature");
2087     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2088 
2089     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
2090     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2091 
2092     state = MsiQueryFeatureStateA(prodcode, "feature");
2093     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2094 
2095     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2096     lstrcatA(keypath, "S-1-5-18\\Components\\");
2097     lstrcatA(keypath, comp_squashed);
2098 
2099     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2100     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2101 
2102     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2103     lstrcatA(keypath, "S-1-5-18\\Components\\");
2104     lstrcatA(keypath, comp_squashed2);
2105 
2106     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
2107     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2108 
2109     state = MsiQueryFeatureStateA(prodcode, "feature");
2110     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2111 
2112     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
2113     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2114 
2115     state = MsiQueryFeatureStateA(prodcode, "feature");
2116     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2117 
2118     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
2119     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2120 
2121     state = MsiQueryFeatureStateA(prodcode, "feature");
2122     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2123 
2124     res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
2125     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2126 
2127     state = MsiQueryFeatureStateA(prodcode, "feature");
2128     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2129 
2130     RegDeleteValueA(compkey, prod_squashed);
2131     RegDeleteValueA(compkey2, prod_squashed);
2132     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2133     delete_key(compkey2, "", access & KEY_WOW64_64KEY);
2134     RegDeleteValueA(localkey, "feature");
2135     RegDeleteValueA(userkey, "feature");
2136     delete_key(userkey, "", access & KEY_WOW64_64KEY);
2137     RegCloseKey(compkey);
2138     RegCloseKey(compkey2);
2139     RegCloseKey(localkey);
2140     RegCloseKey(userkey);
2141     LocalFree(usersid);
2142 }
2143 
2144 static void test_MsiQueryComponentState(void)
2145 {
2146     HKEY compkey, prodkey;
2147     CHAR prodcode[MAX_PATH];
2148     CHAR prod_squashed[MAX_PATH];
2149     CHAR component[MAX_PATH];
2150     CHAR comp_base85[MAX_PATH];
2151     CHAR comp_squashed[MAX_PATH];
2152     CHAR keypath[MAX_PATH];
2153     INSTALLSTATE state;
2154     LPSTR usersid;
2155     LONG res;
2156     UINT r;
2157     REGSAM access = KEY_ALL_ACCESS;
2158     DWORD error;
2159 
2160     static const INSTALLSTATE MAGIC_ERROR = 0xdeadbeef;
2161 
2162     if (!pMsiQueryComponentStateA)
2163     {
2164         win_skip("MsiQueryComponentStateA not implemented\n");
2165         return;
2166     }
2167 
2168     create_test_guid(prodcode, prod_squashed);
2169     compose_base85_guid(component, comp_base85, comp_squashed);
2170     usersid = get_user_sid();
2171 
2172     if (is_wow64)
2173         access |= KEY_WOW64_64KEY;
2174 
2175     /* NULL szProductCode */
2176     state = MAGIC_ERROR;
2177     SetLastError(0xdeadbeef);
2178     r = pMsiQueryComponentStateA(NULL, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2179     error = GetLastError();
2180     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2181     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2182     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2183 
2184     /* empty szProductCode */
2185     state = MAGIC_ERROR;
2186     SetLastError(0xdeadbeef);
2187     r = pMsiQueryComponentStateA("", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2188     error = GetLastError();
2189     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2190     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2191     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2192 
2193     /* random szProductCode */
2194     state = MAGIC_ERROR;
2195     SetLastError(0xdeadbeef);
2196     r = pMsiQueryComponentStateA("random", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2197     error = GetLastError();
2198     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2199     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2200     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2201 
2202     /* GUID-length szProductCode */
2203     state = MAGIC_ERROR;
2204     SetLastError(0xdeadbeef);
2205     r = pMsiQueryComponentStateA("DJANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KDE", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2206     error = GetLastError();
2207     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2208     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2209     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2210 
2211     /* GUID-length with brackets */
2212     state = MAGIC_ERROR;
2213     SetLastError(0xdeadbeef);
2214     r = pMsiQueryComponentStateA("{JANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KD}", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2215     error = GetLastError();
2216     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2217     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2218     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2219 
2220     /* actual GUID */
2221     state = MAGIC_ERROR;
2222     SetLastError(0xdeadbeef);
2223     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2224     error = GetLastError();
2225     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2226     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2227     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2228 
2229     state = MAGIC_ERROR;
2230     SetLastError(0xdeadbeef);
2231     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2232     error = GetLastError();
2233     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2234     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2235     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2236 
2237     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
2238     lstrcatA(keypath, prod_squashed);
2239 
2240     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2241     if (res == ERROR_ACCESS_DENIED)
2242     {
2243         skip("Not enough rights to perform tests\n");
2244         LocalFree(usersid);
2245         return;
2246     }
2247     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2248 
2249     state = MAGIC_ERROR;
2250     SetLastError(0xdeadbeef);
2251     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2252     error = GetLastError();
2253     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2254     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2255     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2256 
2257     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2258     RegCloseKey(prodkey);
2259 
2260     /* create local system product key */
2261     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\");
2262     lstrcatA(keypath, prod_squashed);
2263     lstrcatA(keypath, "\\InstallProperties");
2264 
2265     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2266     if (res == ERROR_ACCESS_DENIED)
2267     {
2268         skip("Not enough rights to perform tests\n");
2269         LocalFree(usersid);
2270         return;
2271     }
2272     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2273 
2274     /* local system product key exists */
2275     state = MAGIC_ERROR;
2276     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2277     error = GetLastError();
2278     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2279     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2280     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2281 
2282     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2283     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2284 
2285     /* LocalPackage value exists */
2286     state = MAGIC_ERROR;
2287     SetLastError(0xdeadbeef);
2288     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2289     error = GetLastError();
2290     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2291     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2292     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2293 
2294     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\");
2295     lstrcatA(keypath, comp_squashed);
2296 
2297     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2298     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2299 
2300     /* component key exists */
2301     state = MAGIC_ERROR;
2302     SetLastError(0xdeadbeef);
2303     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2304     error = GetLastError();
2305     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2306     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2307     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2308 
2309     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
2310     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2311 
2312     /* component\product exists */
2313     state = MAGIC_ERROR;
2314     SetLastError(0xdeadbeef);
2315     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2316     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2317     error = GetLastError();
2318     ok(state == INSTALLSTATE_NOTUSED || state == INSTALLSTATE_LOCAL,
2319        "Expected INSTALLSTATE_NOTUSED or INSTALLSTATE_LOCAL, got %d\n", state);
2320     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2321 
2322     /* NULL component, product exists */
2323     state = MAGIC_ERROR;
2324     SetLastError(0xdeadbeef);
2325     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, NULL, &state);
2326     error = GetLastError();
2327     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2328     ok(state == MAGIC_ERROR, "Expected state not changed, got %d\n", state);
2329     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2330 
2331     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
2332     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2333 
2334     /* INSTALLSTATE_LOCAL */
2335     state = MAGIC_ERROR;
2336     SetLastError(0xdeadbeef);
2337     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2338     error = GetLastError();
2339     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2340     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2341     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2342 
2343     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01\\", 4);
2344     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2345 
2346     /* INSTALLSTATE_SOURCE */
2347     state = MAGIC_ERROR;
2348     SetLastError(0xdeadbeef);
2349     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2350     error = GetLastError();
2351     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2352     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2353     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2354 
2355     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
2356     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2357 
2358     /* bad INSTALLSTATE_SOURCE */
2359     state = MAGIC_ERROR;
2360     SetLastError(0xdeadbeef);
2361     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2362     error = GetLastError();
2363     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2364     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2365     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2366 
2367     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01a", 4);
2368     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2369 
2370     /* INSTALLSTATE_SOURCE */
2371     state = MAGIC_ERROR;
2372     SetLastError(0xdeadbeef);
2373     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2374     error = GetLastError();
2375     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2376     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2377     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2378 
2379     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01:", 4);
2380     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2381 
2382     /* registry component */
2383     state = MAGIC_ERROR;
2384     SetLastError(0xdeadbeef);
2385     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2386     error = GetLastError();
2387     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2388     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2389     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2390 
2391     RegDeleteValueA(prodkey, "LocalPackage");
2392     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2393     RegDeleteValueA(compkey, prod_squashed);
2394     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2395     RegCloseKey(prodkey);
2396     RegCloseKey(compkey);
2397 
2398     /* MSIINSTALLCONTEXT_USERUNMANAGED */
2399 
2400     state = MAGIC_ERROR;
2401     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2402     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2403     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2404 
2405     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2406     lstrcatA(keypath, prod_squashed);
2407 
2408     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
2409     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2410 
2411     state = MAGIC_ERROR;
2412     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2413     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2414     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2415 
2416     RegDeleteKeyA(prodkey, "");
2417     RegCloseKey(prodkey);
2418 
2419     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2420     lstrcatA(keypath, usersid);
2421     lstrcatA(keypath, "\\Products\\");
2422     lstrcatA(keypath, prod_squashed);
2423     lstrcatA(keypath, "\\InstallProperties");
2424 
2425     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2426     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2427 
2428     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2429     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2430 
2431     RegCloseKey(prodkey);
2432 
2433     state = MAGIC_ERROR;
2434     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2435     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2436     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2437 
2438     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2439     lstrcatA(keypath, usersid);
2440     lstrcatA(keypath, "\\Components\\");
2441     lstrcatA(keypath, comp_squashed);
2442 
2443     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2444     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2445 
2446     /* component key exists */
2447     state = MAGIC_ERROR;
2448     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2449     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2450     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2451 
2452     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
2453     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2454 
2455     /* component\product exists */
2456     state = MAGIC_ERROR;
2457     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2458     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2459     ok(state == INSTALLSTATE_NOTUSED || state == INSTALLSTATE_LOCAL,
2460        "Expected INSTALLSTATE_NOTUSED or INSTALLSTATE_LOCAL, got %d\n", state);
2461 
2462     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
2463     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2464 
2465     state = MAGIC_ERROR;
2466     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2467     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2468     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2469 
2470     /* MSIINSTALLCONTEXT_USERMANAGED */
2471 
2472     state = MAGIC_ERROR;
2473     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2474     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2475     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2476 
2477     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2478     lstrcatA(keypath, prod_squashed);
2479 
2480     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
2481     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2482 
2483     state = MAGIC_ERROR;
2484     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2485     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2486     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2487 
2488     RegDeleteKeyA(prodkey, "");
2489     RegCloseKey(prodkey);
2490 
2491     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
2492     lstrcatA(keypath, usersid);
2493     lstrcatA(keypath, "\\Installer\\Products\\");
2494     lstrcatA(keypath, prod_squashed);
2495 
2496     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2497     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2498 
2499     state = MAGIC_ERROR;
2500     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2501     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2502     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2503 
2504     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2505     RegCloseKey(prodkey);
2506 
2507     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2508     lstrcatA(keypath, usersid);
2509     lstrcatA(keypath, "\\Products\\");
2510     lstrcatA(keypath, prod_squashed);
2511     lstrcatA(keypath, "\\InstallProperties");
2512 
2513     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2514     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2515 
2516     res = RegSetValueExA(prodkey, "ManagedLocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2517     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2518 
2519     state = MAGIC_ERROR;
2520     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2521     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2522     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2523 
2524     RegDeleteValueA(prodkey, "LocalPackage");
2525     RegDeleteValueA(prodkey, "ManagedLocalPackage");
2526     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2527     RegDeleteValueA(compkey, prod_squashed);
2528     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2529     RegCloseKey(prodkey);
2530     RegCloseKey(compkey);
2531     LocalFree(usersid);
2532 }
2533 
2534 static void test_MsiGetComponentPath(void)
2535 {
2536     HKEY compkey, prodkey, installprop;
2537     CHAR prodcode[MAX_PATH];
2538     CHAR prod_squashed[MAX_PATH];
2539     CHAR component[MAX_PATH];
2540     CHAR comp_base85[MAX_PATH];
2541     CHAR comp_squashed[MAX_PATH];
2542     CHAR keypath[MAX_PATH];
2543     CHAR path[MAX_PATH];
2544     INSTALLSTATE state;
2545     LPSTR usersid;
2546     DWORD size, val;
2547     REGSAM access = KEY_ALL_ACCESS;
2548     LONG res;
2549 
2550     create_test_guid(prodcode, prod_squashed);
2551     compose_base85_guid(component, comp_base85, comp_squashed);
2552     usersid = get_user_sid();
2553 
2554     if (is_wow64)
2555         access |= KEY_WOW64_64KEY;
2556 
2557     /* NULL szProduct */
2558     size = MAX_PATH;
2559     state = MsiGetComponentPathA(NULL, component, path, &size);
2560     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2561     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2562 
2563     /* NULL szComponent */
2564     size = MAX_PATH;
2565     state = MsiGetComponentPathA(prodcode, NULL, path, &size);
2566     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2567     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2568 
2569     size = MAX_PATH;
2570     state = MsiLocateComponentA(NULL, path, &size);
2571     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2572     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2573 
2574     /* NULL lpPathBuf */
2575     size = MAX_PATH;
2576     state = MsiGetComponentPathA(prodcode, component, NULL, &size);
2577     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2578     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2579 
2580     size = MAX_PATH;
2581     state = MsiLocateComponentA(component, NULL, &size);
2582     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2583     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2584 
2585     /* NULL pcchBuf */
2586     size = MAX_PATH;
2587     state = MsiGetComponentPathA(prodcode, component, path, NULL);
2588     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2589     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2590 
2591     size = MAX_PATH;
2592     state = MsiLocateComponentA(component, path, NULL);
2593     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2594     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2595 
2596     /* all params valid */
2597     size = MAX_PATH;
2598     state = MsiGetComponentPathA(prodcode, component, path, &size);
2599     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2600     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2601 
2602     size = MAX_PATH;
2603     state = MsiLocateComponentA(component, path, &size);
2604     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2605     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2606 
2607     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2608     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
2609     lstrcatA(keypath, comp_squashed);
2610 
2611     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2612     if (res == ERROR_ACCESS_DENIED)
2613     {
2614         skip("Not enough rights to perform tests\n");
2615         LocalFree(usersid);
2616         return;
2617     }
2618     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2619 
2620     /* local system component key exists */
2621     size = MAX_PATH;
2622     state = MsiGetComponentPathA(prodcode, component, path, &size);
2623     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2624     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2625 
2626     size = MAX_PATH;
2627     state = MsiLocateComponentA(component, path, &size);
2628     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2629     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2630 
2631     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2632     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2633 
2634     /* product value exists */
2635     path[0] = 0;
2636     size = MAX_PATH;
2637     state = MsiGetComponentPathA(prodcode, component, path, &size);
2638     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2639     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2640     ok(size == 10, "Expected 10, got %d\n", size);
2641 
2642     path[0] = 0;
2643     size = MAX_PATH;
2644     state = MsiLocateComponentA(component, path, &size);
2645     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2646     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2647     ok(size == 10, "Expected 10, got %d\n", size);
2648 
2649     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2650     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
2651     lstrcatA(keypath, prod_squashed);
2652     lstrcatA(keypath, "\\InstallProperties");
2653 
2654     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &installprop, NULL);
2655     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2656 
2657     val = 1;
2658     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
2659     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2660 
2661     /* install properties key exists */
2662     path[0] = 0;
2663     size = MAX_PATH;
2664     state = MsiGetComponentPathA(prodcode, component, path, &size);
2665     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2666     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2667     ok(size == 10, "Expected 10, got %d\n", size);
2668 
2669     path[0] = 0;
2670     size = MAX_PATH;
2671     state = MsiLocateComponentA(component, path, &size);
2672     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2673     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2674     ok(size == 10, "Expected 10, got %d\n", size);
2675 
2676     create_file("C:\\imapath", 11);
2677 
2678     /* file exists */
2679     path[0] = 'a';
2680     size = 0;
2681     state = MsiGetComponentPathA(prodcode, component, path, &size);
2682     ok(state == INSTALLSTATE_MOREDATA, "Expected INSTALLSTATE_MOREDATA, got %d\n", state);
2683     ok(path[0] == 'a', "got %s\n", path);
2684     ok(size == 10, "Expected 10, got %d\n", size);
2685 
2686     path[0] = 0;
2687     size = MAX_PATH;
2688     state = MsiGetComponentPathA(prodcode, component, path, &size);
2689     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2690     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2691     ok(size == 10, "Expected 10, got %d\n", size);
2692 
2693     size = 0;
2694     path[0] = 'a';
2695     state = MsiLocateComponentA(component, path, &size);
2696     ok(state == INSTALLSTATE_MOREDATA, "Expected INSTALLSTATE_MOREDATA, got %d\n", state);
2697     ok(path[0] == 'a', "got %s\n", path);
2698     ok(size == 10, "Expected 10, got %d\n", size);
2699 
2700     path[0] = 0;
2701     size = MAX_PATH;
2702     state = MsiLocateComponentA(component, path, &size);
2703     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2704     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2705     ok(size == 10, "Expected 10, got %d\n", size);
2706 
2707     RegDeleteValueA(compkey, prod_squashed);
2708     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2709     RegDeleteValueA(installprop, "WindowsInstaller");
2710     delete_key(installprop, "", access & KEY_WOW64_64KEY);
2711     RegCloseKey(compkey);
2712     RegCloseKey(installprop);
2713     DeleteFileA("C:\\imapath");
2714 
2715     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2716     lstrcatA(keypath, "Installer\\UserData\\");
2717     lstrcatA(keypath, usersid);
2718     lstrcatA(keypath, "\\Components\\");
2719     lstrcatA(keypath, comp_squashed);
2720 
2721     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2722     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2723 
2724     /* user managed component key exists */
2725     size = MAX_PATH;
2726     state = MsiGetComponentPathA(prodcode, component, path, &size);
2727     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2728     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2729 
2730     size = MAX_PATH;
2731     state = MsiLocateComponentA(component, path, &size);
2732     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2733     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2734 
2735     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2736     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2737 
2738     /* product value exists */
2739     path[0] = 0;
2740     size = MAX_PATH;
2741     state = MsiGetComponentPathA(prodcode, component, path, &size);
2742     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2743     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2744     ok(size == 10, "Expected 10, got %d\n", size);
2745 
2746     path[0] = 0;
2747     size = MAX_PATH;
2748     state = MsiLocateComponentA(component, path, &size);
2749     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2750     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2751     ok(size == 10, "Expected 10, got %d\n", size);
2752 
2753     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2754     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
2755     lstrcatA(keypath, prod_squashed);
2756     lstrcatA(keypath, "\\InstallProperties");
2757 
2758     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &installprop, NULL);
2759     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2760 
2761     val = 1;
2762     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
2763     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2764 
2765     /* install properties key exists */
2766     path[0] = 0;
2767     size = MAX_PATH;
2768     state = MsiGetComponentPathA(prodcode, component, path, &size);
2769     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2770     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2771     ok(size == 10, "Expected 10, got %d\n", size);
2772 
2773     path[0] = 0;
2774     size = MAX_PATH;
2775     state = MsiLocateComponentA(component, path, &size);
2776     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2777     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2778     ok(size == 10, "Expected 10, got %d\n", size);
2779 
2780     create_file("C:\\imapath", 11);
2781 
2782     /* file exists */
2783     path[0] = 0;
2784     size = MAX_PATH;
2785     state = MsiGetComponentPathA(prodcode, component, path, &size);
2786     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2787     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2788     ok(size == 10, "Expected 10, got %d\n", size);
2789 
2790     path[0] = 0;
2791     size = MAX_PATH;
2792     state = MsiLocateComponentA(component, path, &size);
2793     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2794     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2795     ok(size == 10, "Expected 10, got %d\n", size);
2796 
2797     RegDeleteValueA(compkey, prod_squashed);
2798     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2799     RegDeleteValueA(installprop, "WindowsInstaller");
2800     delete_key(installprop, "", access & KEY_WOW64_64KEY);
2801     RegCloseKey(compkey);
2802     RegCloseKey(installprop);
2803     DeleteFileA("C:\\imapath");
2804 
2805     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2806     lstrcatA(keypath, "Installer\\Managed\\");
2807     lstrcatA(keypath, usersid);
2808     lstrcatA(keypath, "\\Installer\\Products\\");
2809     lstrcatA(keypath, prod_squashed);
2810 
2811     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2812     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2813 
2814     /* user managed product key exists */
2815     size = MAX_PATH;
2816     state = MsiGetComponentPathA(prodcode, component, path, &size);
2817     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2818     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2819 
2820     size = MAX_PATH;
2821     state = MsiLocateComponentA(component, path, &size);
2822     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2823     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2824 
2825     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2826     lstrcatA(keypath, "Installer\\UserData\\");
2827     lstrcatA(keypath, usersid);
2828     lstrcatA(keypath, "\\Components\\");
2829     lstrcatA(keypath, comp_squashed);
2830 
2831     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2832     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2833 
2834     /* user managed component key exists */
2835     size = MAX_PATH;
2836     state = MsiGetComponentPathA(prodcode, component, path, &size);
2837     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2838     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2839 
2840     size = MAX_PATH;
2841     state = MsiLocateComponentA(component, path, &size);
2842     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2843     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2844 
2845     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2846     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2847 
2848     /* product value exists */
2849     path[0] = 0;
2850     size = MAX_PATH;
2851     state = MsiGetComponentPathA(prodcode, component, path, &size);
2852     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2853     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2854     ok(size == 10, "Expected 10, got %d\n", size);
2855 
2856     path[0] = 0;
2857     size = MAX_PATH;
2858     state = MsiLocateComponentA(component, path, &size);
2859     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2860     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2861     ok(size == 10, "Expected 10, got %d\n", size);
2862 
2863     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2864     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
2865     lstrcatA(keypath, prod_squashed);
2866     lstrcatA(keypath, "\\InstallProperties");
2867 
2868     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &installprop, NULL);
2869     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2870 
2871     val = 1;
2872     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
2873     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2874 
2875     /* install properties key exists */
2876     path[0] = 0;
2877     size = MAX_PATH;
2878     state = MsiGetComponentPathA(prodcode, component, path, &size);
2879     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2880     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2881     ok(size == 10, "Expected 10, got %d\n", size);
2882 
2883     path[0] = 0;
2884     size = MAX_PATH;
2885     state = MsiLocateComponentA(component, path, &size);
2886     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2887     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2888     ok(size == 10, "Expected 10, got %d\n", size);
2889 
2890     create_file("C:\\imapath", 11);
2891 
2892     /* file exists */
2893     path[0] = 0;
2894     size = MAX_PATH;
2895     state = MsiGetComponentPathA(prodcode, component, path, &size);
2896     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2897     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2898     ok(size == 10, "Expected 10, got %d\n", size);
2899 
2900     path[0] = 0;
2901     size = MAX_PATH;
2902     state = MsiLocateComponentA(component, path, &size);
2903     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2904     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2905     ok(size == 10, "Expected 10, got %d\n", size);
2906 
2907     RegDeleteValueA(compkey, prod_squashed);
2908     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2909     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2910     RegDeleteValueA(installprop, "WindowsInstaller");
2911     delete_key(installprop, "", access & KEY_WOW64_64KEY);
2912     RegCloseKey(prodkey);
2913     RegCloseKey(compkey);
2914     RegCloseKey(installprop);
2915     DeleteFileA("C:\\imapath");
2916 
2917     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2918     lstrcatA(keypath, prod_squashed);
2919 
2920     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
2921     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2922 
2923     /* user unmanaged product key exists */
2924     size = MAX_PATH;
2925     state = MsiGetComponentPathA(prodcode, component, path, &size);
2926     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2927     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2928 
2929     size = MAX_PATH;
2930     state = MsiLocateComponentA(component, path, &size);
2931     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2932     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2933 
2934     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2935     lstrcatA(keypath, "Installer\\UserData\\");
2936     lstrcatA(keypath, usersid);
2937     lstrcatA(keypath, "\\Components\\");
2938     lstrcatA(keypath, comp_squashed);
2939 
2940     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2941     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2942 
2943     /* user unmanaged component key exists */
2944     size = MAX_PATH;
2945     state = MsiGetComponentPathA(prodcode, component, path, &size);
2946     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2947     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2948 
2949     size = MAX_PATH;
2950     state = MsiLocateComponentA(component, path, &size);
2951     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2952     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2953 
2954     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2955     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2956 
2957     /* product value exists */
2958     path[0] = 0;
2959     size = MAX_PATH;
2960     state = MsiGetComponentPathA(prodcode, component, path, &size);
2961     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2962     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2963     ok(size == 10, "Expected 10, got %d\n", size);
2964 
2965     path[0] = 0;
2966     size = MAX_PATH;
2967     state = MsiLocateComponentA(component, path, &size);
2968     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2969     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2970     ok(size == 10, "Expected 10, got %d\n", size);
2971 
2972     create_file("C:\\imapath", 11);
2973 
2974     /* file exists */
2975     path[0] = 0;
2976     size = MAX_PATH;
2977     state = MsiGetComponentPathA(prodcode, component, path, &size);
2978     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2979     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2980     ok(size == 10, "Expected 10, got %d\n", size);
2981 
2982     path[0] = 0;
2983     size = MAX_PATH;
2984     state = MsiLocateComponentA(component, path, &size);
2985     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2986     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2987     ok(size == 10, "Expected 10, got %d\n", size);
2988 
2989     RegDeleteValueA(compkey, prod_squashed);
2990     RegDeleteKeyA(prodkey, "");
2991     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2992     RegCloseKey(prodkey);
2993     RegCloseKey(compkey);
2994     DeleteFileA("C:\\imapath");
2995 
2996     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
2997     lstrcatA(keypath, prod_squashed);
2998 
2999     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3000     if (res == ERROR_ACCESS_DENIED)
3001     {
3002         skip( "insufficient rights\n" );
3003         LocalFree( usersid );
3004         return;
3005     }
3006     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3007 
3008     /* local classes product key exists */
3009     size = MAX_PATH;
3010     state = MsiGetComponentPathA(prodcode, component, path, &size);
3011     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3012     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3013 
3014     size = MAX_PATH;
3015     state = MsiLocateComponentA(component, path, &size);
3016     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3017     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3018 
3019     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3020     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
3021     lstrcatA(keypath, comp_squashed);
3022 
3023     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3024     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3025 
3026     /* local user component key exists */
3027     size = MAX_PATH;
3028     state = MsiGetComponentPathA(prodcode, component, path, &size);
3029     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3030     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3031 
3032     size = MAX_PATH;
3033     state = MsiLocateComponentA(component, path, &size);
3034     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3035     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3036 
3037     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3038     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3039 
3040     /* product value exists */
3041     path[0] = 0;
3042     size = MAX_PATH;
3043     state = MsiGetComponentPathA(prodcode, component, path, &size);
3044     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3045     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3046     ok(size == 10, "Expected 10, got %d\n", size);
3047 
3048     path[0] = 0;
3049     size = MAX_PATH;
3050     state = MsiLocateComponentA(component, path, &size);
3051     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3052     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3053     ok(size == 10, "Expected 10, got %d\n", size);
3054 
3055     create_file("C:\\imapath", 11);
3056 
3057     /* file exists */
3058     path[0] = 0;
3059     size = MAX_PATH;
3060     state = MsiGetComponentPathA(prodcode, component, path, &size);
3061     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3062     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3063     ok(size == 10, "Expected 10, got %d\n", size);
3064 
3065     path[0] = 0;
3066     size = MAX_PATH;
3067     state = MsiLocateComponentA(component, path, &size);
3068     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3069     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3070     ok(size == 10, "Expected 10, got %d\n", size);
3071 
3072     RegDeleteValueA(compkey, prod_squashed);
3073     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3074     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3075     RegCloseKey(prodkey);
3076     RegCloseKey(compkey);
3077     DeleteFileA("C:\\imapath");
3078     LocalFree(usersid);
3079 }
3080 
3081 static void test_MsiGetComponentPathEx(void)
3082 {
3083     HKEY key_comp, key_installprop, key_prod;
3084     char prod[MAX_PATH], prod_squashed[MAX_PATH];
3085     char comp[MAX_PATH], comp_base85[MAX_PATH], comp_squashed[MAX_PATH];
3086     char path[MAX_PATH], path_key[MAX_PATH], *usersid;
3087     INSTALLSTATE state;
3088     DWORD size, val;
3089     REGSAM access = KEY_ALL_ACCESS;
3090     LONG res;
3091 
3092     if (!pMsiGetComponentPathExA)
3093     {
3094         win_skip( "MsiGetComponentPathExA not present\n" );
3095         return;
3096     }
3097 
3098     if (is_wow64) access |= KEY_WOW64_64KEY;
3099 
3100     create_test_guid( prod, prod_squashed );
3101     compose_base85_guid( comp, comp_base85, comp_squashed );
3102     usersid = get_user_sid();
3103 
3104     /* NULL product */
3105     size = MAX_PATH;
3106     state = pMsiGetComponentPathExA( NULL, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3107     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
3108     todo_wine ok( !size, "got %u\n", size );
3109 
3110     /* NULL component */
3111     size = MAX_PATH;
3112     state = pMsiGetComponentPathExA( prod, NULL, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3113     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
3114     todo_wine ok( !size, "got %u\n", size );
3115 
3116     /* non-NULL usersid, MSIINSTALLCONTEXT_MACHINE */
3117     size = MAX_PATH;
3118     state = pMsiGetComponentPathExA( prod, comp, usersid, MSIINSTALLCONTEXT_MACHINE, path, &size);
3119     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
3120     todo_wine ok( !size, "got %u\n", size );
3121 
3122     /* NULL buf */
3123     size = MAX_PATH;
3124     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, NULL, &size );
3125     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3126     todo_wine ok( size == MAX_PATH * 2, "got %u\n", size );
3127 
3128     /* NULL buflen */
3129     size = MAX_PATH;
3130     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, NULL );
3131     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
3132     ok( size == MAX_PATH, "got %u\n", size );
3133 
3134     /* all params valid */
3135     size = MAX_PATH;
3136     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3137     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3138     todo_wine ok( !size, "got %u\n", size );
3139 
3140     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3141     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Components\\" );
3142     lstrcatA( path_key, comp_squashed );
3143 
3144     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3145     if (res == ERROR_ACCESS_DENIED)
3146     {
3147         skip( "insufficient rights\n" );
3148         LocalFree( usersid );
3149         return;
3150     }
3151     ok( res == ERROR_SUCCESS, "got %d\n", res );
3152 
3153     /* local system component key exists */
3154     size = MAX_PATH;
3155     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3156     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3157 
3158     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3159     ok( res == ERROR_SUCCESS, "got %d\n", res );
3160 
3161     /* product value exists */
3162     path[0] = 0;
3163     size = MAX_PATH;
3164     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3165     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3166     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3167     ok( size == 20, "got %u\n", size );
3168 
3169     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3170     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Products\\" );
3171     lstrcatA( path_key, prod_squashed );
3172     lstrcatA( path_key, "\\InstallProperties" );
3173 
3174     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_installprop, NULL );
3175     ok( res == ERROR_SUCCESS, "got %d\n", res );
3176 
3177     val = 1;
3178     res = RegSetValueExA( key_installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(val) );
3179     ok( res == ERROR_SUCCESS, "got %d\n", res );
3180 
3181     /* install properties key exists */
3182     path[0] = 0;
3183     size = MAX_PATH;
3184     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3185     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3186     ok( !lstrcmpA( path, "c:\\testcomponentpath"), "got %s\n", path );
3187     ok( size == 20, "got %u\n", size );
3188 
3189     create_file( "c:\\testcomponentpath", 21 );
3190 
3191     /* file exists */
3192     path[0] = 0;
3193     size = 0;
3194     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3195     ok( state == INSTALLSTATE_MOREDATA, "got %d\n", state );
3196     ok( !path[0], "got %s\n", path );
3197     todo_wine ok( size == 40, "got %u\n", size );
3198 
3199     path[0] = 0;
3200     size = MAX_PATH;
3201     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3202     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3203     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3204     ok( size == 20, "got %d\n", size );
3205 
3206     RegDeleteValueA( key_comp, prod_squashed );
3207     delete_key( key_comp, "", access & KEY_WOW64_64KEY );
3208     RegDeleteValueA( key_installprop, "WindowsInstaller" );
3209     delete_key( key_installprop, "", access & KEY_WOW64_64KEY );
3210     RegCloseKey( key_comp );
3211     RegCloseKey( key_installprop );
3212     DeleteFileA( "c:\\testcomponentpath" );
3213 
3214     lstrcpyA( path_key, "Software\\Microsoft\\Installer\\Products\\" );
3215     lstrcatA( path_key, prod_squashed );
3216 
3217     res = RegCreateKeyA( HKEY_CURRENT_USER, path_key, &key_prod );
3218     ok( res == ERROR_SUCCESS, "got %d\n", res );
3219 
3220     /* user unmanaged product key exists */
3221     size = MAX_PATH;
3222     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3223     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3224     todo_wine ok(!size, "got %u\n", size);
3225 
3226     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3227     lstrcatA( path_key, "Installer\\UserData\\" );
3228     lstrcatA( path_key, usersid );
3229     lstrcatA( path_key, "\\Components\\" );
3230     lstrcatA( path_key, comp_squashed );
3231 
3232     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3233     ok( res == ERROR_SUCCESS, "got %d\n", res );
3234 
3235     /* user unmanaged component key exists */
3236     size = MAX_PATH;
3237     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3238     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3239     todo_wine ok(!size, "got %u\n", size);
3240 
3241     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3242     ok( res == ERROR_SUCCESS, "got %d\n", res );
3243 
3244     /* product value exists */
3245     path[0] = 0;
3246     size = MAX_PATH;
3247     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3248     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3249     ok( !lstrcmpA( path, "c:\\testcomponentpath"), "got %s\n", path );
3250     ok( size == 20, "got %u\n", size );
3251 
3252     create_file( "c:\\testcomponentpath", 21 );
3253 
3254     /* file exists */
3255     path[0] = 0;
3256     size = MAX_PATH;
3257     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3258     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3259     ok( !lstrcmpA( path, "c:\\testcomponentpath"), "got %s\n", path );
3260     ok( size == 20, "got %u\n", size );
3261 
3262     RegDeleteValueA( key_comp, prod_squashed );
3263     RegDeleteKeyA( key_prod, "" );
3264     delete_key( key_comp, "", access & KEY_WOW64_64KEY );
3265     RegCloseKey( key_prod );
3266     RegCloseKey( key_comp );
3267     DeleteFileA( "c:\\testcomponentpath" );
3268 
3269     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3270     lstrcatA( path_key, "Installer\\Managed\\" );
3271     lstrcatA( path_key, usersid );
3272     lstrcatA( path_key, "\\Installer\\Products\\" );
3273     lstrcatA( path_key, prod_squashed );
3274 
3275     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_prod, NULL );
3276     ok( res == ERROR_SUCCESS, "got %d\n", res );
3277 
3278     /* user managed product key exists */
3279     size = MAX_PATH;
3280     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3281     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3282 
3283     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3284     lstrcatA( path_key, "Installer\\UserData\\" );
3285     lstrcatA( path_key, usersid );
3286     lstrcatA( path_key, "\\Components\\" );
3287     lstrcatA( path_key, comp_squashed );
3288 
3289     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3290     ok( res == ERROR_SUCCESS, "got %d\n", res );
3291 
3292     /* user managed component key exists */
3293     size = MAX_PATH;
3294     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3295     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3296 
3297     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3298     ok( res == ERROR_SUCCESS, "got %d\n", res );
3299 
3300     /* product value exists */
3301     path[0] = 0;
3302     size = MAX_PATH;
3303     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3304     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3305     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3306     ok( size == 20, "got %u\n", size );
3307 
3308     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3309     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Products\\" );
3310     lstrcatA( path_key, prod_squashed );
3311     lstrcatA( path_key, "\\InstallProperties" );
3312 
3313     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_installprop, NULL );
3314     ok( res == ERROR_SUCCESS, "got %d\n", res );
3315 
3316     val = 1;
3317     res = RegSetValueExA( key_installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(val) );
3318     ok( res == ERROR_SUCCESS, "got %d\n", res );
3319 
3320     /* install properties key exists */
3321     path[0] = 0;
3322     size = MAX_PATH;
3323     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3324     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3325     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3326     ok( size == 20, "got %u\n", size );
3327 
3328     create_file( "c:\\testcomponentpath", 21 );
3329 
3330     /* file exists */
3331     path[0] = 0;
3332     size = MAX_PATH;
3333     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3334     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3335     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3336     ok( size == 20, "got %u\n", size );
3337 
3338     RegDeleteValueA( key_comp, prod_squashed );
3339     delete_key( key_prod, "", access & KEY_WOW64_64KEY );
3340     delete_key( key_comp, "", access & KEY_WOW64_64KEY );
3341     RegDeleteValueA( key_installprop, "WindowsInstaller" );
3342     delete_key( key_installprop, "", access & KEY_WOW64_64KEY );
3343     RegCloseKey( key_prod );
3344     RegCloseKey( key_comp );
3345     RegCloseKey( key_installprop );
3346     DeleteFileA( "c:\\testcomponentpath" );
3347     lstrcpyA( path_key, "Software\\Classes\\Installer\\Products\\" );
3348     lstrcatA( path_key, prod_squashed );
3349 
3350     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_prod, NULL );
3351     if (res == ERROR_ACCESS_DENIED)
3352     {
3353         skip( "insufficient rights\n" );
3354         LocalFree( usersid );
3355         return;
3356     }
3357     ok( res == ERROR_SUCCESS, "got %d\n", res );
3358 
3359     /* local classes product key exists */
3360     size = MAX_PATH;
3361     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3362     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3363     todo_wine ok(!size, "got %u\n", size);
3364 
3365     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3366     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Components\\" );
3367     lstrcatA( path_key, comp_squashed );
3368 
3369     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE,  path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3370     ok( res == ERROR_SUCCESS, "got %d\n", res );
3371 
3372     /* local user component key exists */
3373     size = MAX_PATH;
3374     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3375     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3376     todo_wine ok(!size, "got %u\n", size);
3377 
3378     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3379     ok( res == ERROR_SUCCESS, "got %d\n", res );
3380 
3381     /* product value exists */
3382     path[0] = 0;
3383     size = MAX_PATH;
3384     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3385     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3386     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3387     ok( size == 20, "got %u\n", size );
3388 
3389     create_file( "c:\\testcomponentpath", 21 );
3390 
3391     /* file exists */
3392     path[0] = 0;
3393     size = MAX_PATH;
3394     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3395     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3396     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3397     ok( size == 20, "got %u\n", size );
3398 
3399     RegDeleteValueA( key_comp, prod_squashed );
3400     delete_key( key_prod, "", access & KEY_WOW64_64KEY );
3401     delete_key( key_comp, "", access & KEY_WOW64_64KEY );
3402     RegCloseKey( key_prod );
3403     RegCloseKey( key_comp );
3404     DeleteFileA( "c:\\testcomponentpath" );
3405     LocalFree( usersid );
3406 }
3407 
3408 static void test_MsiProvideComponent(void)
3409 {
3410     static const WCHAR sourcedirW[] =
3411         {'s','o','u','r','c','e','d','i','r',0};
3412     static const WCHAR productW[] =
3413         {'{','3','8','8','4','7','3','3','8','-','1','B','B','C','-','4','1','0','4','-',
3414          '8','1','A','C','-','2','F','A','A','C','7','E','C','D','D','C','D','}',0};
3415     static const WCHAR componentW[] =
3416         {'{','D','D','4','2','2','F','9','2','-','3','E','D','8','-','4','9','B','5','-',
3417          'A','0','B','7','-','F','2','6','6','F','9','8','3','5','7','D','F','}',0};
3418     INSTALLSTATE state;
3419     char buf[0x100];
3420     WCHAR bufW[0x100];
3421     DWORD len, len2;
3422     UINT r;
3423 
3424     if (is_process_limited())
3425     {
3426         skip("process is limited\n");
3427         return;
3428     }
3429 
3430     create_test_files();
3431     create_file("msitest\\sourcedir.txt", 1000);
3432     create_database(msifile, sd_tables, ARRAY_SIZE(sd_tables));
3433 
3434     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3435 
3436     buf[0] = 0;
3437     len = sizeof(buf);
3438     r = pMsiProvideComponentA("{90120000-0070-0000-0000-4000000FF1CE}",
3439                               "{17961602-C4E2-482E-800A-DF6E627549CF}",
3440                               "ProductFiles", INSTALLMODE_NODETECTION, buf, &len);
3441     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
3442 
3443     r = MsiInstallProductA(msifile, NULL);
3444     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3445 
3446     state = MsiQueryFeatureStateA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir");
3447     ok(state == INSTALLSTATE_LOCAL, "got %d\n", state);
3448 
3449     buf[0] = 0;
3450     len = sizeof(buf);
3451     r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir",
3452                               "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
3453                               INSTALLMODE_NODETECTION, buf, &len);
3454     ok(r == ERROR_SUCCESS, "got %u\n", r);
3455     ok(buf[0], "empty path\n");
3456     ok(len == lstrlenA(buf), "got %u\n", len);
3457 
3458     len2 = 0;
3459     r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir",
3460                               "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
3461                               INSTALLMODE_NODETECTION, NULL, &len2);
3462     ok(r == ERROR_SUCCESS, "got %u\n", r);
3463     ok(len2 == len, "got %u\n", len2);
3464 
3465     len2 = 0;
3466     r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir",
3467                               "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
3468                               INSTALLMODE_NODETECTION, buf, &len2);
3469     ok(r == ERROR_MORE_DATA, "got %u\n", r);
3470     ok(len2 == len, "got %u\n", len2);
3471 
3472     /* wide version */
3473 
3474     bufW[0] = 0;
3475     len = sizeof(buf);
3476     r = pMsiProvideComponentW(productW, sourcedirW, componentW,
3477                               INSTALLMODE_NODETECTION, bufW, &len);
3478     ok(r == ERROR_SUCCESS, "got %u\n", r);
3479     ok(bufW[0], "empty path\n");
3480     ok(len == lstrlenW(bufW), "got %u\n", len);
3481 
3482     len2 = 0;
3483     r = pMsiProvideComponentW(productW, sourcedirW, componentW,
3484                               INSTALLMODE_NODETECTION, NULL, &len2);
3485     ok(r == ERROR_SUCCESS, "got %u\n", r);
3486     ok(len2 == len, "got %u\n", len2);
3487 
3488     len2 = 0;
3489     r = pMsiProvideComponentW(productW, sourcedirW, componentW,
3490                               INSTALLMODE_NODETECTION, bufW, &len2);
3491     ok(r == ERROR_MORE_DATA, "got %u\n", r);
3492     ok(len2 == len, "got %u\n", len2);
3493 
3494     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3495     ok(r == ERROR_SUCCESS, "got %u\n", r);
3496 
3497     DeleteFileA("msitest\\sourcedir.txt");
3498     delete_test_files();
3499     DeleteFileA(msifile);
3500 }
3501 
3502 static void test_MsiProvideQualifiedComponentEx(void)
3503 {
3504     UINT r;
3505     INSTALLSTATE state;
3506     char comp[39], comp_squashed[33], comp2[39], comp2_base85[21], comp2_squashed[33];
3507     char prod[39], prod_base85[21], prod_squashed[33];
3508     char desc[MAX_PATH], buf[MAX_PATH], keypath[MAX_PATH], path[MAX_PATH];
3509     DWORD len = sizeof(buf);
3510     REGSAM access = KEY_ALL_ACCESS;
3511     HKEY hkey, hkey2, hkey3, hkey4, hkey5;
3512     LONG res;
3513 
3514     if (is_process_limited())
3515     {
3516         skip( "process is limited\n" );
3517         return;
3518     }
3519 
3520     create_test_guid( comp, comp_squashed );
3521     compose_base85_guid( comp2, comp2_base85, comp2_squashed );
3522     compose_base85_guid( prod, prod_base85, prod_squashed );
3523 
3524     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3525     ok( r == ERROR_UNKNOWN_COMPONENT, "got %u\n", r );
3526 
3527     lstrcpyA( keypath, "Software\\Classes\\Installer\\Components\\" );
3528     lstrcatA( keypath, comp_squashed );
3529 
3530     if (is_wow64) access |= KEY_WOW64_64KEY;
3531     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey, NULL );
3532     ok( res == ERROR_SUCCESS, "got %d\n", res );
3533 
3534     lstrcpyA( desc, prod_base85 );
3535     memcpy( desc + lstrlenA(desc), "feature<\0", sizeof("feature<\0") );
3536     res = RegSetValueExA( hkey, "qualifier", 0, REG_MULTI_SZ, (const BYTE *)desc,
3537                           lstrlenA(prod_base85) + sizeof("feature<\0") );
3538     ok( res == ERROR_SUCCESS, "got %d\n", res );
3539 
3540     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3541     ok( r == ERROR_UNKNOWN_PRODUCT, "got %u\n", r );
3542 
3543     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, NULL, 0, 0, buf, &len );
3544     ok( r == ERROR_UNKNOWN_PRODUCT, "got %u\n", r );
3545 
3546     state = MsiQueryProductStateA( prod );
3547     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3548 
3549     lstrcpyA( keypath, "Software\\Classes\\Installer\\Products\\" );
3550     lstrcatA( keypath, prod_squashed );
3551 
3552     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey2, NULL );
3553     ok( res == ERROR_SUCCESS, "got %d\n", res );
3554 
3555     state = MsiQueryProductStateA( prod );
3556     ok( state == INSTALLSTATE_ADVERTISED, "got %d\n", state );
3557 
3558     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3559     todo_wine ok( r == ERROR_UNKNOWN_FEATURE, "got %u\n", r );
3560 
3561     lstrcpyA( keypath, "Software\\Classes\\Installer\\Features\\" );
3562     lstrcatA( keypath, prod_squashed );
3563 
3564     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey3, NULL );
3565     ok( res == ERROR_SUCCESS, "got %d\n", res );
3566 
3567     state = MsiQueryFeatureStateA( prod, "feature" );
3568     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3569 
3570     res = RegSetValueExA( hkey3, "feature", 0, REG_SZ, (const BYTE *)"", 1 );
3571     ok( res == ERROR_SUCCESS, "got %d\n", res );
3572 
3573     state = MsiQueryFeatureStateA( prod, "feature" );
3574     ok( state == INSTALLSTATE_ADVERTISED, "got %d\n", state );
3575 
3576     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3577     ok( r == ERROR_FILE_NOT_FOUND, "got %u\n", r );
3578 
3579     len = sizeof(buf);
3580     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, NULL, 0, 0, buf, &len );
3581     ok( r == ERROR_FILE_NOT_FOUND, "got %u\n", r );
3582 
3583     lstrcpyA( keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\" );
3584     lstrcatA( keypath, prod_squashed );
3585     lstrcatA( keypath, "\\Features" );
3586 
3587     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey4, NULL );
3588     ok( res == ERROR_SUCCESS, "got %d\n", res );
3589 
3590     res = RegSetValueExA( hkey4, "feature", 0, REG_SZ, (const BYTE *)comp2_base85, sizeof(comp2_base85) );
3591     ok( res == ERROR_SUCCESS, "got %d\n", res );
3592 
3593     state = MsiQueryFeatureStateA( prod, "feature" );
3594     ok( state == INSTALLSTATE_ADVERTISED, "got %d\n", state );
3595 
3596     lstrcpyA( keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\" );
3597     lstrcatA( keypath, comp2_squashed );
3598 
3599     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey5, NULL );
3600     ok( res == ERROR_SUCCESS, "got %d\n", res );
3601 
3602     res = RegSetValueExA( hkey5, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\nosuchfile", sizeof("c:\\nosuchfile") );
3603     ok( res == ERROR_SUCCESS, "got %d\n", res );
3604 
3605     state = MsiQueryFeatureStateA( prod, "feature" );
3606     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3607 
3608     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3609     ok( r == ERROR_FILE_NOT_FOUND, "got %u\n", r );
3610 
3611     GetCurrentDirectoryA( MAX_PATH, path );
3612     lstrcatA( path, "\\msitest" );
3613     CreateDirectoryA( path, NULL );
3614     lstrcatA( path, "\\test.txt" );
3615     create_file_data( path, "test", 100 );
3616 
3617     res = RegSetValueExA( hkey5, prod_squashed, 0, REG_SZ, (const BYTE *)path, lstrlenA(path) + 1 );
3618     ok( res == ERROR_SUCCESS, "got %d\n", res );
3619 
3620     buf[0] = 0;
3621     len = sizeof(buf);
3622     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3623     ok( r == ERROR_SUCCESS, "got %u\n", r );
3624     ok( len == lstrlenA(path), "got %u\n", len );
3625     ok( !lstrcmpA( path, buf ), "got '%s'\n", buf );
3626 
3627     DeleteFileA( "msitest\\text.txt" );
3628     RemoveDirectoryA( "msitest" );
3629 
3630     delete_key( hkey5, "", access & KEY_WOW64_64KEY );
3631     RegCloseKey( hkey5 );
3632     delete_key( hkey4, "", access & KEY_WOW64_64KEY );
3633     RegCloseKey( hkey4 );
3634     delete_key( hkey3, "", access & KEY_WOW64_64KEY );
3635     RegCloseKey( hkey3 );
3636     delete_key( hkey2, "", access & KEY_WOW64_64KEY );
3637     RegCloseKey( hkey2 );
3638     delete_key( hkey, "", access & KEY_WOW64_64KEY );
3639     RegCloseKey( hkey );
3640 }
3641 
3642 static void test_MsiGetProductCode(void)
3643 {
3644     HKEY compkey, prodkey;
3645     CHAR prodcode[MAX_PATH];
3646     CHAR prod_squashed[MAX_PATH];
3647     CHAR prodcode2[MAX_PATH];
3648     CHAR prod2_squashed[MAX_PATH];
3649     CHAR component[MAX_PATH];
3650     CHAR comp_base85[MAX_PATH];
3651     CHAR comp_squashed[MAX_PATH];
3652     CHAR keypath[MAX_PATH];
3653     CHAR product[MAX_PATH];
3654     LPSTR usersid;
3655     LONG res;
3656     UINT r;
3657     REGSAM access = KEY_ALL_ACCESS;
3658 
3659     create_test_guid(prodcode, prod_squashed);
3660     create_test_guid(prodcode2, prod2_squashed);
3661     compose_base85_guid(component, comp_base85, comp_squashed);
3662     usersid = get_user_sid();
3663 
3664     if (is_wow64)
3665         access |= KEY_WOW64_64KEY;
3666 
3667     /* szComponent is NULL */
3668     lstrcpyA(product, "prod");
3669     r = MsiGetProductCodeA(NULL, product);
3670     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3671     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3672 
3673     /* szComponent is empty */
3674     lstrcpyA(product, "prod");
3675     r = MsiGetProductCodeA("", product);
3676     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3677     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3678 
3679     /* garbage szComponent */
3680     lstrcpyA(product, "prod");
3681     r = MsiGetProductCodeA("garbage", product);
3682     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3683     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3684 
3685     /* guid without brackets */
3686     lstrcpyA(product, "prod");
3687     r = MsiGetProductCodeA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", product);
3688     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3689     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3690 
3691     /* guid with brackets */
3692     lstrcpyA(product, "prod");
3693     r = MsiGetProductCodeA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", product);
3694     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3695     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3696 
3697     /* same length as guid, but random */
3698     lstrcpyA(product, "prod");
3699     r = MsiGetProductCodeA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", product);
3700     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3701     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3702 
3703     /* all params correct, szComponent not published */
3704     lstrcpyA(product, "prod");
3705     r = MsiGetProductCodeA(component, product);
3706     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3707     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3708 
3709     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3710     lstrcatA(keypath, "Installer\\UserData\\");
3711     lstrcatA(keypath, usersid);
3712     lstrcatA(keypath, "\\Components\\");
3713     lstrcatA(keypath, comp_squashed);
3714 
3715     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3716     if (res == ERROR_ACCESS_DENIED)
3717     {
3718         skip("Not enough rights to perform tests\n");
3719         LocalFree(usersid);
3720         return;
3721     }
3722     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3723 
3724     /* user unmanaged component key exists */
3725     lstrcpyA(product, "prod");
3726     r = MsiGetProductCodeA(component, product);
3727     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3728     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3729 
3730     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3731     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3732 
3733     /* product value exists */
3734     lstrcpyA(product, "prod");
3735     r = MsiGetProductCodeA(component, product);
3736     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3737     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3738 
3739     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
3740     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3741 
3742     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3743     lstrcatA(keypath, "Installer\\Managed\\");
3744     lstrcatA(keypath, usersid);
3745     lstrcatA(keypath, "\\Installer\\Products\\");
3746     lstrcatA(keypath, prod_squashed);
3747 
3748     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3749     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3750 
3751     /* user managed product key of first product exists */
3752     lstrcpyA(product, "prod");
3753     r = MsiGetProductCodeA(component, product);
3754     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3755     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3756 
3757     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3758     RegCloseKey(prodkey);
3759 
3760     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
3761     lstrcatA(keypath, prod_squashed);
3762 
3763     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
3764     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3765 
3766     /* user unmanaged product key exists */
3767     lstrcpyA(product, "prod");
3768     r = MsiGetProductCodeA(component, product);
3769     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3770     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3771 
3772     RegDeleteKeyA(prodkey, "");
3773     RegCloseKey(prodkey);
3774 
3775     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
3776     lstrcatA(keypath, prod_squashed);
3777 
3778     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3779     if (res == ERROR_ACCESS_DENIED)
3780     {
3781         skip( "insufficient rights\n" );
3782         LocalFree( usersid );
3783         return;
3784     }
3785     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3786 
3787     /* local classes product key exists */
3788     lstrcpyA(product, "prod");
3789     r = MsiGetProductCodeA(component, product);
3790     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3791     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3792 
3793     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3794     RegCloseKey(prodkey);
3795 
3796     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3797     lstrcatA(keypath, "Installer\\Managed\\");
3798     lstrcatA(keypath, usersid);
3799     lstrcatA(keypath, "\\Installer\\Products\\");
3800     lstrcatA(keypath, prod2_squashed);
3801 
3802     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3803     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3804 
3805     /* user managed product key of second product exists */
3806     lstrcpyA(product, "prod");
3807     r = MsiGetProductCodeA(component, product);
3808     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3809     ok(!lstrcmpA(product, prodcode2), "Expected %s, got %s\n", prodcode2, product);
3810 
3811     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3812     RegCloseKey(prodkey);
3813     RegDeleteValueA(compkey, prod_squashed);
3814     RegDeleteValueA(compkey, prod2_squashed);
3815     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3816     RegCloseKey(compkey);
3817 
3818     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3819     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
3820     lstrcatA(keypath, comp_squashed);
3821 
3822     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3823     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3824 
3825     /* local user component key exists */
3826     lstrcpyA(product, "prod");
3827     r = MsiGetProductCodeA(component, product);
3828     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3829     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3830 
3831     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3832     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3833 
3834     /* product value exists */
3835     lstrcpyA(product, "prod");
3836     r = MsiGetProductCodeA(component, product);
3837     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3838     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3839 
3840     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
3841     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3842 
3843     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3844     lstrcatA(keypath, "Installer\\Managed\\");
3845     lstrcatA(keypath, usersid);
3846     lstrcatA(keypath, "\\Installer\\Products\\");
3847     lstrcatA(keypath, prod_squashed);
3848 
3849     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3850     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3851 
3852     /* user managed product key of first product exists */
3853     lstrcpyA(product, "prod");
3854     r = MsiGetProductCodeA(component, product);
3855     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3856     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3857 
3858     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3859     RegCloseKey(prodkey);
3860 
3861     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
3862     lstrcatA(keypath, prod_squashed);
3863 
3864     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
3865     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3866 
3867     /* user unmanaged product key exists */
3868     lstrcpyA(product, "prod");
3869     r = MsiGetProductCodeA(component, product);
3870     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3871     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3872 
3873     RegDeleteKeyA(prodkey, "");
3874     RegCloseKey(prodkey);
3875 
3876     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
3877     lstrcatA(keypath, prod_squashed);
3878 
3879     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3880     if (res == ERROR_ACCESS_DENIED)
3881     {
3882         skip( "insufficient rights\n" );
3883         LocalFree( usersid );
3884         return;
3885     }
3886     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3887 
3888     /* local classes product key exists */
3889     lstrcpyA(product, "prod");
3890     r = MsiGetProductCodeA(component, product);
3891     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3892     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3893 
3894     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3895     RegCloseKey(prodkey);
3896 
3897     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3898     lstrcatA(keypath, "Installer\\Managed\\");
3899     lstrcatA(keypath, usersid);
3900     lstrcatA(keypath, "\\Installer\\Products\\");
3901     lstrcatA(keypath, prod2_squashed);
3902 
3903     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3904     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3905 
3906     /* user managed product key of second product exists */
3907     lstrcpyA(product, "prod");
3908     r = MsiGetProductCodeA(component, product);
3909     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3910     ok(!lstrcmpA(product, prodcode2), "Expected %s, got %s\n", prodcode2, product);
3911 
3912     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3913     RegCloseKey(prodkey);
3914     RegDeleteValueA(compkey, prod_squashed);
3915     RegDeleteValueA(compkey, prod2_squashed);
3916     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3917     RegCloseKey(compkey);
3918     LocalFree(usersid);
3919 }
3920 
3921 static void test_MsiEnumClients(void)
3922 {
3923     HKEY compkey;
3924     CHAR prodcode[MAX_PATH];
3925     CHAR prod_squashed[MAX_PATH];
3926     CHAR prodcode2[MAX_PATH];
3927     CHAR prod2_squashed[MAX_PATH];
3928     CHAR component[MAX_PATH];
3929     CHAR comp_base85[MAX_PATH];
3930     CHAR comp_squashed[MAX_PATH];
3931     CHAR product[MAX_PATH];
3932     CHAR keypath[MAX_PATH];
3933     LPSTR usersid;
3934     LONG res;
3935     UINT r;
3936     REGSAM access = KEY_ALL_ACCESS;
3937 
3938     create_test_guid(prodcode, prod_squashed);
3939     create_test_guid(prodcode2, prod2_squashed);
3940     compose_base85_guid(component, comp_base85, comp_squashed);
3941     usersid = get_user_sid();
3942 
3943     if (is_wow64)
3944         access |= KEY_WOW64_64KEY;
3945 
3946     /* NULL szComponent */
3947     product[0] = '\0';
3948     r = MsiEnumClientsA(NULL, 0, product);
3949     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3950     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3951 
3952     /* empty szComponent */
3953     product[0] = '\0';
3954     r = MsiEnumClientsA("", 0, product);
3955     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3956     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3957 
3958     /* NULL lpProductBuf */
3959     r = MsiEnumClientsA(component, 0, NULL);
3960     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3961 
3962     /* all params correct, component missing */
3963     product[0] = '\0';
3964     r = MsiEnumClientsA(component, 0, product);
3965     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3966     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3967 
3968     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3969     lstrcatA(keypath, "Installer\\UserData\\");
3970     lstrcatA(keypath, usersid);
3971     lstrcatA(keypath, "\\Components\\");
3972     lstrcatA(keypath, comp_squashed);
3973 
3974     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3975     if (res == ERROR_ACCESS_DENIED)
3976     {
3977         skip("Not enough rights to perform tests\n");
3978         LocalFree(usersid);
3979         return;
3980     }
3981     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3982 
3983     /* user unmanaged component key exists */
3984     product[0] = '\0';
3985     r = MsiEnumClientsA(component, 0, product);
3986     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3987     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3988 
3989     /* index > 0, no products exist */
3990     product[0] = '\0';
3991     r = MsiEnumClientsA(component, 1, product);
3992     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3993     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3994 
3995     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3996     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3997 
3998     /* product value exists */
3999     r = MsiEnumClientsA(component, 0, product);
4000     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4001     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4002 
4003     /* try index 0 again */
4004     product[0] = '\0';
4005     r = MsiEnumClientsA(component, 0, product);
4006     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4007     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4008 
4009     /* try index 1, second product value does not exist */
4010     product[0] = '\0';
4011     r = MsiEnumClientsA(component, 1, product);
4012     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4013     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4014 
4015     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
4016     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4017 
4018     /* try index 1, second product value does exist */
4019     product[0] = '\0';
4020     r = MsiEnumClientsA(component, 1, product);
4021     todo_wine
4022     {
4023         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4024         ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4025     }
4026 
4027     /* start the enumeration over */
4028     product[0] = '\0';
4029     r = MsiEnumClientsA(component, 0, product);
4030     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4031     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
4032        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
4033 
4034     /* correctly query second product */
4035     product[0] = '\0';
4036     r = MsiEnumClientsA(component, 1, product);
4037     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4038     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
4039        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
4040 
4041     RegDeleteValueA(compkey, prod_squashed);
4042     RegDeleteValueA(compkey, prod2_squashed);
4043     delete_key(compkey, "", access & KEY_WOW64_64KEY);
4044     RegCloseKey(compkey);
4045 
4046     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4047     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
4048     lstrcatA(keypath, comp_squashed);
4049 
4050     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
4051     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4052 
4053     /* user local component key exists */
4054     product[0] = '\0';
4055     r = MsiEnumClientsA(component, 0, product);
4056     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
4057     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4058 
4059     /* index > 0, no products exist */
4060     product[0] = '\0';
4061     r = MsiEnumClientsA(component, 1, product);
4062     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4063     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4064 
4065     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
4066     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4067 
4068     /* product value exists */
4069     product[0] = '\0';
4070     r = MsiEnumClientsA(component, 0, product);
4071     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4072     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4073 
4074     /* try index 0 again */
4075     product[0] = '\0';
4076     r = MsiEnumClientsA(component, 0, product);
4077     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4078 
4079     /* try index 1, second product value does not exist */
4080     product[0] = '\0';
4081     r = MsiEnumClientsA(component, 1, product);
4082     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4083     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4084 
4085     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
4086     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4087 
4088     /* try index 1, second product value does exist */
4089     product[0] = '\0';
4090     r = MsiEnumClientsA(component, 1, product);
4091     todo_wine
4092     {
4093         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4094         ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4095     }
4096 
4097     /* start the enumeration over */
4098     product[0] = '\0';
4099     r = MsiEnumClientsA(component, 0, product);
4100     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4101     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
4102        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
4103 
4104     /* correctly query second product */
4105     product[0] = '\0';
4106     r = MsiEnumClientsA(component, 1, product);
4107     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4108     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
4109        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
4110 
4111     RegDeleteValueA(compkey, prod_squashed);
4112     RegDeleteValueA(compkey, prod2_squashed);
4113     delete_key(compkey, "", access & KEY_WOW64_64KEY);
4114     RegCloseKey(compkey);
4115     LocalFree(usersid);
4116 }
4117 
4118 static void get_version_info(LPSTR path, LPSTR *vercheck, LPDWORD verchecksz,
4119                              LPSTR *langcheck, LPDWORD langchecksz)
4120 {
4121     LPSTR version;
4122     VS_FIXEDFILEINFO *ffi;
4123     DWORD size = GetFileVersionInfoSizeA(path, NULL);
4124     USHORT *lang;
4125 
4126     version = HeapAlloc(GetProcessHeap(), 0, size);
4127     GetFileVersionInfoA(path, 0, size, version);
4128 
4129     VerQueryValueA(version, "\\", (LPVOID *)&ffi, &size);
4130     *vercheck = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
4131     sprintf(*vercheck, "%d.%d.%d.%d", HIWORD(ffi->dwFileVersionMS),
4132             LOWORD(ffi->dwFileVersionMS), HIWORD(ffi->dwFileVersionLS),
4133             LOWORD(ffi->dwFileVersionLS));
4134     *verchecksz = lstrlenA(*vercheck);
4135 
4136     VerQueryValueA(version, "\\VarFileInfo\\Translation", (void **)&lang, &size);
4137     *langcheck = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
4138     sprintf(*langcheck, "%d", *lang);
4139     *langchecksz = lstrlenA(*langcheck);
4140 
4141     HeapFree(GetProcessHeap(), 0, version);
4142 }
4143 
4144 static void test_MsiGetFileVersion(void)
4145 {
4146     UINT r;
4147     DWORD versz, langsz;
4148     char version[MAX_PATH];
4149     char lang[MAX_PATH];
4150     char path[MAX_PATH];
4151     LPSTR vercheck, langcheck;
4152     DWORD verchecksz, langchecksz;
4153 
4154     /* NULL szFilePath */
4155     r = MsiGetFileVersionA(NULL, NULL, NULL, NULL, NULL);
4156     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4157 
4158     versz = MAX_PATH;
4159     langsz = MAX_PATH;
4160     lstrcpyA(version, "version");
4161     lstrcpyA(lang, "lang");
4162     r = MsiGetFileVersionA(NULL, version, &versz, lang, &langsz);
4163     ok(r == ERROR_INVALID_PARAMETER,
4164        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4165     ok(!lstrcmpA(version, "version"),
4166        "Expected version to be unchanged, got %s\n", version);
4167     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4168     ok(!lstrcmpA(lang, "lang"),
4169        "Expected lang to be unchanged, got %s\n", lang);
4170     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4171 
4172     /* empty szFilePath */
4173     r = MsiGetFileVersionA("", NULL, NULL, NULL, NULL);
4174     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4175 
4176     versz = MAX_PATH;
4177     langsz = MAX_PATH;
4178     lstrcpyA(version, "version");
4179     lstrcpyA(lang, "lang");
4180     r = MsiGetFileVersionA("", version, &versz, lang, &langsz);
4181     ok(r == ERROR_FILE_NOT_FOUND,
4182        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4183     ok(!lstrcmpA(version, "version"),
4184        "Expected version to be unchanged, got %s\n", version);
4185     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4186     ok(!lstrcmpA(lang, "lang"),
4187        "Expected lang to be unchanged, got %s\n", lang);
4188     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4189 
4190     /* nonexistent szFilePath */
4191     versz = MAX_PATH;
4192     langsz = MAX_PATH;
4193     lstrcpyA(version, "version");
4194     lstrcpyA(lang, "lang");
4195     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
4196     ok(r == ERROR_FILE_NOT_FOUND,
4197        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4198     ok(!lstrcmpA(version, "version"),
4199        "Expected version to be unchanged, got %s\n", version);
4200     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4201     ok(!lstrcmpA(lang, "lang"),
4202        "Expected lang to be unchanged, got %s\n", lang);
4203     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4204 
4205     /* nonexistent szFilePath, valid lpVersionBuf, NULL pcchVersionBuf */
4206     versz = MAX_PATH;
4207     langsz = MAX_PATH;
4208     lstrcpyA(version, "version");
4209     lstrcpyA(lang, "lang");
4210     r = MsiGetFileVersionA("nonexistent", version, NULL, lang, &langsz);
4211     ok(r == ERROR_INVALID_PARAMETER,
4212        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4213     ok(!lstrcmpA(version, "version"),
4214        "Expected version to be unchanged, got %s\n", version);
4215     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4216     ok(!lstrcmpA(lang, "lang"),
4217        "Expected lang to be unchanged, got %s\n", lang);
4218     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4219 
4220     /* nonexistent szFilePath, valid lpLangBuf, NULL pcchLangBuf */
4221     versz = MAX_PATH;
4222     langsz = MAX_PATH;
4223     lstrcpyA(version, "version");
4224     lstrcpyA(lang, "lang");
4225     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, NULL);
4226     ok(r == ERROR_INVALID_PARAMETER,
4227        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4228     ok(!lstrcmpA(version, "version"),
4229        "Expected version to be unchanged, got %s\n", version);
4230     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4231     ok(!lstrcmpA(lang, "lang"),
4232        "Expected lang to be unchanged, got %s\n", lang);
4233     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4234 
4235     /* nonexistent szFilePath, valid lpVersionBuf, pcchVersionBuf is zero */
4236     versz = 0;
4237     langsz = MAX_PATH;
4238     lstrcpyA(version, "version");
4239     lstrcpyA(lang, "lang");
4240     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
4241     ok(r == ERROR_FILE_NOT_FOUND,
4242        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4243     ok(!lstrcmpA(version, "version"),
4244        "Expected version to be unchanged, got %s\n", version);
4245     ok(versz == 0, "Expected 0, got %d\n", versz);
4246     ok(!lstrcmpA(lang, "lang"),
4247        "Expected lang to be unchanged, got %s\n", lang);
4248     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4249 
4250     /* nonexistent szFilePath, valid lpLangBuf, pcchLangBuf is zero */
4251     versz = MAX_PATH;
4252     langsz = 0;
4253     lstrcpyA(version, "version");
4254     lstrcpyA(lang, "lang");
4255     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
4256     ok(r == ERROR_FILE_NOT_FOUND,
4257        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4258     ok(!lstrcmpA(version, "version"),
4259        "Expected version to be unchanged, got %s\n", version);
4260     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4261     ok(!lstrcmpA(lang, "lang"),
4262        "Expected lang to be unchanged, got %s\n", lang);
4263     ok(langsz == 0, "Expected 0, got %d\n", langsz);
4264 
4265     /* nonexistent szFilePath, rest NULL */
4266     r = MsiGetFileVersionA("nonexistent", NULL, NULL, NULL, NULL);
4267     ok(r == ERROR_FILE_NOT_FOUND,
4268        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4269 
4270     create_file("ver.txt", 20);
4271 
4272     /* file exists, no version information */
4273     r = MsiGetFileVersionA("ver.txt", NULL, NULL, NULL, NULL);
4274     ok(r == ERROR_FILE_INVALID, "Expected ERROR_FILE_INVALID, got %d\n", r);
4275 
4276     versz = MAX_PATH;
4277     langsz = MAX_PATH;
4278     lstrcpyA(version, "version");
4279     lstrcpyA(lang, "lang");
4280     r = MsiGetFileVersionA("ver.txt", version, &versz, lang, &langsz);
4281     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4282     ok(!lstrcmpA(version, "version"),
4283        "Expected version to be unchanged, got %s\n", version);
4284     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4285     ok(!lstrcmpA(lang, "lang"),
4286        "Expected lang to be unchanged, got %s\n", lang);
4287     ok(r == ERROR_FILE_INVALID,
4288        "Expected ERROR_FILE_INVALID, got %d\n", r);
4289 
4290     DeleteFileA("ver.txt");
4291 
4292     /* relative path, has version information */
4293     versz = MAX_PATH;
4294     langsz = MAX_PATH;
4295     lstrcpyA(version, "version");
4296     lstrcpyA(lang, "lang");
4297     r = MsiGetFileVersionA("kernel32.dll", version, &versz, lang, &langsz);
4298     todo_wine
4299     {
4300         ok(r == ERROR_FILE_NOT_FOUND,
4301            "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4302         ok(!lstrcmpA(version, "version"),
4303            "Expected version to be unchanged, got %s\n", version);
4304         ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4305         ok(!lstrcmpA(lang, "lang"),
4306            "Expected lang to be unchanged, got %s\n", lang);
4307         ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4308     }
4309 
4310     GetSystemDirectoryA(path, MAX_PATH);
4311     lstrcatA(path, "\\kernel32.dll");
4312 
4313     get_version_info(path, &vercheck, &verchecksz, &langcheck, &langchecksz);
4314 
4315     /* absolute path, has version information */
4316     versz = MAX_PATH;
4317     langsz = MAX_PATH;
4318     lstrcpyA(version, "version");
4319     lstrcpyA(lang, "lang");
4320     r = MsiGetFileVersionA(path, version, &versz, lang, &langsz);
4321     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4322     if (langchecksz && !langsz)
4323     {
4324         win_skip("broken MsiGetFileVersionA detected\n");
4325         HeapFree(GetProcessHeap(), 0, vercheck);
4326         HeapFree(GetProcessHeap(), 0, langcheck);
4327         return;
4328     }
4329     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4330     ok(strstr(lang, langcheck) != NULL, "Expected \"%s\" in \"%s\"\n", langcheck, lang);
4331     ok(!lstrcmpA(version, vercheck),
4332         "Expected %s, got %s\n", vercheck, version);
4333 
4334     /* only check version */
4335     versz = MAX_PATH;
4336     lstrcpyA(version, "version");
4337     r = MsiGetFileVersionA(path, version, &versz, NULL, NULL);
4338     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4339     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4340     ok(!lstrcmpA(version, vercheck),
4341        "Expected %s, got %s\n", vercheck, version);
4342 
4343     /* only check language */
4344     langsz = MAX_PATH;
4345     lstrcpyA(lang, "lang");
4346     r = MsiGetFileVersionA(path, NULL, NULL, lang, &langsz);
4347     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4348     ok(strstr(lang, langcheck) != NULL, "Expected \"%s\" in \"%s\"\n", langcheck, lang);
4349 
4350     /* check neither version nor language */
4351     r = MsiGetFileVersionA(path, NULL, NULL, NULL, NULL);
4352     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4353 
4354     /* get pcchVersionBuf */
4355     versz = MAX_PATH;
4356     r = MsiGetFileVersionA(path, NULL, &versz, NULL, NULL);
4357     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4358     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4359 
4360     /* get pcchLangBuf */
4361     langsz = MAX_PATH;
4362     r = MsiGetFileVersionA(path, NULL, NULL, NULL, &langsz);
4363     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4364     ok(langsz >= langchecksz, "Expected %d >= %d\n", langsz, langchecksz);
4365 
4366     /* pcchVersionBuf not big enough */
4367     versz = 5;
4368     lstrcpyA(version, "version");
4369     r = MsiGetFileVersionA(path, version, &versz, NULL, NULL);
4370     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4371     ok(!strncmp(version, vercheck, 4),
4372        "Expected first 4 characters of \"%s\", got \"%s\"\n", vercheck, version);
4373     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4374 
4375     /* pcchLangBuf not big enough */
4376     langsz = 4;
4377     lstrcpyA(lang, "lang");
4378     r = MsiGetFileVersionA(path, NULL, NULL, lang, &langsz);
4379     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4380     ok(lstrcmpA(lang, "lang"), "lang not set\n");
4381     ok(langsz >= langchecksz, "Expected %d >= %d\n", langsz, langchecksz);
4382 
4383     /* pcchVersionBuf big enough, pcchLangBuf not big enough */
4384     versz = MAX_PATH;
4385     langsz = 0;
4386     lstrcpyA(version, "version");
4387     r = MsiGetFileVersionA(path, version, &versz, NULL, &langsz);
4388     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4389     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4390     ok(!lstrcmpA(version, vercheck), "Expected \"%s\", got \"%s\"\n", vercheck, version);
4391     ok(langsz >= langchecksz && langsz < MAX_PATH, "Expected %d >= %d\n", langsz, langchecksz);
4392 
4393     /* pcchVersionBuf not big enough, pcchLangBuf big enough */
4394     versz = 5;
4395     langsz = MAX_PATH;
4396     lstrcpyA(lang, "lang");
4397     r = MsiGetFileVersionA(path, NULL, &versz, lang, &langsz);
4398     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4399     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4400     ok(langsz >= langchecksz && langsz < MAX_PATH, "Expected %d >= %d\n", langsz, langchecksz);
4401     ok(strstr(lang, langcheck) != NULL, "expected %s in %s\n", langcheck, lang);
4402 
4403     /* NULL pcchVersionBuf and pcchLangBuf */
4404     r = MsiGetFileVersionA(path, version, NULL, lang, NULL);
4405     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4406 
4407     /* All NULL except szFilePath */
4408     r = MsiGetFileVersionA(path, NULL, NULL, NULL, NULL);
4409     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4410 
4411     HeapFree(GetProcessHeap(), 0, vercheck);
4412     HeapFree(GetProcessHeap(), 0, langcheck);
4413 }
4414 
4415 static void test_MsiGetProductInfo(void)
4416 {
4417     UINT r;
4418     LONG res;
4419     HKEY propkey, source;
4420     HKEY prodkey, localkey;
4421     CHAR prodcode[MAX_PATH];
4422     CHAR prod_squashed[MAX_PATH];
4423     CHAR packcode[MAX_PATH];
4424     CHAR pack_squashed[MAX_PATH];
4425     CHAR buf[MAX_PATH];
4426     CHAR keypath[MAX_PATH];
4427     LPSTR usersid;
4428     DWORD sz, val = 42;
4429     REGSAM access = KEY_ALL_ACCESS;
4430 
4431     create_test_guid(prodcode, prod_squashed);
4432     create_test_guid(packcode, pack_squashed);
4433     usersid = get_user_sid();
4434 
4435     if (is_wow64)
4436         access |= KEY_WOW64_64KEY;
4437 
4438     /* NULL szProduct */
4439     sz = MAX_PATH;
4440     lstrcpyA(buf, "apple");
4441     r = MsiGetProductInfoA(NULL, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4442     ok(r == ERROR_INVALID_PARAMETER,
4443        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4444     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4445     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4446 
4447     /* empty szProduct */
4448     sz = MAX_PATH;
4449     lstrcpyA(buf, "apple");
4450     r = MsiGetProductInfoA("", INSTALLPROPERTY_HELPLINKA, buf, &sz);
4451     ok(r == ERROR_INVALID_PARAMETER,
4452        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4453     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4454     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4455 
4456     /* garbage szProduct */
4457     sz = MAX_PATH;
4458     lstrcpyA(buf, "apple");
4459     r = MsiGetProductInfoA("garbage", INSTALLPROPERTY_HELPLINKA, buf, &sz);
4460     ok(r == ERROR_INVALID_PARAMETER,
4461        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4462     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4463     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4464 
4465     /* guid without brackets */
4466     sz = MAX_PATH;
4467     lstrcpyA(buf, "apple");
4468     r = MsiGetProductInfoA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
4469                            INSTALLPROPERTY_HELPLINKA, buf, &sz);
4470     ok(r == ERROR_INVALID_PARAMETER,
4471        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4472     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4473     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4474 
4475     /* guid with brackets */
4476     sz = MAX_PATH;
4477     lstrcpyA(buf, "apple");
4478     r = MsiGetProductInfoA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
4479                            INSTALLPROPERTY_HELPLINKA, buf, &sz);
4480     ok(r == ERROR_UNKNOWN_PRODUCT,
4481        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4482     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4483     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4484 
4485     /* same length as guid, but random */
4486     sz = MAX_PATH;
4487     lstrcpyA(buf, "apple");
4488     r = MsiGetProductInfoA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
4489                            INSTALLPROPERTY_HELPLINKA, buf, &sz);
4490     ok(r == ERROR_INVALID_PARAMETER,
4491        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4492     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4493     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4494 
4495     /* not installed, NULL szAttribute */
4496     sz = MAX_PATH;
4497     lstrcpyA(buf, "apple");
4498     r = MsiGetProductInfoA(prodcode, NULL, buf, &sz);
4499     ok(r == ERROR_INVALID_PARAMETER,
4500        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4501     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4502     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4503 
4504     /* not installed, NULL lpValueBuf */
4505     sz = MAX_PATH;
4506     lstrcpyA(buf, "apple");
4507     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, &sz);
4508     ok(r == ERROR_UNKNOWN_PRODUCT,
4509        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4510     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4511     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4512 
4513     /* not installed, NULL pcchValueBuf */
4514     sz = MAX_PATH;
4515     lstrcpyA(buf, "apple");
4516     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, NULL);
4517     ok(r == ERROR_INVALID_PARAMETER,
4518        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4519     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4520     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4521 
4522     /* created guid cannot possibly be an installed product code */
4523     sz = MAX_PATH;
4524     lstrcpyA(buf, "apple");
4525     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4526     ok(r == ERROR_UNKNOWN_PRODUCT,
4527        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4528     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4529     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4530 
4531     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
4532     lstrcatA(keypath, usersid);
4533     lstrcatA(keypath, "\\Installer\\Products\\");
4534     lstrcatA(keypath, prod_squashed);
4535 
4536     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4537     if (res == ERROR_ACCESS_DENIED)
4538     {
4539         skip("Not enough rights to perform tests\n");
4540         LocalFree(usersid);
4541         return;
4542     }
4543     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4544 
4545     /* managed product code exists */
4546     sz = MAX_PATH;
4547     lstrcpyA(buf, "apple");
4548     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4549     ok(r == ERROR_UNKNOWN_PROPERTY,
4550        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4551     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4552     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4553 
4554     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4555     RegCloseKey(prodkey);
4556 
4557     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
4558     lstrcatA(keypath, usersid);
4559     lstrcatA(keypath, "\\Products\\");
4560     lstrcatA(keypath, prod_squashed);
4561 
4562     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
4563     if (res == ERROR_ACCESS_DENIED)
4564     {
4565         skip("Not enough rights to perform tests\n");
4566         LocalFree(usersid);
4567         return;
4568     }
4569     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4570 
4571     /* local user product code exists */
4572     sz = MAX_PATH;
4573     lstrcpyA(buf, "apple");
4574     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4575     ok(r == ERROR_UNKNOWN_PRODUCT,
4576        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4577     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4578     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4579 
4580     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
4581     lstrcatA(keypath, usersid);
4582     lstrcatA(keypath, "\\Installer\\Products\\");
4583     lstrcatA(keypath, prod_squashed);
4584 
4585     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4586     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4587 
4588     /* both local and managed product code exist */
4589     sz = MAX_PATH;
4590     lstrcpyA(buf, "apple");
4591     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4592     ok(r == ERROR_UNKNOWN_PROPERTY,
4593        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4594     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4595     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4596 
4597     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
4598     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4599 
4600     /* InstallProperties key exists */
4601     sz = MAX_PATH;
4602     lstrcpyA(buf, "apple");
4603     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4604     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4605     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4606     ok(sz == 0, "Expected 0, got %d\n", sz);
4607 
4608     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
4609     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4610 
4611     /* HelpLink value exists */
4612     sz = MAX_PATH;
4613     lstrcpyA(buf, "apple");
4614     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4615     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4616     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
4617     ok(sz == 4, "Expected 4, got %d\n", sz);
4618 
4619     /* pcchBuf is NULL */
4620     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, NULL);
4621     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4622 
4623     /* lpValueBuf is NULL */
4624     sz = MAX_PATH;
4625     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, &sz);
4626     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4627     ok(sz == 4, "Expected 4, got %d\n", sz);
4628 
4629     /* lpValueBuf is NULL, pcchValueBuf is too small */
4630     sz = 2;
4631     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, &sz);
4632     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4633     ok(sz == 4, "Expected 4, got %d\n", sz);
4634 
4635     /* lpValueBuf is non-NULL, pcchValueBuf is too small */
4636     sz = 2;
4637     lstrcpyA(buf, "apple");
4638     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4639     ok(!lstrcmpA(buf, "apple"), "Expected buf to remain unchanged, got \"%s\"\n", buf);
4640     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4641     ok(sz == 4, "Expected 4, got %d\n", sz);
4642 
4643     /* lpValueBuf is non-NULL, pcchValueBuf is exactly 4 */
4644     sz = 4;
4645     lstrcpyA(buf, "apple");
4646     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4647     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4648     ok(!lstrcmpA(buf, "apple"),
4649        "Expected buf to remain unchanged, got \"%s\"\n", buf);
4650     ok(sz == 4, "Expected 4, got %d\n", sz);
4651 
4652     res = RegSetValueExA(propkey, "IMadeThis", 0, REG_SZ, (LPBYTE)"random", 7);
4653     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4654 
4655     /* random property not supported by MSI, value exists */
4656     sz = MAX_PATH;
4657     lstrcpyA(buf, "apple");
4658     r = MsiGetProductInfoA(prodcode, "IMadeThis", buf, &sz);
4659     ok(r == ERROR_UNKNOWN_PROPERTY,
4660        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4661     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4662     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4663 
4664     RegDeleteValueA(propkey, "IMadeThis");
4665     RegDeleteValueA(propkey, "HelpLink");
4666     delete_key(propkey, "", access & KEY_WOW64_64KEY);
4667     delete_key(localkey, "", access & KEY_WOW64_64KEY);
4668     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4669     RegCloseKey(propkey);
4670     RegCloseKey(localkey);
4671     RegCloseKey(prodkey);
4672 
4673     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
4674     lstrcatA(keypath, prod_squashed);
4675 
4676     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
4677     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4678 
4679     /* user product key exists */
4680     sz = MAX_PATH;
4681     lstrcpyA(buf, "apple");
4682     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4683     ok(r == ERROR_UNKNOWN_PROPERTY,
4684        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4685     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4686     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4687 
4688     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
4689     lstrcatA(keypath, usersid);
4690     lstrcatA(keypath, "\\Products\\");
4691     lstrcatA(keypath, prod_squashed);
4692 
4693     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
4694     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4695 
4696     /* local user product key exists */
4697     sz = MAX_PATH;
4698     lstrcpyA(buf, "apple");
4699     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4700     ok(r == ERROR_UNKNOWN_PROPERTY,
4701        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4702     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4703     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4704 
4705     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
4706     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4707 
4708     /* InstallProperties key exists */
4709     sz = MAX_PATH;
4710     lstrcpyA(buf, "apple");
4711     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4712     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4713     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4714     ok(sz == 0, "Expected 0, got %d\n", sz);
4715 
4716     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
4717     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4718 
4719     /* HelpLink value exists */
4720     sz = MAX_PATH;
4721     lstrcpyA(buf, "apple");
4722     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4723     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4724     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
4725     ok(sz == 4, "Expected 4, got %d\n", sz);
4726 
4727     RegDeleteValueA(propkey, "HelpLink");
4728     delete_key(propkey, "", access & KEY_WOW64_64KEY);
4729     delete_key(localkey, "", access & KEY_WOW64_64KEY);
4730     RegDeleteKeyA(prodkey, "");
4731     RegCloseKey(propkey);
4732     RegCloseKey(localkey);
4733     RegCloseKey(prodkey);
4734 
4735     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
4736     lstrcatA(keypath, prod_squashed);
4737 
4738     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4739     if (res == ERROR_ACCESS_DENIED)
4740     {
4741         skip( "insufficient rights\n" );
4742         LocalFree( usersid );
4743         return;
4744     }
4745     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4746 
4747     /* classes product key exists */
4748     sz = MAX_PATH;
4749     lstrcpyA(buf, "apple");
4750     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4751     ok(r == ERROR_UNKNOWN_PROPERTY,
4752        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4753     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4754     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4755 
4756     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
4757     lstrcatA(keypath, usersid);
4758     lstrcatA(keypath, "\\Products\\");
4759     lstrcatA(keypath, prod_squashed);
4760 
4761     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
4762     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4763 
4764     /* local user product key exists */
4765     sz = MAX_PATH;
4766     lstrcpyA(buf, "apple");
4767     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4768     ok(r == ERROR_UNKNOWN_PROPERTY,
4769        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4770     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4771     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4772 
4773     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
4774     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4775 
4776     /* InstallProperties key exists */
4777     sz = MAX_PATH;
4778     lstrcpyA(buf, "apple");
4779     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4780     ok(r == ERROR_UNKNOWN_PROPERTY,
4781        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4782     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4783     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4784 
4785     delete_key(propkey, "", access & KEY_WOW64_64KEY);
4786     delete_key(localkey, "", access & KEY_WOW64_64KEY);
4787     RegCloseKey(propkey);
4788     RegCloseKey(localkey);
4789 
4790     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
4791     lstrcatA(keypath, "S-1-5-18\\\\Products\\");
4792     lstrcatA(keypath, prod_squashed);
4793 
4794     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
4795     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4796 
4797     /* Local System product key exists */
4798     sz = MAX_PATH;
4799     lstrcpyA(buf, "apple");
4800     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4801     ok(r == ERROR_UNKNOWN_PROPERTY,
4802         "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4803     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4804     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4805 
4806     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
4807     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4808 
4809     /* InstallProperties key exists */
4810     sz = MAX_PATH;
4811     lstrcpyA(buf, "apple");
4812     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4813     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4814     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4815     ok(sz == 0, "Expected 0, got %d\n", sz);
4816 
4817     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
4818     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4819 
4820     /* HelpLink value exists */
4821     sz = MAX_PATH;
4822     lstrcpyA(buf, "apple");
4823     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4824     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4825     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
4826     ok(sz == 4, "Expected 4, got %d\n", sz);
4827 
4828     res = RegSetValueExA(propkey, "HelpLink", 0, REG_DWORD,
4829                          (const BYTE *)&val, sizeof(DWORD));
4830     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4831 
4832     /* HelpLink type is REG_DWORD */
4833     sz = MAX_PATH;
4834     lstrcpyA(buf, "apple");
4835     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4836     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4837     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4838     ok(sz == 2, "Expected 2, got %d\n", sz);
4839 
4840     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
4841     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4842 
4843     /* DisplayName value exists */
4844     sz = MAX_PATH;
4845     lstrcpyA(buf, "apple");
4846     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
4847     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4848     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
4849     ok(sz == 4, "Expected 4, got %d\n", sz);
4850 
4851     res = RegSetValueExA(propkey, "DisplayName", 0, REG_DWORD,
4852                          (const BYTE *)&val, sizeof(DWORD));
4853     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4854 
4855     /* DisplayName type is REG_DWORD */
4856     sz = MAX_PATH;
4857     lstrcpyA(buf, "apple");
4858     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
4859     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4860     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4861     ok(sz == 2, "Expected 2, got %d\n", sz);
4862 
4863     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"1.1.1", 6);
4864     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4865 
4866     /* DisplayVersion value exists */
4867     sz = MAX_PATH;
4868     lstrcpyA(buf, "apple");
4869     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
4870     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4871     ok(!lstrcmpA(buf, "1.1.1"), "Expected \"1.1.1\", got \"%s\"\n", buf);
4872     ok(sz == 5, "Expected 5, got %d\n", sz);
4873 
4874     res = RegSetValueExA(propkey, "DisplayVersion", 0,
4875                          REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
4876     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4877 
4878     /* DisplayVersion type is REG_DWORD */
4879     sz = MAX_PATH;
4880     lstrcpyA(buf, "apple");
4881     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
4882     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4883     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4884     ok(sz == 2, "Expected 2, got %d\n", sz);
4885 
4886     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"tele", 5);
4887     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4888 
4889     /* HelpTelephone value exists */
4890     sz = MAX_PATH;
4891     lstrcpyA(buf, "apple");
4892     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
4893     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4894     ok(!lstrcmpA(buf, "tele"), "Expected \"tele\", got \"%s\"\n", buf);
4895     ok(sz == 4, "Expected 4, got %d\n", sz);
4896 
4897     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_DWORD,
4898                          (const BYTE *)&val, sizeof(DWORD));
4899     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4900 
4901     /* HelpTelephone type is REG_DWORD */
4902     sz = MAX_PATH;
4903     lstrcpyA(buf, "apple");
4904     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
4905     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4906     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4907     ok(sz == 2, "Expected 2, got %d\n", sz);
4908 
4909     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
4910     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4911 
4912     /* InstallLocation value exists */
4913     sz = MAX_PATH;
4914     lstrcpyA(buf, "apple");
4915     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
4916     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4917     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
4918     ok(sz == 3, "Expected 3, got %d\n", sz);
4919 
4920     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_DWORD,
4921                          (const BYTE *)&val, sizeof(DWORD));
4922     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4923 
4924     /* InstallLocation type is REG_DWORD */
4925     sz = MAX_PATH;
4926     lstrcpyA(buf, "apple");
4927     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
4928     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4929     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4930     ok(sz == 2, "Expected 2, got %d\n", sz);
4931 
4932     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
4933     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4934 
4935     /* InstallSource value exists */
4936     sz = MAX_PATH;
4937     lstrcpyA(buf, "apple");
4938     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
4939     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4940     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
4941     ok(sz == 6, "Expected 6, got %d\n", sz);
4942 
4943     res = RegSetValueExA(propkey, "InstallSource", 0, REG_DWORD,
4944                          (const BYTE *)&val, sizeof(DWORD));
4945     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4946 
4947     /* InstallSource type is REG_DWORD */
4948     sz = MAX_PATH;
4949     lstrcpyA(buf, "apple");
4950     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
4951     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4952     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4953     ok(sz == 2, "Expected 2, got %d\n", sz);
4954 
4955     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
4956     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4957 
4958     /* InstallDate value exists */
4959     sz = MAX_PATH;
4960     lstrcpyA(buf, "apple");
4961     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
4962     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4963     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
4964     ok(sz == 4, "Expected 4, got %d\n", sz);
4965 
4966     res = RegSetValueExA(propkey, "InstallDate", 0, REG_DWORD,
4967                          (const BYTE *)&val, sizeof(DWORD));
4968     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4969 
4970     /* InstallDate type is REG_DWORD */
4971     sz = MAX_PATH;
4972     lstrcpyA(buf, "apple");
4973     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
4974     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4975     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4976     ok(sz == 2, "Expected 2, got %d\n", sz);
4977 
4978     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
4979     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4980 
4981     /* Publisher value exists */
4982     sz = MAX_PATH;
4983     lstrcpyA(buf, "apple");
4984     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PUBLISHERA, buf, &sz);
4985     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4986     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
4987     ok(sz == 3, "Expected 3, got %d\n", sz);
4988 
4989     res = RegSetValueExA(propkey, "Publisher", 0, REG_DWORD,
4990                          (const BYTE *)&val, sizeof(DWORD));
4991     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4992 
4993     /* Publisher type is REG_DWORD */
4994     sz = MAX_PATH;
4995     lstrcpyA(buf, "apple");
4996     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PUBLISHERA, buf, &sz);
4997     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4998     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4999     ok(sz == 2, "Expected 2, got %d\n", sz);
5000 
5001     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"pack", 5);
5002     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5003 
5004     /* LocalPackage value exists */
5005     sz = MAX_PATH;
5006     lstrcpyA(buf, "apple");
5007     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
5008     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5009     ok(!lstrcmpA(buf, "pack"), "Expected \"pack\", got \"%s\"\n", buf);
5010     ok(sz == 4, "Expected 4, got %d\n", sz);
5011 
5012     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_DWORD,
5013                          (const BYTE *)&val, sizeof(DWORD));
5014     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5015 
5016     /* LocalPackage type is REG_DWORD */
5017     sz = MAX_PATH;
5018     lstrcpyA(buf, "apple");
5019     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
5020     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5021     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5022     ok(sz == 2, "Expected 2, got %d\n", sz);
5023 
5024     res = RegSetValueExA(propkey, "UrlInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
5025     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5026 
5027     /* UrlInfoAbout value exists */
5028     sz = MAX_PATH;
5029     lstrcpyA(buf, "apple");
5030     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
5031     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5032     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
5033     ok(sz == 5, "Expected 5, got %d\n", sz);
5034 
5035     res = RegSetValueExA(propkey, "UrlInfoAbout", 0, REG_DWORD,
5036                          (const BYTE *)&val, sizeof(DWORD));
5037     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5038 
5039     /* UrlInfoAbout type is REG_DWORD */
5040     sz = MAX_PATH;
5041     lstrcpyA(buf, "apple");
5042     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
5043     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5044     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5045     ok(sz == 2, "Expected 2, got %d\n", sz);
5046 
5047     res = RegSetValueExA(propkey, "UrlUpdateInfo", 0, REG_SZ, (LPBYTE)"info", 5);
5048     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5049 
5050     /* UrlUpdateInfo value exists */
5051     sz = MAX_PATH;
5052     lstrcpyA(buf, "apple");
5053     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
5054     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5055     ok(!lstrcmpA(buf, "info"), "Expected \"info\", got \"%s\"\n", buf);
5056     ok(sz == 4, "Expected 4, got %d\n", sz);
5057 
5058     res = RegSetValueExA(propkey, "UrlUpdateInfo", 0, REG_DWORD,
5059                          (const BYTE *)&val, sizeof(DWORD));
5060     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5061 
5062     /* UrlUpdateInfo type is REG_DWORD */
5063     sz = MAX_PATH;
5064     lstrcpyA(buf, "apple");
5065     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
5066     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5067     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5068     ok(sz == 2, "Expected 2, got %d\n", sz);
5069 
5070     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"1", 2);
5071     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5072 
5073     /* VersionMinor value exists */
5074     sz = MAX_PATH;
5075     lstrcpyA(buf, "apple");
5076     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
5077     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5078     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
5079     ok(sz == 1, "Expected 1, got %d\n", sz);
5080 
5081     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_DWORD,
5082                          (const BYTE *)&val, sizeof(DWORD));
5083     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5084 
5085     /* VersionMinor type is REG_DWORD */
5086     sz = MAX_PATH;
5087     lstrcpyA(buf, "apple");
5088     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
5089     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5090     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5091     ok(sz == 2, "Expected 2, got %d\n", sz);
5092 
5093     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"1", 2);
5094     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5095 
5096     /* VersionMajor value exists */
5097     sz = MAX_PATH;
5098     lstrcpyA(buf, "apple");
5099     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
5100     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5101     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
5102     ok(sz == 1, "Expected 1, got %d\n", sz);
5103 
5104     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_DWORD,
5105                          (const BYTE *)&val, sizeof(DWORD));
5106     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5107 
5108     /* VersionMajor type is REG_DWORD */
5109     sz = MAX_PATH;
5110     lstrcpyA(buf, "apple");
5111     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
5112     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5113     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5114     ok(sz == 2, "Expected 2, got %d\n", sz);
5115 
5116     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
5117     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5118 
5119     /* ProductID value exists */
5120     sz = MAX_PATH;
5121     lstrcpyA(buf, "apple");
5122     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
5123     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5124     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
5125     ok(sz == 2, "Expected 2, got %d\n", sz);
5126 
5127     res = RegSetValueExA(propkey, "ProductID", 0, REG_DWORD,
5128                          (const BYTE *)&val, sizeof(DWORD));
5129     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5130 
5131     /* ProductID type is REG_DWORD */
5132     sz = MAX_PATH;
5133     lstrcpyA(buf, "apple");
5134     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
5135     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5136     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5137     ok(sz == 2, "Expected 2, got %d\n", sz);
5138 
5139     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
5140     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5141 
5142     /* RegCompany value exists */
5143     sz = MAX_PATH;
5144     lstrcpyA(buf, "apple");
5145     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
5146     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5147     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
5148     ok(sz == 4, "Expected 4, got %d\n", sz);
5149 
5150     res = RegSetValueExA(propkey, "RegCompany", 0, REG_DWORD,
5151                          (const BYTE *)&val, sizeof(DWORD));
5152     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5153 
5154     /* RegCompany type is REG_DWORD */
5155     sz = MAX_PATH;
5156     lstrcpyA(buf, "apple");
5157     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
5158     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5159     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5160     ok(sz == 2, "Expected 2, got %d\n", sz);
5161 
5162     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"own", 4);
5163     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5164 
5165     /* RegOwner value exists */
5166     sz = MAX_PATH;
5167     lstrcpyA(buf, "apple");
5168     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGOWNERA, buf, &sz);
5169     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5170     ok(!lstrcmpA(buf, "own"), "Expected \"own\", got \"%s\"\n", buf);
5171     ok(sz == 3, "Expected 3, got %d\n", sz);
5172 
5173     res = RegSetValueExA(propkey, "RegOwner", 0, REG_DWORD,
5174                          (const BYTE *)&val, sizeof(DWORD));
5175     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5176 
5177     /* RegOwner type is REG_DWORD */
5178     sz = MAX_PATH;
5179     lstrcpyA(buf, "apple");
5180     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGOWNERA, buf, &sz);
5181     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5182     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5183     ok(sz == 2, "Expected 2, got %d\n", sz);
5184 
5185     res = RegSetValueExA(propkey, "InstanceType", 0, REG_SZ, (LPBYTE)"type", 5);
5186     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5187 
5188     /* InstanceType value exists */
5189     sz = MAX_PATH;
5190     lstrcpyA(buf, "apple");
5191     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5192     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5193     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5194     ok(sz == 0, "Expected 0, got %d\n", sz);
5195 
5196     res = RegSetValueExA(propkey, "InstanceType", 0, REG_DWORD,
5197                          (const BYTE *)&val, sizeof(DWORD));
5198     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5199 
5200     /* InstanceType type is REG_DWORD */
5201     sz = MAX_PATH;
5202     lstrcpyA(buf, "apple");
5203     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5204     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5205     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5206     ok(sz == 0, "Expected 0, got %d\n", sz);
5207 
5208     res = RegSetValueExA(prodkey, "InstanceType", 0, REG_SZ, (LPBYTE)"type", 5);
5209     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5210 
5211     /* InstanceType value exists */
5212     sz = MAX_PATH;
5213     lstrcpyA(buf, "apple");
5214     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5215     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5216     ok(!lstrcmpA(buf, "type"), "Expected \"type\", got \"%s\"\n", buf);
5217     ok(sz == 4, "Expected 4, got %d\n", sz);
5218 
5219     res = RegSetValueExA(prodkey, "InstanceType", 0, REG_DWORD,
5220                          (const BYTE *)&val, sizeof(DWORD));
5221     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5222 
5223     /* InstanceType type is REG_DWORD */
5224     sz = MAX_PATH;
5225     lstrcpyA(buf, "apple");
5226     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5227     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5228     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5229     ok(sz == 2, "Expected 2, got %d\n", sz);
5230 
5231     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"tforms", 7);
5232     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5233 
5234     /* Transforms value exists */
5235     sz = MAX_PATH;
5236     lstrcpyA(buf, "apple");
5237     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5238     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5239     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5240     ok(sz == 0, "Expected 0, got %d\n", sz);
5241 
5242     res = RegSetValueExA(propkey, "Transforms", 0, REG_DWORD,
5243                          (const BYTE *)&val, sizeof(DWORD));
5244     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5245 
5246     /* Transforms type is REG_DWORD */
5247     sz = MAX_PATH;
5248     lstrcpyA(buf, "apple");
5249     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5250     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5251     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5252     ok(sz == 0, "Expected 0, got %d\n", sz);
5253 
5254     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"tforms", 7);
5255     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5256 
5257     /* Transforms value exists */
5258     sz = MAX_PATH;
5259     lstrcpyA(buf, "apple");
5260     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5261     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5262     ok(!lstrcmpA(buf, "tforms"), "Expected \"tforms\", got \"%s\"\n", buf);
5263     ok(sz == 6, "Expected 6, got %d\n", sz);
5264 
5265     res = RegSetValueExA(prodkey, "Transforms", 0, REG_DWORD,
5266                          (const BYTE *)&val, sizeof(DWORD));
5267     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5268 
5269     /* Transforms type is REG_DWORD */
5270     sz = MAX_PATH;
5271     lstrcpyA(buf, "apple");
5272     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5273     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5274     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5275     ok(sz == 2, "Expected 2, got %d\n", sz);
5276 
5277     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
5278     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5279 
5280     /* Language value exists */
5281     sz = MAX_PATH;
5282     lstrcpyA(buf, "apple");
5283     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5284     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5285     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5286     ok(sz == 0, "Expected 0, got %d\n", sz);
5287 
5288     res = RegSetValueExA(propkey, "Language", 0, REG_DWORD,
5289                          (const BYTE *)&val, sizeof(DWORD));
5290     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5291 
5292     /* Language type is REG_DWORD */
5293     sz = MAX_PATH;
5294     lstrcpyA(buf, "apple");
5295     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5296     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5297     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5298     ok(sz == 0, "Expected 0, got %d\n", sz);
5299 
5300     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
5301     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5302 
5303     /* Language value exists */
5304     sz = MAX_PATH;
5305     lstrcpyA(buf, "apple");
5306     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5307     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5308     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
5309     ok(sz == 4, "Expected 4, got %d\n", sz);
5310 
5311     res = RegSetValueExA(prodkey, "Language", 0, REG_DWORD,
5312                          (const BYTE *)&val, sizeof(DWORD));
5313     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5314 
5315     /* Language type is REG_DWORD */
5316     sz = MAX_PATH;
5317     lstrcpyA(buf, "apple");
5318     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5319     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5320     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5321     ok(sz == 2, "Expected 2, got %d\n", sz);
5322 
5323     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
5324     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5325 
5326     /* ProductName value exists */
5327     sz = MAX_PATH;
5328     lstrcpyA(buf, "apple");
5329     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5330     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5331     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5332     ok(sz == 0, "Expected 0, got %d\n", sz);
5333 
5334     res = RegSetValueExA(propkey, "ProductName", 0, REG_DWORD,
5335                          (const BYTE *)&val, sizeof(DWORD));
5336     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5337 
5338     /* ProductName type is REG_DWORD */
5339     sz = MAX_PATH;
5340     lstrcpyA(buf, "apple");
5341     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5342     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5343     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5344     ok(sz == 0, "Expected 0, got %d\n", sz);
5345 
5346     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
5347     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5348 
5349     /* ProductName value exists */
5350     sz = MAX_PATH;
5351     lstrcpyA(buf, "apple");
5352     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5353     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5354     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
5355     ok(sz == 4, "Expected 4, got %d\n", sz);
5356 
5357     res = RegSetValueExA(prodkey, "ProductName", 0, REG_DWORD,
5358                          (const BYTE *)&val, sizeof(DWORD));
5359     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5360 
5361     /* ProductName type is REG_DWORD */
5362     sz = MAX_PATH;
5363     lstrcpyA(buf, "apple");
5364     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5365     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5366     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5367     ok(sz == 2, "Expected 2, got %d\n", sz);
5368 
5369     res = RegSetValueExA(propkey, "Assignment", 0, REG_SZ, (LPBYTE)"at", 3);
5370     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5371 
5372     /* Assignment value exists */
5373     sz = MAX_PATH;
5374     lstrcpyA(buf, "apple");
5375     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5376     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5377     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5378     ok(sz == 0, "Expected 0, got %d\n", sz);
5379 
5380     res = RegSetValueExA(propkey, "Assignment", 0, REG_DWORD,
5381                          (const BYTE *)&val, sizeof(DWORD));
5382     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5383 
5384     /* Assignment type is REG_DWORD */
5385     sz = MAX_PATH;
5386     lstrcpyA(buf, "apple");
5387     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5388     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5389     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5390     ok(sz == 0, "Expected 0, got %d\n", sz);
5391 
5392     res = RegSetValueExA(prodkey, "Assignment", 0, REG_SZ, (LPBYTE)"at", 3);
5393     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5394 
5395     /* Assignment value exists */
5396     sz = MAX_PATH;
5397     lstrcpyA(buf, "apple");
5398     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5399     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5400     ok(!lstrcmpA(buf, "at"), "Expected \"at\", got \"%s\"\n", buf);
5401     ok(sz == 2, "Expected 2, got %d\n", sz);
5402 
5403     res = RegSetValueExA(prodkey, "Assignment", 0, REG_DWORD,
5404                          (const BYTE *)&val, sizeof(DWORD));
5405     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5406 
5407     /* Assignment type is REG_DWORD */
5408     sz = MAX_PATH;
5409     lstrcpyA(buf, "apple");
5410     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5411     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5412     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5413     ok(sz == 2, "Expected 2, got %d\n", sz);
5414 
5415     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
5416     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5417 
5418     /* PackageCode value exists */
5419     sz = MAX_PATH;
5420     lstrcpyA(buf, "apple");
5421     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5422     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5423     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5424     ok(sz == 0, "Expected 0, got %d\n", sz);
5425 
5426     res = RegSetValueExA(propkey, "PackageCode", 0, REG_DWORD,
5427                          (const BYTE *)&val, sizeof(DWORD));
5428     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5429 
5430     /* PackageCode type is REG_DWORD */
5431     sz = MAX_PATH;
5432     lstrcpyA(buf, "apple");
5433     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5434     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5435     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5436     ok(sz == 0, "Expected 0, got %d\n", sz);
5437 
5438     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
5439     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5440 
5441     /* PackageCode value exists */
5442     sz = MAX_PATH;
5443     lstrcpyA(buf, "apple");
5444     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5445     ok(r == ERROR_BAD_CONFIGURATION,
5446        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
5447     ok(!lstrcmpA(buf, "code"), "Expected \"code\", got \"%s\"\n", buf);
5448     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5449 
5450     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_DWORD,
5451                          (const BYTE *)&val, sizeof(DWORD));
5452     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5453 
5454     /* PackageCode type is REG_DWORD */
5455     sz = MAX_PATH;
5456     lstrcpyA(buf, "apple");
5457     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5458     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5459     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5460     ok(sz == 2, "Expected 2, got %d\n", sz);
5461 
5462     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)pack_squashed, 33);
5463     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5464 
5465     /* PackageCode value exists */
5466     sz = MAX_PATH;
5467     lstrcpyA(buf, "apple");
5468     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5469     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5470     ok(!lstrcmpA(buf, packcode), "Expected \"%s\", got \"%s\"\n", packcode, buf);
5471     ok(sz == 38, "Expected 38, got %d\n", sz);
5472 
5473     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
5474     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5475 
5476     /* Version value exists */
5477     sz = MAX_PATH;
5478     lstrcpyA(buf, "apple");
5479     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5480     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5481     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5482     ok(sz == 0, "Expected 0, got %d\n", sz);
5483 
5484     res = RegSetValueExA(propkey, "Version", 0, REG_DWORD,
5485                          (const BYTE *)&val, sizeof(DWORD));
5486     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5487 
5488     /* Version type is REG_DWORD */
5489     sz = MAX_PATH;
5490     lstrcpyA(buf, "apple");
5491     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5492     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5493     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5494     ok(sz == 0, "Expected 0, got %d\n", sz);
5495 
5496     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
5497     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5498 
5499     /* Version value exists */
5500     sz = MAX_PATH;
5501     lstrcpyA(buf, "apple");
5502     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5503     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5504     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
5505     ok(sz == 3, "Expected 3, got %d\n", sz);
5506 
5507     res = RegSetValueExA(prodkey, "Version", 0, REG_DWORD,
5508                          (const BYTE *)&val, sizeof(DWORD));
5509     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5510 
5511     /* Version type is REG_DWORD */
5512     sz = MAX_PATH;
5513     lstrcpyA(buf, "apple");
5514     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5515     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5516     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5517     ok(sz == 2, "Expected 2, got %d\n", sz);
5518 
5519     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"ico", 4);
5520     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5521 
5522     /* ProductIcon value exists */
5523     sz = MAX_PATH;
5524     lstrcpyA(buf, "apple");
5525     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5526     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5527     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5528     ok(sz == 0, "Expected 0, got %d\n", sz);
5529 
5530     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_DWORD,
5531                          (const BYTE *)&val, sizeof(DWORD));
5532     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5533 
5534     /* ProductIcon type is REG_DWORD */
5535     sz = MAX_PATH;
5536     lstrcpyA(buf, "apple");
5537     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5538     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5539     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5540     ok(sz == 0, "Expected 0, got %d\n", sz);
5541 
5542     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"ico", 4);
5543     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5544 
5545     /* ProductIcon value exists */
5546     sz = MAX_PATH;
5547     lstrcpyA(buf, "apple");
5548     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5549     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5550     ok(!lstrcmpA(buf, "ico"), "Expected \"ico\", got \"%s\"\n", buf);
5551     ok(sz == 3, "Expected 3, got %d\n", sz);
5552 
5553     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_DWORD,
5554                          (const BYTE *)&val, sizeof(DWORD));
5555     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5556 
5557     /* ProductIcon type is REG_DWORD */
5558     sz = MAX_PATH;
5559     lstrcpyA(buf, "apple");
5560     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5561     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5562     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5563     ok(sz == 2, "Expected 2, got %d\n", sz);
5564 
5565     /* SourceList key does not exist */
5566     sz = MAX_PATH;
5567     lstrcpyA(buf, "apple");
5568     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5569     ok(r == ERROR_UNKNOWN_PRODUCT,
5570        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5571     ok(!lstrcmpA(buf, "apple"),
5572        "Expected buf to be unchanged, got \"%s\"\n", buf);
5573     ok(sz == MAX_PATH, "Expected sz to be unchanged, got %d\n", sz);
5574 
5575     res = RegCreateKeyExA(prodkey, "SourceList", 0, NULL, 0, access, NULL, &source, NULL);
5576     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5577 
5578     /* SourceList key exists, but PackageName val does not exist */
5579     sz = MAX_PATH;
5580     lstrcpyA(buf, "apple");
5581     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5582     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5583     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5584     ok(sz == 0, "Expected 0, got %d\n", sz);
5585 
5586     res = RegSetValueExA(source, "PackageName", 0, REG_SZ, (LPBYTE)"packname", 9);
5587     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5588 
5589     /* PackageName val exists */
5590     sz = MAX_PATH;
5591     lstrcpyA(buf, "apple");
5592     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5593     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5594     ok(!lstrcmpA(buf, "packname"), "Expected \"packname\", got \"%s\"\n", buf);
5595     ok(sz == 8, "Expected 8, got %d\n", sz);
5596 
5597     res = RegSetValueExA(source, "PackageName", 0, REG_DWORD,
5598                          (const BYTE *)&val, sizeof(DWORD));
5599     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5600 
5601     /* PackageName type is REG_DWORD */
5602     sz = MAX_PATH;
5603     lstrcpyA(buf, "apple");
5604     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5605     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5606     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5607     ok(sz == 2, "Expected 2, got %d\n", sz);
5608 
5609     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
5610     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5611 
5612     /* Authorized value exists */
5613     sz = MAX_PATH;
5614     lstrcpyA(buf, "apple");
5615     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5616     if (r != ERROR_UNKNOWN_PROPERTY)
5617     {
5618         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5619         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5620         ok(sz == 0, "Expected 0, got %d\n", sz);
5621     }
5622 
5623     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_DWORD,
5624                          (const BYTE *)&val, sizeof(DWORD));
5625     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5626 
5627     /* AuthorizedLUAApp type is REG_DWORD */
5628     sz = MAX_PATH;
5629     lstrcpyA(buf, "apple");
5630     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5631     if (r != ERROR_UNKNOWN_PROPERTY)
5632     {
5633         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5634         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5635         ok(sz == 0, "Expected 0, got %d\n", sz);
5636     }
5637 
5638     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
5639     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5640 
5641     /* Authorized value exists */
5642     sz = MAX_PATH;
5643     lstrcpyA(buf, "apple");
5644     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5645     if (r != ERROR_UNKNOWN_PROPERTY)
5646     {
5647         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5648         ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
5649         ok(sz == 4, "Expected 4, got %d\n", sz);
5650     }
5651 
5652     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_DWORD,
5653                          (const BYTE *)&val, sizeof(DWORD));
5654     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5655 
5656     /* AuthorizedLUAApp type is REG_DWORD */
5657     sz = MAX_PATH;
5658     lstrcpyA(buf, "apple");
5659     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5660     if (r != ERROR_UNKNOWN_PROPERTY)
5661     {
5662         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5663         ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5664         ok(sz == 2, "Expected 2, got %d\n", sz);
5665     }
5666 
5667     RegDeleteValueA(propkey, "HelpLink");
5668     RegDeleteValueA(propkey, "DisplayName");
5669     RegDeleteValueA(propkey, "DisplayVersion");
5670     RegDeleteValueA(propkey, "HelpTelephone");
5671     RegDeleteValueA(propkey, "InstallLocation");
5672     RegDeleteValueA(propkey, "InstallSource");
5673     RegDeleteValueA(propkey, "InstallDate");
5674     RegDeleteValueA(propkey, "Publisher");
5675     RegDeleteValueA(propkey, "LocalPackage");
5676     RegDeleteValueA(propkey, "UrlInfoAbout");
5677     RegDeleteValueA(propkey, "UrlUpdateInfo");
5678     RegDeleteValueA(propkey, "VersionMinor");
5679     RegDeleteValueA(propkey, "VersionMajor");
5680     RegDeleteValueA(propkey, "ProductID");
5681     RegDeleteValueA(propkey, "RegCompany");
5682     RegDeleteValueA(propkey, "RegOwner");
5683     RegDeleteValueA(propkey, "InstanceType");
5684     RegDeleteValueA(propkey, "Transforms");
5685     RegDeleteValueA(propkey, "Language");
5686     RegDeleteValueA(propkey, "ProductName");
5687     RegDeleteValueA(propkey, "Assignment");
5688     RegDeleteValueA(propkey, "PackageCode");
5689     RegDeleteValueA(propkey, "Version");
5690     RegDeleteValueA(propkey, "ProductIcon");
5691     RegDeleteValueA(propkey, "AuthorizedLUAApp");
5692     delete_key(propkey, "", access & KEY_WOW64_64KEY);
5693     delete_key(localkey, "", access & KEY_WOW64_64KEY);
5694     RegDeleteValueA(prodkey, "InstanceType");
5695     RegDeleteValueA(prodkey, "Transforms");
5696     RegDeleteValueA(prodkey, "Language");
5697     RegDeleteValueA(prodkey, "ProductName");
5698     RegDeleteValueA(prodkey, "Assignment");
5699     RegDeleteValueA(prodkey, "PackageCode");
5700     RegDeleteValueA(prodkey, "Version");
5701     RegDeleteValueA(prodkey, "ProductIcon");
5702     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
5703     RegDeleteValueA(source, "PackageName");
5704     delete_key(source, "", access & KEY_WOW64_64KEY);
5705     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
5706     RegCloseKey(propkey);
5707     RegCloseKey(localkey);
5708     RegCloseKey(source);
5709     RegCloseKey(prodkey);
5710     LocalFree(usersid);
5711 }
5712 
5713 static void test_MsiGetProductInfoEx(void)
5714 {
5715     UINT r;
5716     LONG res;
5717     HKEY propkey, userkey;
5718     HKEY prodkey, localkey;
5719     CHAR prodcode[MAX_PATH];
5720     CHAR prod_squashed[MAX_PATH];
5721     CHAR packcode[MAX_PATH];
5722     CHAR pack_squashed[MAX_PATH];
5723     CHAR buf[MAX_PATH];
5724     CHAR keypath[MAX_PATH];
5725     LPSTR usersid;
5726     DWORD sz;
5727     REGSAM access = KEY_ALL_ACCESS;
5728 
5729     if (!pMsiGetProductInfoExA)
5730     {
5731         win_skip("MsiGetProductInfoExA is not available\n");
5732         return;
5733     }
5734 
5735     create_test_guid(prodcode, prod_squashed);
5736     create_test_guid(packcode, pack_squashed);
5737     usersid = get_user_sid();
5738 
5739     if (is_wow64)
5740         access |= KEY_WOW64_64KEY;
5741 
5742     /* NULL szProductCode */
5743     sz = MAX_PATH;
5744     lstrcpyA(buf, "apple");
5745     r = pMsiGetProductInfoExA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
5746                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5747     ok(r == ERROR_INVALID_PARAMETER,
5748        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5749     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5750     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5751 
5752     /* empty szProductCode */
5753     sz = MAX_PATH;
5754     lstrcpyA(buf, "apple");
5755     r = pMsiGetProductInfoExA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
5756                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5757     ok(r == ERROR_INVALID_PARAMETER,
5758        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5759     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5760     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5761 
5762     /* garbage szProductCode */
5763     sz = MAX_PATH;
5764     lstrcpyA(buf, "apple");
5765     r = pMsiGetProductInfoExA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
5766                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5767     ok(r == ERROR_INVALID_PARAMETER,
5768        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5769     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5770     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5771 
5772     /* guid without brackets */
5773     sz = MAX_PATH;
5774     lstrcpyA(buf, "apple");
5775     r = pMsiGetProductInfoExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", usersid,
5776                               MSIINSTALLCONTEXT_USERUNMANAGED,
5777                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5778     ok(r == ERROR_INVALID_PARAMETER,
5779        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5780     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5781     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5782 
5783     /* guid with brackets */
5784     sz = MAX_PATH;
5785     lstrcpyA(buf, "apple");
5786     r = pMsiGetProductInfoExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", usersid,
5787                               MSIINSTALLCONTEXT_USERUNMANAGED,
5788                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5789     ok(r == ERROR_UNKNOWN_PRODUCT,
5790        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5791     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5792     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5793 
5794     /* szValue is non-NULL while pcchValue is NULL */
5795     lstrcpyA(buf, "apple");
5796     r = pMsiGetProductInfoExA(prodcode, usersid,
5797                               MSIINSTALLCONTEXT_USERUNMANAGED,
5798                               INSTALLPROPERTY_PRODUCTSTATEA, buf, NULL);
5799     ok(r == ERROR_INVALID_PARAMETER,
5800        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5801     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5802 
5803     /* dwContext is out of range */
5804     sz = MAX_PATH;
5805     lstrcpyA(buf, "apple");
5806     r = pMsiGetProductInfoExA(prodcode, usersid, 42,
5807                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5808     ok(r == ERROR_INVALID_PARAMETER,
5809        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5810     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5811     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5812 
5813     /* szProperty is NULL */
5814     sz = MAX_PATH;
5815     lstrcpyA(buf, "apple");
5816     r = pMsiGetProductInfoExA(prodcode, usersid,
5817                               MSIINSTALLCONTEXT_USERUNMANAGED,
5818                               NULL, buf, &sz);
5819     ok(r == ERROR_INVALID_PARAMETER,
5820        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5821     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5822     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5823 
5824     /* szProperty is empty */
5825     sz = MAX_PATH;
5826     lstrcpyA(buf, "apple");
5827     r = pMsiGetProductInfoExA(prodcode, usersid,
5828                               MSIINSTALLCONTEXT_USERUNMANAGED,
5829                               "", buf, &sz);
5830     ok(r == ERROR_INVALID_PARAMETER,
5831        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5832     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5833     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5834 
5835     /* szProperty is not a valid property */
5836     sz = MAX_PATH;
5837     lstrcpyA(buf, "apple");
5838     r = pMsiGetProductInfoExA(prodcode, usersid,
5839                               MSIINSTALLCONTEXT_USERUNMANAGED,
5840                               "notvalid", buf, &sz);
5841     ok(r == ERROR_UNKNOWN_PRODUCT,
5842        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5843     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5844     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5845 
5846     /* same length as guid, but random */
5847     sz = MAX_PATH;
5848     lstrcpyA(buf, "apple");
5849     r = pMsiGetProductInfoExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", usersid,
5850                               MSIINSTALLCONTEXT_USERUNMANAGED,
5851                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5852     ok(r == ERROR_INVALID_PARAMETER,
5853        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5854     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5855     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5856 
5857     /* MSIINSTALLCONTEXT_USERUNMANAGED */
5858 
5859     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
5860     lstrcatA(keypath, usersid);
5861     lstrcatA(keypath, "\\Products\\");
5862     lstrcatA(keypath, prod_squashed);
5863 
5864     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
5865     if (res == ERROR_ACCESS_DENIED)
5866     {
5867         skip("Not enough rights to perform tests\n");
5868         LocalFree(usersid);
5869         return;
5870     }
5871     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5872 
5873     /* local user product key exists */
5874     sz = MAX_PATH;
5875     lstrcpyA(buf, "apple");
5876     r = pMsiGetProductInfoExA(prodcode, usersid,
5877                               MSIINSTALLCONTEXT_USERUNMANAGED,
5878                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5879     ok(r == ERROR_UNKNOWN_PRODUCT,
5880        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5881     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5882     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5883 
5884     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
5885     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5886 
5887     /* InstallProperties key exists */
5888     sz = MAX_PATH;
5889     lstrcpyA(buf, "apple");
5890     r = pMsiGetProductInfoExA(prodcode, usersid,
5891                               MSIINSTALLCONTEXT_USERUNMANAGED,
5892                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5893     ok(r == ERROR_UNKNOWN_PRODUCT,
5894        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5895     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5896     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5897 
5898     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
5899     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5900 
5901     /* LocalPackage value exists */
5902     sz = MAX_PATH;
5903     lstrcpyA(buf, "apple");
5904     r = pMsiGetProductInfoExA(prodcode, usersid,
5905                               MSIINSTALLCONTEXT_USERUNMANAGED,
5906                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5907     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5908     ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
5909     ok(sz == 1, "Expected 1, got %d\n", sz);
5910 
5911     RegDeleteValueA(propkey, "LocalPackage");
5912 
5913     /* LocalPackage value must exist */
5914     sz = MAX_PATH;
5915     lstrcpyA(buf, "apple");
5916     r = pMsiGetProductInfoExA(prodcode, usersid,
5917                               MSIINSTALLCONTEXT_USERUNMANAGED,
5918                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
5919     ok(r == ERROR_UNKNOWN_PRODUCT,
5920        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5921     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5922     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5923 
5924     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
5925     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5926 
5927     /* LocalPackage exists, but HelpLink does not exist */
5928     sz = MAX_PATH;
5929     lstrcpyA(buf, "apple");
5930     r = pMsiGetProductInfoExA(prodcode, usersid,
5931                               MSIINSTALLCONTEXT_USERUNMANAGED,
5932                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
5933     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5934     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5935     ok(sz == 0, "Expected 0, got %d\n", sz);
5936 
5937     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
5938     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5939 
5940     /* HelpLink value exists */
5941     sz = MAX_PATH;
5942     lstrcpyA(buf, "apple");
5943     r = pMsiGetProductInfoExA(prodcode, usersid,
5944                               MSIINSTALLCONTEXT_USERUNMANAGED,
5945                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
5946     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5947     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
5948     ok(sz == 4, "Expected 4, got %d\n", sz);
5949 
5950     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
5951     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5952 
5953     /* HelpTelephone value exists */
5954     sz = MAX_PATH;
5955     lstrcpyA(buf, "apple");
5956     r = pMsiGetProductInfoExA(prodcode, usersid,
5957                               MSIINSTALLCONTEXT_USERUNMANAGED,
5958                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
5959     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5960     ok(!lstrcmpA(buf, "phone"), "Expected \"phone\", got \"%s\"\n", buf);
5961     ok(sz == 5, "Expected 5, got %d\n", sz);
5962 
5963     /* szValue and pcchValue are NULL */
5964     r = pMsiGetProductInfoExA(prodcode, usersid,
5965                               MSIINSTALLCONTEXT_USERUNMANAGED,
5966                               INSTALLPROPERTY_HELPTELEPHONEA, NULL, NULL);
5967     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5968 
5969     /* pcchValue is exactly 5 */
5970     sz = 5;
5971     lstrcpyA(buf, "apple");
5972     r = pMsiGetProductInfoExA(prodcode, usersid,
5973                               MSIINSTALLCONTEXT_USERUNMANAGED,
5974                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
5975     ok(r == ERROR_MORE_DATA,
5976        "Expected ERROR_MORE_DATA, got %d\n", r);
5977     ok(sz == 10, "Expected 10, got %d\n", sz);
5978 
5979     /* szValue is NULL, pcchValue is exactly 5 */
5980     sz = 5;
5981     r = pMsiGetProductInfoExA(prodcode, usersid,
5982                               MSIINSTALLCONTEXT_USERUNMANAGED,
5983                               INSTALLPROPERTY_HELPTELEPHONEA, NULL, &sz);
5984     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5985     ok(sz == 10, "Expected 10, got %d\n", sz);
5986 
5987     /* szValue is NULL, pcchValue is MAX_PATH */
5988     sz = MAX_PATH;
5989     r = pMsiGetProductInfoExA(prodcode, usersid,
5990                               MSIINSTALLCONTEXT_USERUNMANAGED,
5991                               INSTALLPROPERTY_HELPTELEPHONEA, NULL, &sz);
5992     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5993     ok(sz == 10, "Expected 10, got %d\n", sz);
5994 
5995     /* pcchValue is exactly 0 */
5996     sz = 0;
5997     lstrcpyA(buf, "apple");
5998     r = pMsiGetProductInfoExA(prodcode, usersid,
5999                               MSIINSTALLCONTEXT_USERUNMANAGED,
6000                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
6001     ok(r == ERROR_MORE_DATA,
6002        "Expected ERROR_MORE_DATA, got %d\n", r);
6003     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
6004     ok(sz == 10, "Expected 10, got %d\n", sz);
6005 
6006     res = RegSetValueExA(propkey, "notvalid", 0, REG_SZ, (LPBYTE)"invalid", 8);
6007     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6008 
6009     /* szProperty is not a valid property */
6010     sz = MAX_PATH;
6011     lstrcpyA(buf, "apple");
6012     r = pMsiGetProductInfoExA(prodcode, usersid,
6013                               MSIINSTALLCONTEXT_USERUNMANAGED,
6014                               "notvalid", buf, &sz);
6015     ok(r == ERROR_UNKNOWN_PROPERTY,
6016        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6017     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6018     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6019 
6020     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
6021     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6022 
6023     /* InstallDate value exists */
6024     sz = MAX_PATH;
6025     lstrcpyA(buf, "apple");
6026     r = pMsiGetProductInfoExA(prodcode, usersid,
6027                               MSIINSTALLCONTEXT_USERUNMANAGED,
6028                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
6029     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6030     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
6031     ok(sz == 4, "Expected 4, got %d\n", sz);
6032 
6033     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
6034     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6035 
6036     /* DisplayName value exists */
6037     sz = MAX_PATH;
6038     lstrcpyA(buf, "apple");
6039     r = pMsiGetProductInfoExA(prodcode, usersid,
6040                               MSIINSTALLCONTEXT_USERUNMANAGED,
6041                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
6042     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6043     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
6044     ok(sz == 4, "Expected 4, got %d\n", sz);
6045 
6046     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
6047     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6048 
6049     /* InstallLocation value exists */
6050     sz = MAX_PATH;
6051     lstrcpyA(buf, "apple");
6052     r = pMsiGetProductInfoExA(prodcode, usersid,
6053                               MSIINSTALLCONTEXT_USERUNMANAGED,
6054                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
6055     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6056     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
6057     ok(sz == 3, "Expected 3, got %d\n", sz);
6058 
6059     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
6060     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6061 
6062     /* InstallSource value exists */
6063     sz = MAX_PATH;
6064     lstrcpyA(buf, "apple");
6065     r = pMsiGetProductInfoExA(prodcode, usersid,
6066                               MSIINSTALLCONTEXT_USERUNMANAGED,
6067                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
6068     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6069     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
6070     ok(sz == 6, "Expected 6, got %d\n", sz);
6071 
6072     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6073     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6074 
6075     /* LocalPackage value exists */
6076     sz = MAX_PATH;
6077     lstrcpyA(buf, "apple");
6078     r = pMsiGetProductInfoExA(prodcode, usersid,
6079                               MSIINSTALLCONTEXT_USERUNMANAGED,
6080                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
6081     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6082     ok(!lstrcmpA(buf, "local"), "Expected \"local\", got \"%s\"\n", buf);
6083     ok(sz == 5, "Expected 5, got %d\n", sz);
6084 
6085     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
6086     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6087 
6088     /* Publisher value exists */
6089     sz = MAX_PATH;
6090     lstrcpyA(buf, "apple");
6091     r = pMsiGetProductInfoExA(prodcode, usersid,
6092                               MSIINSTALLCONTEXT_USERUNMANAGED,
6093                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
6094     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6095     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
6096     ok(sz == 3, "Expected 3, got %d\n", sz);
6097 
6098     res = RegSetValueExA(propkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
6099     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6100 
6101     /* URLInfoAbout value exists */
6102     sz = MAX_PATH;
6103     lstrcpyA(buf, "apple");
6104     r = pMsiGetProductInfoExA(prodcode, usersid,
6105                               MSIINSTALLCONTEXT_USERUNMANAGED,
6106                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
6107     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6108     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
6109     ok(sz == 5, "Expected 5, got %d\n", sz);
6110 
6111     res = RegSetValueExA(propkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
6112     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6113 
6114     /* URLUpdateInfo value exists */
6115     sz = MAX_PATH;
6116     lstrcpyA(buf, "apple");
6117     r = pMsiGetProductInfoExA(prodcode, usersid,
6118                               MSIINSTALLCONTEXT_USERUNMANAGED,
6119                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
6120     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6121     ok(!lstrcmpA(buf, "update"), "Expected \"update\", got \"%s\"\n", buf);
6122     ok(sz == 6, "Expected 6, got %d\n", sz);
6123 
6124     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
6125     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6126 
6127     /* VersionMinor value exists */
6128     sz = MAX_PATH;
6129     lstrcpyA(buf, "apple");
6130     r = pMsiGetProductInfoExA(prodcode, usersid,
6131                               MSIINSTALLCONTEXT_USERUNMANAGED,
6132                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
6133     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6134     ok(!lstrcmpA(buf, "2"), "Expected \"2\", got \"%s\"\n", buf);
6135     ok(sz == 1, "Expected 1, got %d\n", sz);
6136 
6137     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
6138     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6139 
6140     /* VersionMajor value exists */
6141     sz = MAX_PATH;
6142     lstrcpyA(buf, "apple");
6143     r = pMsiGetProductInfoExA(prodcode, usersid,
6144                               MSIINSTALLCONTEXT_USERUNMANAGED,
6145                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
6146     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6147     ok(!lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
6148     ok(sz == 1, "Expected 1, got %d\n", sz);
6149 
6150     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
6151     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6152 
6153     /* DisplayVersion value exists */
6154     sz = MAX_PATH;
6155     lstrcpyA(buf, "apple");
6156     r = pMsiGetProductInfoExA(prodcode, usersid,
6157                               MSIINSTALLCONTEXT_USERUNMANAGED,
6158                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
6159     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6160     ok(!lstrcmpA(buf, "3.2.1"), "Expected \"3.2.1\", got \"%s\"\n", buf);
6161     ok(sz == 5, "Expected 5, got %d\n", sz);
6162 
6163     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
6164     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6165 
6166     /* ProductID value exists */
6167     sz = MAX_PATH;
6168     lstrcpyA(buf, "apple");
6169     r = pMsiGetProductInfoExA(prodcode, usersid,
6170                               MSIINSTALLCONTEXT_USERUNMANAGED,
6171                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
6172     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6173     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
6174     ok(sz == 2, "Expected 2, got %d\n", sz);
6175 
6176     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
6177     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6178 
6179     /* RegCompany value exists */
6180     sz = MAX_PATH;
6181     lstrcpyA(buf, "apple");
6182     r = pMsiGetProductInfoExA(prodcode, usersid,
6183                               MSIINSTALLCONTEXT_USERUNMANAGED,
6184                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
6185     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6186     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
6187     ok(sz == 4, "Expected 4, got %d\n", sz);
6188 
6189     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
6190     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6191 
6192     /* RegOwner value exists */
6193     sz = MAX_PATH;
6194     lstrcpyA(buf, "apple");
6195     r = pMsiGetProductInfoExA(prodcode, usersid,
6196                               MSIINSTALLCONTEXT_USERUNMANAGED,
6197                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
6198     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6199     ok(!lstrcmpA(buf, "owner"), "Expected \"owner\", got \"%s\"\n", buf);
6200     ok(sz == 5, "Expected 5, got %d\n", sz);
6201 
6202     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
6203     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6204 
6205     /* Transforms value exists */
6206     sz = MAX_PATH;
6207     lstrcpyA(buf, "apple");
6208     r = pMsiGetProductInfoExA(prodcode, usersid,
6209                               MSIINSTALLCONTEXT_USERUNMANAGED,
6210                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
6211     ok(r == ERROR_UNKNOWN_PRODUCT,
6212        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6213     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6214     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6215 
6216     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
6217     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6218 
6219     /* Language value exists */
6220     sz = MAX_PATH;
6221     lstrcpyA(buf, "apple");
6222     r = pMsiGetProductInfoExA(prodcode, usersid,
6223                               MSIINSTALLCONTEXT_USERUNMANAGED,
6224                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
6225     ok(r == ERROR_UNKNOWN_PRODUCT,
6226        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6227     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6228     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6229 
6230     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
6231     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6232 
6233     /* ProductName value exists */
6234     sz = MAX_PATH;
6235     lstrcpyA(buf, "apple");
6236     r = pMsiGetProductInfoExA(prodcode, usersid,
6237                               MSIINSTALLCONTEXT_USERUNMANAGED,
6238                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
6239     ok(r == ERROR_UNKNOWN_PRODUCT,
6240        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6241     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6242     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6243 
6244     res = RegSetValueExA(propkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
6245     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6246 
6247     /* FIXME */
6248 
6249     /* AssignmentType value exists */
6250     sz = MAX_PATH;
6251     lstrcpyA(buf, "apple");
6252     r = pMsiGetProductInfoExA(prodcode, usersid,
6253                               MSIINSTALLCONTEXT_USERUNMANAGED,
6254                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
6255     ok(r == ERROR_UNKNOWN_PRODUCT,
6256        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6257     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6258     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6259 
6260     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
6261     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6262 
6263     /* PackageCode value exists */
6264     sz = MAX_PATH;
6265     lstrcpyA(buf, "apple");
6266     r = pMsiGetProductInfoExA(prodcode, usersid,
6267                               MSIINSTALLCONTEXT_USERUNMANAGED,
6268                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
6269     ok(r == ERROR_UNKNOWN_PRODUCT,
6270        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6271     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6272     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6273 
6274     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
6275     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6276 
6277     /* Version value exists */
6278     sz = MAX_PATH;
6279     lstrcpyA(buf, "apple");
6280     r = pMsiGetProductInfoExA(prodcode, usersid,
6281                               MSIINSTALLCONTEXT_USERUNMANAGED,
6282                               INSTALLPROPERTY_VERSIONA, buf, &sz);
6283     ok(r == ERROR_UNKNOWN_PRODUCT,
6284        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6285     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6286     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6287 
6288     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
6289     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6290 
6291     /* ProductIcon value exists */
6292     sz = MAX_PATH;
6293     lstrcpyA(buf, "apple");
6294     r = pMsiGetProductInfoExA(prodcode, usersid,
6295                               MSIINSTALLCONTEXT_USERUNMANAGED,
6296                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
6297     ok(r == ERROR_UNKNOWN_PRODUCT,
6298        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6299     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6300     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6301 
6302     res = RegSetValueExA(propkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
6303     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6304 
6305     /* PackageName value exists */
6306     sz = MAX_PATH;
6307     lstrcpyA(buf, "apple");
6308     r = pMsiGetProductInfoExA(prodcode, usersid,
6309                               MSIINSTALLCONTEXT_USERUNMANAGED,
6310                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
6311     ok(r == ERROR_UNKNOWN_PRODUCT,
6312        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6313     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6314     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6315 
6316     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
6317     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6318 
6319     /* AuthorizedLUAApp value exists */
6320     sz = MAX_PATH;
6321     lstrcpyA(buf, "apple");
6322     r = pMsiGetProductInfoExA(prodcode, usersid,
6323                               MSIINSTALLCONTEXT_USERUNMANAGED,
6324                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
6325     ok(r == ERROR_UNKNOWN_PRODUCT,
6326        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6327     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6328     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6329 
6330     RegDeleteValueA(propkey, "AuthorizedLUAApp");
6331     RegDeleteValueA(propkey, "PackageName");
6332     RegDeleteValueA(propkey, "ProductIcon");
6333     RegDeleteValueA(propkey, "Version");
6334     RegDeleteValueA(propkey, "PackageCode");
6335     RegDeleteValueA(propkey, "AssignmentType");
6336     RegDeleteValueA(propkey, "ProductName");
6337     RegDeleteValueA(propkey, "Language");
6338     RegDeleteValueA(propkey, "Transforms");
6339     RegDeleteValueA(propkey, "RegOwner");
6340     RegDeleteValueA(propkey, "RegCompany");
6341     RegDeleteValueA(propkey, "ProductID");
6342     RegDeleteValueA(propkey, "DisplayVersion");
6343     RegDeleteValueA(propkey, "VersionMajor");
6344     RegDeleteValueA(propkey, "VersionMinor");
6345     RegDeleteValueA(propkey, "URLUpdateInfo");
6346     RegDeleteValueA(propkey, "URLInfoAbout");
6347     RegDeleteValueA(propkey, "Publisher");
6348     RegDeleteValueA(propkey, "LocalPackage");
6349     RegDeleteValueA(propkey, "InstallSource");
6350     RegDeleteValueA(propkey, "InstallLocation");
6351     RegDeleteValueA(propkey, "DisplayName");
6352     RegDeleteValueA(propkey, "InstallDate");
6353     RegDeleteValueA(propkey, "HelpTelephone");
6354     RegDeleteValueA(propkey, "HelpLink");
6355     RegDeleteValueA(propkey, "LocalPackage");
6356     RegDeleteKeyA(propkey, "");
6357     RegCloseKey(propkey);
6358     RegDeleteKeyA(localkey, "");
6359     RegCloseKey(localkey);
6360 
6361     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
6362     lstrcatA(keypath, usersid);
6363     lstrcatA(keypath, "\\Installer\\Products\\");
6364     lstrcatA(keypath, prod_squashed);
6365 
6366     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
6367     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6368 
6369     /* user product key exists */
6370     sz = MAX_PATH;
6371     lstrcpyA(buf, "apple");
6372     r = pMsiGetProductInfoExA(prodcode, usersid,
6373                               MSIINSTALLCONTEXT_USERUNMANAGED,
6374                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6375     ok(r == ERROR_UNKNOWN_PRODUCT,
6376        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6377     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6378     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6379 
6380     RegDeleteKeyA(userkey, "");
6381     RegCloseKey(userkey);
6382 
6383     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
6384     lstrcatA(keypath, prod_squashed);
6385 
6386     res = RegCreateKeyExA(HKEY_CURRENT_USER, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
6387     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6388 
6389     sz = MAX_PATH;
6390     lstrcpyA(buf, "apple");
6391     r = pMsiGetProductInfoExA(prodcode, usersid,
6392                               MSIINSTALLCONTEXT_USERUNMANAGED,
6393                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6394     ok(r == ERROR_SUCCESS || broken(r == ERROR_UNKNOWN_PRODUCT), "Expected ERROR_SUCCESS, got %d\n", r);
6395     if (r == ERROR_UNKNOWN_PRODUCT)
6396     {
6397         win_skip("skipping remaining tests for MsiGetProductInfoEx\n");
6398         delete_key(prodkey, "", access);
6399         RegCloseKey(prodkey);
6400         return;
6401     }
6402     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
6403     ok(sz == 1, "Expected 1, got %d\n", sz);
6404 
6405     res = RegSetValueExA(prodkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
6406     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6407 
6408     /* HelpLink value exists */
6409     sz = MAX_PATH;
6410     lstrcpyA(buf, "apple");
6411     r = pMsiGetProductInfoExA(prodcode, usersid,
6412                               MSIINSTALLCONTEXT_USERUNMANAGED,
6413                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
6414     ok(r == ERROR_UNKNOWN_PROPERTY,
6415        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6416     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6417     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6418 
6419     res = RegSetValueExA(prodkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
6420     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6421 
6422     /* HelpTelephone value exists */
6423     sz = MAX_PATH;
6424     lstrcpyA(buf, "apple");
6425     r = pMsiGetProductInfoExA(prodcode, usersid,
6426                               MSIINSTALLCONTEXT_USERUNMANAGED,
6427                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
6428     ok(r == ERROR_UNKNOWN_PROPERTY,
6429        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6430     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6431     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6432 
6433     res = RegSetValueExA(prodkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
6434     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6435 
6436     /* InstallDate value exists */
6437     sz = MAX_PATH;
6438     lstrcpyA(buf, "apple");
6439     r = pMsiGetProductInfoExA(prodcode, usersid,
6440                               MSIINSTALLCONTEXT_USERUNMANAGED,
6441                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
6442     ok(r == ERROR_UNKNOWN_PROPERTY,
6443        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6444     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6445     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6446 
6447     res = RegSetValueExA(prodkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
6448     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6449 
6450     /* DisplayName value exists */
6451     sz = MAX_PATH;
6452     lstrcpyA(buf, "apple");
6453     r = pMsiGetProductInfoExA(prodcode, usersid,
6454                               MSIINSTALLCONTEXT_USERUNMANAGED,
6455                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
6456     ok(r == ERROR_UNKNOWN_PROPERTY,
6457        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6458     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6459     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6460 
6461     res = RegSetValueExA(prodkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
6462     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6463 
6464     /* InstallLocation value exists */
6465     sz = MAX_PATH;
6466     lstrcpyA(buf, "apple");
6467     r = pMsiGetProductInfoExA(prodcode, usersid,
6468                               MSIINSTALLCONTEXT_USERUNMANAGED,
6469                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
6470     ok(r == ERROR_UNKNOWN_PROPERTY,
6471        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6472     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6473     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6474 
6475     res = RegSetValueExA(prodkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
6476     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6477 
6478     /* InstallSource value exists */
6479     sz = MAX_PATH;
6480     lstrcpyA(buf, "apple");
6481     r = pMsiGetProductInfoExA(prodcode, usersid,
6482                               MSIINSTALLCONTEXT_USERUNMANAGED,
6483                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
6484     ok(r == ERROR_UNKNOWN_PROPERTY,
6485        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6486     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6487     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6488 
6489     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6490     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6491 
6492     /* LocalPackage value exists */
6493     sz = MAX_PATH;
6494     lstrcpyA(buf, "apple");
6495     r = pMsiGetProductInfoExA(prodcode, usersid,
6496                               MSIINSTALLCONTEXT_USERUNMANAGED,
6497                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
6498     ok(r == ERROR_UNKNOWN_PROPERTY,
6499        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6500     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6501     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6502 
6503     res = RegSetValueExA(prodkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
6504     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6505 
6506     /* Publisher value exists */
6507     sz = MAX_PATH;
6508     lstrcpyA(buf, "apple");
6509     r = pMsiGetProductInfoExA(prodcode, usersid,
6510                               MSIINSTALLCONTEXT_USERUNMANAGED,
6511                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
6512     ok(r == ERROR_UNKNOWN_PROPERTY,
6513        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6514     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6515     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6516 
6517     res = RegSetValueExA(prodkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
6518     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6519 
6520     /* URLInfoAbout value exists */
6521     sz = MAX_PATH;
6522     lstrcpyA(buf, "apple");
6523     r = pMsiGetProductInfoExA(prodcode, usersid,
6524                               MSIINSTALLCONTEXT_USERUNMANAGED,
6525                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
6526     ok(r == ERROR_UNKNOWN_PROPERTY,
6527        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6528     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6529     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6530 
6531     res = RegSetValueExA(prodkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
6532     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6533 
6534     /* URLUpdateInfo value exists */
6535     sz = MAX_PATH;
6536     lstrcpyA(buf, "apple");
6537     r = pMsiGetProductInfoExA(prodcode, usersid,
6538                               MSIINSTALLCONTEXT_USERUNMANAGED,
6539                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
6540     ok(r == ERROR_UNKNOWN_PROPERTY,
6541        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6542     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6543     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6544 
6545     res = RegSetValueExA(prodkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
6546     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6547 
6548     /* VersionMinor value exists */
6549     sz = MAX_PATH;
6550     lstrcpyA(buf, "apple");
6551     r = pMsiGetProductInfoExA(prodcode, usersid,
6552                               MSIINSTALLCONTEXT_USERUNMANAGED,
6553                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
6554     ok(r == ERROR_UNKNOWN_PROPERTY,
6555        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6556     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6557     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6558 
6559     res = RegSetValueExA(prodkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
6560     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6561 
6562     /* VersionMajor value exists */
6563     sz = MAX_PATH;
6564     lstrcpyA(buf, "apple");
6565     r = pMsiGetProductInfoExA(prodcode, usersid,
6566                               MSIINSTALLCONTEXT_USERUNMANAGED,
6567                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
6568     ok(r == ERROR_UNKNOWN_PROPERTY,
6569        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6570     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6571     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6572 
6573     res = RegSetValueExA(prodkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
6574     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6575 
6576     /* DisplayVersion value exists */
6577     sz = MAX_PATH;
6578     lstrcpyA(buf, "apple");
6579     r = pMsiGetProductInfoExA(prodcode, usersid,
6580                               MSIINSTALLCONTEXT_USERUNMANAGED,
6581                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
6582     ok(r == ERROR_UNKNOWN_PROPERTY,
6583        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6584     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6585     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6586 
6587     res = RegSetValueExA(prodkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
6588     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6589 
6590     /* ProductID value exists */
6591     sz = MAX_PATH;
6592     lstrcpyA(buf, "apple");
6593     r = pMsiGetProductInfoExA(prodcode, usersid,
6594                               MSIINSTALLCONTEXT_USERUNMANAGED,
6595                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
6596     ok(r == ERROR_UNKNOWN_PROPERTY,
6597        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6598     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6599     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6600 
6601     res = RegSetValueExA(prodkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
6602     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6603 
6604     /* RegCompany value exists */
6605     sz = MAX_PATH;
6606     lstrcpyA(buf, "apple");
6607     r = pMsiGetProductInfoExA(prodcode, usersid,
6608                               MSIINSTALLCONTEXT_USERUNMANAGED,
6609                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
6610     ok(r == ERROR_UNKNOWN_PROPERTY,
6611        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6612     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6613     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6614 
6615     res = RegSetValueExA(prodkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
6616     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6617 
6618     /* RegOwner value exists */
6619     sz = MAX_PATH;
6620     lstrcpyA(buf, "apple");
6621     r = pMsiGetProductInfoExA(prodcode, usersid,
6622                               MSIINSTALLCONTEXT_USERUNMANAGED,
6623                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
6624     ok(r == ERROR_UNKNOWN_PROPERTY,
6625        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6626     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6627     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6628 
6629     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
6630     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6631 
6632     /* Transforms value exists */
6633     sz = MAX_PATH;
6634     lstrcpyA(buf, "apple");
6635     r = pMsiGetProductInfoExA(prodcode, usersid,
6636                               MSIINSTALLCONTEXT_USERUNMANAGED,
6637                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
6638     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6639     ok(!lstrcmpA(buf, "trans"), "Expected \"trans\", got \"%s\"\n", buf);
6640     ok(sz == 5, "Expected 5, got %d\n", sz);
6641 
6642     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
6643     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6644 
6645     /* Language value exists */
6646     sz = MAX_PATH;
6647     lstrcpyA(buf, "apple");
6648     r = pMsiGetProductInfoExA(prodcode, usersid,
6649                               MSIINSTALLCONTEXT_USERUNMANAGED,
6650                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
6651     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6652     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
6653     ok(sz == 4, "Expected 4, got %d\n", sz);
6654 
6655     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
6656     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6657 
6658     /* ProductName value exists */
6659     sz = MAX_PATH;
6660     lstrcpyA(buf, "apple");
6661     r = pMsiGetProductInfoExA(prodcode, usersid,
6662                               MSIINSTALLCONTEXT_USERUNMANAGED,
6663                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
6664     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6665     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
6666     ok(sz == 4, "Expected 4, got %d\n", sz);
6667 
6668     res = RegSetValueExA(prodkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
6669     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6670 
6671     /* FIXME */
6672 
6673     /* AssignmentType value exists */
6674     sz = MAX_PATH;
6675     lstrcpyA(buf, "apple");
6676     r = pMsiGetProductInfoExA(prodcode, usersid,
6677                               MSIINSTALLCONTEXT_USERUNMANAGED,
6678                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
6679     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6680     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
6681     ok(sz == 0, "Expected 0, got %d\n", sz);
6682 
6683     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
6684     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6685 
6686     /* FIXME */
6687 
6688     /* PackageCode value exists */
6689     sz = MAX_PATH;
6690     lstrcpyA(buf, "apple");
6691     r = pMsiGetProductInfoExA(prodcode, usersid,
6692                               MSIINSTALLCONTEXT_USERUNMANAGED,
6693                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
6694     todo_wine
6695     {
6696         ok(r == ERROR_BAD_CONFIGURATION,
6697            "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
6698         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6699         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6700     }
6701 
6702     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
6703     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6704 
6705     /* Version value exists */
6706     sz = MAX_PATH;
6707     lstrcpyA(buf, "apple");
6708     r = pMsiGetProductInfoExA(prodcode, usersid,
6709                               MSIINSTALLCONTEXT_USERUNMANAGED,
6710                               INSTALLPROPERTY_VERSIONA, buf, &sz);
6711     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6712     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
6713     ok(sz == 3, "Expected 3, got %d\n", sz);
6714 
6715     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
6716     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6717 
6718     /* ProductIcon value exists */
6719     sz = MAX_PATH;
6720     lstrcpyA(buf, "apple");
6721     r = pMsiGetProductInfoExA(prodcode, usersid,
6722                               MSIINSTALLCONTEXT_USERUNMANAGED,
6723                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
6724     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6725     ok(!lstrcmpA(buf, "icon"), "Expected \"icon\", got \"%s\"\n", buf);
6726     ok(sz == 4, "Expected 4, got %d\n", sz);
6727 
6728     res = RegSetValueExA(prodkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
6729     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6730 
6731     /* PackageName value exists */
6732     sz = MAX_PATH;
6733     lstrcpyA(buf, "apple");
6734     r = pMsiGetProductInfoExA(prodcode, usersid,
6735                               MSIINSTALLCONTEXT_USERUNMANAGED,
6736                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
6737     todo_wine
6738     {
6739         ok(r == ERROR_UNKNOWN_PRODUCT,
6740            "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6741         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6742         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6743     }
6744 
6745     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
6746     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6747 
6748     /* AuthorizedLUAApp value exists */
6749     sz = MAX_PATH;
6750     lstrcpyA(buf, "apple");
6751     r = pMsiGetProductInfoExA(prodcode, usersid,
6752                               MSIINSTALLCONTEXT_USERUNMANAGED,
6753                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
6754     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6755     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
6756     ok(sz == 4, "Expected 4, got %d\n", sz);
6757 
6758     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
6759     RegDeleteValueA(prodkey, "PackageName");
6760     RegDeleteValueA(prodkey, "ProductIcon");
6761     RegDeleteValueA(prodkey, "Version");
6762     RegDeleteValueA(prodkey, "PackageCode");
6763     RegDeleteValueA(prodkey, "AssignmentType");
6764     RegDeleteValueA(prodkey, "ProductName");
6765     RegDeleteValueA(prodkey, "Language");
6766     RegDeleteValueA(prodkey, "Transforms");
6767     RegDeleteValueA(prodkey, "RegOwner");
6768     RegDeleteValueA(prodkey, "RegCompany");
6769     RegDeleteValueA(prodkey, "ProductID");
6770     RegDeleteValueA(prodkey, "DisplayVersion");
6771     RegDeleteValueA(prodkey, "VersionMajor");
6772     RegDeleteValueA(prodkey, "VersionMinor");
6773     RegDeleteValueA(prodkey, "URLUpdateInfo");
6774     RegDeleteValueA(prodkey, "URLInfoAbout");
6775     RegDeleteValueA(prodkey, "Publisher");
6776     RegDeleteValueA(prodkey, "LocalPackage");
6777     RegDeleteValueA(prodkey, "InstallSource");
6778     RegDeleteValueA(prodkey, "InstallLocation");
6779     RegDeleteValueA(prodkey, "DisplayName");
6780     RegDeleteValueA(prodkey, "InstallDate");
6781     RegDeleteValueA(prodkey, "HelpTelephone");
6782     RegDeleteValueA(prodkey, "HelpLink");
6783     RegDeleteValueA(prodkey, "LocalPackage");
6784     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
6785     RegCloseKey(prodkey);
6786 
6787     /* MSIINSTALLCONTEXT_USERMANAGED */
6788 
6789     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
6790     lstrcatA(keypath, usersid);
6791     lstrcatA(keypath, "\\Products\\");
6792     lstrcatA(keypath, prod_squashed);
6793 
6794     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
6795     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6796 
6797     /* local user product key exists */
6798     sz = MAX_PATH;
6799     lstrcpyA(buf, "apple");
6800     r = pMsiGetProductInfoExA(prodcode, usersid,
6801                               MSIINSTALLCONTEXT_USERMANAGED,
6802                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6803     ok(r == ERROR_UNKNOWN_PRODUCT,
6804        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6805     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6806     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6807 
6808     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
6809     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6810 
6811     /* InstallProperties key exists */
6812     sz = MAX_PATH;
6813     lstrcpyA(buf, "apple");
6814     r = pMsiGetProductInfoExA(prodcode, usersid,
6815                               MSIINSTALLCONTEXT_USERMANAGED,
6816                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6817     ok(r == ERROR_UNKNOWN_PRODUCT,
6818        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6819     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6820     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6821 
6822     res = RegSetValueExA(propkey, "ManagedLocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6823     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6824 
6825     /* ManagedLocalPackage value exists */
6826     sz = MAX_PATH;
6827     lstrcpyA(buf, "apple");
6828     r = pMsiGetProductInfoExA(prodcode, usersid,
6829                               MSIINSTALLCONTEXT_USERMANAGED,
6830                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6831     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6832     ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
6833     ok(sz == 1, "Expected 1, got %d\n", sz);
6834 
6835     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
6836     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6837 
6838     /* HelpLink value exists */
6839     sz = MAX_PATH;
6840     lstrcpyA(buf, "apple");
6841     r = pMsiGetProductInfoExA(prodcode, usersid,
6842                               MSIINSTALLCONTEXT_USERMANAGED,
6843                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
6844     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6845     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
6846     ok(sz == 4, "Expected 4, got %d\n", sz);
6847 
6848     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
6849     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6850 
6851     /* HelpTelephone value exists */
6852     sz = MAX_PATH;
6853     lstrcpyA(buf, "apple");
6854     r = pMsiGetProductInfoExA(prodcode, usersid,
6855                               MSIINSTALLCONTEXT_USERMANAGED,
6856                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
6857     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6858     ok(!lstrcmpA(buf, "phone"), "Expected \"phone\", got \"%s\"\n", buf);
6859     ok(sz == 5, "Expected 5, got %d\n", sz);
6860 
6861     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
6862     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6863 
6864     /* InstallDate value exists */
6865     sz = MAX_PATH;
6866     lstrcpyA(buf, "apple");
6867     r = pMsiGetProductInfoExA(prodcode, usersid,
6868                               MSIINSTALLCONTEXT_USERMANAGED,
6869                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
6870     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6871     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
6872     ok(sz == 4, "Expected 4, got %d\n", sz);
6873 
6874     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
6875     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6876 
6877     /* DisplayName value exists */
6878     sz = MAX_PATH;
6879     lstrcpyA(buf, "apple");
6880     r = pMsiGetProductInfoExA(prodcode, usersid,
6881                               MSIINSTALLCONTEXT_USERMANAGED,
6882                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
6883     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6884     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
6885     ok(sz == 4, "Expected 4, got %d\n", sz);
6886 
6887     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
6888     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6889 
6890     /* InstallLocation value exists */
6891     sz = MAX_PATH;
6892     lstrcpyA(buf, "apple");
6893     r = pMsiGetProductInfoExA(prodcode, usersid,
6894                               MSIINSTALLCONTEXT_USERMANAGED,
6895                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
6896     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6897     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
6898     ok(sz == 3, "Expected 3, got %d\n", sz);
6899 
6900     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
6901     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6902 
6903     /* InstallSource value exists */
6904     sz = MAX_PATH;
6905     lstrcpyA(buf, "apple");
6906     r = pMsiGetProductInfoExA(prodcode, usersid,
6907                               MSIINSTALLCONTEXT_USERMANAGED,
6908                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
6909     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6910     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
6911     ok(sz == 6, "Expected 6, got %d\n", sz);
6912 
6913     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6914     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6915 
6916     /* LocalPackage value exists */
6917     sz = MAX_PATH;
6918     lstrcpyA(buf, "apple");
6919     r = pMsiGetProductInfoExA(prodcode, usersid,
6920                               MSIINSTALLCONTEXT_USERMANAGED,
6921                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
6922     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6923     ok(!lstrcmpA(buf, "local"), "Expected \"local\", got \"%s\"\n", buf);
6924     ok(sz == 5, "Expected 5, got %d\n", sz);
6925 
6926     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
6927     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6928 
6929     /* Publisher value exists */
6930     sz = MAX_PATH;
6931     lstrcpyA(buf, "apple");
6932     r = pMsiGetProductInfoExA(prodcode, usersid,
6933                               MSIINSTALLCONTEXT_USERMANAGED,
6934                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
6935     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6936     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
6937     ok(sz == 3, "Expected 3, got %d\n", sz);
6938 
6939     res = RegSetValueExA(propkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
6940     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6941 
6942     /* URLInfoAbout value exists */
6943     sz = MAX_PATH;
6944     lstrcpyA(buf, "apple");
6945     r = pMsiGetProductInfoExA(prodcode, usersid,
6946                               MSIINSTALLCONTEXT_USERMANAGED,
6947                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
6948     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6949     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
6950     ok(sz == 5, "Expected 5, got %d\n", sz);
6951 
6952     res = RegSetValueExA(propkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
6953     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6954 
6955     /* URLUpdateInfo value exists */
6956     sz = MAX_PATH;
6957     lstrcpyA(buf, "apple");
6958     r = pMsiGetProductInfoExA(prodcode, usersid,
6959                               MSIINSTALLCONTEXT_USERMANAGED,
6960                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
6961     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6962     ok(!lstrcmpA(buf, "update"), "Expected \"update\", got \"%s\"\n", buf);
6963     ok(sz == 6, "Expected 6, got %d\n", sz);
6964 
6965     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
6966     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6967 
6968     /* VersionMinor value exists */
6969     sz = MAX_PATH;
6970     lstrcpyA(buf, "apple");
6971     r = pMsiGetProductInfoExA(prodcode, usersid,
6972                               MSIINSTALLCONTEXT_USERMANAGED,
6973                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
6974     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6975     ok(!lstrcmpA(buf, "2"), "Expected \"2\", got \"%s\"\n", buf);
6976     ok(sz == 1, "Expected 1, got %d\n", sz);
6977 
6978     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
6979     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6980 
6981     /* VersionMajor value exists */
6982     sz = MAX_PATH;
6983     lstrcpyA(buf, "apple");
6984     r = pMsiGetProductInfoExA(prodcode, usersid,
6985                               MSIINSTALLCONTEXT_USERMANAGED,
6986                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
6987     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6988     ok(!lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
6989     ok(sz == 1, "Expected 1, got %d\n", sz);
6990 
6991     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
6992     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6993 
6994     /* DisplayVersion value exists */
6995     sz = MAX_PATH;
6996     lstrcpyA(buf, "apple");
6997     r = pMsiGetProductInfoExA(prodcode, usersid,
6998                               MSIINSTALLCONTEXT_USERMANAGED,
6999                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
7000     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7001     ok(!lstrcmpA(buf, "3.2.1"), "Expected \"3.2.1\", got \"%s\"\n", buf);
7002     ok(sz == 5, "Expected 5, got %d\n", sz);
7003 
7004     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
7005     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7006 
7007     /* ProductID value exists */
7008     sz = MAX_PATH;
7009     lstrcpyA(buf, "apple");
7010     r = pMsiGetProductInfoExA(prodcode, usersid,
7011                               MSIINSTALLCONTEXT_USERMANAGED,
7012                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
7013     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7014     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
7015     ok(sz == 2, "Expected 2, got %d\n", sz);
7016 
7017     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
7018     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7019 
7020     /* RegCompany value exists */
7021     sz = MAX_PATH;
7022     lstrcpyA(buf, "apple");
7023     r = pMsiGetProductInfoExA(prodcode, usersid,
7024                               MSIINSTALLCONTEXT_USERMANAGED,
7025                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
7026     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7027     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
7028     ok(sz == 4, "Expected 4, got %d\n", sz);
7029 
7030     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
7031     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7032 
7033     /* RegOwner value exists */
7034     sz = MAX_PATH;
7035     lstrcpyA(buf, "apple");
7036     r = pMsiGetProductInfoExA(prodcode, usersid,
7037                               MSIINSTALLCONTEXT_USERMANAGED,
7038                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
7039     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7040     ok(!lstrcmpA(buf, "owner"), "Expected \"owner\", got \"%s\"\n", buf);
7041     ok(sz == 5, "Expected 5, got %d\n", sz);
7042 
7043     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
7044     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7045 
7046     /* Transforms value exists */
7047     sz = MAX_PATH;
7048     lstrcpyA(buf, "apple");
7049     r = pMsiGetProductInfoExA(prodcode, usersid,
7050                               MSIINSTALLCONTEXT_USERMANAGED,
7051                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
7052     ok(r == ERROR_UNKNOWN_PRODUCT,
7053        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7054     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7055     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7056 
7057     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
7058     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7059 
7060     /* Language value exists */
7061     sz = MAX_PATH;
7062     lstrcpyA(buf, "apple");
7063     r = pMsiGetProductInfoExA(prodcode, usersid,
7064                               MSIINSTALLCONTEXT_USERMANAGED,
7065                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
7066     ok(r == ERROR_UNKNOWN_PRODUCT,
7067        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7068     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7069     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7070 
7071     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
7072     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7073 
7074     /* ProductName value exists */
7075     sz = MAX_PATH;
7076     lstrcpyA(buf, "apple");
7077     r = pMsiGetProductInfoExA(prodcode, usersid,
7078                               MSIINSTALLCONTEXT_USERMANAGED,
7079                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
7080     ok(r == ERROR_UNKNOWN_PRODUCT,
7081        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7082     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7083     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7084 
7085     res = RegSetValueExA(propkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
7086     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7087 
7088     /* FIXME */
7089 
7090     /* AssignmentType value exists */
7091     sz = MAX_PATH;
7092     lstrcpyA(buf, "apple");
7093     r = pMsiGetProductInfoExA(prodcode, usersid,
7094                               MSIINSTALLCONTEXT_USERMANAGED,
7095                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
7096     ok(r == ERROR_UNKNOWN_PRODUCT,
7097        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7098     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7099     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7100 
7101     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
7102     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7103 
7104     /* PackageCode value exists */
7105     sz = MAX_PATH;
7106     lstrcpyA(buf, "apple");
7107     r = pMsiGetProductInfoExA(prodcode, usersid,
7108                               MSIINSTALLCONTEXT_USERMANAGED,
7109                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
7110     ok(r == ERROR_UNKNOWN_PRODUCT,
7111        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7112     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7113     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7114 
7115     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
7116     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7117 
7118     /* Version value exists */
7119     sz = MAX_PATH;
7120     lstrcpyA(buf, "apple");
7121     r = pMsiGetProductInfoExA(prodcode, usersid,
7122                               MSIINSTALLCONTEXT_USERMANAGED,
7123                               INSTALLPROPERTY_VERSIONA, buf, &sz);
7124     ok(r == ERROR_UNKNOWN_PRODUCT,
7125        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7126     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7127     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7128 
7129     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
7130     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7131 
7132     /* ProductIcon value exists */
7133     sz = MAX_PATH;
7134     lstrcpyA(buf, "apple");
7135     r = pMsiGetProductInfoExA(prodcode, usersid,
7136                               MSIINSTALLCONTEXT_USERMANAGED,
7137                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
7138     ok(r == ERROR_UNKNOWN_PRODUCT,
7139        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7140     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7141     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7142 
7143     res = RegSetValueExA(propkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
7144     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7145 
7146     /* PackageName value exists */
7147     sz = MAX_PATH;
7148     lstrcpyA(buf, "apple");
7149     r = pMsiGetProductInfoExA(prodcode, usersid,
7150                               MSIINSTALLCONTEXT_USERMANAGED,
7151                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
7152     ok(r == ERROR_UNKNOWN_PRODUCT,
7153        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7154     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7155     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7156 
7157     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
7158     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7159 
7160     /* AuthorizedLUAApp value exists */
7161     sz = MAX_PATH;
7162     lstrcpyA(buf, "apple");
7163     r = pMsiGetProductInfoExA(prodcode, usersid,
7164                               MSIINSTALLCONTEXT_USERMANAGED,
7165                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
7166     ok(r == ERROR_UNKNOWN_PRODUCT,
7167        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7168     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7169     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7170 
7171     RegDeleteValueA(propkey, "AuthorizedLUAApp");
7172     RegDeleteValueA(propkey, "PackageName");
7173     RegDeleteValueA(propkey, "ProductIcon");
7174     RegDeleteValueA(propkey, "Version");
7175     RegDeleteValueA(propkey, "PackageCode");
7176     RegDeleteValueA(propkey, "AssignmentType");
7177     RegDeleteValueA(propkey, "ProductName");
7178     RegDeleteValueA(propkey, "Language");
7179     RegDeleteValueA(propkey, "Transforms");
7180     RegDeleteValueA(propkey, "RegOwner");
7181     RegDeleteValueA(propkey, "RegCompany");
7182     RegDeleteValueA(propkey, "ProductID");
7183     RegDeleteValueA(propkey, "DisplayVersion");
7184     RegDeleteValueA(propkey, "VersionMajor");
7185     RegDeleteValueA(propkey, "VersionMinor");
7186     RegDeleteValueA(propkey, "URLUpdateInfo");
7187     RegDeleteValueA(propkey, "URLInfoAbout");
7188     RegDeleteValueA(propkey, "Publisher");
7189     RegDeleteValueA(propkey, "LocalPackage");
7190     RegDeleteValueA(propkey, "InstallSource");
7191     RegDeleteValueA(propkey, "InstallLocation");
7192     RegDeleteValueA(propkey, "DisplayName");
7193     RegDeleteValueA(propkey, "InstallDate");
7194     RegDeleteValueA(propkey, "HelpTelephone");
7195     RegDeleteValueA(propkey, "HelpLink");
7196     RegDeleteValueA(propkey, "ManagedLocalPackage");
7197     delete_key(propkey, "", access & KEY_WOW64_64KEY);
7198     RegCloseKey(propkey);
7199     delete_key(localkey, "", access & KEY_WOW64_64KEY);
7200     RegCloseKey(localkey);
7201 
7202     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
7203     lstrcatA(keypath, usersid);
7204     lstrcatA(keypath, "\\Installer\\Products\\");
7205     lstrcatA(keypath, prod_squashed);
7206 
7207     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
7208     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7209 
7210     /* user product key exists */
7211     sz = MAX_PATH;
7212     lstrcpyA(buf, "apple");
7213     r = pMsiGetProductInfoExA(prodcode, usersid,
7214                               MSIINSTALLCONTEXT_USERMANAGED,
7215                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7216     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7217     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
7218     ok(sz == 1, "Expected 1, got %d\n", sz);
7219 
7220     delete_key(userkey, "", access & KEY_WOW64_64KEY);
7221     RegCloseKey(userkey);
7222 
7223     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
7224     lstrcatA(keypath, prod_squashed);
7225 
7226     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
7227     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7228 
7229     /* current user product key exists */
7230     sz = MAX_PATH;
7231     lstrcpyA(buf, "apple");
7232     r = pMsiGetProductInfoExA(prodcode, usersid,
7233                               MSIINSTALLCONTEXT_USERMANAGED,
7234                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7235     ok(r == ERROR_UNKNOWN_PRODUCT,
7236        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7237     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7238     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7239 
7240     res = RegSetValueExA(prodkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
7241     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7242 
7243     /* HelpLink value exists, user product key does not exist */
7244     sz = MAX_PATH;
7245     lstrcpyA(buf, "apple");
7246     r = pMsiGetProductInfoExA(prodcode, usersid,
7247                               MSIINSTALLCONTEXT_USERMANAGED,
7248                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
7249     ok(r == ERROR_UNKNOWN_PRODUCT,
7250        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7251     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7252     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7253 
7254     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
7255     lstrcatA(keypath, usersid);
7256     lstrcatA(keypath, "\\Installer\\Products\\");
7257     lstrcatA(keypath, prod_squashed);
7258 
7259     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
7260     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7261 
7262     res = RegSetValueExA(userkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
7263     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7264 
7265     /* HelpLink value exists, user product key does exist */
7266     sz = MAX_PATH;
7267     lstrcpyA(buf, "apple");
7268     r = pMsiGetProductInfoExA(prodcode, usersid,
7269                               MSIINSTALLCONTEXT_USERMANAGED,
7270                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
7271     ok(r == ERROR_UNKNOWN_PROPERTY,
7272        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7273     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7274     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7275 
7276     res = RegSetValueExA(userkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
7277     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7278 
7279     /* HelpTelephone value exists */
7280     sz = MAX_PATH;
7281     lstrcpyA(buf, "apple");
7282     r = pMsiGetProductInfoExA(prodcode, usersid,
7283                               MSIINSTALLCONTEXT_USERMANAGED,
7284                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
7285     ok(r == ERROR_UNKNOWN_PROPERTY,
7286        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7287     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7288     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7289 
7290     res = RegSetValueExA(userkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
7291     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7292 
7293     /* InstallDate value exists */
7294     sz = MAX_PATH;
7295     lstrcpyA(buf, "apple");
7296     r = pMsiGetProductInfoExA(prodcode, usersid,
7297                               MSIINSTALLCONTEXT_USERMANAGED,
7298                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
7299     ok(r == ERROR_UNKNOWN_PROPERTY,
7300        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7301     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7302     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7303 
7304     res = RegSetValueExA(userkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
7305     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7306 
7307     /* DisplayName value exists */
7308     sz = MAX_PATH;
7309     lstrcpyA(buf, "apple");
7310     r = pMsiGetProductInfoExA(prodcode, usersid,
7311                               MSIINSTALLCONTEXT_USERMANAGED,
7312                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
7313     ok(r == ERROR_UNKNOWN_PROPERTY,
7314        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7315     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7316     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7317 
7318     res = RegSetValueExA(userkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
7319     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7320 
7321     /* InstallLocation value exists */
7322     sz = MAX_PATH;
7323     lstrcpyA(buf, "apple");
7324     r = pMsiGetProductInfoExA(prodcode, usersid,
7325                               MSIINSTALLCONTEXT_USERMANAGED,
7326                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
7327     ok(r == ERROR_UNKNOWN_PROPERTY,
7328        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7329     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7330     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7331 
7332     res = RegSetValueExA(userkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
7333     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7334 
7335     /* InstallSource value exists */
7336     sz = MAX_PATH;
7337     lstrcpyA(buf, "apple");
7338     r = pMsiGetProductInfoExA(prodcode, usersid,
7339                               MSIINSTALLCONTEXT_USERMANAGED,
7340                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
7341     ok(r == ERROR_UNKNOWN_PROPERTY,
7342        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7343     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7344     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7345 
7346     res = RegSetValueExA(userkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
7347     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7348 
7349     /* LocalPackage value exists */
7350     sz = MAX_PATH;
7351     lstrcpyA(buf, "apple");
7352     r = pMsiGetProductInfoExA(prodcode, usersid,
7353                               MSIINSTALLCONTEXT_USERMANAGED,
7354                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
7355     ok(r == ERROR_UNKNOWN_PROPERTY,
7356        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7357     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7358     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7359 
7360     res = RegSetValueExA(userkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
7361     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7362 
7363     /* Publisher value exists */
7364     sz = MAX_PATH;
7365     lstrcpyA(buf, "apple");
7366     r = pMsiGetProductInfoExA(prodcode, usersid,
7367                               MSIINSTALLCONTEXT_USERMANAGED,
7368                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
7369     ok(r == ERROR_UNKNOWN_PROPERTY,
7370        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7371     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7372     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7373 
7374     res = RegSetValueExA(userkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
7375     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7376 
7377     /* URLInfoAbout value exists */
7378     sz = MAX_PATH;
7379     lstrcpyA(buf, "apple");
7380     r = pMsiGetProductInfoExA(prodcode, usersid,
7381                               MSIINSTALLCONTEXT_USERMANAGED,
7382                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
7383     ok(r == ERROR_UNKNOWN_PROPERTY,
7384        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7385     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7386     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7387 
7388     res = RegSetValueExA(userkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
7389     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7390 
7391     /* URLUpdateInfo value exists */
7392     sz = MAX_PATH;
7393     lstrcpyA(buf, "apple");
7394     r = pMsiGetProductInfoExA(prodcode, usersid,
7395                               MSIINSTALLCONTEXT_USERMANAGED,
7396                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
7397     ok(r == ERROR_UNKNOWN_PROPERTY,
7398        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7399     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7400     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7401 
7402     res = RegSetValueExA(userkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
7403     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7404 
7405     /* VersionMinor value exists */
7406     sz = MAX_PATH;
7407     lstrcpyA(buf, "apple");
7408     r = pMsiGetProductInfoExA(prodcode, usersid,
7409                               MSIINSTALLCONTEXT_USERMANAGED,
7410                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
7411     ok(r == ERROR_UNKNOWN_PROPERTY,
7412        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7413     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7414     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7415 
7416     res = RegSetValueExA(userkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
7417     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7418 
7419     /* VersionMajor value exists */
7420     sz = MAX_PATH;
7421     lstrcpyA(buf, "apple");
7422     r = pMsiGetProductInfoExA(prodcode, usersid,
7423                               MSIINSTALLCONTEXT_USERMANAGED,
7424                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
7425     ok(r == ERROR_UNKNOWN_PROPERTY,
7426        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7427     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7428     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7429 
7430     res = RegSetValueExA(userkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
7431     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7432 
7433     /* DisplayVersion value exists */
7434     sz = MAX_PATH;
7435     lstrcpyA(buf, "apple");
7436     r = pMsiGetProductInfoExA(prodcode, usersid,
7437                               MSIINSTALLCONTEXT_USERMANAGED,
7438                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
7439     ok(r == ERROR_UNKNOWN_PROPERTY,
7440        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7441     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7442     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7443 
7444     res = RegSetValueExA(userkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
7445     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7446 
7447     /* ProductID value exists */
7448     sz = MAX_PATH;
7449     lstrcpyA(buf, "apple");
7450     r = pMsiGetProductInfoExA(prodcode, usersid,
7451                               MSIINSTALLCONTEXT_USERMANAGED,
7452                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
7453     ok(r == ERROR_UNKNOWN_PROPERTY,
7454        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7455     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7456     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7457 
7458     res = RegSetValueExA(userkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
7459     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7460 
7461     /* RegCompany value exists */
7462     sz = MAX_PATH;
7463     lstrcpyA(buf, "apple");
7464     r = pMsiGetProductInfoExA(prodcode, usersid,
7465                               MSIINSTALLCONTEXT_USERMANAGED,
7466                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
7467     ok(r == ERROR_UNKNOWN_PROPERTY,
7468        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7469     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7470     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7471 
7472     res = RegSetValueExA(userkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
7473     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7474 
7475     /* RegOwner value exists */
7476     sz = MAX_PATH;
7477     lstrcpyA(buf, "apple");
7478     r = pMsiGetProductInfoExA(prodcode, usersid,
7479                               MSIINSTALLCONTEXT_USERMANAGED,
7480                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
7481     ok(r == ERROR_UNKNOWN_PROPERTY,
7482        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7483     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7484     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7485 
7486     res = RegSetValueExA(userkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
7487     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7488 
7489     /* Transforms value exists */
7490     sz = MAX_PATH;
7491     lstrcpyA(buf, "apple");
7492     r = pMsiGetProductInfoExA(prodcode, usersid,
7493                               MSIINSTALLCONTEXT_USERMANAGED,
7494                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
7495     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7496     ok(!lstrcmpA(buf, "trans"), "Expected \"trans\", got \"%s\"\n", buf);
7497     ok(sz == 5, "Expected 5, got %d\n", sz);
7498 
7499     res = RegSetValueExA(userkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
7500     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7501 
7502     /* Language value exists */
7503     sz = MAX_PATH;
7504     lstrcpyA(buf, "apple");
7505     r = pMsiGetProductInfoExA(prodcode, usersid,
7506                               MSIINSTALLCONTEXT_USERMANAGED,
7507                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
7508     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7509     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
7510     ok(sz == 4, "Expected 4, got %d\n", sz);
7511 
7512     res = RegSetValueExA(userkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
7513     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7514 
7515     /* ProductName value exists */
7516     sz = MAX_PATH;
7517     lstrcpyA(buf, "apple");
7518     r = pMsiGetProductInfoExA(prodcode, usersid,
7519                               MSIINSTALLCONTEXT_USERMANAGED,
7520                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
7521     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7522     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
7523     ok(sz == 4, "Expected 4, got %d\n", sz);
7524 
7525     res = RegSetValueExA(userkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
7526     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7527 
7528     /* FIXME */
7529 
7530     /* AssignmentType value exists */
7531     sz = MAX_PATH;
7532     lstrcpyA(buf, "apple");
7533     r = pMsiGetProductInfoExA(prodcode, usersid,
7534                               MSIINSTALLCONTEXT_USERMANAGED,
7535                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
7536     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7537     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7538     ok(sz == 0, "Expected 0, got %d\n", sz);
7539 
7540     res = RegSetValueExA(userkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
7541     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7542 
7543     /* FIXME */
7544 
7545     /* PackageCode value exists */
7546     sz = MAX_PATH;
7547     lstrcpyA(buf, "apple");
7548     r = pMsiGetProductInfoExA(prodcode, usersid,
7549                               MSIINSTALLCONTEXT_USERMANAGED,
7550                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
7551     todo_wine
7552     {
7553         ok(r == ERROR_BAD_CONFIGURATION,
7554            "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
7555         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7556         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7557     }
7558 
7559     res = RegSetValueExA(userkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
7560     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7561 
7562     /* Version value exists */
7563     sz = MAX_PATH;
7564     lstrcpyA(buf, "apple");
7565     r = pMsiGetProductInfoExA(prodcode, usersid,
7566                               MSIINSTALLCONTEXT_USERMANAGED,
7567                               INSTALLPROPERTY_VERSIONA, buf, &sz);
7568     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7569     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
7570     ok(sz == 3, "Expected 3, got %d\n", sz);
7571 
7572     res = RegSetValueExA(userkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
7573     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7574 
7575     /* ProductIcon value exists */
7576     sz = MAX_PATH;
7577     lstrcpyA(buf, "apple");
7578     r = pMsiGetProductInfoExA(prodcode, usersid,
7579                               MSIINSTALLCONTEXT_USERMANAGED,
7580                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
7581     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7582     ok(!lstrcmpA(buf, "icon"), "Expected \"icon\", got \"%s\"\n", buf);
7583     ok(sz == 4, "Expected 4, got %d\n", sz);
7584 
7585     res = RegSetValueExA(userkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
7586     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7587 
7588     /* PackageName value exists */
7589     sz = MAX_PATH;
7590     lstrcpyA(buf, "apple");
7591     r = pMsiGetProductInfoExA(prodcode, usersid,
7592                               MSIINSTALLCONTEXT_USERMANAGED,
7593                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
7594     todo_wine
7595     {
7596         ok(r == ERROR_UNKNOWN_PRODUCT,
7597            "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7598         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7599         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7600     }
7601 
7602     res = RegSetValueExA(userkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
7603     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7604 
7605     /* AuthorizedLUAApp value exists */
7606     sz = MAX_PATH;
7607     lstrcpyA(buf, "apple");
7608     r = pMsiGetProductInfoExA(prodcode, usersid,
7609                               MSIINSTALLCONTEXT_USERMANAGED,
7610                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
7611     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7612     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
7613     ok(sz == 4, "Expected 4, got %d\n", sz);
7614 
7615     RegDeleteValueA(userkey, "AuthorizedLUAApp");
7616     RegDeleteValueA(userkey, "PackageName");
7617     RegDeleteValueA(userkey, "ProductIcon");
7618     RegDeleteValueA(userkey, "Version");
7619     RegDeleteValueA(userkey, "PackageCode");
7620     RegDeleteValueA(userkey, "AssignmentType");
7621     RegDeleteValueA(userkey, "ProductName");
7622     RegDeleteValueA(userkey, "Language");
7623     RegDeleteValueA(userkey, "Transforms");
7624     RegDeleteValueA(userkey, "RegOwner");
7625     RegDeleteValueA(userkey, "RegCompany");
7626     RegDeleteValueA(userkey, "ProductID");
7627     RegDeleteValueA(userkey, "DisplayVersion");
7628     RegDeleteValueA(userkey, "VersionMajor");
7629     RegDeleteValueA(userkey, "VersionMinor");
7630     RegDeleteValueA(userkey, "URLUpdateInfo");
7631     RegDeleteValueA(userkey, "URLInfoAbout");
7632     RegDeleteValueA(userkey, "Publisher");
7633     RegDeleteValueA(userkey, "LocalPackage");
7634     RegDeleteValueA(userkey, "InstallSource");
7635     RegDeleteValueA(userkey, "InstallLocation");
7636     RegDeleteValueA(userkey, "DisplayName");
7637     RegDeleteValueA(userkey, "InstallDate");
7638     RegDeleteValueA(userkey, "HelpTelephone");
7639     RegDeleteValueA(userkey, "HelpLink");
7640     delete_key(userkey, "", access & KEY_WOW64_64KEY);
7641     RegCloseKey(userkey);
7642     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
7643     RegCloseKey(prodkey);
7644 
7645     /* MSIINSTALLCONTEXT_MACHINE */
7646 
7647     /* szUserSid is non-NULL */
7648     sz = MAX_PATH;
7649     lstrcpyA(buf, "apple");
7650     r = pMsiGetProductInfoExA(prodcode, usersid,
7651                               MSIINSTALLCONTEXT_MACHINE,
7652                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7653     ok(r == ERROR_INVALID_PARAMETER,
7654        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
7655     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7656     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7657 
7658     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\");
7659     lstrcatA(keypath, prod_squashed);
7660 
7661     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
7662     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7663 
7664     /* local system product key exists */
7665     sz = MAX_PATH;
7666     lstrcpyA(buf, "apple");
7667     r = pMsiGetProductInfoExA(prodcode, NULL,
7668                               MSIINSTALLCONTEXT_MACHINE,
7669                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7670     ok(r == ERROR_UNKNOWN_PRODUCT,
7671        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7672     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7673     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7674 
7675     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
7676     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7677 
7678     /* InstallProperties key exists */
7679     sz = MAX_PATH;
7680     lstrcpyA(buf, "apple");
7681     r = pMsiGetProductInfoExA(prodcode, NULL,
7682                               MSIINSTALLCONTEXT_MACHINE,
7683                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7684     ok(r == ERROR_UNKNOWN_PRODUCT,
7685        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7686     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7687     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7688 
7689     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
7690     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7691 
7692     /* LocalPackage value exists */
7693     sz = MAX_PATH;
7694     lstrcpyA(buf, "apple");
7695     r = pMsiGetProductInfoExA(prodcode, NULL,
7696                               MSIINSTALLCONTEXT_MACHINE,
7697                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7698     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7699     ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
7700     ok(sz == 1, "Expected 1, got %d\n", sz);
7701 
7702     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
7703     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7704 
7705     /* HelpLink value exists */
7706     sz = MAX_PATH;
7707     lstrcpyA(buf, "apple");
7708     r = pMsiGetProductInfoExA(prodcode, NULL,
7709                               MSIINSTALLCONTEXT_MACHINE,
7710                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
7711     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7712     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
7713     ok(sz == 4, "Expected 4, got %d\n", sz);
7714 
7715     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
7716     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7717 
7718     /* HelpTelephone value exists */
7719     sz = MAX_PATH;
7720     lstrcpyA(buf, "apple");
7721     r = pMsiGetProductInfoExA(prodcode, NULL,
7722                               MSIINSTALLCONTEXT_MACHINE,
7723                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
7724     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7725     ok(!lstrcmpA(buf, "phone"), "Expected \"phone\", got \"%s\"\n", buf);
7726     ok(sz == 5, "Expected 5, got %d\n", sz);
7727 
7728     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
7729     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7730 
7731     /* InstallDate value exists */
7732     sz = MAX_PATH;
7733     lstrcpyA(buf, "apple");
7734     r = pMsiGetProductInfoExA(prodcode, NULL,
7735                               MSIINSTALLCONTEXT_MACHINE,
7736                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
7737     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7738     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
7739     ok(sz == 4, "Expected 4, got %d\n", sz);
7740 
7741     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
7742     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7743 
7744     /* DisplayName value exists */
7745     sz = MAX_PATH;
7746     lstrcpyA(buf, "apple");
7747     r = pMsiGetProductInfoExA(prodcode, NULL,
7748                               MSIINSTALLCONTEXT_MACHINE,
7749                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
7750     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7751     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
7752     ok(sz == 4, "Expected 4, got %d\n", sz);
7753 
7754     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
7755     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7756 
7757     /* InstallLocation value exists */
7758     sz = MAX_PATH;
7759     lstrcpyA(buf, "apple");
7760     r = pMsiGetProductInfoExA(prodcode, NULL,
7761                               MSIINSTALLCONTEXT_MACHINE,
7762                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
7763     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7764     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
7765     ok(sz == 3, "Expected 3, got %d\n", sz);
7766 
7767     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
7768     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7769 
7770     /* InstallSource value exists */
7771     sz = MAX_PATH;
7772     lstrcpyA(buf, "apple");
7773     r = pMsiGetProductInfoExA(prodcode, NULL,
7774                               MSIINSTALLCONTEXT_MACHINE,
7775                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
7776     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7777     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
7778     ok(sz == 6, "Expected 6, got %d\n", sz);
7779 
7780     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
7781     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7782 
7783     /* LocalPackage value exists */
7784     sz = MAX_PATH;
7785     lstrcpyA(buf, "apple");
7786     r = pMsiGetProductInfoExA(prodcode, NULL,
7787                               MSIINSTALLCONTEXT_MACHINE,
7788                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
7789     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7790     ok(!lstrcmpA(buf, "local"), "Expected \"local\", got \"%s\"\n", buf);
7791     ok(sz == 5, "Expected 5, got %d\n", sz);
7792 
7793     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
7794     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7795 
7796     /* Publisher value exists */
7797     sz = MAX_PATH;
7798     lstrcpyA(buf, "apple");
7799     r = pMsiGetProductInfoExA(prodcode, NULL,
7800                               MSIINSTALLCONTEXT_MACHINE,
7801                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
7802     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7803     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
7804     ok(sz == 3, "Expected 3, got %d\n", sz);
7805 
7806     res = RegSetValueExA(propkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
7807     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7808 
7809     /* URLInfoAbout value exists */
7810     sz = MAX_PATH;
7811     lstrcpyA(buf, "apple");
7812     r = pMsiGetProductInfoExA(prodcode, NULL,
7813                               MSIINSTALLCONTEXT_MACHINE,
7814                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
7815     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7816     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
7817     ok(sz == 5, "Expected 5, got %d\n", sz);
7818 
7819     res = RegSetValueExA(propkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
7820     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7821 
7822     /* URLUpdateInfo value exists */
7823     sz = MAX_PATH;
7824     lstrcpyA(buf, "apple");
7825     r = pMsiGetProductInfoExA(prodcode, NULL,
7826                               MSIINSTALLCONTEXT_MACHINE,
7827                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
7828     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7829     ok(!lstrcmpA(buf, "update"), "Expected \"update\", got \"%s\"\n", buf);
7830     ok(sz == 6, "Expected 6, got %d\n", sz);
7831 
7832     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
7833     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7834 
7835     /* VersionMinor value exists */
7836     sz = MAX_PATH;
7837     lstrcpyA(buf, "apple");
7838     r = pMsiGetProductInfoExA(prodcode, NULL,
7839                               MSIINSTALLCONTEXT_MACHINE,
7840                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
7841     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7842     ok(!lstrcmpA(buf, "2"), "Expected \"2\", got \"%s\"\n", buf);
7843     ok(sz == 1, "Expected 1, got %d\n", sz);
7844 
7845     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
7846     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7847 
7848     /* VersionMajor value exists */
7849     sz = MAX_PATH;
7850     lstrcpyA(buf, "apple");
7851     r = pMsiGetProductInfoExA(prodcode, NULL,
7852                               MSIINSTALLCONTEXT_MACHINE,
7853                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
7854     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7855     ok(!lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
7856     ok(sz == 1, "Expected 1, got %d\n", sz);
7857 
7858     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
7859     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7860 
7861     /* DisplayVersion value exists */
7862     sz = MAX_PATH;
7863     lstrcpyA(buf, "apple");
7864     r = pMsiGetProductInfoExA(prodcode, NULL,
7865                               MSIINSTALLCONTEXT_MACHINE,
7866                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
7867     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7868     ok(!lstrcmpA(buf, "3.2.1"), "Expected \"3.2.1\", got \"%s\"\n", buf);
7869     ok(sz == 5, "Expected 5, got %d\n", sz);
7870 
7871     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
7872     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7873 
7874     /* ProductID value exists */
7875     sz = MAX_PATH;
7876     lstrcpyA(buf, "apple");
7877     r = pMsiGetProductInfoExA(prodcode, NULL,
7878                               MSIINSTALLCONTEXT_MACHINE,
7879                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
7880     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7881     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
7882     ok(sz == 2, "Expected 2, got %d\n", sz);
7883 
7884     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
7885     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7886 
7887     /* RegCompany value exists */
7888     sz = MAX_PATH;
7889     lstrcpyA(buf, "apple");
7890     r = pMsiGetProductInfoExA(prodcode, NULL,
7891                               MSIINSTALLCONTEXT_MACHINE,
7892                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
7893     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7894     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
7895     ok(sz == 4, "Expected 4, got %d\n", sz);
7896 
7897     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
7898     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7899 
7900     /* RegOwner value exists */
7901     sz = MAX_PATH;
7902     lstrcpyA(buf, "apple");
7903     r = pMsiGetProductInfoExA(prodcode, NULL,
7904                               MSIINSTALLCONTEXT_MACHINE,
7905                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
7906     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7907     ok(!lstrcmpA(buf, "owner"), "Expected \"owner\", got \"%s\"\n", buf);
7908     ok(sz == 5, "Expected 5, got %d\n", sz);
7909 
7910     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
7911     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7912 
7913     /* Transforms value exists */
7914     sz = MAX_PATH;
7915     lstrcpyA(buf, "apple");
7916     r = pMsiGetProductInfoExA(prodcode, NULL,
7917                               MSIINSTALLCONTEXT_MACHINE,
7918                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
7919     ok(r == ERROR_UNKNOWN_PRODUCT,
7920        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7921     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7922     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7923 
7924     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
7925     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7926 
7927     /* Language value exists */
7928     sz = MAX_PATH;
7929     lstrcpyA(buf, "apple");
7930     r = pMsiGetProductInfoExA(prodcode, NULL,
7931                               MSIINSTALLCONTEXT_MACHINE,
7932                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
7933     ok(r == ERROR_UNKNOWN_PRODUCT,
7934        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7935     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7936     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7937 
7938     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
7939     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7940 
7941     /* ProductName value exists */
7942     sz = MAX_PATH;
7943     lstrcpyA(buf, "apple");
7944     r = pMsiGetProductInfoExA(prodcode, NULL,
7945                               MSIINSTALLCONTEXT_MACHINE,
7946                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
7947     ok(r == ERROR_UNKNOWN_PRODUCT,
7948        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7949     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7950     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7951 
7952     res = RegSetValueExA(propkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
7953     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7954 
7955     /* FIXME */
7956 
7957     /* AssignmentType value exists */
7958     sz = MAX_PATH;
7959     lstrcpyA(buf, "apple");
7960     r = pMsiGetProductInfoExA(prodcode, NULL,
7961                               MSIINSTALLCONTEXT_MACHINE,
7962                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
7963     ok(r == ERROR_UNKNOWN_PRODUCT,
7964        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7965     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7966     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7967 
7968     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
7969     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7970 
7971     /* PackageCode value exists */
7972     sz = MAX_PATH;
7973     lstrcpyA(buf, "apple");
7974     r = pMsiGetProductInfoExA(prodcode, NULL,
7975                               MSIINSTALLCONTEXT_MACHINE,
7976                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
7977     ok(r == ERROR_UNKNOWN_PRODUCT,
7978        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7979     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7980     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7981 
7982     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
7983     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7984 
7985     /* Version value exists */
7986     sz = MAX_PATH;
7987     lstrcpyA(buf, "apple");
7988     r = pMsiGetProductInfoExA(prodcode, NULL,
7989                               MSIINSTALLCONTEXT_MACHINE,
7990                               INSTALLPROPERTY_VERSIONA, buf, &sz);
7991     ok(r == ERROR_UNKNOWN_PRODUCT,
7992        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7993     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7994     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7995 
7996     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
7997     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7998 
7999     /* ProductIcon value exists */
8000     sz = MAX_PATH;
8001     lstrcpyA(buf, "apple");
8002     r = pMsiGetProductInfoExA(prodcode, NULL,
8003                               MSIINSTALLCONTEXT_MACHINE,
8004                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
8005     ok(r == ERROR_UNKNOWN_PRODUCT,
8006        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8007     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8008     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8009 
8010     res = RegSetValueExA(propkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
8011     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8012 
8013     /* PackageName value exists */
8014     sz = MAX_PATH;
8015     lstrcpyA(buf, "apple");
8016     r = pMsiGetProductInfoExA(prodcode, NULL,
8017                               MSIINSTALLCONTEXT_MACHINE,
8018                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
8019     ok(r == ERROR_UNKNOWN_PRODUCT,
8020        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8021     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8022     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8023 
8024     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
8025     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8026 
8027     /* AuthorizedLUAApp value exists */
8028     sz = MAX_PATH;
8029     lstrcpyA(buf, "apple");
8030     r = pMsiGetProductInfoExA(prodcode, NULL,
8031                               MSIINSTALLCONTEXT_MACHINE,
8032                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
8033     ok(r == ERROR_UNKNOWN_PRODUCT,
8034        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8035     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8036     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8037 
8038     RegDeleteValueA(propkey, "AuthorizedLUAApp");
8039     RegDeleteValueA(propkey, "PackageName");
8040     RegDeleteValueA(propkey, "ProductIcon");
8041     RegDeleteValueA(propkey, "Version");
8042     RegDeleteValueA(propkey, "PackageCode");
8043     RegDeleteValueA(propkey, "AssignmentType");
8044     RegDeleteValueA(propkey, "ProductName");
8045     RegDeleteValueA(propkey, "Language");
8046     RegDeleteValueA(propkey, "Transforms");
8047     RegDeleteValueA(propkey, "RegOwner");
8048     RegDeleteValueA(propkey, "RegCompany");
8049     RegDeleteValueA(propkey, "ProductID");
8050     RegDeleteValueA(propkey, "DisplayVersion");
8051     RegDeleteValueA(propkey, "VersionMajor");
8052     RegDeleteValueA(propkey, "VersionMinor");
8053     RegDeleteValueA(propkey, "URLUpdateInfo");
8054     RegDeleteValueA(propkey, "URLInfoAbout");
8055     RegDeleteValueA(propkey, "Publisher");
8056     RegDeleteValueA(propkey, "LocalPackage");
8057     RegDeleteValueA(propkey, "InstallSource");
8058     RegDeleteValueA(propkey, "InstallLocation");
8059     RegDeleteValueA(propkey, "DisplayName");
8060     RegDeleteValueA(propkey, "InstallDate");
8061     RegDeleteValueA(propkey, "HelpTelephone");
8062     RegDeleteValueA(propkey, "HelpLink");
8063     RegDeleteValueA(propkey, "LocalPackage");
8064     delete_key(propkey, "", access & KEY_WOW64_64KEY);
8065     RegCloseKey(propkey);
8066     delete_key(localkey, "", access & KEY_WOW64_64KEY);
8067     RegCloseKey(localkey);
8068 
8069     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
8070     lstrcatA(keypath, prod_squashed);
8071 
8072     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8073     if (res == ERROR_ACCESS_DENIED)
8074     {
8075         skip( "insufficient rights\n" );
8076         LocalFree( usersid );
8077         return;
8078     }
8079     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8080 
8081     /* local classes product key exists */
8082     sz = MAX_PATH;
8083     lstrcpyA(buf, "apple");
8084     r = pMsiGetProductInfoExA(prodcode, NULL,
8085                               MSIINSTALLCONTEXT_MACHINE,
8086                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
8087     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8088     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
8089     ok(sz == 1, "Expected 1, got %d\n", sz);
8090 
8091     res = RegSetValueExA(prodkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
8092     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8093 
8094     /* HelpLink value exists */
8095     sz = MAX_PATH;
8096     lstrcpyA(buf, "apple");
8097     r = pMsiGetProductInfoExA(prodcode, NULL,
8098                               MSIINSTALLCONTEXT_MACHINE,
8099                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
8100     ok(r == ERROR_UNKNOWN_PROPERTY,
8101        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8102     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8103     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8104 
8105     res = RegSetValueExA(prodkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
8106     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8107 
8108     /* HelpTelephone value exists */
8109     sz = MAX_PATH;
8110     lstrcpyA(buf, "apple");
8111     r = pMsiGetProductInfoExA(prodcode, NULL,
8112                               MSIINSTALLCONTEXT_MACHINE,
8113                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
8114     ok(r == ERROR_UNKNOWN_PROPERTY,
8115        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8116     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8117     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8118 
8119     res = RegSetValueExA(prodkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
8120     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8121 
8122     /* InstallDate value exists */
8123     sz = MAX_PATH;
8124     lstrcpyA(buf, "apple");
8125     r = pMsiGetProductInfoExA(prodcode, NULL,
8126                               MSIINSTALLCONTEXT_MACHINE,
8127                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
8128     ok(r == ERROR_UNKNOWN_PROPERTY,
8129        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8130     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8131     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8132 
8133     res = RegSetValueExA(prodkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
8134     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8135 
8136     /* DisplayName value exists */
8137     sz = MAX_PATH;
8138     lstrcpyA(buf, "apple");
8139     r = pMsiGetProductInfoExA(prodcode, NULL,
8140                               MSIINSTALLCONTEXT_MACHINE,
8141                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
8142     ok(r == ERROR_UNKNOWN_PROPERTY,
8143        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8144     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8145     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8146 
8147     res = RegSetValueExA(prodkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
8148     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8149 
8150     /* InstallLocation value exists */
8151     sz = MAX_PATH;
8152     lstrcpyA(buf, "apple");
8153     r = pMsiGetProductInfoExA(prodcode, NULL,
8154                               MSIINSTALLCONTEXT_MACHINE,
8155                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
8156     ok(r == ERROR_UNKNOWN_PROPERTY,
8157        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8158     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8159     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8160 
8161     res = RegSetValueExA(prodkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
8162     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8163 
8164     /* InstallSource value exists */
8165     sz = MAX_PATH;
8166     lstrcpyA(buf, "apple");
8167     r = pMsiGetProductInfoExA(prodcode, NULL,
8168                               MSIINSTALLCONTEXT_MACHINE,
8169                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
8170     ok(r == ERROR_UNKNOWN_PROPERTY,
8171        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8172     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8173     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8174 
8175     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
8176     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8177 
8178     /* LocalPackage value exists */
8179     sz = MAX_PATH;
8180     lstrcpyA(buf, "apple");
8181     r = pMsiGetProductInfoExA(prodcode, NULL,
8182                               MSIINSTALLCONTEXT_MACHINE,
8183                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
8184     ok(r == ERROR_UNKNOWN_PROPERTY,
8185        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8186     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8187     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8188 
8189     res = RegSetValueExA(prodkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
8190     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8191 
8192     /* Publisher value exists */
8193     sz = MAX_PATH;
8194     lstrcpyA(buf, "apple");
8195     r = pMsiGetProductInfoExA(prodcode, NULL,
8196                               MSIINSTALLCONTEXT_MACHINE,
8197                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
8198     ok(r == ERROR_UNKNOWN_PROPERTY,
8199        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8200     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8201     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8202 
8203     res = RegSetValueExA(prodkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
8204     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8205 
8206     /* URLInfoAbout value exists */
8207     sz = MAX_PATH;
8208     lstrcpyA(buf, "apple");
8209     r = pMsiGetProductInfoExA(prodcode, NULL,
8210                               MSIINSTALLCONTEXT_MACHINE,
8211                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
8212     ok(r == ERROR_UNKNOWN_PROPERTY,
8213        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8214     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8215     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8216 
8217     res = RegSetValueExA(prodkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
8218     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8219 
8220     /* URLUpdateInfo value exists */
8221     sz = MAX_PATH;
8222     lstrcpyA(buf, "apple");
8223     r = pMsiGetProductInfoExA(prodcode, NULL,
8224                               MSIINSTALLCONTEXT_MACHINE,
8225                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
8226     ok(r == ERROR_UNKNOWN_PROPERTY,
8227        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8228     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8229     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8230 
8231     res = RegSetValueExA(prodkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
8232     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8233 
8234     /* VersionMinor value exists */
8235     sz = MAX_PATH;
8236     lstrcpyA(buf, "apple");
8237     r = pMsiGetProductInfoExA(prodcode, NULL,
8238                               MSIINSTALLCONTEXT_MACHINE,
8239                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
8240     ok(r == ERROR_UNKNOWN_PROPERTY,
8241        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8242     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8243     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8244 
8245     res = RegSetValueExA(prodkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
8246     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8247 
8248     /* VersionMajor value exists */
8249     sz = MAX_PATH;
8250     lstrcpyA(buf, "apple");
8251     r = pMsiGetProductInfoExA(prodcode, NULL,
8252                               MSIINSTALLCONTEXT_MACHINE,
8253                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
8254     ok(r == ERROR_UNKNOWN_PROPERTY,
8255        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8256     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8257     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8258 
8259     res = RegSetValueExA(prodkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
8260     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8261 
8262     /* DisplayVersion value exists */
8263     sz = MAX_PATH;
8264     lstrcpyA(buf, "apple");
8265     r = pMsiGetProductInfoExA(prodcode, NULL,
8266                               MSIINSTALLCONTEXT_MACHINE,
8267                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
8268     ok(r == ERROR_UNKNOWN_PROPERTY,
8269        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8270     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8271     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8272 
8273     res = RegSetValueExA(prodkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
8274     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8275 
8276     /* ProductID value exists */
8277     sz = MAX_PATH;
8278     lstrcpyA(buf, "apple");
8279     r = pMsiGetProductInfoExA(prodcode, NULL,
8280                               MSIINSTALLCONTEXT_MACHINE,
8281                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
8282     ok(r == ERROR_UNKNOWN_PROPERTY,
8283        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8284     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8285     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8286 
8287     res = RegSetValueExA(prodkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
8288     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8289 
8290     /* RegCompany value exists */
8291     sz = MAX_PATH;
8292     lstrcpyA(buf, "apple");
8293     r = pMsiGetProductInfoExA(prodcode, NULL,
8294                               MSIINSTALLCONTEXT_MACHINE,
8295                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
8296     ok(r == ERROR_UNKNOWN_PROPERTY,
8297        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8298     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8299     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8300 
8301     res = RegSetValueExA(prodkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
8302     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8303 
8304     /* RegOwner value exists */
8305     sz = MAX_PATH;
8306     lstrcpyA(buf, "apple");
8307     r = pMsiGetProductInfoExA(prodcode, NULL,
8308                               MSIINSTALLCONTEXT_MACHINE,
8309                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
8310     ok(r == ERROR_UNKNOWN_PROPERTY,
8311        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8312     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8313     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8314 
8315     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
8316     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8317 
8318     /* Transforms value exists */
8319     sz = MAX_PATH;
8320     lstrcpyA(buf, "apple");
8321     r = pMsiGetProductInfoExA(prodcode, NULL,
8322                               MSIINSTALLCONTEXT_MACHINE,
8323                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
8324     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8325     ok(!lstrcmpA(buf, "trans"), "Expected \"trans\", got \"%s\"\n", buf);
8326     ok(sz == 5, "Expected 5, got %d\n", sz);
8327 
8328     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
8329     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8330 
8331     /* Language value exists */
8332     sz = MAX_PATH;
8333     lstrcpyA(buf, "apple");
8334     r = pMsiGetProductInfoExA(prodcode, NULL,
8335                               MSIINSTALLCONTEXT_MACHINE,
8336                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
8337     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8338     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
8339     ok(sz == 4, "Expected 4, got %d\n", sz);
8340 
8341     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
8342     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8343 
8344     /* ProductName value exists */
8345     sz = MAX_PATH;
8346     lstrcpyA(buf, "apple");
8347     r = pMsiGetProductInfoExA(prodcode, NULL,
8348                               MSIINSTALLCONTEXT_MACHINE,
8349                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
8350     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8351     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
8352     ok(sz == 4, "Expected 4, got %d\n", sz);
8353 
8354     res = RegSetValueExA(prodkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
8355     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8356 
8357     /* FIXME */
8358 
8359     /* AssignmentType value exists */
8360     sz = MAX_PATH;
8361     lstrcpyA(buf, "apple");
8362     r = pMsiGetProductInfoExA(prodcode, NULL,
8363                               MSIINSTALLCONTEXT_MACHINE,
8364                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
8365     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8366     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
8367     ok(sz == 0, "Expected 0, got %d\n", sz);
8368 
8369     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
8370     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8371 
8372     /* FIXME */
8373 
8374     /* PackageCode value exists */
8375     sz = MAX_PATH;
8376     lstrcpyA(buf, "apple");
8377     r = pMsiGetProductInfoExA(prodcode, NULL,
8378                               MSIINSTALLCONTEXT_MACHINE,
8379                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
8380     todo_wine
8381     {
8382         ok(r == ERROR_BAD_CONFIGURATION,
8383            "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
8384         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8385         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8386     }
8387 
8388     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
8389     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8390 
8391     /* Version value exists */
8392     sz = MAX_PATH;
8393     lstrcpyA(buf, "apple");
8394     r = pMsiGetProductInfoExA(prodcode, NULL,
8395                               MSIINSTALLCONTEXT_MACHINE,
8396                               INSTALLPROPERTY_VERSIONA, buf, &sz);
8397     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8398     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
8399     ok(sz == 3, "Expected 3, got %d\n", sz);
8400 
8401     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
8402     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8403 
8404     /* ProductIcon value exists */
8405     sz = MAX_PATH;
8406     lstrcpyA(buf, "apple");
8407     r = pMsiGetProductInfoExA(prodcode, NULL,
8408                               MSIINSTALLCONTEXT_MACHINE,
8409                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
8410     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8411     ok(!lstrcmpA(buf, "icon"), "Expected \"icon\", got \"%s\"\n", buf);
8412     ok(sz == 4, "Expected 4, got %d\n", sz);
8413 
8414     res = RegSetValueExA(prodkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
8415     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8416 
8417     /* PackageName value exists */
8418     sz = MAX_PATH;
8419     lstrcpyA(buf, "apple");
8420     r = pMsiGetProductInfoExA(prodcode, NULL,
8421                               MSIINSTALLCONTEXT_MACHINE,
8422                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
8423     todo_wine
8424     {
8425         ok(r == ERROR_UNKNOWN_PRODUCT,
8426            "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8427         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8428         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8429     }
8430 
8431     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
8432     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8433 
8434     /* AuthorizedLUAApp value exists */
8435     sz = MAX_PATH;
8436     lstrcpyA(buf, "apple");
8437     r = pMsiGetProductInfoExA(prodcode, NULL,
8438                               MSIINSTALLCONTEXT_MACHINE,
8439                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
8440     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8441     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
8442     ok(sz == 4, "Expected 4, got %d\n", sz);
8443 
8444     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
8445     RegDeleteValueA(prodkey, "PackageName");
8446     RegDeleteValueA(prodkey, "ProductIcon");
8447     RegDeleteValueA(prodkey, "Version");
8448     RegDeleteValueA(prodkey, "PackageCode");
8449     RegDeleteValueA(prodkey, "AssignmentType");
8450     RegDeleteValueA(prodkey, "ProductName");
8451     RegDeleteValueA(prodkey, "Language");
8452     RegDeleteValueA(prodkey, "Transforms");
8453     RegDeleteValueA(prodkey, "RegOwner");
8454     RegDeleteValueA(prodkey, "RegCompany");
8455     RegDeleteValueA(prodkey, "ProductID");
8456     RegDeleteValueA(prodkey, "DisplayVersion");
8457     RegDeleteValueA(prodkey, "VersionMajor");
8458     RegDeleteValueA(prodkey, "VersionMinor");
8459     RegDeleteValueA(prodkey, "URLUpdateInfo");
8460     RegDeleteValueA(prodkey, "URLInfoAbout");
8461     RegDeleteValueA(prodkey, "Publisher");
8462     RegDeleteValueA(prodkey, "LocalPackage");
8463     RegDeleteValueA(prodkey, "InstallSource");
8464     RegDeleteValueA(prodkey, "InstallLocation");
8465     RegDeleteValueA(prodkey, "DisplayName");
8466     RegDeleteValueA(prodkey, "InstallDate");
8467     RegDeleteValueA(prodkey, "HelpTelephone");
8468     RegDeleteValueA(prodkey, "HelpLink");
8469     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
8470     RegCloseKey(prodkey);
8471     LocalFree(usersid);
8472 }
8473 
8474 #define INIT_USERINFO() \
8475     lstrcpyA(user, "apple"); \
8476     lstrcpyA(org, "orange"); \
8477     lstrcpyA(serial, "banana"); \
8478     usersz = orgsz = serialsz = MAX_PATH;
8479 
8480 static void test_MsiGetUserInfo(void)
8481 {
8482     USERINFOSTATE state;
8483     CHAR user[MAX_PATH];
8484     CHAR org[MAX_PATH];
8485     CHAR serial[MAX_PATH];
8486     DWORD usersz, orgsz, serialsz;
8487     CHAR keypath[MAX_PATH * 2];
8488     CHAR prodcode[MAX_PATH];
8489     CHAR prod_squashed[MAX_PATH];
8490     HKEY prodkey, userprod, props;
8491     LPSTR usersid;
8492     LONG res;
8493     REGSAM access = KEY_ALL_ACCESS;
8494 
8495     create_test_guid(prodcode, prod_squashed);
8496     usersid = get_user_sid();
8497 
8498     if (is_wow64)
8499         access |= KEY_WOW64_64KEY;
8500 
8501     /* NULL szProduct */
8502     INIT_USERINFO();
8503     state = MsiGetUserInfoA(NULL, user, &usersz, org, &orgsz, serial, &serialsz);
8504     ok(state == USERINFOSTATE_INVALIDARG,
8505        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8506     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8507     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8508     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8509     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8510     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8511     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8512 
8513     /* empty szProductCode */
8514     INIT_USERINFO();
8515     state = MsiGetUserInfoA("", user, &usersz, org, &orgsz, serial, &serialsz);
8516     ok(state == USERINFOSTATE_INVALIDARG,
8517        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8518     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8519     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8520     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8521     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8522     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8523     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8524 
8525     /* garbage szProductCode */
8526     INIT_USERINFO();
8527     state = MsiGetUserInfoA("garbage", user, &usersz, org, &orgsz, serial, &serialsz);
8528     ok(state == USERINFOSTATE_INVALIDARG,
8529        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8530     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8531     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8532     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8533     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8534     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8535     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8536 
8537     /* guid without brackets */
8538     INIT_USERINFO();
8539     state = MsiGetUserInfoA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
8540                             user, &usersz, org, &orgsz, serial, &serialsz);
8541     ok(state == USERINFOSTATE_INVALIDARG,
8542        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8543     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8544     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8545     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8546     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8547     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8548     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8549 
8550     /* guid with brackets */
8551     INIT_USERINFO();
8552     state = MsiGetUserInfoA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
8553                             user, &usersz, org, &orgsz, serial, &serialsz);
8554     ok(state == USERINFOSTATE_UNKNOWN,
8555        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8556     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8557     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8558     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8559     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8560     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8561     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8562 
8563     /* NULL lpUserNameBuf */
8564     INIT_USERINFO();
8565     state = MsiGetUserInfoA(prodcode, NULL, &usersz, org, &orgsz, serial, &serialsz);
8566     ok(state == USERINFOSTATE_UNKNOWN,
8567        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8568     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8569     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8570     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8571     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8572     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8573 
8574     /* NULL pcchUserNameBuf */
8575     INIT_USERINFO();
8576     state = MsiGetUserInfoA(prodcode, user, NULL, org, &orgsz, serial, &serialsz);
8577     ok(state == USERINFOSTATE_INVALIDARG,
8578        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8579     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8580     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8581     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8582     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8583     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8584 
8585     /* both lpUserNameBuf and pcchUserNameBuf NULL */
8586     INIT_USERINFO();
8587     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
8588     ok(state == USERINFOSTATE_UNKNOWN,
8589        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8590     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8591     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8592     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8593     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8594 
8595     /* NULL lpOrgNameBuf */
8596     INIT_USERINFO();
8597     state = MsiGetUserInfoA(prodcode, user, &usersz, NULL, &orgsz, serial, &serialsz);
8598     ok(state == USERINFOSTATE_UNKNOWN,
8599        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8600     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8601     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8602     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8603     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8604     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8605 
8606     /* NULL pcchOrgNameBuf */
8607     INIT_USERINFO();
8608     state = MsiGetUserInfoA(prodcode, user, &usersz, org, NULL, serial, &serialsz);
8609     ok(state == USERINFOSTATE_INVALIDARG,
8610        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8611     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8612     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8613     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8614     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8615     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8616 
8617     /* both lpOrgNameBuf and pcchOrgNameBuf NULL */
8618     INIT_USERINFO();
8619     state = MsiGetUserInfoA(prodcode, user, &usersz, NULL, NULL, serial, &serialsz);
8620     ok(state == USERINFOSTATE_UNKNOWN,
8621        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8622     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8623     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8624     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8625     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8626 
8627     /* NULL lpSerialBuf */
8628     INIT_USERINFO();
8629     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, NULL, &serialsz);
8630     ok(state == USERINFOSTATE_UNKNOWN,
8631        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8632     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8633     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8634     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8635     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8636     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8637 
8638     /* NULL pcchSerialBuf */
8639     INIT_USERINFO();
8640     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, NULL);
8641     ok(state == USERINFOSTATE_INVALIDARG,
8642        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8643     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8644     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8645     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8646     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8647     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8648 
8649     /* both lpSerialBuf and pcchSerialBuf NULL */
8650     INIT_USERINFO();
8651     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, NULL, NULL);
8652     ok(state == USERINFOSTATE_UNKNOWN,
8653        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8654     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8655     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8656     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8657     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8658 
8659     /* MSIINSTALLCONTEXT_USERMANAGED */
8660 
8661     /* create local system product key */
8662     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
8663     lstrcatA(keypath, usersid);
8664     lstrcatA(keypath, "\\Installer\\Products\\");
8665     lstrcatA(keypath, prod_squashed);
8666 
8667     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8668     if (res == ERROR_ACCESS_DENIED)
8669     {
8670         skip("Not enough rights to perform tests\n");
8671         LocalFree(usersid);
8672         return;
8673     }
8674     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8675 
8676     /* managed product key exists */
8677     INIT_USERINFO();
8678     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8679     ok(state == USERINFOSTATE_ABSENT,
8680        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8681     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8682     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8683     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8684     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8685     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8686     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8687 
8688     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8689     lstrcatA(keypath, "Installer\\UserData\\");
8690     lstrcatA(keypath, usersid);
8691     lstrcatA(keypath, "\\Products\\");
8692     lstrcatA(keypath, prod_squashed);
8693 
8694     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL);
8695     if (res == ERROR_ACCESS_DENIED)
8696     {
8697         skip("Not enough rights to perform tests\n");
8698         LocalFree(usersid);
8699         return;
8700     }
8701     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8702 
8703     res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8704     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8705 
8706     /* InstallProperties key exists */
8707     INIT_USERINFO();
8708     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8709     ok(state == USERINFOSTATE_ABSENT,
8710        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8711     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8712     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8713     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8714     ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", usersz);
8715     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8716     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8717 
8718     /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */
8719     INIT_USERINFO();
8720     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
8721     ok(state == USERINFOSTATE_ABSENT,
8722        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8723     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
8724     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8725     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
8726     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
8727 
8728     /* RegOwner, RegCompany don't exist, out params are NULL */
8729     INIT_USERINFO();
8730     state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz);
8731     ok(state == USERINFOSTATE_ABSENT,
8732        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8733     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8734     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
8735 
8736     res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
8737     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8738 
8739     /* RegOwner value exists */
8740     INIT_USERINFO();
8741     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8742     ok(state == USERINFOSTATE_ABSENT,
8743        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8744     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8745     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
8746     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8747     ok(usersz == 5, "Expected 5, got %d\n", usersz);
8748     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
8749     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
8750 
8751     res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8);
8752     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8753 
8754     /* RegCompany value exists */
8755     INIT_USERINFO();
8756     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8757     ok(state == USERINFOSTATE_ABSENT,
8758        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8759     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8760     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8761     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8762     ok(usersz == 5, "Expected 5, got %d\n", usersz);
8763     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
8764     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
8765 
8766     res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3);
8767     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8768 
8769     /* ProductID value exists */
8770     INIT_USERINFO();
8771     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8772     ok(state == USERINFOSTATE_PRESENT,
8773        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
8774     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8775     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8776     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
8777     ok(usersz == 5, "Expected 5, got %d\n", usersz);
8778     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
8779     ok(serialsz == 2, "Expected 2, got %d\n", serialsz);
8780 
8781     /* pcchUserNameBuf is too small */
8782     INIT_USERINFO();
8783     usersz = 0;
8784     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8785     ok(state == USERINFOSTATE_MOREDATA,
8786        "Expected USERINFOSTATE_MOREDATA, got %d\n", state);
8787     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8788     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8789     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8790     ok(usersz == 5, "Expected 5, got %d\n", usersz);
8791     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8792     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8793 
8794     /* pcchUserNameBuf has no room for NULL terminator */
8795     INIT_USERINFO();
8796     usersz = 5;
8797     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8798     ok(state == USERINFOSTATE_MOREDATA,
8799        "Expected USERINFOSTATE_MOREDATA, got %d\n", state);
8800     todo_wine
8801     {
8802         ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8803     }
8804     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8805     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8806     ok(usersz == 5, "Expected 5, got %d\n", usersz);
8807     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8808     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8809 
8810     /* pcchUserNameBuf is too small, lpUserNameBuf is NULL */
8811     INIT_USERINFO();
8812     usersz = 0;
8813     state = MsiGetUserInfoA(prodcode, NULL, &usersz, org, &orgsz, serial, &serialsz);
8814     ok(state == USERINFOSTATE_PRESENT,
8815        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
8816     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8817     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8818     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
8819     ok(usersz == 5, "Expected 5, got %d\n", usersz);
8820     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
8821     ok(serialsz == 2, "Expected 2, got %d\n", serialsz);
8822 
8823     RegDeleteValueA(props, "ProductID");
8824     RegDeleteValueA(props, "RegCompany");
8825     RegDeleteValueA(props, "RegOwner");
8826     delete_key(props, "", access & KEY_WOW64_64KEY);
8827     RegCloseKey(props);
8828     delete_key(userprod, "", access & KEY_WOW64_64KEY);
8829     RegCloseKey(userprod);
8830     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
8831     RegCloseKey(prodkey);
8832 
8833     /* MSIINSTALLCONTEXT_USERUNMANAGED */
8834 
8835     /* create local system product key */
8836     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
8837     lstrcatA(keypath, prod_squashed);
8838 
8839     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
8840     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8841 
8842     /* product key exists */
8843     INIT_USERINFO();
8844     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8845     ok(state == USERINFOSTATE_ABSENT,
8846        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8847     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8848     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8849     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8850     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8851     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8852     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8853 
8854     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8855     lstrcatA(keypath, "Installer\\UserData\\");
8856     lstrcatA(keypath, usersid);
8857     lstrcatA(keypath, "\\Products\\");
8858     lstrcatA(keypath, prod_squashed);
8859 
8860     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL);
8861     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8862 
8863     res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8864     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8865 
8866     /* InstallProperties key exists */
8867     INIT_USERINFO();
8868     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8869     ok(state == USERINFOSTATE_ABSENT,
8870        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8871     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8872     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8873     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8874     ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", usersz);
8875     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8876     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8877 
8878     /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */
8879     INIT_USERINFO();
8880     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
8881     ok(state == USERINFOSTATE_ABSENT,
8882        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8883     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
8884     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8885     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
8886     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
8887 
8888     /* RegOwner, RegCompany don't exist, out params are NULL */
8889     INIT_USERINFO();
8890     state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz);
8891     ok(state == USERINFOSTATE_ABSENT,
8892        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8893     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8894     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
8895 
8896     res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
8897     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8898 
8899     /* RegOwner value exists */
8900     INIT_USERINFO();
8901     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8902     ok(state == USERINFOSTATE_ABSENT,
8903        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8904     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8905     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
8906     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8907     ok(usersz == 5, "Expected 5, got %d\n", usersz);
8908     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
8909     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
8910 
8911     res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8);
8912     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8913 
8914     /* RegCompany value exists */
8915     INIT_USERINFO();
8916     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8917     ok(state == USERINFOSTATE_ABSENT,
8918        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8919     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8920     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8921     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8922     ok(usersz == 5, "Expected 5, got %d\n", usersz);
8923     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
8924     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
8925 
8926     res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3);
8927     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8928 
8929     /* ProductID value exists */
8930     INIT_USERINFO();
8931     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8932     ok(state == USERINFOSTATE_PRESENT,
8933        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
8934     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8935     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8936     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
8937     ok(usersz == 5, "Expected 5, got %d\n", usersz);
8938     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
8939     ok(serialsz == 2, "Expected 2, got %d\n", serialsz);
8940 
8941     RegDeleteValueA(props, "ProductID");
8942     RegDeleteValueA(props, "RegCompany");
8943     RegDeleteValueA(props, "RegOwner");
8944     delete_key(props, "", access & KEY_WOW64_64KEY);
8945     RegCloseKey(props);
8946     delete_key(userprod, "", access & KEY_WOW64_64KEY);
8947     RegCloseKey(userprod);
8948     RegDeleteKeyA(prodkey, "");
8949     RegCloseKey(prodkey);
8950 
8951     /* MSIINSTALLCONTEXT_MACHINE */
8952 
8953     /* create local system product key */
8954     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
8955     lstrcatA(keypath, prod_squashed);
8956 
8957     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8958     if (res == ERROR_ACCESS_DENIED)
8959     {
8960         skip( "insufficient rights\n" );
8961         LocalFree( usersid );
8962         return;
8963     }
8964     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8965 
8966     /* product key exists */
8967     INIT_USERINFO();
8968     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8969     ok(state == USERINFOSTATE_ABSENT,
8970        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8971     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8972     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8973     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8974     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8975     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8976     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8977 
8978     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8979     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18");
8980     lstrcatA(keypath, "\\Products\\");
8981     lstrcatA(keypath, prod_squashed);
8982 
8983     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL);
8984     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8985 
8986     res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8987     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8988 
8989     /* InstallProperties key exists */
8990     INIT_USERINFO();
8991     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8992     ok(state == USERINFOSTATE_ABSENT,
8993        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8994     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8995     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8996     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8997     ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", usersz);
8998     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8999     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
9000 
9001     /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */
9002     INIT_USERINFO();
9003     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
9004     ok(state == USERINFOSTATE_ABSENT,
9005        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9006     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
9007     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9008     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
9009     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9010 
9011     /* RegOwner, RegCompany don't exist, out params are NULL */
9012     INIT_USERINFO();
9013     state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz);
9014     ok(state == USERINFOSTATE_ABSENT,
9015        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9016     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9017     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9018 
9019     res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
9020     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9021 
9022     /* RegOwner value exists */
9023     INIT_USERINFO();
9024     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9025     ok(state == USERINFOSTATE_ABSENT,
9026        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9027     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9028     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
9029     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9030     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9031     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
9032     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9033 
9034     res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8);
9035     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9036 
9037     /* RegCompany value exists */
9038     INIT_USERINFO();
9039     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9040     ok(state == USERINFOSTATE_ABSENT,
9041        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9042     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9043     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9044     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9045     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9046     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
9047     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9048 
9049     res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3);
9050     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9051 
9052     /* ProductID value exists */
9053     INIT_USERINFO();
9054     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9055     ok(state == USERINFOSTATE_PRESENT,
9056        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
9057     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9058     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9059     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
9060     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9061     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
9062     ok(serialsz == 2, "Expected 2, got %d\n", serialsz);
9063 
9064     RegDeleteValueA(props, "ProductID");
9065     RegDeleteValueA(props, "RegCompany");
9066     RegDeleteValueA(props, "RegOwner");
9067     delete_key(props, "", access & KEY_WOW64_64KEY);
9068     RegCloseKey(props);
9069     delete_key(userprod, "", access & KEY_WOW64_64KEY);
9070     RegCloseKey(userprod);
9071     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
9072     RegCloseKey(prodkey);
9073     LocalFree(usersid);
9074 }
9075 
9076 static void test_MsiOpenProduct(void)
9077 {
9078     MSIHANDLE hprod, hdb;
9079     CHAR val[MAX_PATH];
9080     CHAR path[MAX_PATH];
9081     CHAR keypath[MAX_PATH*2];
9082     CHAR prodcode[MAX_PATH];
9083     CHAR prod_squashed[MAX_PATH];
9084     HKEY prodkey, userkey, props;
9085     LPSTR usersid;
9086     DWORD size;
9087     LONG res;
9088     UINT r;
9089     REGSAM access = KEY_ALL_ACCESS;
9090 
9091     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
9092 
9093     GetCurrentDirectoryA(MAX_PATH, path);
9094     lstrcatA(path, "\\");
9095 
9096     create_test_guid(prodcode, prod_squashed);
9097     usersid = get_user_sid();
9098 
9099     if (is_wow64)
9100         access |= KEY_WOW64_64KEY;
9101 
9102     hdb = create_package_db(prodcode);
9103     MsiCloseHandle(hdb);
9104 
9105     /* NULL szProduct */
9106     hprod = 0xdeadbeef;
9107     r = MsiOpenProductA(NULL, &hprod);
9108     ok(r == ERROR_INVALID_PARAMETER,
9109        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9110     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9111 
9112     /* empty szProduct */
9113     hprod = 0xdeadbeef;
9114     r = MsiOpenProductA("", &hprod);
9115     ok(r == ERROR_INVALID_PARAMETER,
9116        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9117     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9118 
9119     /* garbage szProduct */
9120     hprod = 0xdeadbeef;
9121     r = MsiOpenProductA("garbage", &hprod);
9122     ok(r == ERROR_INVALID_PARAMETER,
9123        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9124     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9125 
9126     /* guid without brackets */
9127     hprod = 0xdeadbeef;
9128     r = MsiOpenProductA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", &hprod);
9129     ok(r == ERROR_INVALID_PARAMETER,
9130        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9131     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9132 
9133     /* guid with brackets */
9134     hprod = 0xdeadbeef;
9135     r = MsiOpenProductA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", &hprod);
9136     ok(r == ERROR_UNKNOWN_PRODUCT,
9137        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9138     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9139 
9140     /* same length as guid, but random */
9141     hprod = 0xdeadbeef;
9142     r = MsiOpenProductA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", &hprod);
9143     ok(r == ERROR_INVALID_PARAMETER,
9144        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9145     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9146 
9147     /* hProduct is NULL */
9148     hprod = 0xdeadbeef;
9149     r = MsiOpenProductA(prodcode, NULL);
9150     ok(r == ERROR_INVALID_PARAMETER,
9151        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9152     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9153 
9154     /* MSIINSTALLCONTEXT_USERMANAGED */
9155 
9156     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9157     lstrcatA(keypath, "Installer\\Managed\\");
9158     lstrcatA(keypath, usersid);
9159     lstrcatA(keypath, "\\Installer\\Products\\");
9160     lstrcatA(keypath, prod_squashed);
9161 
9162     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
9163     if (res == ERROR_ACCESS_DENIED)
9164     {
9165         skip("Not enough rights to perform tests\n");
9166         LocalFree(usersid);
9167         return;
9168     }
9169     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9170 
9171     /* managed product key exists */
9172     hprod = 0xdeadbeef;
9173     r = MsiOpenProductA(prodcode, &hprod);
9174     ok(r == ERROR_UNKNOWN_PRODUCT,
9175        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9176     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9177 
9178     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9179     lstrcatA(keypath, "Installer\\UserData\\");
9180     lstrcatA(keypath, usersid);
9181     lstrcatA(keypath, "\\Products\\");
9182     lstrcatA(keypath, prod_squashed);
9183 
9184     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
9185     if (res == ERROR_ACCESS_DENIED)
9186     {
9187         skip("Not enough rights to perform tests\n");
9188         LocalFree(usersid);
9189         return;
9190     }
9191     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9192 
9193     /* user product key exists */
9194     hprod = 0xdeadbeef;
9195     r = MsiOpenProductA(prodcode, &hprod);
9196     ok(r == ERROR_UNKNOWN_PRODUCT,
9197        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9198     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9199 
9200     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9201     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9202 
9203     /* InstallProperties key exists */
9204     hprod = 0xdeadbeef;
9205     r = MsiOpenProductA(prodcode, &hprod);
9206     ok(r == ERROR_UNKNOWN_PRODUCT,
9207        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9208     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9209 
9210     lstrcpyA(val, path);
9211     lstrcatA(val, "\\winetest.msi");
9212     res = RegSetValueExA(props, "ManagedLocalPackage", 0, REG_SZ,
9213                          (const BYTE *)val, lstrlenA(val) + 1);
9214     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9215 
9216     /* ManagedLocalPackage value exists */
9217     hprod = 0xdeadbeef;
9218     r = MsiOpenProductA(prodcode, &hprod);
9219     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9220     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
9221 
9222     size = MAX_PATH;
9223     r = MsiGetPropertyA(hprod, "ProductCode", val, &size);
9224     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9225     ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val);
9226     ok(size == lstrlenA(prodcode), "Expected %d, got %d\n", lstrlenA(prodcode), size);
9227 
9228     MsiCloseHandle(hprod);
9229 
9230     RegDeleteValueA(props, "ManagedLocalPackage");
9231     delete_key(props, "", access & KEY_WOW64_64KEY);
9232     RegCloseKey(props);
9233     delete_key(userkey, "", access & KEY_WOW64_64KEY);
9234     RegCloseKey(userkey);
9235     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
9236     RegCloseKey(prodkey);
9237 
9238     /* MSIINSTALLCONTEXT_USERUNMANAGED */
9239 
9240     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
9241     lstrcatA(keypath, prod_squashed);
9242 
9243     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
9244     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9245 
9246     /* unmanaged product key exists */
9247     hprod = 0xdeadbeef;
9248     r = MsiOpenProductA(prodcode, &hprod);
9249     ok(r == ERROR_UNKNOWN_PRODUCT,
9250        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9251     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9252 
9253     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9254     lstrcatA(keypath, "Installer\\UserData\\");
9255     lstrcatA(keypath, usersid);
9256     lstrcatA(keypath, "\\Products\\");
9257     lstrcatA(keypath, prod_squashed);
9258 
9259     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
9260     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9261 
9262     /* user product key exists */
9263     hprod = 0xdeadbeef;
9264     r = MsiOpenProductA(prodcode, &hprod);
9265     ok(r == ERROR_UNKNOWN_PRODUCT,
9266        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9267     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9268 
9269     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9270     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9271 
9272     /* InstallProperties key exists */
9273     hprod = 0xdeadbeef;
9274     r = MsiOpenProductA(prodcode, &hprod);
9275     ok(r == ERROR_UNKNOWN_PRODUCT,
9276        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9277     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9278 
9279     lstrcpyA(val, path);
9280     lstrcatA(val, "\\winetest.msi");
9281     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
9282                          (const BYTE *)val, lstrlenA(val) + 1);
9283     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9284 
9285     /* LocalPackage value exists */
9286     hprod = 0xdeadbeef;
9287     r = MsiOpenProductA(prodcode, &hprod);
9288     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9289     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
9290 
9291     size = MAX_PATH;
9292     r = MsiGetPropertyA(hprod, "ProductCode", val, &size);
9293     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9294     ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val);
9295     ok(size == lstrlenA(prodcode), "Expected %d, got %d\n", lstrlenA(prodcode), size);
9296 
9297     MsiCloseHandle(hprod);
9298 
9299     RegDeleteValueA(props, "LocalPackage");
9300     delete_key(props, "", access & KEY_WOW64_64KEY);
9301     RegCloseKey(props);
9302     delete_key(userkey, "", access & KEY_WOW64_64KEY);
9303     RegCloseKey(userkey);
9304     RegDeleteKeyA(prodkey, "");
9305     RegCloseKey(prodkey);
9306 
9307     /* MSIINSTALLCONTEXT_MACHINE */
9308 
9309     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
9310     lstrcatA(keypath, prod_squashed);
9311 
9312     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
9313     if (res == ERROR_ACCESS_DENIED)
9314     {
9315         skip( "insufficient rights\n" );
9316         LocalFree( usersid );
9317         return;
9318     }
9319     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9320 
9321     /* managed product key exists */
9322     hprod = 0xdeadbeef;
9323     r = MsiOpenProductA(prodcode, &hprod);
9324     ok(r == ERROR_UNKNOWN_PRODUCT,
9325        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9326     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9327 
9328     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9329     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
9330     lstrcatA(keypath, prod_squashed);
9331 
9332     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
9333     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9334 
9335     /* user product key exists */
9336     hprod = 0xdeadbeef;
9337     r = MsiOpenProductA(prodcode, &hprod);
9338     ok(r == ERROR_UNKNOWN_PRODUCT,
9339        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9340     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9341 
9342     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9343     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9344 
9345     /* InstallProperties key exists */
9346     hprod = 0xdeadbeef;
9347     r = MsiOpenProductA(prodcode, &hprod);
9348     ok(r == ERROR_UNKNOWN_PRODUCT,
9349        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9350     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9351 
9352     lstrcpyA(val, path);
9353     lstrcatA(val, "\\winetest.msi");
9354     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
9355                          (const BYTE *)val, lstrlenA(val) + 1);
9356     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9357 
9358     /* LocalPackage value exists */
9359     hprod = 0xdeadbeef;
9360     r = MsiOpenProductA(prodcode, &hprod);
9361     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9362     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
9363 
9364     size = MAX_PATH;
9365     r = MsiGetPropertyA(hprod, "ProductCode", val, &size);
9366     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9367     ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val);
9368     ok(size == lstrlenA(prodcode), "Expected %d, got %d\n", lstrlenA(prodcode), size);
9369 
9370     MsiCloseHandle(hprod);
9371 
9372     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
9373                          (const BYTE *)"winetest.msi", 13);
9374     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9375 
9376     lstrcpyA(val, path);
9377     lstrcatA(val, "\\winetest.msi");
9378     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
9379                          (const BYTE *)val, lstrlenA(val) + 1);
9380     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9381 
9382     DeleteFileA(msifile);
9383 
9384     /* local package does not exist */
9385     hprod = 0xdeadbeef;
9386     r = MsiOpenProductA(prodcode, &hprod);
9387     ok(r == ERROR_UNKNOWN_PRODUCT,
9388        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9389     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9390 
9391     RegDeleteValueA(props, "LocalPackage");
9392     delete_key(props, "", access & KEY_WOW64_64KEY);
9393     RegCloseKey(props);
9394     delete_key(userkey, "", access & KEY_WOW64_64KEY);
9395     RegCloseKey(userkey);
9396     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
9397     RegCloseKey(prodkey);
9398 
9399     DeleteFileA(msifile);
9400     LocalFree(usersid);
9401 }
9402 
9403 static void test_MsiEnumPatchesEx_usermanaged(LPCSTR usersid, LPCSTR expectedsid)
9404 {
9405     MSIINSTALLCONTEXT context;
9406     CHAR keypath[MAX_PATH], patch[MAX_PATH];
9407     CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
9408     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
9409     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
9410     HKEY prodkey, patches, udprod, udpatch, hpatch;
9411     DWORD size, data;
9412     LONG res;
9413     UINT r;
9414     REGSAM access = KEY_ALL_ACCESS;
9415 
9416     create_test_guid(prodcode, prod_squashed);
9417     create_test_guid(patch, patch_squashed);
9418 
9419     if (is_wow64)
9420         access |= KEY_WOW64_64KEY;
9421 
9422     /* MSIPATCHSTATE_APPLIED */
9423 
9424     lstrcpyA(patchcode, "apple");
9425     lstrcpyA(targetprod, "banana");
9426     context = 0xdeadbeef;
9427     lstrcpyA(targetsid, "kiwi");
9428     size = MAX_PATH;
9429     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9430                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9431                            &context, targetsid, &size);
9432     if (r == ERROR_ACCESS_DENIED)
9433     {
9434         skip("Not enough rights to perform tests\n");
9435         return;
9436     }
9437     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9438     ok(!lstrcmpA(patchcode, "apple"),
9439        "Expected patchcode to be unchanged, got %s\n", patchcode);
9440     ok(!lstrcmpA(targetprod, "banana"),
9441        "Expected targetprod to be unchanged, got %s\n", targetprod);
9442     ok(context == 0xdeadbeef,
9443        "Expected context to be unchanged, got %d\n", context);
9444     ok(!lstrcmpA(targetsid, "kiwi"),
9445        "Expected targetsid to be unchanged, got %s\n", targetsid);
9446     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9447 
9448     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
9449     lstrcatA(keypath, expectedsid);
9450     lstrcatA(keypath, "\\Installer\\Products\\");
9451     lstrcatA(keypath, prod_squashed);
9452 
9453     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
9454     if (res == ERROR_ACCESS_DENIED)
9455     {
9456         skip("Not enough rights to perform tests\n");
9457         return;
9458     }
9459     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9460 
9461     /* managed product key exists */
9462     lstrcpyA(patchcode, "apple");
9463     lstrcpyA(targetprod, "banana");
9464     context = 0xdeadbeef;
9465     lstrcpyA(targetsid, "kiwi");
9466     size = MAX_PATH;
9467     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9468                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9469                            &context, targetsid, &size);
9470     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9471     ok(!lstrcmpA(patchcode, "apple"),
9472        "Expected patchcode to be unchanged, got %s\n", patchcode);
9473     ok(!lstrcmpA(targetprod, "banana"),
9474        "Expected targetprod to be unchanged, got %s\n", targetprod);
9475     ok(context == 0xdeadbeef,
9476        "Expected context to be unchanged, got %d\n", context);
9477     ok(!lstrcmpA(targetsid, "kiwi"),
9478        "Expected targetsid to be unchanged, got %s\n", targetsid);
9479     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9480 
9481     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
9482     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9483 
9484     /* patches key exists */
9485     lstrcpyA(patchcode, "apple");
9486     lstrcpyA(targetprod, "banana");
9487     context = 0xdeadbeef;
9488     lstrcpyA(targetsid, "kiwi");
9489     size = MAX_PATH;
9490     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9491                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9492                            &context, targetsid, &size);
9493     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9494     ok(!lstrcmpA(patchcode, "apple"),
9495        "Expected patchcode to be unchanged, got %s\n", patchcode);
9496     ok(!lstrcmpA(targetprod, "banana"),
9497        "Expected targetprod to be unchanged, got %s\n", targetprod);
9498     ok(context == 0xdeadbeef,
9499        "Expected context to be unchanged, got %d\n", context);
9500     ok(!lstrcmpA(targetsid, "kiwi"),
9501        "Expected targetsid to be unchanged, got %s\n", targetsid);
9502     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9503 
9504     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
9505                          (const BYTE *)patch_squashed,
9506                          lstrlenA(patch_squashed) + 1);
9507     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9508 
9509     /* Patches value exists, is not REG_MULTI_SZ */
9510     lstrcpyA(patchcode, "apple");
9511     lstrcpyA(targetprod, "banana");
9512     context = 0xdeadbeef;
9513     lstrcpyA(targetsid, "kiwi");
9514     size = MAX_PATH;
9515     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9516                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9517                            &context, targetsid, &size);
9518     ok(r == ERROR_BAD_CONFIGURATION,
9519        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9520     ok(!lstrcmpA(patchcode, "apple"),
9521        "Expected patchcode to be unchanged, got %s\n", patchcode);
9522     ok(!lstrcmpA(targetprod, "banana"),
9523        "Expected targetprod to be unchanged, got %s\n", targetprod);
9524     ok(context == 0xdeadbeef,
9525        "Expected context to be unchanged, got %d\n", context);
9526     ok(!lstrcmpA(targetsid, "kiwi"),
9527        "Expected targetsid to be unchanged, got %s\n", targetsid);
9528     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9529 
9530     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
9531                          (const BYTE *)"a\0b\0c\0\0", 7);
9532     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9533 
9534     /* Patches value exists, is not a squashed guid */
9535     lstrcpyA(patchcode, "apple");
9536     lstrcpyA(targetprod, "banana");
9537     context = 0xdeadbeef;
9538     lstrcpyA(targetsid, "kiwi");
9539     size = MAX_PATH;
9540     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9541                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9542                            &context, targetsid, &size);
9543     ok(r == ERROR_BAD_CONFIGURATION,
9544        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9545     ok(!lstrcmpA(patchcode, "apple"),
9546        "Expected patchcode to be unchanged, got %s\n", patchcode);
9547     ok(!lstrcmpA(targetprod, "banana"),
9548        "Expected targetprod to be unchanged, got %s\n", targetprod);
9549     ok(context == 0xdeadbeef,
9550        "Expected context to be unchanged, got %d\n", context);
9551     ok(!lstrcmpA(targetsid, "kiwi"),
9552        "Expected targetsid to be unchanged, got %s\n", targetsid);
9553     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9554 
9555     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
9556     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
9557                          (const BYTE *)patch_squashed,
9558                          lstrlenA(patch_squashed) + 2);
9559     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9560 
9561     /* Patches value exists */
9562     lstrcpyA(patchcode, "apple");
9563     lstrcpyA(targetprod, "banana");
9564     context = 0xdeadbeef;
9565     lstrcpyA(targetsid, "kiwi");
9566     size = MAX_PATH;
9567     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9568                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9569                            &context, targetsid, &size);
9570     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9571     ok(!lstrcmpA(patchcode, "apple"),
9572        "Expected patchcode to be unchanged, got %s\n", patchcode);
9573     ok(!lstrcmpA(targetprod, "banana"),
9574        "Expected targetprod to be unchanged, got %s\n", targetprod);
9575     ok(context == 0xdeadbeef,
9576        "Expected context to be unchanged, got %d\n", context);
9577     ok(!lstrcmpA(targetsid, "kiwi"),
9578        "Expected targetsid to be unchanged, got %s\n", targetsid);
9579     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9580 
9581     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
9582                          (const BYTE *)"whatever", 9);
9583     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9584 
9585     /* patch squashed value exists */
9586     lstrcpyA(patchcode, "apple");
9587     lstrcpyA(targetprod, "banana");
9588     context = 0xdeadbeef;
9589     lstrcpyA(targetsid, "kiwi");
9590     size = MAX_PATH;
9591     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9592                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9593                            &context, targetsid, &size);
9594     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9595     ok(!lstrcmpA(patchcode, patch),
9596        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9597     ok(!lstrcmpA(targetprod, prodcode),
9598        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9599     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9600        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9601     ok(!lstrcmpA(targetsid, expectedsid),
9602        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9603     ok(size == lstrlenA(expectedsid),
9604        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9605 
9606     /* increase the index */
9607     lstrcpyA(patchcode, "apple");
9608     lstrcpyA(targetprod, "banana");
9609     context = 0xdeadbeef;
9610     lstrcpyA(targetsid, "kiwi");
9611     size = MAX_PATH;
9612     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9613                            MSIPATCHSTATE_APPLIED, 1, patchcode, targetprod,
9614                            &context, targetsid, &size);
9615     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9616     ok(!lstrcmpA(patchcode, "apple"),
9617        "Expected patchcode to be unchanged, got %s\n", patchcode);
9618     ok(!lstrcmpA(targetprod, "banana"),
9619        "Expected targetprod to be unchanged, got %s\n", targetprod);
9620     ok(context == 0xdeadbeef,
9621        "Expected context to be unchanged, got %d\n", context);
9622     ok(!lstrcmpA(targetsid, "kiwi"),
9623        "Expected targetsid to be unchanged, got %s\n", targetsid);
9624     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9625 
9626     /* increase again */
9627     lstrcpyA(patchcode, "apple");
9628     lstrcpyA(targetprod, "banana");
9629     context = 0xdeadbeef;
9630     lstrcpyA(targetsid, "kiwi");
9631     size = MAX_PATH;
9632     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9633                            MSIPATCHSTATE_APPLIED, 2, patchcode, targetprod,
9634                            &context, targetsid, &size);
9635     ok(r == ERROR_INVALID_PARAMETER,
9636        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9637     ok(!lstrcmpA(patchcode, "apple"),
9638        "Expected patchcode to be unchanged, got %s\n", patchcode);
9639     ok(!lstrcmpA(targetprod, "banana"),
9640        "Expected targetprod to be unchanged, got %s\n", targetprod);
9641     ok(context == 0xdeadbeef,
9642        "Expected context to be unchanged, got %d\n", context);
9643     ok(!lstrcmpA(targetsid, "kiwi"),
9644        "Expected targetsid to be unchanged, got %s\n", targetsid);
9645     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9646 
9647     /* szPatchCode is NULL */
9648     lstrcpyA(targetprod, "banana");
9649     context = 0xdeadbeef;
9650     lstrcpyA(targetsid, "kiwi");
9651     size = MAX_PATH;
9652     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9653                            MSIPATCHSTATE_APPLIED, 0, NULL, targetprod,
9654                            &context, targetsid, &size);
9655     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9656     ok(!lstrcmpA(targetprod, prodcode),
9657        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9658     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9659        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9660     ok(!lstrcmpA(targetsid, expectedsid),
9661        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9662     ok(size == lstrlenA(expectedsid),
9663        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9664 
9665     /* szTargetProductCode is NULL */
9666     lstrcpyA(patchcode, "apple");
9667     context = 0xdeadbeef;
9668     lstrcpyA(targetsid, "kiwi");
9669     size = MAX_PATH;
9670     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9671                            MSIPATCHSTATE_APPLIED, 0, patchcode, NULL,
9672                            &context, targetsid, &size);
9673     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9674     ok(!lstrcmpA(patchcode, patch),
9675        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9676     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9677        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9678     ok(!lstrcmpA(targetsid, expectedsid),
9679        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9680     ok(size == lstrlenA(expectedsid),
9681        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9682 
9683     /* pdwTargetProductContext is NULL */
9684     lstrcpyA(patchcode, "apple");
9685     lstrcpyA(targetprod, "banana");
9686     lstrcpyA(targetsid, "kiwi");
9687     size = MAX_PATH;
9688     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9689                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9690                            NULL, targetsid, &size);
9691     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9692     ok(!lstrcmpA(patchcode, patch),
9693        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9694     ok(!lstrcmpA(targetprod, prodcode),
9695        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9696     ok(!lstrcmpA(targetsid, expectedsid),
9697        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9698     ok(size == lstrlenA(expectedsid),
9699        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9700 
9701     /* szTargetUserSid is NULL */
9702     lstrcpyA(patchcode, "apple");
9703     lstrcpyA(targetprod, "banana");
9704     context = 0xdeadbeef;
9705     size = MAX_PATH;
9706     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9707                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9708                            &context, NULL, &size);
9709     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9710     ok(!lstrcmpA(patchcode, patch),
9711        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9712     ok(!lstrcmpA(targetprod, prodcode),
9713        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9714     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9715        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9716     ok(size == lstrlenA(expectedsid) * sizeof(WCHAR),
9717        "Expected %d*sizeof(WCHAR), got %d\n", lstrlenA(expectedsid), size);
9718 
9719     /* pcchTargetUserSid is exactly the length of szTargetUserSid */
9720     lstrcpyA(patchcode, "apple");
9721     lstrcpyA(targetprod, "banana");
9722     context = 0xdeadbeef;
9723     lstrcpyA(targetsid, "kiwi");
9724     size = lstrlenA(expectedsid);
9725     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9726                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9727                            &context, targetsid, &size);
9728     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
9729     ok(!lstrcmpA(patchcode, patch),
9730        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9731     ok(!lstrcmpA(targetprod, prodcode),
9732        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9733     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9734        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9735     ok(!strncmp(targetsid, expectedsid, lstrlenA(expectedsid) - 1),
9736        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9737     ok(size == lstrlenA(expectedsid) * sizeof(WCHAR),
9738        "Expected %d*sizeof(WCHAR), got %d\n", lstrlenA(expectedsid), size);
9739 
9740     /* pcchTargetUserSid has enough room for NULL terminator */
9741     lstrcpyA(patchcode, "apple");
9742     lstrcpyA(targetprod, "banana");
9743     context = 0xdeadbeef;
9744     lstrcpyA(targetsid, "kiwi");
9745     size = lstrlenA(expectedsid) + 1;
9746     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9747                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9748                            &context, targetsid, &size);
9749     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9750     ok(!lstrcmpA(patchcode, patch),
9751        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9752     ok(!lstrcmpA(targetprod, prodcode),
9753        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9754     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9755        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9756     ok(!lstrcmpA(targetsid, expectedsid),
9757        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9758     ok(size == lstrlenA(expectedsid),
9759        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9760 
9761     /* both szTargetuserSid and pcchTargetUserSid are NULL */
9762     lstrcpyA(patchcode, "apple");
9763     lstrcpyA(targetprod, "banana");
9764     context = 0xdeadbeef;
9765     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9766                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9767                            &context, NULL, NULL);
9768     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9769     ok(!lstrcmpA(patchcode, patch),
9770        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9771     ok(!lstrcmpA(targetprod, prodcode),
9772        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9773     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9774        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9775 
9776     /* MSIPATCHSTATE_SUPERSEDED */
9777 
9778     lstrcpyA(patchcode, "apple");
9779     lstrcpyA(targetprod, "banana");
9780     context = 0xdeadbeef;
9781     lstrcpyA(targetsid, "kiwi");
9782     size = MAX_PATH;
9783     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9784                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
9785                            &context, targetsid, &size);
9786     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9787     ok(!lstrcmpA(patchcode, "apple"),
9788        "Expected patchcode to be unchanged, got %s\n", patchcode);
9789     ok(!lstrcmpA(targetprod, "banana"),
9790        "Expected targetprod to be unchanged, got %s\n", targetprod);
9791     ok(context == 0xdeadbeef,
9792        "Expected context to be unchanged, got %d\n", context);
9793     ok(!lstrcmpA(targetsid, "kiwi"),
9794        "Expected targetsid to be unchanged, got %s\n", targetsid);
9795     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9796 
9797     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
9798     lstrcatA(keypath, expectedsid);
9799     lstrcatA(keypath, "\\Products\\");
9800     lstrcatA(keypath, prod_squashed);
9801 
9802     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
9803     if (res == ERROR_ACCESS_DENIED)
9804     {
9805         skip("Not enough rights to perform tests\n");
9806         return;
9807     }
9808     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9809 
9810     /* UserData product key exists */
9811     lstrcpyA(patchcode, "apple");
9812     lstrcpyA(targetprod, "banana");
9813     context = 0xdeadbeef;
9814     lstrcpyA(targetsid, "kiwi");
9815     size = MAX_PATH;
9816     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9817                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
9818                            &context, targetsid, &size);
9819     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9820     ok(!lstrcmpA(patchcode, "apple"),
9821        "Expected patchcode to be unchanged, got %s\n", patchcode);
9822     ok(!lstrcmpA(targetprod, "banana"),
9823        "Expected targetprod to be unchanged, got %s\n", targetprod);
9824     ok(context == 0xdeadbeef,
9825        "Expected context to be unchanged, got %d\n", context);
9826     ok(!lstrcmpA(targetsid, "kiwi"),
9827        "Expected targetsid to be unchanged, got %s\n", targetsid);
9828     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9829 
9830     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
9831     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9832 
9833     /* UserData patches key exists */
9834     lstrcpyA(patchcode, "apple");
9835     lstrcpyA(targetprod, "banana");
9836     context = 0xdeadbeef;
9837     lstrcpyA(targetsid, "kiwi");
9838     size = MAX_PATH;
9839     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9840                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
9841                            &context, targetsid, &size);
9842     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9843     ok(!lstrcmpA(patchcode, "apple"),
9844        "Expected patchcode to be unchanged, got %s\n", patchcode);
9845     ok(!lstrcmpA(targetprod, "banana"),
9846        "Expected targetprod to be unchanged, got %s\n", targetprod);
9847     ok(context == 0xdeadbeef,
9848        "Expected context to be unchanged, got %d\n", context);
9849     ok(!lstrcmpA(targetsid, "kiwi"),
9850        "Expected targetsid to be unchanged, got %s\n", targetsid);
9851     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9852 
9853     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
9854     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9855 
9856     /* specific UserData patch key exists */
9857     lstrcpyA(patchcode, "apple");
9858     lstrcpyA(targetprod, "banana");
9859     context = 0xdeadbeef;
9860     lstrcpyA(targetsid, "kiwi");
9861     size = MAX_PATH;
9862     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9863                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
9864                            &context, targetsid, &size);
9865     ok(r == ERROR_BAD_CONFIGURATION,
9866        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9867     ok(!lstrcmpA(patchcode, "apple"),
9868        "Expected patchcode to be unchanged, got %s\n", patchcode);
9869     ok(!lstrcmpA(targetprod, "banana"),
9870        "Expected targetprod to be unchanged, got %s\n", targetprod);
9871     ok(context == 0xdeadbeef,
9872        "Expected context to be unchanged, got %d\n", context);
9873     ok(!lstrcmpA(targetsid, "kiwi"),
9874        "Expected targetsid to be unchanged, got %s\n", targetsid);
9875     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9876 
9877     data = MSIPATCHSTATE_SUPERSEDED;
9878     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
9879                          (const BYTE *)&data, sizeof(DWORD));
9880     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9881 
9882     /* State value exists */
9883     lstrcpyA(patchcode, "apple");
9884     lstrcpyA(targetprod, "banana");
9885     context = 0xdeadbeef;
9886     lstrcpyA(targetsid, "kiwi");
9887     size = MAX_PATH;
9888     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9889                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
9890                            &context, targetsid, &size);
9891     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9892     ok(!lstrcmpA(patchcode, patch),
9893        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9894     ok(!lstrcmpA(targetprod, prodcode),
9895        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9896     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9897        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9898     ok(!lstrcmpA(targetsid, expectedsid),
9899        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9900     ok(size == lstrlenA(expectedsid),
9901        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9902 
9903     /* MSIPATCHSTATE_OBSOLETED */
9904 
9905     lstrcpyA(patchcode, "apple");
9906     lstrcpyA(targetprod, "banana");
9907     context = 0xdeadbeef;
9908     lstrcpyA(targetsid, "kiwi");
9909     size = MAX_PATH;
9910     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9911                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
9912                            &context, targetsid, &size);
9913     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9914     ok(!lstrcmpA(patchcode, "apple"),
9915        "Expected patchcode to be unchanged, got %s\n", patchcode);
9916     ok(!lstrcmpA(targetprod, "banana"),
9917        "Expected targetprod to be unchanged, got %s\n", targetprod);
9918     ok(context == 0xdeadbeef,
9919        "Expected context to be unchanged, got %d\n", context);
9920     ok(!lstrcmpA(targetsid, "kiwi"),
9921        "Expected targetsid to be unchanged, got %s\n", targetsid);
9922     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9923 
9924     data = MSIPATCHSTATE_OBSOLETED;
9925     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
9926                          (const BYTE *)&data, sizeof(DWORD));
9927     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9928 
9929     /* State value is obsoleted */
9930     lstrcpyA(patchcode, "apple");
9931     lstrcpyA(targetprod, "banana");
9932     context = 0xdeadbeef;
9933     lstrcpyA(targetsid, "kiwi");
9934     size = MAX_PATH;
9935     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9936                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
9937                            &context, targetsid, &size);
9938     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9939     ok(!lstrcmpA(patchcode, patch),
9940        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9941     ok(!lstrcmpA(targetprod, prodcode),
9942        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9943     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9944        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9945     ok(!lstrcmpA(targetsid, expectedsid),
9946        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9947     ok(size == lstrlenA(expectedsid),
9948        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9949 
9950     /* MSIPATCHSTATE_REGISTERED */
9951     /* FIXME */
9952 
9953     /* MSIPATCHSTATE_ALL */
9954 
9955     /* 1st */
9956     lstrcpyA(patchcode, "apple");
9957     lstrcpyA(targetprod, "banana");
9958     context = 0xdeadbeef;
9959     lstrcpyA(targetsid, "kiwi");
9960     size = MAX_PATH;
9961     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9962                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
9963                            &context, targetsid, &size);
9964     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9965     ok(!lstrcmpA(patchcode, patch),
9966        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9967     ok(!lstrcmpA(targetprod, prodcode),
9968        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9969     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9970        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9971     ok(!lstrcmpA(targetsid, expectedsid),
9972        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9973     ok(size == lstrlenA(expectedsid),
9974        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9975 
9976     /* same patch in multiple places, only one is enumerated */
9977     lstrcpyA(patchcode, "apple");
9978     lstrcpyA(targetprod, "banana");
9979     context = 0xdeadbeef;
9980     lstrcpyA(targetsid, "kiwi");
9981     size = MAX_PATH;
9982     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9983                            MSIPATCHSTATE_ALL, 1, patchcode, targetprod,
9984                            &context, targetsid, &size);
9985     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9986     ok(!lstrcmpA(patchcode, "apple"),
9987        "Expected patchcode to be unchanged, got %s\n", patchcode);
9988     ok(!lstrcmpA(targetprod, "banana"),
9989        "Expected targetprod to be unchanged, got %s\n", targetprod);
9990     ok(context == 0xdeadbeef,
9991        "Expected context to be unchanged, got %d\n", context);
9992     ok(!lstrcmpA(targetsid, "kiwi"),
9993        "Expected targetsid to be unchanged, got %s\n", targetsid);
9994     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9995 
9996     RegDeleteValueA(hpatch, "State");
9997     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
9998     RegCloseKey(hpatch);
9999     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
10000     RegCloseKey(udpatch);
10001     delete_key(udprod, "", access & KEY_WOW64_64KEY);
10002     RegCloseKey(udprod);
10003     RegDeleteValueA(patches, "Patches");
10004     delete_key(patches, "", access & KEY_WOW64_64KEY);
10005     RegCloseKey(patches);
10006     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
10007     RegCloseKey(prodkey);
10008 }
10009 
10010 static void test_MsiEnumPatchesEx_userunmanaged(LPCSTR usersid, LPCSTR expectedsid)
10011 {
10012     MSIINSTALLCONTEXT context;
10013     CHAR keypath[MAX_PATH], patch[MAX_PATH];
10014     CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
10015     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
10016     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
10017     HKEY prodkey, patches, udprod, udpatch;
10018     HKEY userkey, hpatch;
10019     DWORD size, data;
10020     LONG res;
10021     UINT r;
10022     REGSAM access = KEY_ALL_ACCESS;
10023 
10024     create_test_guid(prodcode, prod_squashed);
10025     create_test_guid(patch, patch_squashed);
10026 
10027     if (is_wow64)
10028         access |= KEY_WOW64_64KEY;
10029 
10030     /* MSIPATCHSTATE_APPLIED */
10031 
10032     lstrcpyA(patchcode, "apple");
10033     lstrcpyA(targetprod, "banana");
10034     context = 0xdeadbeef;
10035     lstrcpyA(targetsid, "kiwi");
10036     size = MAX_PATH;
10037     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10038                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10039                            &context, targetsid, &size);
10040     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10041     ok(!lstrcmpA(patchcode, "apple"),
10042        "Expected patchcode to be unchanged, got %s\n", patchcode);
10043     ok(!lstrcmpA(targetprod, "banana"),
10044        "Expected targetprod to be unchanged, got %s\n", targetprod);
10045     ok(context == 0xdeadbeef,
10046        "Expected context to be unchanged, got %d\n", context);
10047     ok(!lstrcmpA(targetsid, "kiwi"),
10048        "Expected targetsid to be unchanged, got %s\n", targetsid);
10049     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10050 
10051     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
10052     lstrcatA(keypath, prod_squashed);
10053 
10054     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
10055     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10056 
10057     /* current user product key exists */
10058     lstrcpyA(patchcode, "apple");
10059     lstrcpyA(targetprod, "banana");
10060     context = 0xdeadbeef;
10061     lstrcpyA(targetsid, "kiwi");
10062     size = MAX_PATH;
10063     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10064                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10065                            &context, targetsid, &size);
10066     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10067     ok(!lstrcmpA(patchcode, "apple"),
10068        "Expected patchcode to be unchanged, got %s\n", patchcode);
10069     ok(!lstrcmpA(targetprod, "banana"),
10070        "Expected targetprod to be unchanged, got %s\n", targetprod);
10071     ok(context == 0xdeadbeef,
10072        "Expected context to be unchanged, got %d\n", context);
10073     ok(!lstrcmpA(targetsid, "kiwi"),
10074        "Expected targetsid to be unchanged, got %s\n", targetsid);
10075     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10076 
10077     res = RegCreateKeyA(prodkey, "Patches", &patches);
10078     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10079 
10080     /* Patches key exists */
10081     lstrcpyA(patchcode, "apple");
10082     lstrcpyA(targetprod, "banana");
10083     context = 0xdeadbeef;
10084     lstrcpyA(targetsid, "kiwi");
10085     size = MAX_PATH;
10086     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10087                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10088                            &context, targetsid, &size);
10089     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10090     ok(!lstrcmpA(patchcode, "apple"),
10091        "Expected patchcode to be unchanged, got %s\n", patchcode);
10092     ok(!lstrcmpA(targetprod, "banana"),
10093        "Expected targetprod to be unchanged, got %s\n", targetprod);
10094     ok(context == 0xdeadbeef,
10095        "Expected context to be unchanged, got %d\n", context);
10096     ok(!lstrcmpA(targetsid, "kiwi"),
10097        "Expected targetsid to be unchanged, got %s\n", targetsid);
10098     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10099 
10100     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
10101                          (const BYTE *)patch_squashed,
10102                          lstrlenA(patch_squashed) + 1);
10103     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10104 
10105     /* Patches value exists, is not REG_MULTI_SZ */
10106     lstrcpyA(patchcode, "apple");
10107     lstrcpyA(targetprod, "banana");
10108     context = 0xdeadbeef;
10109     lstrcpyA(targetsid, "kiwi");
10110     size = MAX_PATH;
10111     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10112                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10113                            &context, targetsid, &size);
10114     ok(r == ERROR_BAD_CONFIGURATION,
10115        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10116     ok(!lstrcmpA(patchcode, "apple"),
10117        "Expected patchcode to be unchanged, got %s\n", patchcode);
10118     ok(!lstrcmpA(targetprod, "banana"),
10119        "Expected targetprod to be unchanged, got %s\n", targetprod);
10120     ok(context == 0xdeadbeef,
10121        "Expected context to be unchanged, got %d\n", context);
10122     ok(!lstrcmpA(targetsid, "kiwi"),
10123        "Expected targetsid to be unchanged, got %s\n", targetsid);
10124     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10125 
10126     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10127                          (const BYTE *)"a\0b\0c\0\0", 7);
10128     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10129 
10130     /* Patches value exists, is not a squashed guid */
10131     lstrcpyA(patchcode, "apple");
10132     lstrcpyA(targetprod, "banana");
10133     context = 0xdeadbeef;
10134     lstrcpyA(targetsid, "kiwi");
10135     size = MAX_PATH;
10136     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10137                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10138                            &context, targetsid, &size);
10139     ok(r == ERROR_BAD_CONFIGURATION,
10140        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10141     ok(!lstrcmpA(patchcode, "apple"),
10142        "Expected patchcode to be unchanged, got %s\n", patchcode);
10143     ok(!lstrcmpA(targetprod, "banana"),
10144        "Expected targetprod to be unchanged, got %s\n", targetprod);
10145     ok(context == 0xdeadbeef,
10146        "Expected context to be unchanged, got %d\n", context);
10147     ok(!lstrcmpA(targetsid, "kiwi"),
10148        "Expected targetsid to be unchanged, got %s\n", targetsid);
10149     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10150 
10151     patch_squashed[lstrlenA(patch_squashed) + 1] = 0;
10152     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10153                          (const BYTE *)patch_squashed,
10154                          lstrlenA(patch_squashed) + 2);
10155     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10156 
10157     /* Patches value exists */
10158     lstrcpyA(patchcode, "apple");
10159     lstrcpyA(targetprod, "banana");
10160     context = 0xdeadbeef;
10161     lstrcpyA(targetsid, "kiwi");
10162     size = MAX_PATH;
10163     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10164                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10165                            &context, targetsid, &size);
10166     ok(r == ERROR_NO_MORE_ITEMS ||
10167        broken(r == ERROR_BAD_CONFIGURATION), /* Windows Installer 3.0 */
10168        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10169     ok(!lstrcmpA(patchcode, "apple"),
10170        "Expected patchcode to be unchanged, got %s\n", patchcode);
10171     ok(!lstrcmpA(targetprod, "banana"),
10172        "Expected targetprod to be unchanged, got %s\n", targetprod);
10173     ok(context == 0xdeadbeef,
10174        "Expected context to be unchanged, got %d\n", context);
10175     ok(!lstrcmpA(targetsid, "kiwi"),
10176        "Expected targetsid to be unchanged, got %s\n", targetsid);
10177     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10178 
10179     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
10180                          (const BYTE *)"whatever", 9);
10181     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10182 
10183     /* patch code value exists */
10184     lstrcpyA(patchcode, "apple");
10185     lstrcpyA(targetprod, "banana");
10186     context = 0xdeadbeef;
10187     lstrcpyA(targetsid, "kiwi");
10188     size = MAX_PATH;
10189     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10190                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10191                            &context, targetsid, &size);
10192     ok(r == ERROR_NO_MORE_ITEMS ||
10193        broken(r == ERROR_BAD_CONFIGURATION), /* Windows Installer 3.0 */
10194        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10195     ok(!lstrcmpA(patchcode, "apple"),
10196        "Expected patchcode to be unchanged, got %s\n", patchcode);
10197     ok(!lstrcmpA(targetprod, "banana"),
10198        "Expected targetprod to be unchanged, got %s\n", targetprod);
10199     ok(context == 0xdeadbeef,
10200        "Expected context to be unchanged, got %d\n", context);
10201     ok(!lstrcmpA(targetsid, "kiwi"),
10202        "Expected targetsid to be unchanged, got %s\n", targetsid);
10203     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10204 
10205     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
10206     lstrcatA(keypath, expectedsid);
10207     lstrcatA(keypath, "\\Patches\\");
10208     lstrcatA(keypath, patch_squashed);
10209 
10210     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
10211     if (res == ERROR_ACCESS_DENIED)
10212     {
10213         skip("Not enough rights to perform tests\n");
10214         goto error;
10215     }
10216     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10217 
10218     /* userdata patch key exists */
10219     lstrcpyA(patchcode, "apple");
10220     lstrcpyA(targetprod, "banana");
10221     context = 0xdeadbeef;
10222     lstrcpyA(targetsid, "kiwi");
10223     size = MAX_PATH;
10224     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10225                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10226                            &context, targetsid, &size);
10227     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10228     ok(!lstrcmpA(patchcode, patch),
10229        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10230     ok(!lstrcmpA(targetprod, prodcode),
10231        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10232     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
10233        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
10234     ok(!lstrcmpA(targetsid, expectedsid),
10235        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10236     ok(size == lstrlenA(expectedsid),
10237        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10238 
10239     /* MSIPATCHSTATE_SUPERSEDED */
10240 
10241     lstrcpyA(patchcode, "apple");
10242     lstrcpyA(targetprod, "banana");
10243     context = 0xdeadbeef;
10244     lstrcpyA(targetsid, "kiwi");
10245     size = MAX_PATH;
10246     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10247                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10248                            &context, targetsid, &size);
10249     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10250     ok(!lstrcmpA(patchcode, "apple"),
10251        "Expected patchcode to be unchanged, got %s\n", patchcode);
10252     ok(!lstrcmpA(targetprod, "banana"),
10253        "Expected targetprod to be unchanged, got %s\n", targetprod);
10254     ok(context == 0xdeadbeef,
10255        "Expected context to be unchanged, got %d\n", context);
10256     ok(!lstrcmpA(targetsid, "kiwi"),
10257        "Expected targetsid to be unchanged, got %s\n", targetsid);
10258     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10259 
10260     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
10261     lstrcatA(keypath, expectedsid);
10262     lstrcatA(keypath, "\\Products\\");
10263     lstrcatA(keypath, prod_squashed);
10264 
10265     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
10266     if (res == ERROR_ACCESS_DENIED)
10267     {
10268         skip("Not enough rights to perform tests\n");
10269         goto error;
10270     }
10271     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10272 
10273     /* UserData product key exists */
10274     lstrcpyA(patchcode, "apple");
10275     lstrcpyA(targetprod, "banana");
10276     context = 0xdeadbeef;
10277     lstrcpyA(targetsid, "kiwi");
10278     size = MAX_PATH;
10279     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10280                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10281                            &context, targetsid, &size);
10282     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10283     ok(!lstrcmpA(patchcode, "apple"),
10284        "Expected patchcode to be unchanged, got %s\n", patchcode);
10285     ok(!lstrcmpA(targetprod, "banana"),
10286        "Expected targetprod to be unchanged, got %s\n", targetprod);
10287     ok(context == 0xdeadbeef,
10288        "Expected context to be unchanged, got %d\n", context);
10289     ok(!lstrcmpA(targetsid, "kiwi"),
10290        "Expected targetsid to be unchanged, got %s\n", targetsid);
10291     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10292 
10293     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
10294     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10295 
10296     /* UserData patches key exists */
10297     lstrcpyA(patchcode, "apple");
10298     lstrcpyA(targetprod, "banana");
10299     context = 0xdeadbeef;
10300     lstrcpyA(targetsid, "kiwi");
10301     size = MAX_PATH;
10302     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10303                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10304                            &context, targetsid, &size);
10305     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10306     ok(!lstrcmpA(patchcode, "apple"),
10307        "Expected patchcode to be unchanged, got %s\n", patchcode);
10308     ok(!lstrcmpA(targetprod, "banana"),
10309        "Expected targetprod to be unchanged, got %s\n", targetprod);
10310     ok(context == 0xdeadbeef,
10311        "Expected context to be unchanged, got %d\n", context);
10312     ok(!lstrcmpA(targetsid, "kiwi"),
10313        "Expected targetsid to be unchanged, got %s\n", targetsid);
10314     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10315 
10316     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
10317     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10318 
10319     /* specific UserData patch key exists */
10320     lstrcpyA(patchcode, "apple");
10321     lstrcpyA(targetprod, "banana");
10322     context = 0xdeadbeef;
10323     lstrcpyA(targetsid, "kiwi");
10324     size = MAX_PATH;
10325     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10326                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10327                            &context, targetsid, &size);
10328     ok(r == ERROR_BAD_CONFIGURATION,
10329        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10330     ok(!lstrcmpA(patchcode, "apple"),
10331        "Expected patchcode to be unchanged, got %s\n", patchcode);
10332     ok(!lstrcmpA(targetprod, "banana"),
10333        "Expected targetprod to be unchanged, got %s\n", targetprod);
10334     ok(context == 0xdeadbeef,
10335        "Expected context to be unchanged, got %d\n", context);
10336     ok(!lstrcmpA(targetsid, "kiwi"),
10337        "Expected targetsid to be unchanged, got %s\n", targetsid);
10338     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10339 
10340     data = MSIPATCHSTATE_SUPERSEDED;
10341     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10342                          (const BYTE *)&data, sizeof(DWORD));
10343     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10344 
10345     /* State value exists */
10346     lstrcpyA(patchcode, "apple");
10347     lstrcpyA(targetprod, "banana");
10348     context = 0xdeadbeef;
10349     lstrcpyA(targetsid, "kiwi");
10350     size = MAX_PATH;
10351     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10352                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10353                            &context, targetsid, &size);
10354     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10355     ok(!lstrcmpA(patchcode, patch),
10356        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10357     ok(!lstrcmpA(targetprod, prodcode),
10358        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10359     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
10360        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
10361     ok(!lstrcmpA(targetsid, expectedsid),
10362        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10363     ok(size == lstrlenA(expectedsid),
10364        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10365 
10366     /* MSIPATCHSTATE_OBSOLETED */
10367 
10368     lstrcpyA(patchcode, "apple");
10369     lstrcpyA(targetprod, "banana");
10370     context = 0xdeadbeef;
10371     lstrcpyA(targetsid, "kiwi");
10372     size = MAX_PATH;
10373     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10374                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
10375                            &context, targetsid, &size);
10376     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10377     ok(!lstrcmpA(patchcode, "apple"),
10378        "Expected patchcode to be unchanged, got %s\n", patchcode);
10379     ok(!lstrcmpA(targetprod, "banana"),
10380        "Expected targetprod to be unchanged, got %s\n", targetprod);
10381     ok(context == 0xdeadbeef,
10382        "Expected context to be unchanged, got %d\n", context);
10383     ok(!lstrcmpA(targetsid, "kiwi"),
10384        "Expected targetsid to be unchanged, got %s\n", targetsid);
10385     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10386 
10387     data = MSIPATCHSTATE_OBSOLETED;
10388     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10389                          (const BYTE *)&data, sizeof(DWORD));
10390     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10391 
10392     /* State value is obsoleted */
10393     lstrcpyA(patchcode, "apple");
10394     lstrcpyA(targetprod, "banana");
10395     context = 0xdeadbeef;
10396     lstrcpyA(targetsid, "kiwi");
10397     size = MAX_PATH;
10398     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10399                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
10400                            &context, targetsid, &size);
10401     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10402     ok(!lstrcmpA(patchcode, patch),
10403        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10404     ok(!lstrcmpA(targetprod, prodcode),
10405        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10406     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
10407        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
10408     ok(!lstrcmpA(targetsid, expectedsid),
10409        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10410     ok(size == lstrlenA(expectedsid),
10411        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10412 
10413     /* MSIPATCHSTATE_REGISTERED */
10414     /* FIXME */
10415 
10416     /* MSIPATCHSTATE_ALL */
10417 
10418     /* 1st */
10419     lstrcpyA(patchcode, "apple");
10420     lstrcpyA(targetprod, "banana");
10421     context = 0xdeadbeef;
10422     lstrcpyA(targetsid, "kiwi");
10423     size = MAX_PATH;
10424     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10425                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
10426                            &context, targetsid, &size);
10427     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10428     ok(!lstrcmpA(patchcode, patch),
10429        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10430     ok(!lstrcmpA(targetprod, prodcode),
10431        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10432     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
10433        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
10434     ok(!lstrcmpA(targetsid, expectedsid),
10435        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10436     ok(size == lstrlenA(expectedsid),
10437        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10438 
10439     /* same patch in multiple places, only one is enumerated */
10440     lstrcpyA(patchcode, "apple");
10441     lstrcpyA(targetprod, "banana");
10442     context = 0xdeadbeef;
10443     lstrcpyA(targetsid, "kiwi");
10444     size = MAX_PATH;
10445     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10446                            MSIPATCHSTATE_ALL, 1, patchcode, targetprod,
10447                            &context, targetsid, &size);
10448     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10449     ok(!lstrcmpA(patchcode, "apple"),
10450        "Expected patchcode to be unchanged, got %s\n", patchcode);
10451     ok(!lstrcmpA(targetprod, "banana"),
10452        "Expected targetprod to be unchanged, got %s\n", targetprod);
10453     ok(context == 0xdeadbeef,
10454        "Expected context to be unchanged, got %d\n", context);
10455     ok(!lstrcmpA(targetsid, "kiwi"),
10456        "Expected targetsid to be unchanged, got %s\n", targetsid);
10457     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10458 
10459     RegDeleteValueA(hpatch, "State");
10460     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
10461     RegCloseKey(hpatch);
10462     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
10463     RegCloseKey(udpatch);
10464     delete_key(udprod, "", access & KEY_WOW64_64KEY);
10465     RegCloseKey(udprod);
10466     delete_key(userkey, "", access & KEY_WOW64_64KEY);
10467     RegCloseKey(userkey);
10468     RegDeleteValueA(patches, patch_squashed);
10469     RegDeleteValueA(patches, "Patches");
10470 
10471 error:
10472     RegDeleteKeyA(patches, "");
10473     RegCloseKey(patches);
10474     RegDeleteKeyA(prodkey, "");
10475     RegCloseKey(prodkey);
10476 }
10477 
10478 static void test_MsiEnumPatchesEx_machine(void)
10479 {
10480     CHAR keypath[MAX_PATH], patch[MAX_PATH];
10481     CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
10482     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
10483     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
10484     HKEY prodkey, patches, udprod, udpatch;
10485     HKEY hpatch;
10486     MSIINSTALLCONTEXT context;
10487     DWORD size, data;
10488     LONG res;
10489     UINT r;
10490     REGSAM access = KEY_ALL_ACCESS;
10491 
10492     create_test_guid(prodcode, prod_squashed);
10493     create_test_guid(patch, patch_squashed);
10494 
10495     if (is_wow64)
10496         access |= KEY_WOW64_64KEY;
10497 
10498     /* MSIPATCHSTATE_APPLIED */
10499 
10500     lstrcpyA(patchcode, "apple");
10501     lstrcpyA(targetprod, "banana");
10502     context = 0xdeadbeef;
10503     lstrcpyA(targetsid, "kiwi");
10504     size = MAX_PATH;
10505     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10506                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10507                            &context, targetsid, &size);
10508     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10509     ok(!lstrcmpA(patchcode, "apple"),
10510        "Expected patchcode to be unchanged, got %s\n", patchcode);
10511     ok(!lstrcmpA(targetprod, "banana"),
10512        "Expected targetprod to be unchanged, got %s\n", targetprod);
10513     ok(context == 0xdeadbeef,
10514        "Expected context to be unchanged, got %d\n", context);
10515     ok(!lstrcmpA(targetsid, "kiwi"),
10516        "Expected targetsid to be unchanged, got %s\n", targetsid);
10517     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10518 
10519     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
10520     lstrcatA(keypath, prod_squashed);
10521 
10522     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
10523     if (res == ERROR_ACCESS_DENIED)
10524     {
10525         skip("Not enough rights to perform tests\n");
10526         return;
10527     }
10528     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10529 
10530     /* local product key exists */
10531     lstrcpyA(patchcode, "apple");
10532     lstrcpyA(targetprod, "banana");
10533     context = 0xdeadbeef;
10534     lstrcpyA(targetsid, "kiwi");
10535     size = MAX_PATH;
10536     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10537                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10538                            &context, targetsid, &size);
10539     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10540     ok(!lstrcmpA(patchcode, "apple"),
10541        "Expected patchcode to be unchanged, got %s\n", patchcode);
10542     ok(!lstrcmpA(targetprod, "banana"),
10543        "Expected targetprod to be unchanged, got %s\n", targetprod);
10544     ok(context == 0xdeadbeef,
10545        "Expected context to be unchanged, got %d\n", context);
10546     ok(!lstrcmpA(targetsid, "kiwi"),
10547        "Expected targetsid to be unchanged, got %s\n", targetsid);
10548     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10549 
10550     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
10551     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10552 
10553     /* Patches key exists */
10554     lstrcpyA(patchcode, "apple");
10555     lstrcpyA(targetprod, "banana");
10556     context = 0xdeadbeef;
10557     lstrcpyA(targetsid, "kiwi");
10558     size = MAX_PATH;
10559     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10560                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10561                            &context, targetsid, &size);
10562     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10563     ok(!lstrcmpA(patchcode, "apple"),
10564        "Expected patchcode to be unchanged, got %s\n", patchcode);
10565     ok(!lstrcmpA(targetprod, "banana"),
10566        "Expected targetprod to be unchanged, got %s\n", targetprod);
10567     ok(context == 0xdeadbeef,
10568        "Expected context to be unchanged, got %d\n", context);
10569     ok(!lstrcmpA(targetsid, "kiwi"),
10570        "Expected targetsid to be unchanged, got %s\n", targetsid);
10571     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10572 
10573     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
10574                          (const BYTE *)patch_squashed,
10575                          lstrlenA(patch_squashed) + 1);
10576     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10577 
10578     /* Patches value exists, is not REG_MULTI_SZ */
10579     lstrcpyA(patchcode, "apple");
10580     lstrcpyA(targetprod, "banana");
10581     context = 0xdeadbeef;
10582     lstrcpyA(targetsid, "kiwi");
10583     size = MAX_PATH;
10584     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10585                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10586                            &context, targetsid, &size);
10587     ok(r == ERROR_BAD_CONFIGURATION,
10588        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10589     ok(!lstrcmpA(patchcode, "apple"),
10590        "Expected patchcode to be unchanged, got %s\n", patchcode);
10591     ok(!lstrcmpA(targetprod, "banana"),
10592        "Expected targetprod to be unchanged, got %s\n", targetprod);
10593     ok(context == 0xdeadbeef,
10594        "Expected context to be unchanged, got %d\n", context);
10595     ok(!lstrcmpA(targetsid, "kiwi"),
10596        "Expected targetsid to be unchanged, got %s\n", targetsid);
10597     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10598 
10599     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10600                          (const BYTE *)"a\0b\0c\0\0", 7);
10601     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10602 
10603     /* Patches value exists, is not a squashed guid */
10604     lstrcpyA(patchcode, "apple");
10605     lstrcpyA(targetprod, "banana");
10606     context = 0xdeadbeef;
10607     lstrcpyA(targetsid, "kiwi");
10608     size = MAX_PATH;
10609     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10610                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10611                            &context, targetsid, &size);
10612     ok(r == ERROR_BAD_CONFIGURATION,
10613        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10614     ok(!lstrcmpA(patchcode, "apple"),
10615        "Expected patchcode to be unchanged, got %s\n", patchcode);
10616     ok(!lstrcmpA(targetprod, "banana"),
10617        "Expected targetprod to be unchanged, got %s\n", targetprod);
10618     ok(context == 0xdeadbeef,
10619        "Expected context to be unchanged, got %d\n", context);
10620     ok(!lstrcmpA(targetsid, "kiwi"),
10621        "Expected targetsid to be unchanged, got %s\n", targetsid);
10622     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10623 
10624     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
10625     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10626                          (const BYTE *)patch_squashed,
10627                          lstrlenA(patch_squashed) + 2);
10628     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10629 
10630     /* Patches value exists */
10631     lstrcpyA(patchcode, "apple");
10632     lstrcpyA(targetprod, "banana");
10633     context = 0xdeadbeef;
10634     lstrcpyA(targetsid, "kiwi");
10635     size = MAX_PATH;
10636     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10637                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10638                            &context, targetsid, &size);
10639     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10640     ok(!lstrcmpA(patchcode, "apple"),
10641        "Expected patchcode to be unchanged, got %s\n", patchcode);
10642     ok(!lstrcmpA(targetprod, "banana"),
10643        "Expected targetprod to be unchanged, got %s\n", targetprod);
10644     ok(context == 0xdeadbeef,
10645        "Expected context to be unchanged, got %d\n", context);
10646     ok(!lstrcmpA(targetsid, "kiwi"),
10647        "Expected targetsid to be unchanged, got %s\n", targetsid);
10648     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10649 
10650     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
10651                          (const BYTE *)"whatever", 9);
10652     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10653 
10654     /* patch code value exists */
10655     lstrcpyA(patchcode, "apple");
10656     lstrcpyA(targetprod, "banana");
10657     context = 0xdeadbeef;
10658     lstrcpyA(targetsid, "kiwi");
10659     size = MAX_PATH;
10660     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10661                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10662                            &context, targetsid, &size);
10663     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10664     ok(!lstrcmpA(patchcode, patch),
10665        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10666     ok(!lstrcmpA(targetprod, prodcode),
10667        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10668     ok(context == MSIINSTALLCONTEXT_MACHINE,
10669        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10670     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
10671     ok(size == 0, "Expected 0, got %d\n", size);
10672 
10673     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
10674     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
10675     lstrcatA(keypath, prod_squashed);
10676 
10677     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
10678     if (res == ERROR_ACCESS_DENIED)
10679     {
10680         skip("Not enough rights to perform tests\n");
10681         goto done;
10682     }
10683     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10684 
10685     /* local UserData product key exists */
10686     lstrcpyA(patchcode, "apple");
10687     lstrcpyA(targetprod, "banana");
10688     context = 0xdeadbeef;
10689     lstrcpyA(targetsid, "kiwi");
10690     size = MAX_PATH;
10691     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10692                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10693                            &context, targetsid, &size);
10694     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10695     ok(!lstrcmpA(patchcode, patch),
10696        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10697     ok(!lstrcmpA(targetprod, prodcode),
10698        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10699     ok(context == MSIINSTALLCONTEXT_MACHINE,
10700        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10701     ok(!lstrcmpA(targetsid, ""),
10702        "Expected \"\", got \"%s\"\n", targetsid);
10703     ok(size == 0, "Expected 0, got %d\n", size);
10704 
10705     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
10706     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10707 
10708     /* local UserData Patches key exists */
10709     lstrcpyA(patchcode, "apple");
10710     lstrcpyA(targetprod, "banana");
10711     context = 0xdeadbeef;
10712     lstrcpyA(targetsid, "kiwi");
10713     size = MAX_PATH;
10714     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10715                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10716                            &context, targetsid, &size);
10717     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10718     ok(!lstrcmpA(patchcode, patch),
10719        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10720     ok(!lstrcmpA(targetprod, prodcode),
10721        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10722     ok(context == MSIINSTALLCONTEXT_MACHINE,
10723        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10724     ok(!lstrcmpA(targetsid, ""),
10725        "Expected \"\", got \"%s\"\n", targetsid);
10726     ok(size == 0, "Expected 0, got %d\n", size);
10727 
10728     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
10729     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10730 
10731     /* local UserData Product patch key exists */
10732     lstrcpyA(patchcode, "apple");
10733     lstrcpyA(targetprod, "banana");
10734     context = 0xdeadbeef;
10735     lstrcpyA(targetsid, "kiwi");
10736     size = MAX_PATH;
10737     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10738                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10739                            &context, targetsid, &size);
10740     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10741     ok(!lstrcmpA(patchcode, "apple"),
10742        "Expected patchcode to be unchanged, got %s\n", patchcode);
10743     ok(!lstrcmpA(targetprod, "banana"),
10744        "Expected targetprod to be unchanged, got %s\n", targetprod);
10745     ok(context == 0xdeadbeef,
10746        "Expected context to be unchanged, got %d\n", context);
10747     ok(!lstrcmpA(targetsid, "kiwi"),
10748        "Expected targetsid to be unchanged, got %s\n", targetsid);
10749     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10750 
10751     data = MSIPATCHSTATE_APPLIED;
10752     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10753                          (const BYTE *)&data, sizeof(DWORD));
10754     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10755 
10756     /* State value exists */
10757     lstrcpyA(patchcode, "apple");
10758     lstrcpyA(targetprod, "banana");
10759     context = 0xdeadbeef;
10760     lstrcpyA(targetsid, "kiwi");
10761     size = MAX_PATH;
10762     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10763                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10764                            &context, targetsid, &size);
10765     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10766     ok(!lstrcmpA(patchcode, patch),
10767        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10768     ok(!lstrcmpA(targetprod, prodcode),
10769        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10770     ok(context == MSIINSTALLCONTEXT_MACHINE,
10771        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10772     ok(!lstrcmpA(targetsid, ""),
10773        "Expected \"\", got \"%s\"\n", targetsid);
10774     ok(size == 0, "Expected 0, got %d\n", size);
10775 
10776     /* MSIPATCHSTATE_SUPERSEDED */
10777 
10778     lstrcpyA(patchcode, "apple");
10779     lstrcpyA(targetprod, "banana");
10780     context = 0xdeadbeef;
10781     lstrcpyA(targetsid, "kiwi");
10782     size = MAX_PATH;
10783     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10784                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10785                            &context, targetsid, &size);
10786     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10787     ok(!lstrcmpA(patchcode, "apple"),
10788        "Expected patchcode to be unchanged, got %s\n", patchcode);
10789     ok(!lstrcmpA(targetprod, "banana"),
10790        "Expected targetprod to be unchanged, got %s\n", targetprod);
10791     ok(context == 0xdeadbeef,
10792        "Expected context to be unchanged, got %d\n", context);
10793     ok(!lstrcmpA(targetsid, "kiwi"),
10794        "Expected targetsid to be unchanged, got %s\n", targetsid);
10795     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10796 
10797     data = MSIPATCHSTATE_SUPERSEDED;
10798     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10799                          (const BYTE *)&data, sizeof(DWORD));
10800     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10801 
10802     /* State value is MSIPATCHSTATE_SUPERSEDED */
10803     lstrcpyA(patchcode, "apple");
10804     lstrcpyA(targetprod, "banana");
10805     context = 0xdeadbeef;
10806     lstrcpyA(targetsid, "kiwi");
10807     size = MAX_PATH;
10808     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10809                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10810                            &context, targetsid, &size);
10811     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10812     ok(!lstrcmpA(patchcode, patch),
10813        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10814     ok(!lstrcmpA(targetprod, prodcode),
10815        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10816     ok(context == MSIINSTALLCONTEXT_MACHINE,
10817        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10818     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
10819     ok(size == 0, "Expected 0, got %d\n", size);
10820 
10821     /* MSIPATCHSTATE_OBSOLETED */
10822 
10823     lstrcpyA(patchcode, "apple");
10824     lstrcpyA(targetprod, "banana");
10825     context = 0xdeadbeef;
10826     lstrcpyA(targetsid, "kiwi");
10827     size = MAX_PATH;
10828     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10829                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
10830                            &context, targetsid, &size);
10831     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10832     ok(!lstrcmpA(patchcode, "apple"),
10833        "Expected patchcode to be unchanged, got %s\n", patchcode);
10834     ok(!lstrcmpA(targetprod, "banana"),
10835        "Expected targetprod to be unchanged, got %s\n", targetprod);
10836     ok(context == 0xdeadbeef,
10837        "Expected context to be unchanged, got %d\n", context);
10838     ok(!lstrcmpA(targetsid, "kiwi"),
10839        "Expected targetsid to be unchanged, got %s\n", targetsid);
10840     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10841 
10842     data = MSIPATCHSTATE_OBSOLETED;
10843     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10844                          (const BYTE *)&data, sizeof(DWORD));
10845     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10846 
10847     /* State value is obsoleted */
10848     lstrcpyA(patchcode, "apple");
10849     lstrcpyA(targetprod, "banana");
10850     context = 0xdeadbeef;
10851     lstrcpyA(targetsid, "kiwi");
10852     size = MAX_PATH;
10853     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10854                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
10855                            &context, targetsid, &size);
10856     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10857     ok(!lstrcmpA(patchcode, patch),
10858        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10859     ok(!lstrcmpA(targetprod, prodcode),
10860        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10861     ok(context == MSIINSTALLCONTEXT_MACHINE,
10862        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10863     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
10864     ok(size == 0, "Expected 0, got %d\n", size);
10865 
10866     /* MSIPATCHSTATE_REGISTERED */
10867     /* FIXME */
10868 
10869     /* MSIPATCHSTATE_ALL */
10870 
10871     /* 1st */
10872     lstrcpyA(patchcode, "apple");
10873     lstrcpyA(targetprod, "banana");
10874     context = 0xdeadbeef;
10875     lstrcpyA(targetsid, "kiwi");
10876     size = MAX_PATH;
10877     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10878                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
10879                            &context, targetsid, &size);
10880     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10881     ok(!lstrcmpA(patchcode, patch),
10882        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10883     ok(!lstrcmpA(targetprod, prodcode),
10884        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10885     ok(context == MSIINSTALLCONTEXT_MACHINE,
10886        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10887     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
10888     ok(size == 0, "Expected 0, got %d\n", size);
10889 
10890     /* same patch in multiple places, only one is enumerated */
10891     lstrcpyA(patchcode, "apple");
10892     lstrcpyA(targetprod, "banana");
10893     context = 0xdeadbeef;
10894     lstrcpyA(targetsid, "kiwi");
10895     size = MAX_PATH;
10896     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10897                            MSIPATCHSTATE_ALL, 1, patchcode, targetprod,
10898                            &context, targetsid, &size);
10899     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10900     ok(!lstrcmpA(patchcode, "apple"),
10901        "Expected patchcode to be unchanged, got %s\n", patchcode);
10902     ok(!lstrcmpA(targetprod, "banana"),
10903        "Expected targetprod to be unchanged, got %s\n", targetprod);
10904     ok(context == 0xdeadbeef,
10905        "Expected context to be unchanged, got %d\n", context);
10906     ok(!lstrcmpA(targetsid, "kiwi"),
10907        "Expected targetsid to be unchanged, got %s\n", targetsid);
10908     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10909 
10910     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
10911     RegDeleteValueA(hpatch, "State");
10912     RegCloseKey(hpatch);
10913     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
10914     RegCloseKey(udpatch);
10915     delete_key(udprod, "", access & KEY_WOW64_64KEY);
10916     RegCloseKey(udprod);
10917 
10918 done:
10919     RegDeleteValueA(patches, patch_squashed);
10920     RegDeleteValueA(patches, "Patches");
10921     delete_key(patches, "", access & KEY_WOW64_64KEY);
10922     RegCloseKey(patches);
10923     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
10924     RegCloseKey(prodkey);
10925 }
10926 
10927 static void test_MsiEnumPatchesEx(void)
10928 {
10929     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
10930     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
10931     CHAR patchcode[MAX_PATH];
10932     MSIINSTALLCONTEXT context;
10933     LPSTR usersid;
10934     DWORD size;
10935     UINT r;
10936 
10937     if (!pMsiEnumPatchesExA)
10938     {
10939         win_skip("MsiEnumPatchesExA not implemented\n");
10940         return;
10941     }
10942 
10943     create_test_guid(prodcode, prod_squashed);
10944     usersid = get_user_sid();
10945 
10946     /* empty szProductCode */
10947     lstrcpyA(patchcode, "apple");
10948     lstrcpyA(targetprod, "banana");
10949     context = 0xdeadbeef;
10950     lstrcpyA(targetsid, "kiwi");
10951     size = MAX_PATH;
10952     r = pMsiEnumPatchesExA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10953                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod, &context,
10954                            targetsid, &size);
10955     ok(r == ERROR_INVALID_PARAMETER,
10956        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10957     ok(!lstrcmpA(patchcode, "apple"),
10958        "Expected patchcode to be unchanged, got %s\n", patchcode);
10959     ok(!lstrcmpA(targetprod, "banana"),
10960        "Expected targetprod to be unchanged, got %s\n", targetprod);
10961     ok(context == 0xdeadbeef,
10962        "Expected context to be unchanged, got %d\n", context);
10963     ok(!lstrcmpA(targetsid, "kiwi"),
10964        "Expected targetsid to be unchanged, got %s\n", targetsid);
10965     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10966 
10967     /* garbage szProductCode */
10968     lstrcpyA(patchcode, "apple");
10969     lstrcpyA(targetprod, "banana");
10970     context = 0xdeadbeef;
10971     lstrcpyA(targetsid, "kiwi");
10972     size = MAX_PATH;
10973     r = pMsiEnumPatchesExA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10974                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod, &context,
10975                            targetsid, &size);
10976     ok(r == ERROR_INVALID_PARAMETER,
10977        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10978     ok(!lstrcmpA(patchcode, "apple"),
10979        "Expected patchcode to be unchanged, got %s\n", patchcode);
10980     ok(!lstrcmpA(targetprod, "banana"),
10981        "Expected targetprod to be unchanged, got %s\n", targetprod);
10982     ok(context == 0xdeadbeef,
10983        "Expected context to be unchanged, got %d\n", context);
10984     ok(!lstrcmpA(targetsid, "kiwi"),
10985        "Expected targetsid to be unchanged, got %s\n", targetsid);
10986     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10987 
10988     /* guid without brackets */
10989     lstrcpyA(patchcode, "apple");
10990     lstrcpyA(targetprod, "banana");
10991     context = 0xdeadbeef;
10992     lstrcpyA(targetsid, "kiwi");
10993     size = MAX_PATH;
10994     r = pMsiEnumPatchesExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", usersid,
10995                            MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
10996                            0, patchcode, targetprod, &context,
10997                            targetsid, &size);
10998     ok(r == ERROR_INVALID_PARAMETER,
10999        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11000     ok(!lstrcmpA(patchcode, "apple"),
11001        "Expected patchcode to be unchanged, got %s\n", patchcode);
11002     ok(!lstrcmpA(targetprod, "banana"),
11003        "Expected targetprod to be unchanged, got %s\n", targetprod);
11004     ok(context == 0xdeadbeef,
11005        "Expected context to be unchanged, got %d\n", context);
11006     ok(!lstrcmpA(targetsid, "kiwi"),
11007        "Expected targetsid to be unchanged, got %s\n", targetsid);
11008     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11009 
11010     /* guid with brackets */
11011     lstrcpyA(patchcode, "apple");
11012     lstrcpyA(targetprod, "banana");
11013     context = 0xdeadbeef;
11014     lstrcpyA(targetsid, "kiwi");
11015     size = MAX_PATH;
11016     r = pMsiEnumPatchesExA("{6700E8CF-95AB-4D9C-BC2C-15840DDA7A5D}", usersid,
11017                            MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
11018                            0, patchcode, targetprod, &context,
11019                            targetsid, &size);
11020     ok(r == ERROR_NO_MORE_ITEMS,
11021        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11022     ok(!lstrcmpA(patchcode, "apple"),
11023        "Expected patchcode to be unchanged, got %s\n", patchcode);
11024     ok(!lstrcmpA(targetprod, "banana"),
11025        "Expected targetprod to be unchanged, got %s\n", targetprod);
11026     ok(context == 0xdeadbeef,
11027        "Expected context to be unchanged, got %d\n", context);
11028     ok(!lstrcmpA(targetsid, "kiwi"),
11029        "Expected targetsid to be unchanged, got %s\n", targetsid);
11030     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11031 
11032     /* szUserSid is S-1-5-18 */
11033     lstrcpyA(patchcode, "apple");
11034     lstrcpyA(targetprod, "banana");
11035     context = 0xdeadbeef;
11036     lstrcpyA(targetsid, "kiwi");
11037     size = MAX_PATH;
11038     r = pMsiEnumPatchesExA(prodcode, "S-1-5-18",
11039                            MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
11040                            0, patchcode, targetprod, &context,
11041                            targetsid, &size);
11042     ok(r == ERROR_INVALID_PARAMETER,
11043        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11044     ok(!lstrcmpA(patchcode, "apple"),
11045        "Expected patchcode to be unchanged, got %s\n", patchcode);
11046     ok(!lstrcmpA(targetprod, "banana"),
11047        "Expected targetprod to be unchanged, got %s\n", targetprod);
11048     ok(context == 0xdeadbeef,
11049        "Expected context to be unchanged, got %d\n", context);
11050     ok(!lstrcmpA(targetsid, "kiwi"),
11051        "Expected targetsid to be unchanged, got %s\n", targetsid);
11052     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11053 
11054     /* dwContext is MSIINSTALLCONTEXT_MACHINE, but szUserSid is non-NULL */
11055     lstrcpyA(patchcode, "apple");
11056     lstrcpyA(targetprod, "banana");
11057     context = 0xdeadbeef;
11058     lstrcpyA(targetsid, "kiwi");
11059     size = MAX_PATH;
11060     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_MACHINE,
11061                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
11062                            &context, targetsid, &size);
11063     ok(r == ERROR_INVALID_PARAMETER,
11064        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11065     ok(!lstrcmpA(patchcode, "apple"),
11066        "Expected patchcode to be unchanged, got %s\n", patchcode);
11067     ok(!lstrcmpA(targetprod, "banana"),
11068        "Expected targetprod to be unchanged, got %s\n", targetprod);
11069     ok(context == 0xdeadbeef,
11070        "Expected context to be unchanged, got %d\n", context);
11071     ok(!lstrcmpA(targetsid, "kiwi"),
11072        "Expected targetsid to be unchanged, got %s\n", targetsid);
11073     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11074 
11075     /* dwContext is out of bounds */
11076     lstrcpyA(patchcode, "apple");
11077     lstrcpyA(targetprod, "banana");
11078     context = 0xdeadbeef;
11079     lstrcpyA(targetsid, "kiwi");
11080     size = MAX_PATH;
11081     r = pMsiEnumPatchesExA(prodcode, usersid, 0,
11082                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
11083                            &context, targetsid, &size);
11084     ok(r == ERROR_INVALID_PARAMETER,
11085        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11086     ok(!lstrcmpA(patchcode, "apple"),
11087        "Expected patchcode to be unchanged, got %s\n", patchcode);
11088     ok(!lstrcmpA(targetprod, "banana"),
11089        "Expected targetprod to be unchanged, got %s\n", targetprod);
11090     ok(context == 0xdeadbeef,
11091        "Expected context to be unchanged, got %d\n", context);
11092     ok(!lstrcmpA(targetsid, "kiwi"),
11093        "Expected targetsid to be unchanged, got %s\n", targetsid);
11094     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11095 
11096     /* dwContext is out of bounds */
11097     lstrcpyA(patchcode, "apple");
11098     lstrcpyA(targetprod, "banana");
11099     context = 0xdeadbeef;
11100     lstrcpyA(targetsid, "kiwi");
11101     size = MAX_PATH;
11102     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_ALL + 1,
11103                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
11104                            &context, targetsid, &size);
11105     ok(r == ERROR_INVALID_PARAMETER,
11106        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11107     ok(!lstrcmpA(patchcode, "apple"),
11108        "Expected patchcode to be unchanged, got %s\n", patchcode);
11109     ok(!lstrcmpA(targetprod, "banana"),
11110        "Expected targetprod to be unchanged, got %s\n", targetprod);
11111     ok(context == 0xdeadbeef,
11112        "Expected context to be unchanged, got %d\n", context);
11113     ok(!lstrcmpA(targetsid, "kiwi"),
11114        "Expected targetsid to be unchanged, got %s\n", targetsid);
11115     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11116 
11117     /* dwFilter is out of bounds */
11118     lstrcpyA(patchcode, "apple");
11119     lstrcpyA(targetprod, "banana");
11120     context = 0xdeadbeef;
11121     lstrcpyA(targetsid, "kiwi");
11122     size = MAX_PATH;
11123     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
11124                            MSIPATCHSTATE_INVALID, 0, patchcode, targetprod,
11125                            &context, targetsid, &size);
11126     ok(r == ERROR_INVALID_PARAMETER,
11127        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11128     ok(!lstrcmpA(patchcode, "apple"),
11129        "Expected patchcode to be unchanged, got %s\n", patchcode);
11130     ok(!lstrcmpA(targetprod, "banana"),
11131        "Expected targetprod to be unchanged, got %s\n", targetprod);
11132     ok(context == 0xdeadbeef,
11133        "Expected context to be unchanged, got %d\n", context);
11134     ok(!lstrcmpA(targetsid, "kiwi"),
11135        "Expected targetsid to be unchanged, got %s\n", targetsid);
11136     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11137 
11138     /* dwFilter is out of bounds */
11139     lstrcpyA(patchcode, "apple");
11140     lstrcpyA(targetprod, "banana");
11141     context = 0xdeadbeef;
11142     lstrcpyA(targetsid, "kiwi");
11143     size = MAX_PATH;
11144     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
11145                            MSIPATCHSTATE_ALL + 1, 0, patchcode, targetprod,
11146                            &context, targetsid, &size);
11147     ok(r == ERROR_INVALID_PARAMETER,
11148        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11149     ok(!lstrcmpA(patchcode, "apple"),
11150        "Expected patchcode to be unchanged, got %s\n", patchcode);
11151     ok(!lstrcmpA(targetprod, "banana"),
11152        "Expected targetprod to be unchanged, got %s\n", targetprod);
11153     ok(context == 0xdeadbeef,
11154        "Expected context to be unchanged, got %d\n", context);
11155     ok(!lstrcmpA(targetsid, "kiwi"),
11156        "Expected targetsid to be unchanged, got %s\n", targetsid);
11157     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11158 
11159     /* pcchTargetUserSid is NULL while szTargetUserSid is non-NULL */
11160     lstrcpyA(patchcode, "apple");
11161     lstrcpyA(targetprod, "banana");
11162     context = 0xdeadbeef;
11163     lstrcpyA(targetsid, "kiwi");
11164     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
11165                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
11166                            &context, targetsid, NULL);
11167     ok(r == ERROR_INVALID_PARAMETER,
11168        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11169     ok(!lstrcmpA(patchcode, "apple"),
11170        "Expected patchcode to be unchanged, got %s\n", patchcode);
11171     ok(!lstrcmpA(targetprod, "banana"),
11172        "Expected targetprod to be unchanged, got %s\n", targetprod);
11173     ok(context == 0xdeadbeef,
11174        "Expected context to be unchanged, got %d\n", context);
11175     ok(!lstrcmpA(targetsid, "kiwi"),
11176        "Expected targetsid to be unchanged, got %s\n", targetsid);
11177 
11178     test_MsiEnumPatchesEx_usermanaged(usersid, usersid);
11179     test_MsiEnumPatchesEx_usermanaged(NULL, usersid);
11180     test_MsiEnumPatchesEx_usermanaged("S-1-2-34", "S-1-2-34");
11181     test_MsiEnumPatchesEx_userunmanaged(usersid, usersid);
11182     test_MsiEnumPatchesEx_userunmanaged(NULL, usersid);
11183     /* FIXME: Successfully test userunmanaged with a different user */
11184     test_MsiEnumPatchesEx_machine();
11185     LocalFree(usersid);
11186 }
11187 
11188 static void test_MsiEnumPatches(void)
11189 {
11190     CHAR keypath[MAX_PATH], patch[MAX_PATH];
11191     CHAR patchcode[MAX_PATH], patch_squashed[MAX_PATH];
11192     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
11193     CHAR transforms[MAX_PATH];
11194     WCHAR patchW[MAX_PATH], prodcodeW[MAX_PATH], transformsW[MAX_PATH];
11195     HKEY prodkey, patches, udprod;
11196     HKEY userkey, hpatch, udpatch;
11197     DWORD size, data;
11198     LPSTR usersid;
11199     LONG res;
11200     UINT r;
11201     REGSAM access = KEY_ALL_ACCESS;
11202 
11203     create_test_guid(prodcode, prod_squashed);
11204     create_test_guid(patchcode, patch_squashed);
11205     usersid = get_user_sid();
11206 
11207     if (is_wow64)
11208         access |= KEY_WOW64_64KEY;
11209 
11210     /* NULL szProduct */
11211     size = MAX_PATH;
11212     lstrcpyA(patch, "apple");
11213     lstrcpyA(transforms, "banana");
11214     r = MsiEnumPatchesA(NULL, 0, patch, transforms, &size);
11215     ok(r == ERROR_INVALID_PARAMETER,
11216        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11217     ok(!lstrcmpA(patch, "apple"),
11218        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11219     ok(!lstrcmpA(transforms, "banana"),
11220        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11221     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11222 
11223     /* empty szProduct */
11224     size = MAX_PATH;
11225     lstrcpyA(patch, "apple");
11226     lstrcpyA(transforms, "banana");
11227     r = MsiEnumPatchesA("", 0, patch, transforms, &size);
11228     ok(r == ERROR_INVALID_PARAMETER,
11229        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11230     ok(!lstrcmpA(patch, "apple"),
11231        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11232     ok(!lstrcmpA(transforms, "banana"),
11233        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11234     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11235 
11236     /* garbage szProduct */
11237     size = MAX_PATH;
11238     lstrcpyA(patch, "apple");
11239     lstrcpyA(transforms, "banana");
11240     r = MsiEnumPatchesA("garbage", 0, patch, transforms, &size);
11241     ok(r == ERROR_INVALID_PARAMETER,
11242        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11243     ok(!lstrcmpA(patch, "apple"),
11244        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11245     ok(!lstrcmpA(transforms, "banana"),
11246        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11247     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11248 
11249     /* guid without brackets */
11250     size = MAX_PATH;
11251     lstrcpyA(patch, "apple");
11252     lstrcpyA(transforms, "banana");
11253     r = MsiEnumPatchesA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", 0, patch,
11254                         transforms, &size);
11255     ok(r == ERROR_INVALID_PARAMETER,
11256        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11257     ok(!lstrcmpA(patch, "apple"),
11258        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11259     ok(!lstrcmpA(transforms, "banana"),
11260        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11261     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11262 
11263     /* guid with brackets */
11264     size = MAX_PATH;
11265     lstrcpyA(patch, "apple");
11266     lstrcpyA(transforms, "banana");
11267     r = MsiEnumPatchesA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", 0, patch,
11268                         transforms, &size);
11269     ok(r == ERROR_UNKNOWN_PRODUCT,
11270        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11271     ok(!lstrcmpA(patch, "apple"),
11272        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11273     ok(!lstrcmpA(transforms, "banana"),
11274        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11275     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11276 
11277     /* same length as guid, but random */
11278     size = MAX_PATH;
11279     lstrcpyA(patch, "apple");
11280     lstrcpyA(transforms, "banana");
11281     r = MsiEnumPatchesA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", 0, patch,
11282                         transforms, &size);
11283     ok(r == ERROR_INVALID_PARAMETER,
11284        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11285     ok(!lstrcmpA(patch, "apple"),
11286        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11287     ok(!lstrcmpA(transforms, "banana"),
11288        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11289     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11290 
11291     /* MSIINSTALLCONTEXT_USERMANAGED */
11292 
11293     size = MAX_PATH;
11294     lstrcpyA(patch, "apple");
11295     lstrcpyA(transforms, "banana");
11296     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11297     ok(r == ERROR_UNKNOWN_PRODUCT,
11298        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11299     ok(!lstrcmpA(patch, "apple"),
11300        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11301     ok(!lstrcmpA(transforms, "banana"),
11302        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11303     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11304 
11305     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
11306     lstrcatA(keypath, usersid);
11307     lstrcatA(keypath, "\\Installer\\Products\\");
11308     lstrcatA(keypath, prod_squashed);
11309 
11310     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
11311     if (res == ERROR_ACCESS_DENIED)
11312     {
11313         skip("Not enough rights to perform tests\n");
11314         LocalFree(usersid);
11315         return;
11316     }
11317     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11318 
11319     /* managed product key exists */
11320     size = MAX_PATH;
11321     lstrcpyA(patch, "apple");
11322     lstrcpyA(transforms, "banana");
11323     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11324     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11325     ok(!lstrcmpA(patch, "apple"),
11326        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11327     ok(!lstrcmpA(transforms, "banana"),
11328        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11329     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11330 
11331     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
11332     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11333 
11334     /* patches key exists */
11335     size = MAX_PATH;
11336     lstrcpyA(patch, "apple");
11337     lstrcpyA(transforms, "banana");
11338     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11339     ok(r == ERROR_NO_MORE_ITEMS ||
11340        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11341        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11342     ok(!lstrcmpA(patch, "apple"),
11343        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11344     ok(!lstrcmpA(transforms, "banana"),
11345        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11346     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11347 
11348     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
11349                          (const BYTE *)patch_squashed,
11350                          lstrlenA(patch_squashed) + 1);
11351     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11352 
11353     /* Patches value exists, is not REG_MULTI_SZ */
11354     size = MAX_PATH;
11355     lstrcpyA(patch, "apple");
11356     lstrcpyA(transforms, "banana");
11357     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11358     ok(r == ERROR_BAD_CONFIGURATION ||
11359        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
11360        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11361     ok(!lstrcmpA(patch, "apple"),
11362        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11363     ok(!lstrcmpA(transforms, "banana"),
11364        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11365     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11366 
11367     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11368                          (const BYTE *)"a\0b\0c\0\0", 7);
11369     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11370 
11371     /* Patches value exists, is not a squashed guid */
11372     size = MAX_PATH;
11373     lstrcpyA(patch, "apple");
11374     lstrcpyA(transforms, "banana");
11375     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11376     ok(r == ERROR_BAD_CONFIGURATION,
11377        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11378     ok(!lstrcmpA(patch, "apple"),
11379        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11380     ok(!lstrcmpA(transforms, "banana"),
11381        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11382     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11383 
11384     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
11385     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11386                          (const BYTE *)patch_squashed,
11387                          lstrlenA(patch_squashed) + 2);
11388     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11389 
11390     /* Patches value exists */
11391     size = MAX_PATH;
11392     lstrcpyA(patch, "apple");
11393     lstrcpyA(transforms, "banana");
11394     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11395     ok(r == ERROR_NO_MORE_ITEMS ||
11396        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11397        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11398     ok(!lstrcmpA(patch, "apple") ||
11399        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
11400        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11401     ok(!lstrcmpA(transforms, "banana"),
11402        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11403     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11404 
11405     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
11406                          (const BYTE *)"whatever", 9);
11407     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11408 
11409     /* patch squashed value exists */
11410     size = MAX_PATH;
11411     lstrcpyA(patch, "apple");
11412     lstrcpyA(transforms, "banana");
11413     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11414     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11415     ok(!lstrcmpA(patch, patchcode),
11416        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11417     ok(!lstrcmpA(transforms, "whatever"),
11418        "Expected \"whatever\", got \"%s\"\n", transforms);
11419     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
11420 
11421     /* lpPatchBuf is NULL */
11422     size = MAX_PATH;
11423     lstrcpyA(transforms, "banana");
11424     r = MsiEnumPatchesA(prodcode, 0, NULL, transforms, &size);
11425     ok(r == ERROR_INVALID_PARAMETER,
11426        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11427     ok(!lstrcmpA(transforms, "banana"),
11428        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11429     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11430 
11431     /* lpTransformsBuf is NULL, pcchTransformsBuf is not */
11432     size = MAX_PATH;
11433     lstrcpyA(patch, "apple");
11434     r = MsiEnumPatchesA(prodcode, 0, patch, NULL, &size);
11435     ok(r == ERROR_INVALID_PARAMETER,
11436        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11437     ok(!lstrcmpA(patch, "apple"),
11438        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11439     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11440 
11441     /* pcchTransformsBuf is NULL, lpTransformsBuf is not */
11442     lstrcpyA(patch, "apple");
11443     lstrcpyA(transforms, "banana");
11444     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, NULL);
11445     ok(r == ERROR_INVALID_PARAMETER,
11446        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11447     ok(!lstrcmpA(patch, "apple"),
11448        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11449     ok(!lstrcmpA(transforms, "banana"),
11450        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11451 
11452     /* pcchTransformsBuf is too small */
11453     size = 6;
11454     lstrcpyA(patch, "apple");
11455     lstrcpyA(transforms, "banana");
11456     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11457     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
11458     ok(!lstrcmpA(patch, patchcode),
11459        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11460     ok(!lstrcmpA(transforms, "whate") ||
11461        broken(!lstrcmpA(transforms, "banana")), /* Windows Installer < 3.0 */
11462        "Expected \"whate\", got \"%s\"\n", transforms);
11463     ok(size == 8 || size == 16, "Expected 8 or 16, got %d\n", size);
11464 
11465     /* increase the index */
11466     size = MAX_PATH;
11467     lstrcpyA(patch, "apple");
11468     lstrcpyA(transforms, "banana");
11469     r = MsiEnumPatchesA(prodcode, 1, patch, transforms, &size);
11470     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11471     ok(!lstrcmpA(patch, "apple"),
11472        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11473     ok(!lstrcmpA(transforms, "banana"),
11474        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11475     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11476 
11477     /* increase again */
11478     size = MAX_PATH;
11479     lstrcpyA(patch, "apple");
11480     lstrcpyA(transforms, "banana");
11481     r = MsiEnumPatchesA(prodcode, 2, patch, transforms, &size);
11482     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11483     ok(!lstrcmpA(patch, "apple"),
11484        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11485     ok(!lstrcmpA(transforms, "banana"),
11486        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11487     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11488 
11489     RegDeleteValueA(patches, "Patches");
11490     delete_key(patches, "", access & KEY_WOW64_64KEY);
11491     RegCloseKey(patches);
11492     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
11493     RegCloseKey(prodkey);
11494 
11495     /* MSIINSTALLCONTEXT_USERUNMANAGED */
11496 
11497     size = MAX_PATH;
11498     lstrcpyA(patch, "apple");
11499     lstrcpyA(transforms, "banana");
11500     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11501     ok(r == ERROR_UNKNOWN_PRODUCT,
11502        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11503     ok(!lstrcmpA(patch, "apple"),
11504        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11505     ok(!lstrcmpA(transforms, "banana"),
11506        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11507     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11508 
11509     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
11510     lstrcatA(keypath, prod_squashed);
11511 
11512     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
11513     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11514 
11515     /* current user product key exists */
11516     size = MAX_PATH;
11517     lstrcpyA(patch, "apple");
11518     lstrcpyA(transforms, "banana");
11519     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11520     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11521     ok(!lstrcmpA(patch, "apple"),
11522        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11523     ok(!lstrcmpA(transforms, "banana"),
11524        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11525     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11526 
11527     res = RegCreateKeyA(prodkey, "Patches", &patches);
11528     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11529 
11530     /* Patches key exists */
11531     size = MAX_PATH;
11532     lstrcpyA(patch, "apple");
11533     lstrcpyA(transforms, "banana");
11534     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11535     ok(r == ERROR_NO_MORE_ITEMS ||
11536        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11537        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11538     ok(!lstrcmpA(patch, "apple"),
11539        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11540     ok(!lstrcmpA(transforms, "banana"),
11541        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11542     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11543 
11544     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
11545                          (const BYTE *)patch_squashed,
11546                          lstrlenA(patch_squashed) + 1);
11547     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11548 
11549     /* Patches value exists, is not REG_MULTI_SZ */
11550     size = MAX_PATH;
11551     lstrcpyA(patch, "apple");
11552     lstrcpyA(transforms, "banana");
11553     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11554     ok(r == ERROR_BAD_CONFIGURATION ||
11555        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
11556        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11557     ok(!lstrcmpA(patch, "apple"),
11558        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11559     ok(!lstrcmpA(transforms, "banana"),
11560        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11561     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11562 
11563     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11564                          (const BYTE *)"a\0b\0c\0\0", 7);
11565     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11566 
11567     /* Patches value exists, is not a squashed guid */
11568     size = MAX_PATH;
11569     lstrcpyA(patch, "apple");
11570     lstrcpyA(transforms, "banana");
11571     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11572     ok(r == ERROR_BAD_CONFIGURATION,
11573        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11574     ok(!lstrcmpA(patch, "apple"),
11575        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11576     ok(!lstrcmpA(transforms, "banana"),
11577        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11578     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11579 
11580     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
11581     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11582                          (const BYTE *)patch_squashed,
11583                          lstrlenA(patch_squashed) + 2);
11584     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11585 
11586     /* Patches value exists */
11587     size = MAX_PATH;
11588     lstrcpyA(patch, "apple");
11589     lstrcpyA(transforms, "banana");
11590     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11591     ok(r == ERROR_NO_MORE_ITEMS ||
11592        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11593        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11594     ok(!lstrcmpA(patch, "apple") ||
11595        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
11596        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11597     ok(!lstrcmpA(transforms, "banana"),
11598        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11599     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11600 
11601     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
11602                          (const BYTE *)"whatever", 9);
11603     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11604 
11605     /* patch code value exists */
11606     size = MAX_PATH;
11607     lstrcpyA(patch, "apple");
11608     lstrcpyA(transforms, "banana");
11609     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11610     ok(r == ERROR_NO_MORE_ITEMS ||
11611        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
11612        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11613     ok(!lstrcmpA(patch, "apple") ||
11614        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
11615        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11616     ok(!lstrcmpA(transforms, "banana") ||
11617        broken(!lstrcmpA(transforms, "whatever")), /* Windows Installer < 3.0 */
11618        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11619     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11620 
11621     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
11622     lstrcatA(keypath, usersid);
11623     lstrcatA(keypath, "\\Patches\\");
11624     lstrcatA(keypath, patch_squashed);
11625 
11626     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
11627     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11628 
11629     /* userdata patch key exists */
11630     size = MAX_PATH;
11631     lstrcpyA(patch, "apple");
11632     lstrcpyA(transforms, "banana");
11633     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11634     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11635     ok(!lstrcmpA(patch, patchcode),
11636        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11637     ok(!lstrcmpA(transforms, "whatever"),
11638        "Expected \"whatever\", got \"%s\"\n", transforms);
11639     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
11640 
11641     delete_key(userkey, "", access & KEY_WOW64_64KEY);
11642     RegCloseKey(userkey);
11643     RegDeleteValueA(patches, patch_squashed);
11644     RegDeleteValueA(patches, "Patches");
11645     RegDeleteKeyA(patches, "");
11646     RegCloseKey(patches);
11647     RegDeleteKeyA(prodkey, "");
11648     RegCloseKey(prodkey);
11649 
11650     /* MSIINSTALLCONTEXT_MACHINE */
11651 
11652     size = MAX_PATH;
11653     lstrcpyA(patch, "apple");
11654     lstrcpyA(transforms, "banana");
11655     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11656     ok(r == ERROR_UNKNOWN_PRODUCT,
11657        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11658     ok(!lstrcmpA(patch, "apple"),
11659        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11660     ok(!lstrcmpA(transforms, "banana"),
11661        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11662     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11663 
11664     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
11665     lstrcatA(keypath, prod_squashed);
11666 
11667     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
11668     if (res == ERROR_ACCESS_DENIED)
11669     {
11670         skip("Not enough rights to perform tests\n");
11671         LocalFree(usersid);
11672         return;
11673     }
11674     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11675 
11676     /* local product key exists */
11677     size = MAX_PATH;
11678     lstrcpyA(patch, "apple");
11679     lstrcpyA(transforms, "banana");
11680     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11681     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11682     ok(!lstrcmpA(patch, "apple"),
11683        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11684     ok(!lstrcmpA(transforms, "banana"),
11685        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11686     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11687 
11688     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
11689     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11690 
11691     /* Patches key exists */
11692     size = MAX_PATH;
11693     lstrcpyA(patch, "apple");
11694     lstrcpyA(transforms, "banana");
11695     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11696     ok(r == ERROR_NO_MORE_ITEMS ||
11697        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11698        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11699     ok(!lstrcmpA(patch, "apple"),
11700        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11701     ok(!lstrcmpA(transforms, "banana"),
11702        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11703     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11704 
11705     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
11706                          (const BYTE *)patch_squashed,
11707                          lstrlenA(patch_squashed) + 1);
11708     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11709 
11710     /* Patches value exists, is not REG_MULTI_SZ */
11711     size = MAX_PATH;
11712     lstrcpyA(patch, "apple");
11713     lstrcpyA(transforms, "banana");
11714     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11715     ok(r == ERROR_BAD_CONFIGURATION ||
11716        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
11717        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11718     ok(!lstrcmpA(patch, "apple"),
11719        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11720     ok(!lstrcmpA(transforms, "banana"),
11721        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11722     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11723 
11724     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11725                          (const BYTE *)"a\0b\0c\0\0", 7);
11726     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11727 
11728     /* Patches value exists, is not a squashed guid */
11729     size = MAX_PATH;
11730     lstrcpyA(patch, "apple");
11731     lstrcpyA(transforms, "banana");
11732     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11733     ok(r == ERROR_BAD_CONFIGURATION,
11734        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11735     ok(!lstrcmpA(patch, "apple"),
11736        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11737     ok(!lstrcmpA(transforms, "banana"),
11738        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11739     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11740 
11741     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
11742     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11743                          (const BYTE *)patch_squashed,
11744                          lstrlenA(patch_squashed) + 2);
11745     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11746 
11747     /* Patches value exists */
11748     size = MAX_PATH;
11749     lstrcpyA(patch, "apple");
11750     lstrcpyA(transforms, "banana");
11751     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11752     ok(r == ERROR_NO_MORE_ITEMS ||
11753        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11754        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11755     ok(!lstrcmpA(patch, "apple") ||
11756        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
11757        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11758     ok(!lstrcmpA(transforms, "banana"),
11759        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11760     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11761 
11762     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
11763                          (const BYTE *)"whatever", 9);
11764     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11765 
11766     /* patch code value exists */
11767     size = MAX_PATH;
11768     lstrcpyA(patch, "apple");
11769     lstrcpyA(transforms, "banana");
11770     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11771     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11772     ok(!lstrcmpA(patch, patchcode),
11773        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11774     ok(!lstrcmpA(transforms, "whatever"),
11775        "Expected \"whatever\", got \"%s\"\n", transforms);
11776     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
11777 
11778     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
11779     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
11780     lstrcatA(keypath, prod_squashed);
11781 
11782     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
11783     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11784 
11785     /* local UserData product key exists */
11786     size = MAX_PATH;
11787     lstrcpyA(patch, "apple");
11788     lstrcpyA(transforms, "banana");
11789     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11790     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11791     ok(!lstrcmpA(patch, patchcode),
11792        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11793     ok(!lstrcmpA(transforms, "whatever"),
11794        "Expected \"whatever\", got \"%s\"\n", transforms);
11795     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
11796 
11797     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
11798     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11799 
11800     /* local UserData Patches key exists */
11801     size = MAX_PATH;
11802     lstrcpyA(patch, "apple");
11803     lstrcpyA(transforms, "banana");
11804     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11805     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11806     ok(!lstrcmpA(patch, patchcode),
11807        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11808     ok(!lstrcmpA(transforms, "whatever"),
11809        "Expected \"whatever\", got \"%s\"\n", transforms);
11810     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
11811 
11812     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
11813     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11814 
11815     /* local UserData Product patch key exists */
11816     size = MAX_PATH;
11817     lstrcpyA(patch, "apple");
11818     lstrcpyA(transforms, "banana");
11819     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11820     ok(r == ERROR_NO_MORE_ITEMS ||
11821        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
11822        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11823     ok(!lstrcmpA(patch, "apple") ||
11824        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
11825        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11826     ok(!lstrcmpA(transforms, "banana") ||
11827        broken(!lstrcmpA(transforms, "whatever")), /* Windows Installer < 3.0 */
11828        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11829     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11830 
11831     data = MSIPATCHSTATE_APPLIED;
11832     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
11833                          (const BYTE *)&data, sizeof(DWORD));
11834     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11835 
11836     /* State value exists */
11837     size = MAX_PATH;
11838     lstrcpyA(patch, "apple");
11839     lstrcpyA(transforms, "banana");
11840     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11841     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11842     ok(!lstrcmpA(patch, patchcode),
11843        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11844     ok(!lstrcmpA(transforms, "whatever"),
11845        "Expected \"whatever\", got \"%s\"\n", transforms);
11846     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
11847 
11848     /* now duplicate some of the tests for the W version */
11849 
11850     /* pcchTransformsBuf is too small */
11851     size = 6;
11852     MultiByteToWideChar( CP_ACP, 0, prodcode, -1, prodcodeW, MAX_PATH );
11853     MultiByteToWideChar( CP_ACP, 0, "apple", -1, patchW, MAX_PATH );
11854     MultiByteToWideChar( CP_ACP, 0, "banana", -1, transformsW, MAX_PATH );
11855     r = MsiEnumPatchesW(prodcodeW, 0, patchW, transformsW, &size);
11856     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
11857     WideCharToMultiByte( CP_ACP, 0, patchW, -1, patch, MAX_PATH, NULL, NULL );
11858     WideCharToMultiByte( CP_ACP, 0, transformsW, -1, transforms, MAX_PATH, NULL, NULL );
11859     ok(!lstrcmpA(patch, patchcode),
11860        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11861     ok(!lstrcmpA(transforms, "whate") ||
11862        broken(!lstrcmpA(transforms, "banana")), /* Windows Installer < 3.0 */
11863        "Expected \"whate\", got \"%s\"\n", transforms);
11864     ok(size == 8, "Expected 8, got %d\n", size);
11865 
11866     /* patch code value exists */
11867     size = MAX_PATH;
11868     MultiByteToWideChar( CP_ACP, 0, "apple", -1, patchW, MAX_PATH );
11869     MultiByteToWideChar( CP_ACP, 0, "banana", -1, transformsW, MAX_PATH );
11870     r = MsiEnumPatchesW(prodcodeW, 0, patchW, transformsW, &size);
11871     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11872     WideCharToMultiByte( CP_ACP, 0, patchW, -1, patch, MAX_PATH, NULL, NULL );
11873     WideCharToMultiByte( CP_ACP, 0, transformsW, -1, transforms, MAX_PATH, NULL, NULL );
11874     ok(!lstrcmpA(patch, patchcode),
11875        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11876     ok(!lstrcmpA(transforms, "whatever"),
11877        "Expected \"whatever\", got \"%s\"\n", transforms);
11878     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
11879 
11880     RegDeleteValueA(patches, patch_squashed);
11881     RegDeleteValueA(patches, "Patches");
11882     delete_key(patches, "", access & KEY_WOW64_64KEY);
11883     RegCloseKey(patches);
11884     RegDeleteValueA(hpatch, "State");
11885     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
11886     RegCloseKey(hpatch);
11887     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
11888     RegCloseKey(udpatch);
11889     delete_key(udprod, "", access & KEY_WOW64_64KEY);
11890     RegCloseKey(udprod);
11891     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
11892     RegCloseKey(prodkey);
11893     LocalFree(usersid);
11894 }
11895 
11896 static void test_MsiGetPatchInfoEx(void)
11897 {
11898     CHAR keypath[MAX_PATH], val[MAX_PATH];
11899     CHAR patchcode[MAX_PATH], patch_squashed[MAX_PATH];
11900     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
11901     HKEY prodkey, patches, udprod, props;
11902     HKEY hpatch, udpatch, prodpatches;
11903     LPSTR usersid;
11904     DWORD size;
11905     LONG res;
11906     UINT r;
11907     REGSAM access = KEY_ALL_ACCESS;
11908 
11909     if (!pMsiGetPatchInfoExA)
11910     {
11911         win_skip("MsiGetPatchInfoEx not implemented\n");
11912         return;
11913     }
11914 
11915     create_test_guid(prodcode, prod_squashed);
11916     create_test_guid(patchcode, patch_squashed);
11917     usersid = get_user_sid();
11918 
11919     if (is_wow64)
11920         access |= KEY_WOW64_64KEY;
11921 
11922     /* NULL szPatchCode */
11923     lstrcpyA(val, "apple");
11924     size = MAX_PATH;
11925     r = pMsiGetPatchInfoExA(NULL, prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED,
11926                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11927     ok(r == ERROR_INVALID_PARAMETER,
11928        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11929     ok(!lstrcmpA(val, "apple"),
11930        "Expected val to be unchanged, got \"%s\"\n", val);
11931     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11932 
11933     /* empty szPatchCode */
11934     size = MAX_PATH;
11935     lstrcpyA(val, "apple");
11936     r = pMsiGetPatchInfoExA("", prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED,
11937                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11938     ok(r == ERROR_INVALID_PARAMETER,
11939        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11940     ok(!lstrcmpA(val, "apple"),
11941        "Expected val to be unchanged, got \"%s\"\n", val);
11942     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11943 
11944     /* garbage szPatchCode */
11945     size = MAX_PATH;
11946     lstrcpyA(val, "apple");
11947     r = pMsiGetPatchInfoExA("garbage", prodcode, NULL,
11948                             MSIINSTALLCONTEXT_USERMANAGED,
11949                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11950     ok(r == ERROR_INVALID_PARAMETER,
11951        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11952     ok(!lstrcmpA(val, "apple"),
11953        "Expected val to be unchanged, got \"%s\"\n", val);
11954     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11955 
11956     /* guid without brackets */
11957     size = MAX_PATH;
11958     lstrcpyA(val, "apple");
11959     r = pMsiGetPatchInfoExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", prodcode,
11960                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
11961                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11962     ok(r == ERROR_INVALID_PARAMETER,
11963        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11964     ok(!lstrcmpA(val, "apple"),
11965        "Expected val to be unchanged, got \"%s\"\n", val);
11966     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11967 
11968     /* guid with brackets */
11969     size = MAX_PATH;
11970     lstrcpyA(val, "apple");
11971     r = pMsiGetPatchInfoExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", prodcode,
11972                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
11973                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11974     ok(r == ERROR_UNKNOWN_PRODUCT,
11975        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11976     ok(!lstrcmpA(val, "apple"),
11977        "Expected val to be unchanged, got \"%s\"\n", val);
11978     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11979 
11980     /* same length as guid, but random */
11981     size = MAX_PATH;
11982     lstrcpyA(val, "apple");
11983     r = pMsiGetPatchInfoExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", prodcode,
11984                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
11985                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11986     ok(r == ERROR_INVALID_PARAMETER,
11987        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11988     ok(!lstrcmpA(val, "apple"),
11989        "Expected val to be unchanged, got \"%s\"\n", val);
11990     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11991 
11992     /* NULL szProductCode */
11993     lstrcpyA(val, "apple");
11994     size = MAX_PATH;
11995     r = pMsiGetPatchInfoExA(patchcode, NULL, NULL, MSIINSTALLCONTEXT_USERMANAGED,
11996                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11997     ok(r == ERROR_INVALID_PARAMETER,
11998        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11999     ok(!lstrcmpA(val, "apple"),
12000        "Expected val to be unchanged, got \"%s\"\n", val);
12001     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12002 
12003     /* empty szProductCode */
12004     size = MAX_PATH;
12005     lstrcpyA(val, "apple");
12006     r = pMsiGetPatchInfoExA(patchcode, "", NULL, MSIINSTALLCONTEXT_USERMANAGED,
12007                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12008     ok(r == ERROR_INVALID_PARAMETER,
12009        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12010     ok(!lstrcmpA(val, "apple"),
12011        "Expected val to be unchanged, got \"%s\"\n", val);
12012     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12013 
12014     /* garbage szProductCode */
12015     size = MAX_PATH;
12016     lstrcpyA(val, "apple");
12017     r = pMsiGetPatchInfoExA(patchcode, "garbage", NULL,
12018                             MSIINSTALLCONTEXT_USERMANAGED,
12019                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12020     ok(r == ERROR_INVALID_PARAMETER,
12021        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12022     ok(!lstrcmpA(val, "apple"),
12023        "Expected val to be unchanged, got \"%s\"\n", val);
12024     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12025 
12026     /* guid without brackets */
12027     size = MAX_PATH;
12028     lstrcpyA(val, "apple");
12029     r = pMsiGetPatchInfoExA(patchcode, "6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
12030                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
12031                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12032     ok(r == ERROR_INVALID_PARAMETER,
12033        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12034     ok(!lstrcmpA(val, "apple"),
12035        "Expected val to be unchanged, got \"%s\"\n", val);
12036     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12037 
12038     /* guid with brackets */
12039     size = MAX_PATH;
12040     lstrcpyA(val, "apple");
12041     r = pMsiGetPatchInfoExA(patchcode, "{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
12042                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
12043                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12044     ok(r == ERROR_UNKNOWN_PRODUCT,
12045        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12046     ok(!lstrcmpA(val, "apple"),
12047        "Expected val to be unchanged, got \"%s\"\n", val);
12048     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12049 
12050     /* same length as guid, but random */
12051     size = MAX_PATH;
12052     lstrcpyA(val, "apple");
12053     r = pMsiGetPatchInfoExA(patchcode, "A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
12054                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
12055                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12056     ok(r == ERROR_INVALID_PARAMETER,
12057        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12058     ok(!lstrcmpA(val, "apple"),
12059        "Expected val to be unchanged, got \"%s\"\n", val);
12060     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12061 
12062     /* szUserSid cannot be S-1-5-18 for MSIINSTALLCONTEXT_USERMANAGED */
12063     size = MAX_PATH;
12064     lstrcpyA(val, "apple");
12065     r = pMsiGetPatchInfoExA(patchcode, prodcode, "S-1-5-18",
12066                             MSIINSTALLCONTEXT_USERMANAGED,
12067                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12068     ok(r == ERROR_INVALID_PARAMETER,
12069        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12070     ok(!lstrcmpA(val, "apple"),
12071        "Expected val to be unchanged, got \"%s\"\n", val);
12072     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12073 
12074     /* szUserSid cannot be S-1-5-18 for MSIINSTALLCONTEXT_USERUNMANAGED */
12075     size = MAX_PATH;
12076     lstrcpyA(val, "apple");
12077     r = pMsiGetPatchInfoExA(patchcode, prodcode, "S-1-5-18",
12078                             MSIINSTALLCONTEXT_USERUNMANAGED,
12079                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12080     ok(r == ERROR_INVALID_PARAMETER,
12081        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12082     ok(!lstrcmpA(val, "apple"),
12083        "Expected val to be unchanged, got \"%s\"\n", val);
12084     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12085 
12086     /* szUserSid cannot be S-1-5-18 for MSIINSTALLCONTEXT_MACHINE */
12087     size = MAX_PATH;
12088     lstrcpyA(val, "apple");
12089     r = pMsiGetPatchInfoExA(patchcode, prodcode, "S-1-5-18",
12090                             MSIINSTALLCONTEXT_MACHINE,
12091                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12092     ok(r == ERROR_INVALID_PARAMETER,
12093        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12094     ok(!lstrcmpA(val, "apple"),
12095        "Expected val to be unchanged, got \"%s\"\n", val);
12096     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12097 
12098     /* szUserSid must be NULL for MSIINSTALLCONTEXT_MACHINE */
12099     size = MAX_PATH;
12100     lstrcpyA(val, "apple");
12101     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12102                             MSIINSTALLCONTEXT_MACHINE,
12103                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12104     ok(r == ERROR_INVALID_PARAMETER,
12105        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12106     ok(!lstrcmpA(val, "apple"),
12107        "Expected val to be unchanged, got \"%s\"\n", val);
12108     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12109 
12110     /* dwContext is out of range */
12111     size = MAX_PATH;
12112     lstrcpyA(val, "apple");
12113     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12114                             MSIINSTALLCONTEXT_NONE,
12115                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12116     ok(r == ERROR_INVALID_PARAMETER,
12117        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12118     ok(!lstrcmpA(val, "apple"),
12119        "Expected val to be unchanged, got \"%s\"\n", val);
12120     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12121 
12122     /* dwContext is out of range */
12123     size = MAX_PATH;
12124     lstrcpyA(val, "apple");
12125     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12126                             MSIINSTALLCONTEXT_ALL,
12127                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12128     ok(r == ERROR_INVALID_PARAMETER,
12129        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12130     ok(!lstrcmpA(val, "apple"),
12131        "Expected val to be unchanged, got \"%s\"\n", val);
12132     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12133 
12134     /* dwContext is invalid */
12135     size = MAX_PATH;
12136     lstrcpyA(val, "apple");
12137     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid, 3,
12138                            INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12139     ok(r == ERROR_INVALID_PARAMETER,
12140        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12141     ok(!lstrcmpA(val, "apple"),
12142        "Expected val to be unchanged, got \"%s\"\n", val);
12143     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12144 
12145     /* MSIINSTALLCONTEXT_USERMANAGED */
12146 
12147     size = MAX_PATH;
12148     lstrcpyA(val, "apple");
12149     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12150                             MSIINSTALLCONTEXT_USERMANAGED,
12151                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12152     ok(r == ERROR_UNKNOWN_PRODUCT,
12153        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12154     ok(!lstrcmpA(val, "apple"),
12155        "Expected val to be unchanged, got \"%s\"\n", val);
12156     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12157 
12158     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
12159     lstrcatA(keypath, usersid);
12160     lstrcatA(keypath, "\\Products\\");
12161     lstrcatA(keypath, prod_squashed);
12162 
12163     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
12164     if (res == ERROR_ACCESS_DENIED)
12165     {
12166         skip("Not enough rights to perform tests\n");
12167         LocalFree(usersid);
12168         return;
12169     }
12170     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12171 
12172     /* local UserData product key exists */
12173     size = MAX_PATH;
12174     lstrcpyA(val, "apple");
12175     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12176                             MSIINSTALLCONTEXT_USERMANAGED,
12177                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12178     ok(r == ERROR_UNKNOWN_PRODUCT,
12179        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12180     ok(!lstrcmpA(val, "apple"),
12181        "Expected val to be unchanged, got \"%s\"\n", val);
12182     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12183 
12184     res = RegCreateKeyExA(udprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
12185     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12186 
12187     /* InstallProperties key exists */
12188     size = MAX_PATH;
12189     lstrcpyA(val, "apple");
12190     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12191                             MSIINSTALLCONTEXT_USERMANAGED,
12192                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12193     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12194     ok(!lstrcmpA(val, "apple"),
12195        "Expected val to be unchanged, got \"%s\"\n", val);
12196     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12197 
12198     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
12199     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12200 
12201     /* Patches key exists */
12202     size = MAX_PATH;
12203     lstrcpyA(val, "apple");
12204     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12205                             MSIINSTALLCONTEXT_USERMANAGED,
12206                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12207     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCHA, got %d\n", r);
12208     ok(!lstrcmpA(val, "apple"),
12209        "Expected val to be unchanged, got \"%s\"\n", val);
12210     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12211 
12212     res = RegCreateKeyExA(patches, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
12213     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12214 
12215     /* Patches key exists */
12216     size = MAX_PATH;
12217     lstrcpyA(val, "apple");
12218     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12219                             MSIINSTALLCONTEXT_USERMANAGED,
12220                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12221     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12222     ok(!lstrcmpA(val, "apple"),
12223        "Expected val to be unchanged, got \"%s\"\n", val);
12224     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12225 
12226     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
12227     lstrcatA(keypath, usersid);
12228     lstrcatA(keypath, "\\Installer\\Products\\");
12229     lstrcatA(keypath, prod_squashed);
12230 
12231     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
12232     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12233 
12234     /* managed product key exists */
12235     size = MAX_PATH;
12236     lstrcpyA(val, "apple");
12237     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12238                             MSIINSTALLCONTEXT_USERMANAGED,
12239                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12240     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12241     ok(!lstrcmpA(val, "apple"),
12242        "Expected val to be unchanged, got \"%s\"\n", val);
12243     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12244 
12245     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &prodpatches, NULL);
12246     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12247 
12248     /* Patches key exists */
12249     size = MAX_PATH;
12250     lstrcpyA(val, "apple");
12251     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12252                             MSIINSTALLCONTEXT_USERMANAGED,
12253                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12254     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12255     ok(!lstrcmpA(val, "apple"),
12256        "Expected val to be unchanged, got \"%s\"\n", val);
12257     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12258 
12259     res = RegSetValueExA(prodpatches, patch_squashed, 0, REG_SZ,
12260                          (const BYTE *)"transforms", 11);
12261     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12262 
12263     /* specific patch value exists */
12264     size = MAX_PATH;
12265     lstrcpyA(val, "apple");
12266     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12267                             MSIINSTALLCONTEXT_USERMANAGED,
12268                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12269     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12270     ok(!lstrcmpA(val, "apple"),
12271        "Expected val to be unchanged, got \"%s\"\n", val);
12272     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12273 
12274     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
12275     lstrcatA(keypath, usersid);
12276     lstrcatA(keypath, "\\Patches\\");
12277     lstrcatA(keypath, patch_squashed);
12278 
12279     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udpatch, NULL);
12280     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12281 
12282     /* UserData Patches key exists */
12283     size = MAX_PATH;
12284     lstrcpyA(val, "apple");
12285     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12286                             MSIINSTALLCONTEXT_USERMANAGED,
12287                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12288     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12289     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
12290     ok(size == 0, "Expected 0, got %d\n", size);
12291 
12292     res = RegSetValueExA(udpatch, "ManagedLocalPackage", 0, REG_SZ,
12293                          (const BYTE *)"pack", 5);
12294     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12295 
12296     /* ManagedLocalPatch value exists */
12297     size = MAX_PATH;
12298     lstrcpyA(val, "apple");
12299     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12300                             MSIINSTALLCONTEXT_USERMANAGED,
12301                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12302     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12303     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12304     ok(size == 4, "Expected 4, got %d\n", size);
12305 
12306     size = MAX_PATH;
12307     lstrcpyA(val, "apple");
12308     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12309                             MSIINSTALLCONTEXT_USERMANAGED,
12310                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12311     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12312     ok(!lstrcmpA(val, "transforms"), "Expected \"transforms\", got \"%s\"\n", val);
12313     ok(size == 10, "Expected 10, got %d\n", size);
12314 
12315     res = RegSetValueExA(hpatch, "Installed", 0, REG_SZ,
12316                          (const BYTE *)"mydate", 7);
12317     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12318 
12319     /* Installed value exists */
12320     size = MAX_PATH;
12321     lstrcpyA(val, "apple");
12322     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12323                             MSIINSTALLCONTEXT_USERMANAGED,
12324                             INSTALLPROPERTY_INSTALLDATEA, val, &size);
12325     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12326     ok(!lstrcmpA(val, "mydate"), "Expected \"mydate\", got \"%s\"\n", val);
12327     ok(size == 6, "Expected 6, got %d\n", size);
12328 
12329     res = RegSetValueExA(hpatch, "Uninstallable", 0, REG_SZ,
12330                          (const BYTE *)"yes", 4);
12331     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12332 
12333     /* Uninstallable value exists */
12334     size = MAX_PATH;
12335     lstrcpyA(val, "apple");
12336     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12337                             MSIINSTALLCONTEXT_USERMANAGED,
12338                             INSTALLPROPERTY_UNINSTALLABLEA, val, &size);
12339     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12340     ok(!lstrcmpA(val, "yes"), "Expected \"yes\", got \"%s\"\n", val);
12341     ok(size == 3, "Expected 3, got %d\n", size);
12342 
12343     res = RegSetValueExA(hpatch, "State", 0, REG_SZ,
12344                          (const BYTE *)"good", 5);
12345     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12346 
12347     /* State value exists */
12348     size = MAX_PATH;
12349     lstrcpyA(val, "apple");
12350     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12351                             MSIINSTALLCONTEXT_USERMANAGED,
12352                             INSTALLPROPERTY_PATCHSTATEA, val, &size);
12353     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12354     ok(!lstrcmpA(val, "good"), "Expected \"good\", got \"%s\"\n", val);
12355     ok(size == 4, "Expected 4, got %d\n", size);
12356 
12357     size = 1;
12358     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
12359                          (const BYTE *)&size, sizeof(DWORD));
12360     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12361 
12362     /* State value exists */
12363     size = MAX_PATH;
12364     lstrcpyA(val, "apple");
12365     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12366                             MSIINSTALLCONTEXT_USERMANAGED,
12367                             INSTALLPROPERTY_PATCHSTATEA, val, &size);
12368     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12369     ok(!lstrcmpA(val, "1"), "Expected \"1\", got \"%s\"\n", val);
12370     ok(size == 1, "Expected 1, got %d\n", size);
12371 
12372     size = 1;
12373     res = RegSetValueExA(hpatch, "Uninstallable", 0, REG_DWORD,
12374                          (const BYTE *)&size, sizeof(DWORD));
12375     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12376 
12377     /* Uninstallable value exists */
12378     size = MAX_PATH;
12379     lstrcpyA(val, "apple");
12380     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12381                             MSIINSTALLCONTEXT_USERMANAGED,
12382                             INSTALLPROPERTY_UNINSTALLABLEA, val, &size);
12383     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12384     ok(!lstrcmpA(val, "1"), "Expected \"1\", got \"%s\"\n", val);
12385     ok(size == 1, "Expected 1, got %d\n", size);
12386 
12387     res = RegSetValueExA(hpatch, "DisplayName", 0, REG_SZ,
12388                          (const BYTE *)"display", 8);
12389     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12390 
12391     /* DisplayName value exists */
12392     size = MAX_PATH;
12393     lstrcpyA(val, "apple");
12394     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12395                             MSIINSTALLCONTEXT_USERMANAGED,
12396                             INSTALLPROPERTY_DISPLAYNAMEA, val, &size);
12397     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12398     ok(!lstrcmpA(val, "display"), "Expected \"display\", got \"%s\"\n", val);
12399     ok(size == 7, "Expected 7, got %d\n", size);
12400 
12401     res = RegSetValueExA(hpatch, "MoreInfoURL", 0, REG_SZ,
12402                          (const BYTE *)"moreinfo", 9);
12403     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12404 
12405     /* MoreInfoURL value exists */
12406     size = MAX_PATH;
12407     lstrcpyA(val, "apple");
12408     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12409                             MSIINSTALLCONTEXT_USERMANAGED,
12410                             INSTALLPROPERTY_MOREINFOURLA, val, &size);
12411     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12412     ok(!lstrcmpA(val, "moreinfo"), "Expected \"moreinfo\", got \"%s\"\n", val);
12413     ok(size == 8, "Expected 8, got %d\n", size);
12414 
12415     /* szProperty is invalid */
12416     size = MAX_PATH;
12417     lstrcpyA(val, "apple");
12418     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12419                             MSIINSTALLCONTEXT_USERMANAGED,
12420                             "IDontExist", val, &size);
12421     ok(r == ERROR_UNKNOWN_PROPERTY,
12422        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
12423     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
12424     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
12425 
12426     /* lpValue is NULL, while pcchValue is non-NULL */
12427     size = MAX_PATH;
12428     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12429                             MSIINSTALLCONTEXT_USERMANAGED,
12430                             INSTALLPROPERTY_MOREINFOURLA, NULL, &size);
12431     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12432     ok(size == 16, "Expected 16, got %d\n", size);
12433 
12434     /* pcchValue is NULL, while lpValue is non-NULL */
12435     lstrcpyA(val, "apple");
12436     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12437                             MSIINSTALLCONTEXT_USERMANAGED,
12438                             INSTALLPROPERTY_MOREINFOURLA, val, NULL);
12439     ok(r == ERROR_INVALID_PARAMETER,
12440        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12441     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
12442 
12443     /* both lpValue and pcchValue are NULL */
12444     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12445                             MSIINSTALLCONTEXT_USERMANAGED,
12446                             INSTALLPROPERTY_MOREINFOURLA, NULL, NULL);
12447     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12448 
12449     /* pcchValue doesn't have enough room for NULL terminator */
12450     size = 8;
12451     lstrcpyA(val, "apple");
12452     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12453                             MSIINSTALLCONTEXT_USERMANAGED,
12454                             INSTALLPROPERTY_MOREINFOURLA, val, &size);
12455     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
12456     ok(!lstrcmpA(val, "moreinf"),
12457        "Expected \"moreinf\", got \"%s\"\n", val);
12458     ok(size == 16, "Expected 16, got %d\n", size);
12459 
12460     /* pcchValue has exactly enough room for NULL terminator */
12461     size = 9;
12462     lstrcpyA(val, "apple");
12463     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12464                             MSIINSTALLCONTEXT_USERMANAGED,
12465                             INSTALLPROPERTY_MOREINFOURLA, val, &size);
12466     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12467     ok(!lstrcmpA(val, "moreinfo"),
12468        "Expected \"moreinfo\", got \"%s\"\n", val);
12469     ok(size == 8, "Expected 8, got %d\n", size);
12470 
12471     /* pcchValue is too small, lpValue is NULL */
12472     size = 0;
12473     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12474                             MSIINSTALLCONTEXT_USERMANAGED,
12475                             INSTALLPROPERTY_MOREINFOURLA, NULL, &size);
12476     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12477     ok(size == 16, "Expected 16, got %d\n", size);
12478 
12479     RegDeleteValueA(prodpatches, patch_squashed);
12480     delete_key(prodpatches, "", access & KEY_WOW64_64KEY);
12481     RegCloseKey(prodpatches);
12482     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
12483     RegCloseKey(prodkey);
12484 
12485     /* UserData is sufficient for all properties
12486      * except INSTALLPROPERTY_TRANSFORMS
12487      */
12488     size = MAX_PATH;
12489     lstrcpyA(val, "apple");
12490     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12491                             MSIINSTALLCONTEXT_USERMANAGED,
12492                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12493     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12494     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12495     ok(size == 4, "Expected 4, got %d\n", size);
12496 
12497     /* UserData is sufficient for all properties
12498      * except INSTALLPROPERTY_TRANSFORMS
12499      */
12500     size = MAX_PATH;
12501     lstrcpyA(val, "apple");
12502     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12503                             MSIINSTALLCONTEXT_USERMANAGED,
12504                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12505     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12506     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
12507     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
12508 
12509     RegDeleteValueA(hpatch, "MoreInfoURL");
12510     RegDeleteValueA(hpatch, "Display");
12511     RegDeleteValueA(hpatch, "State");
12512     RegDeleteValueA(hpatch, "Uninstallable");
12513     RegDeleteValueA(hpatch, "Installed");
12514     RegDeleteValueA(udpatch, "ManagedLocalPackage");
12515     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
12516     RegCloseKey(udpatch);
12517     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
12518     RegCloseKey(hpatch);
12519     delete_key(patches, "", access & KEY_WOW64_64KEY);
12520     RegCloseKey(patches);
12521     delete_key(props, "", access & KEY_WOW64_64KEY);
12522     RegCloseKey(props);
12523     delete_key(udprod, "", access & KEY_WOW64_64KEY);
12524     RegCloseKey(udprod);
12525 
12526     /* MSIINSTALLCONTEXT_USERUNMANAGED */
12527 
12528     size = MAX_PATH;
12529     lstrcpyA(val, "apple");
12530     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12531                             MSIINSTALLCONTEXT_USERUNMANAGED,
12532                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12533     ok(r == ERROR_UNKNOWN_PRODUCT,
12534        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12535     ok(!lstrcmpA(val, "apple"),
12536        "Expected val to be unchanged, got \"%s\"\n", val);
12537     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12538 
12539     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
12540     lstrcatA(keypath, usersid);
12541     lstrcatA(keypath, "\\Products\\");
12542     lstrcatA(keypath, prod_squashed);
12543 
12544     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
12545     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12546 
12547     /* local UserData product key exists */
12548     size = MAX_PATH;
12549     lstrcpyA(val, "apple");
12550     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12551                             MSIINSTALLCONTEXT_USERUNMANAGED,
12552                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12553     ok(r == ERROR_UNKNOWN_PRODUCT,
12554        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12555     ok(!lstrcmpA(val, "apple"),
12556        "Expected val to be unchanged, got \"%s\"\n", val);
12557     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12558 
12559     res = RegCreateKeyExA(udprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
12560     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12561 
12562     /* InstallProperties key exists */
12563     size = MAX_PATH;
12564     lstrcpyA(val, "apple");
12565     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12566                             MSIINSTALLCONTEXT_USERUNMANAGED,
12567                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12568     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12569     ok(!lstrcmpA(val, "apple"),
12570        "Expected val to be unchanged, got \"%s\"\n", val);
12571     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12572 
12573     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
12574     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12575 
12576     /* Patches key exists */
12577     size = MAX_PATH;
12578     lstrcpyA(val, "apple");
12579     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12580                             MSIINSTALLCONTEXT_USERUNMANAGED,
12581                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12582     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12583     ok(!lstrcmpA(val, "apple"),
12584        "Expected val to be unchanged, got \"%s\"\n", val);
12585     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12586 
12587     res = RegCreateKeyExA(patches, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
12588     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12589 
12590     /* Patches key exists */
12591     size = MAX_PATH;
12592     lstrcpyA(val, "apple");
12593     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12594                             MSIINSTALLCONTEXT_USERUNMANAGED,
12595                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12596     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12597     ok(!lstrcmpA(val, "apple"),
12598        "Expected val to be unchanged, got \"%s\"\n", val);
12599     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12600 
12601     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
12602     lstrcatA(keypath, prod_squashed);
12603 
12604     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
12605     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12606 
12607     /* current user product key exists */
12608     size = MAX_PATH;
12609     lstrcpyA(val, "apple");
12610     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12611                             MSIINSTALLCONTEXT_USERUNMANAGED,
12612                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12613     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12614     ok(!lstrcmpA(val, "apple"),
12615        "Expected val to be unchanged, got \"%s\"\n", val);
12616     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12617 
12618     res = RegCreateKeyA(prodkey, "Patches", &prodpatches);
12619     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12620 
12621     /* Patches key exists */
12622     size = MAX_PATH;
12623     lstrcpyA(val, "apple");
12624     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12625                             MSIINSTALLCONTEXT_USERUNMANAGED,
12626                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12627     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12628     ok(!lstrcmpA(val, "apple"),
12629        "Expected val to be unchanged, got \"%s\"\n", val);
12630     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12631 
12632     res = RegSetValueExA(prodpatches, patch_squashed, 0, REG_SZ,
12633                          (const BYTE *)"transforms", 11);
12634     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12635 
12636     /* specific patch value exists */
12637     size = MAX_PATH;
12638     lstrcpyA(val, "apple");
12639     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12640                             MSIINSTALLCONTEXT_USERUNMANAGED,
12641                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12642     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12643     ok(!lstrcmpA(val, "apple"),
12644        "Expected val to be unchanged, got \"%s\"\n", val);
12645     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12646 
12647     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
12648     lstrcatA(keypath, usersid);
12649     lstrcatA(keypath, "\\Patches\\");
12650     lstrcatA(keypath, patch_squashed);
12651 
12652     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udpatch, NULL);
12653     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12654 
12655     /* UserData Patches key exists */
12656     size = MAX_PATH;
12657     lstrcpyA(val, "apple");
12658     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12659                             MSIINSTALLCONTEXT_USERUNMANAGED,
12660                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12661     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12662     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
12663     ok(size == 0, "Expected 0, got %d\n", size);
12664 
12665     res = RegSetValueExA(udpatch, "LocalPackage", 0, REG_SZ,
12666                          (const BYTE *)"pack", 5);
12667     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12668 
12669     /* LocalPatch value exists */
12670     size = MAX_PATH;
12671     lstrcpyA(val, "apple");
12672     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12673                             MSIINSTALLCONTEXT_USERUNMANAGED,
12674                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12675     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12676     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12677     ok(size == 4, "Expected 4, got %d\n", size);
12678 
12679     size = MAX_PATH;
12680     lstrcpyA(val, "apple");
12681     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12682                             MSIINSTALLCONTEXT_USERUNMANAGED,
12683                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12684     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12685     ok(!lstrcmpA(val, "transforms"), "Expected \"transforms\", got \"%s\"\n", val);
12686     ok(size == 10, "Expected 10, got %d\n", size);
12687 
12688     RegDeleteValueA(prodpatches, patch_squashed);
12689     delete_key(prodpatches, "", access & KEY_WOW64_64KEY);
12690     RegCloseKey(prodpatches);
12691     RegDeleteKeyA(prodkey, "");
12692     RegCloseKey(prodkey);
12693 
12694     /* UserData is sufficient for all properties
12695      * except INSTALLPROPERTY_TRANSFORMS
12696      */
12697     size = MAX_PATH;
12698     lstrcpyA(val, "apple");
12699     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12700                             MSIINSTALLCONTEXT_USERUNMANAGED,
12701                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12702     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12703     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12704     ok(size == 4, "Expected 4, got %d\n", size);
12705 
12706     /* UserData is sufficient for all properties
12707      * except INSTALLPROPERTY_TRANSFORMS
12708      */
12709     size = MAX_PATH;
12710     lstrcpyA(val, "apple");
12711     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12712                             MSIINSTALLCONTEXT_USERUNMANAGED,
12713                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12714     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12715     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
12716     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
12717 
12718     RegDeleteValueA(udpatch, "LocalPackage");
12719     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
12720     RegCloseKey(udpatch);
12721     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
12722     RegCloseKey(hpatch);
12723     delete_key(patches, "", access & KEY_WOW64_64KEY);
12724     RegCloseKey(patches);
12725     delete_key(props, "", access & KEY_WOW64_64KEY);
12726     RegCloseKey(props);
12727     delete_key(udprod, "", access & KEY_WOW64_64KEY);
12728     RegCloseKey(udprod);
12729 
12730     /* MSIINSTALLCONTEXT_MACHINE */
12731 
12732     size = MAX_PATH;
12733     lstrcpyA(val, "apple");
12734     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12735                             MSIINSTALLCONTEXT_MACHINE,
12736                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12737     ok(r == ERROR_UNKNOWN_PRODUCT,
12738        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12739     ok(!lstrcmpA(val, "apple"),
12740        "Expected val to be unchanged, got \"%s\"\n", val);
12741     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12742 
12743     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
12744     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Products\\");
12745     lstrcatA(keypath, prod_squashed);
12746 
12747     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
12748     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12749 
12750     /* local UserData product key exists */
12751     size = MAX_PATH;
12752     lstrcpyA(val, "apple");
12753     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12754                             MSIINSTALLCONTEXT_MACHINE,
12755                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12756     ok(r == ERROR_UNKNOWN_PRODUCT,
12757        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12758     ok(!lstrcmpA(val, "apple"),
12759        "Expected val to be unchanged, got \"%s\"\n", val);
12760     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12761 
12762     res = RegCreateKeyExA(udprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
12763     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12764 
12765     /* InstallProperties key exists */
12766     size = MAX_PATH;
12767     lstrcpyA(val, "apple");
12768     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12769                             MSIINSTALLCONTEXT_MACHINE,
12770                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12771     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12772     ok(!lstrcmpA(val, "apple"),
12773        "Expected val to be unchanged, got \"%s\"\n", val);
12774     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12775 
12776     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
12777     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12778 
12779     /* Patches key exists */
12780     size = MAX_PATH;
12781     lstrcpyA(val, "apple");
12782     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12783                             MSIINSTALLCONTEXT_MACHINE,
12784                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12785     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12786     ok(!lstrcmpA(val, "apple"),
12787        "Expected val to be unchanged, got \"%s\"\n", val);
12788     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12789 
12790     res = RegCreateKeyExA(patches, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
12791     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12792 
12793     /* Patches key exists */
12794     size = MAX_PATH;
12795     lstrcpyA(val, "apple");
12796     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12797                             MSIINSTALLCONTEXT_MACHINE,
12798                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12799     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12800     ok(!lstrcmpA(val, "apple"),
12801        "Expected val to be unchanged, got \"%s\"\n", val);
12802     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12803 
12804     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
12805     lstrcatA(keypath, prod_squashed);
12806 
12807     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
12808     if (res == ERROR_ACCESS_DENIED)
12809     {
12810         skip( "insufficient rights\n" );
12811         LocalFree( usersid );
12812         return;
12813     }
12814     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12815 
12816     /* local product key exists */
12817     size = MAX_PATH;
12818     lstrcpyA(val, "apple");
12819     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12820                             MSIINSTALLCONTEXT_MACHINE,
12821                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12822     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12823     ok(!lstrcmpA(val, "apple"),
12824        "Expected val to be unchanged, got \"%s\"\n", val);
12825     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12826 
12827     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &prodpatches, NULL);
12828     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12829 
12830     /* Patches key exists */
12831     size = MAX_PATH;
12832     lstrcpyA(val, "apple");
12833     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12834                             MSIINSTALLCONTEXT_MACHINE,
12835                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12836     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12837     ok(!lstrcmpA(val, "apple"),
12838        "Expected val to be unchanged, got \"%s\"\n", val);
12839     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12840 
12841     res = RegSetValueExA(prodpatches, patch_squashed, 0, REG_SZ,
12842                          (const BYTE *)"transforms", 11);
12843     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12844 
12845     /* specific patch value exists */
12846     size = MAX_PATH;
12847     lstrcpyA(val, "apple");
12848     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12849                             MSIINSTALLCONTEXT_MACHINE,
12850                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12851     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12852     ok(!lstrcmpA(val, "apple"),
12853        "Expected val to be unchanged, got \"%s\"\n", val);
12854     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12855 
12856     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
12857     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Patches\\");
12858     lstrcatA(keypath, patch_squashed);
12859 
12860     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udpatch, NULL);
12861     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12862 
12863     /* UserData Patches key exists */
12864     size = MAX_PATH;
12865     lstrcpyA(val, "apple");
12866     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12867                             MSIINSTALLCONTEXT_MACHINE,
12868                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12869     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12870     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
12871     ok(size == 0, "Expected 0, got %d\n", size);
12872 
12873     res = RegSetValueExA(udpatch, "LocalPackage", 0, REG_SZ,
12874                          (const BYTE *)"pack", 5);
12875     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12876 
12877     /* LocalPatch value exists */
12878     size = MAX_PATH;
12879     lstrcpyA(val, "apple");
12880     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12881                             MSIINSTALLCONTEXT_MACHINE,
12882                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12883     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12884     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12885     ok(size == 4, "Expected 4, got %d\n", size);
12886 
12887     size = MAX_PATH;
12888     lstrcpyA(val, "apple");
12889     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12890                             MSIINSTALLCONTEXT_MACHINE,
12891                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12892     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12893     ok(!lstrcmpA(val, "transforms"), "Expected \"transforms\", got \"%s\"\n", val);
12894     ok(size == 10, "Expected 10, got %d\n", size);
12895 
12896     RegDeleteValueA(prodpatches, patch_squashed);
12897     delete_key(prodpatches, "", access & KEY_WOW64_64KEY);
12898     RegCloseKey(prodpatches);
12899     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
12900     RegCloseKey(prodkey);
12901 
12902     /* UserData is sufficient for all properties
12903      * except INSTALLPROPERTY_TRANSFORMS
12904      */
12905     size = MAX_PATH;
12906     lstrcpyA(val, "apple");
12907     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12908                             MSIINSTALLCONTEXT_MACHINE,
12909                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12910     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12911     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12912     ok(size == 4, "Expected 4, got %d\n", size);
12913 
12914     /* UserData is sufficient for all properties
12915      * except INSTALLPROPERTY_TRANSFORMS
12916      */
12917     size = MAX_PATH;
12918     lstrcpyA(val, "apple");
12919     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12920                             MSIINSTALLCONTEXT_MACHINE,
12921                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12922     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12923     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
12924     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
12925 
12926     RegDeleteValueA(udpatch, "LocalPackage");
12927     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
12928     RegCloseKey(udpatch);
12929     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
12930     RegCloseKey(hpatch);
12931     delete_key(patches, "", access & KEY_WOW64_64KEY);
12932     RegCloseKey(patches);
12933     delete_key(props, "", access & KEY_WOW64_64KEY);
12934     RegCloseKey(props);
12935     delete_key(udprod, "", access & KEY_WOW64_64KEY);
12936     RegCloseKey(udprod);
12937     LocalFree(usersid);
12938 }
12939 
12940 static void test_MsiGetPatchInfo(void)
12941 {
12942     UINT r;
12943     char prod_code[MAX_PATH], prod_squashed[MAX_PATH], val[MAX_PATH];
12944     char patch_code[MAX_PATH], patch_squashed[MAX_PATH], keypath[MAX_PATH];
12945     WCHAR valW[MAX_PATH], patch_codeW[MAX_PATH];
12946     HKEY hkey_product, hkey_patch, hkey_patches, hkey_udprops, hkey_udproduct;
12947     HKEY hkey_udpatch, hkey_udpatches, hkey_udproductpatches, hkey_udproductpatch;
12948     DWORD size;
12949     LONG res;
12950     REGSAM access = KEY_ALL_ACCESS;
12951 
12952     create_test_guid(patch_code, patch_squashed);
12953     create_test_guid(prod_code, prod_squashed);
12954     MultiByteToWideChar(CP_ACP, 0, patch_code, -1, patch_codeW, MAX_PATH);
12955 
12956     if (is_wow64)
12957         access |= KEY_WOW64_64KEY;
12958 
12959     r = MsiGetPatchInfoA(NULL, NULL, NULL, NULL);
12960     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
12961 
12962     r = MsiGetPatchInfoA(patch_code, NULL, NULL, NULL);
12963     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
12964 
12965     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, NULL, NULL);
12966     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
12967 
12968     size = 0;
12969     r = MsiGetPatchInfoA(patch_code, NULL, NULL, &size);
12970     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
12971 
12972     r = MsiGetPatchInfoA(patch_code, "", NULL, &size);
12973     ok(r == ERROR_UNKNOWN_PROPERTY, "expected ERROR_UNKNOWN_PROPERTY, got %u\n", r);
12974 
12975     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
12976     lstrcatA(keypath, prod_squashed);
12977 
12978     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey_product, NULL);
12979     if (res == ERROR_ACCESS_DENIED)
12980     {
12981         skip("Not enough rights to perform tests\n");
12982         return;
12983     }
12984     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
12985 
12986     /* product key exists */
12987     size = MAX_PATH;
12988     lstrcpyA(val, "apple");
12989     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12990     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
12991     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged, got \"%s\"\n", val);
12992     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
12993 
12994     res = RegCreateKeyExA(hkey_product, "Patches", 0, NULL, 0, access, NULL, &hkey_patches, NULL);
12995     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
12996 
12997     /* patches key exists */
12998     size = MAX_PATH;
12999     lstrcpyA(val, "apple");
13000     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13001     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13002     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
13003     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
13004 
13005     res = RegCreateKeyExA(hkey_patches, patch_squashed, 0, NULL, 0, access, NULL, &hkey_patch, NULL);
13006     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13007 
13008     /* patch key exists */
13009     size = MAX_PATH;
13010     lstrcpyA(val, "apple");
13011     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13012     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13013     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
13014     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
13015 
13016     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
13017     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Products\\");
13018     lstrcatA(keypath, prod_squashed);
13019 
13020     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey_udproduct, NULL);
13021     if (res == ERROR_ACCESS_DENIED)
13022     {
13023         skip("Not enough rights to perform tests\n");
13024         goto done;
13025     }
13026     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
13027 
13028     /* UserData product key exists */
13029     size = MAX_PATH;
13030     lstrcpyA(val, "apple");
13031     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13032     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13033     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
13034     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
13035 
13036     res = RegCreateKeyExA(hkey_udproduct, "InstallProperties", 0, NULL, 0, access, NULL, &hkey_udprops, NULL);
13037     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13038 
13039     /* InstallProperties key exists */
13040     size = MAX_PATH;
13041     lstrcpyA(val, "apple");
13042     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13043     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13044     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged, got \"%s\"\n", val);
13045     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
13046 
13047     res = RegCreateKeyExA(hkey_udproduct, "Patches", 0, NULL, 0, access, NULL, &hkey_udpatches, NULL);
13048     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13049 
13050     /* UserData Patches key exists */
13051     size = MAX_PATH;
13052     lstrcpyA(val, "apple");
13053     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13054     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13055     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
13056     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
13057 
13058     res = RegCreateKeyExA(hkey_udproduct, "Patches", 0, NULL, 0, access, NULL, &hkey_udproductpatches, NULL);
13059     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13060 
13061     res = RegCreateKeyExA(hkey_udproductpatches, patch_squashed, 0, NULL, 0, access, NULL, &hkey_udproductpatch, NULL);
13062     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13063 
13064     /* UserData product patch key exists */
13065     size = MAX_PATH;
13066     lstrcpyA(val, "apple");
13067     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13068     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13069     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
13070     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
13071 
13072     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
13073     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Patches\\");
13074     lstrcatA(keypath, patch_squashed);
13075 
13076     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey_udpatch, NULL);
13077     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13078 
13079     res = RegSetValueExA(hkey_udpatch, "LocalPackage", 0, REG_SZ, (const BYTE *)"c:\\test.msp", 12);
13080     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13081 
13082     /* UserData Patch key exists */
13083     size = 0;
13084     lstrcpyA(val, "apple");
13085     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13086     ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", r);
13087     ok(!lstrcmpA(val, "apple"), "expected \"apple\", got \"%s\"\n", val);
13088     ok(size == 11, "expected 11 got %u\n", size);
13089 
13090     size = MAX_PATH;
13091     lstrcpyA(val, "apple");
13092     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13093     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS got %u\n", r);
13094     ok(!lstrcmpA(val, "c:\\test.msp"), "expected \"c:\\test.msp\", got \"%s\"\n", val);
13095     ok(size == 11, "expected 11 got %u\n", size);
13096 
13097     size = 0;
13098     valW[0] = 0;
13099     r = MsiGetPatchInfoW(patch_codeW, INSTALLPROPERTY_LOCALPACKAGEW, valW, &size);
13100     ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", r);
13101     ok(!valW[0], "expected 0 got %u\n", valW[0]);
13102     ok(size == 11, "expected 11 got %u\n", size);
13103 
13104     size = MAX_PATH;
13105     valW[0] = 0;
13106     r = MsiGetPatchInfoW(patch_codeW, INSTALLPROPERTY_LOCALPACKAGEW, valW, &size);
13107     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS got %u\n", r);
13108     ok(valW[0], "expected > 0 got %u\n", valW[0]);
13109     ok(size == 11, "expected 11 got %u\n", size);
13110 
13111     delete_key(hkey_udproductpatch, "", access & KEY_WOW64_64KEY);
13112     RegCloseKey(hkey_udproductpatch);
13113     delete_key(hkey_udproductpatches, "", access & KEY_WOW64_64KEY);
13114     RegCloseKey(hkey_udproductpatches);
13115     delete_key(hkey_udpatch, "", access & KEY_WOW64_64KEY);
13116     RegCloseKey(hkey_udpatch);
13117     delete_key(hkey_udpatches, "", access & KEY_WOW64_64KEY);
13118     RegCloseKey(hkey_udpatches);
13119     delete_key(hkey_udprops, "", access & KEY_WOW64_64KEY);
13120     RegCloseKey(hkey_udprops);
13121     delete_key(hkey_udproduct, "", access & KEY_WOW64_64KEY);
13122     RegCloseKey(hkey_udproduct);
13123 
13124 done:
13125     delete_key(hkey_patches, "", access & KEY_WOW64_64KEY);
13126     RegCloseKey(hkey_patches);
13127     delete_key(hkey_product, "", access & KEY_WOW64_64KEY);
13128     RegCloseKey(hkey_product);
13129     delete_key(hkey_patch, "", access & KEY_WOW64_64KEY);
13130     RegCloseKey(hkey_patch);
13131 }
13132 
13133 static void test_MsiEnumProducts(void)
13134 {
13135     UINT r;
13136     BOOL found1, found2, found3;
13137     DWORD index;
13138     char product1[39], product2[39], product3[39], guid[39];
13139     char product_squashed1[33], product_squashed2[33], product_squashed3[33];
13140     char keypath1[MAX_PATH], keypath2[MAX_PATH], keypath3[MAX_PATH];
13141     char *usersid;
13142     HKEY key1, key2, key3;
13143     REGSAM access = KEY_ALL_ACCESS;
13144 
13145     if (is_process_limited())
13146     {
13147         skip( "process is limited\n" );
13148         return;
13149     }
13150 
13151     create_test_guid(product1, product_squashed1);
13152     create_test_guid(product2, product_squashed2);
13153     create_test_guid(product3, product_squashed3);
13154     usersid = get_user_sid();
13155 
13156     if (is_wow64)
13157         access |= KEY_WOW64_64KEY;
13158 
13159     strcpy(keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
13160     strcat(keypath2, usersid);
13161     strcat(keypath2, "\\Installer\\Products\\");
13162     strcat(keypath2, product_squashed2);
13163 
13164     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL);
13165     if (r == ERROR_ACCESS_DENIED)
13166     {
13167         skip("Not enough rights to perform tests\n");
13168         LocalFree(usersid);
13169         return;
13170     }
13171     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13172 
13173     strcpy(keypath1, "Software\\Classes\\Installer\\Products\\");
13174     strcat(keypath1, product_squashed1);
13175 
13176     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL);
13177     if (r == ERROR_ACCESS_DENIED)
13178     {
13179         skip( "insufficient rights\n" );
13180         LocalFree( usersid );
13181         return;
13182     }
13183     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13184 
13185     strcpy(keypath3, "Software\\Microsoft\\Installer\\Products\\");
13186     strcat(keypath3, product_squashed3);
13187 
13188     r = RegCreateKeyA(HKEY_CURRENT_USER, keypath3, &key3);
13189     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13190 
13191     index = 0;
13192     r = MsiEnumProductsA(index, guid);
13193     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13194 
13195     r = MsiEnumProductsA(index, NULL);
13196     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
13197 
13198     index = 2;
13199     r = MsiEnumProductsA(index, guid);
13200     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
13201 
13202     index = 0;
13203     r = MsiEnumProductsA(index, guid);
13204     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13205 
13206     found1 = found2 = found3 = FALSE;
13207     while ((r = MsiEnumProductsA(index, guid)) == ERROR_SUCCESS)
13208     {
13209         if (!strcmp(product1, guid)) found1 = TRUE;
13210         if (!strcmp(product2, guid)) found2 = TRUE;
13211         if (!strcmp(product3, guid)) found3 = TRUE;
13212         if (found1 && found2 && found3) break;
13213         index++;
13214     }
13215     ok(found1, "product1 not found\n");
13216     ok(found2, "product2 not found\n");
13217     ros_skip_flaky
13218     ok(found3, "product3 not found\n");
13219 
13220     delete_key(key1, "", access & KEY_WOW64_64KEY);
13221     delete_key(key2, "", access & KEY_WOW64_64KEY);
13222     RegDeleteKeyA(key3, "");
13223     RegCloseKey(key1);
13224     RegCloseKey(key2);
13225     RegCloseKey(key3);
13226     LocalFree(usersid);
13227 }
13228 
13229 static void test_MsiGetFileSignatureInformation(void)
13230 {
13231     HRESULT hr;
13232     const CERT_CONTEXT *cert;
13233     DWORD len;
13234 
13235     hr = MsiGetFileSignatureInformationA( NULL, 0, NULL, NULL, NULL );
13236     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13237 
13238     hr = MsiGetFileSignatureInformationA( NULL, 0, NULL, NULL, &len );
13239     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13240 
13241     hr = MsiGetFileSignatureInformationA( NULL, 0, &cert, NULL, &len );
13242     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13243 
13244     hr = MsiGetFileSignatureInformationA( "", 0, NULL, NULL, NULL );
13245     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13246 
13247     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, NULL );
13248     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13249 
13250     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, &len );
13251     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13252 
13253     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, &cert, NULL, &len );
13254     todo_wine ok(hr == CRYPT_E_FILE_ERROR, "expected CRYPT_E_FILE_ERROR got 0x%08x\n", hr);
13255 
13256     create_file_data( "signature.bin", "signature", sizeof("signature") );
13257 
13258     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, NULL );
13259     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13260 
13261     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, &len );
13262     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13263 
13264     cert = (const CERT_CONTEXT *)0xdeadbeef;
13265     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, &cert, NULL, &len );
13266     todo_wine ok(hr == HRESULT_FROM_WIN32(ERROR_FUNCTION_FAILED), "got 0x%08x\n", hr);
13267     ok(cert == NULL, "got %p\n", cert);
13268 
13269     DeleteFileA( "signature.bin" );
13270 }
13271 
13272 static void test_MsiEnumProductsEx(void)
13273 {
13274     UINT r;
13275     DWORD len, index;
13276     MSIINSTALLCONTEXT context;
13277     char product0[39], product1[39], product2[39], product3[39], guid[39], sid[128];
13278     char product_squashed1[33], product_squashed2[33], product_squashed3[33];
13279     char keypath1[MAX_PATH], keypath2[MAX_PATH], keypath3[MAX_PATH];
13280     HKEY key1 = NULL, key2 = NULL, key3 = NULL;
13281     REGSAM access = KEY_ALL_ACCESS;
13282     char *usersid = get_user_sid();
13283     BOOL found1, found2, found3;
13284 
13285     if (!pMsiEnumProductsExA)
13286     {
13287         win_skip("MsiEnumProductsExA not implemented\n");
13288         return;
13289     }
13290 
13291     create_test_guid( product0, NULL );
13292     create_test_guid( product1, product_squashed1 );
13293     create_test_guid( product2, product_squashed2 );
13294     create_test_guid( product3, product_squashed3 );
13295 
13296     if (is_wow64) access |= KEY_WOW64_64KEY;
13297 
13298     strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\" );
13299     strcat( keypath2, usersid );
13300     strcat( keypath2, "\\Installer\\Products\\" );
13301     strcat( keypath2, product_squashed2 );
13302 
13303     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
13304     if (r == ERROR_ACCESS_DENIED)
13305     {
13306         skip( "insufficient rights\n" );
13307         goto done;
13308     }
13309     ok( r == ERROR_SUCCESS, "got %u\n", r );
13310 
13311     strcpy( keypath1, "Software\\Classes\\Installer\\Products\\" );
13312     strcat( keypath1, product_squashed1 );
13313 
13314     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
13315     if (r == ERROR_ACCESS_DENIED)
13316     {
13317         skip( "insufficient rights\n" );
13318         goto done;
13319     }
13320     ok( r == ERROR_SUCCESS, "got %u\n", r );
13321 
13322     strcpy( keypath3, usersid );
13323     strcat( keypath3, "\\Software\\Microsoft\\Installer\\Products\\" );
13324     strcat( keypath3, product_squashed3 );
13325 
13326     r = RegCreateKeyExA( HKEY_USERS, keypath3, 0, NULL, 0, access, NULL, &key3, NULL );
13327     ok( r == ERROR_SUCCESS, "got %u\n", r );
13328 
13329     r = pMsiEnumProductsExA( NULL, NULL, 0, 0, NULL, NULL, NULL, NULL );
13330     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13331 
13332     len = sizeof(sid);
13333     r = pMsiEnumProductsExA( NULL, NULL, 0, 0, NULL, NULL, NULL, &len );
13334     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13335     ok( len == sizeof(sid), "got %u\n", len );
13336 
13337     r = pMsiEnumProductsExA( NULL, NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, NULL, NULL );
13338     ok( r == ERROR_SUCCESS, "got %u\n", r );
13339 
13340     sid[0] = 0;
13341     len = sizeof(sid);
13342     r = pMsiEnumProductsExA( product0, NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, &len );
13343     ok( r == ERROR_NO_MORE_ITEMS, "got %u\n", r );
13344     ok( len == sizeof(sid), "got %u\n", len );
13345     ok( !sid[0], "got %s\n", sid );
13346 
13347     sid[0] = 0;
13348     len = sizeof(sid);
13349     r = pMsiEnumProductsExA( product0, usersid, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, &len );
13350     ok( r == ERROR_NO_MORE_ITEMS, "got %u\n", r );
13351     ok( len == sizeof(sid), "got %u\n", len );
13352     ok( !sid[0], "got %s\n", sid );
13353 
13354     sid[0] = 0;
13355     len = 0;
13356     r = pMsiEnumProductsExA( NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, 0, NULL, NULL, sid, &len );
13357     ok( r == ERROR_MORE_DATA, "got %u\n", r );
13358     ok( len, "length unchanged\n" );
13359     ok( !sid[0], "got %s\n", sid );
13360 
13361     guid[0] = 0;
13362     context = 0xdeadbeef;
13363     sid[0] = 0;
13364     len = sizeof(sid);
13365     r = pMsiEnumProductsExA( NULL, NULL, MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
13366     ok( r == ERROR_SUCCESS, "got %u\n", r );
13367     ok( guid[0], "empty guid\n" );
13368     ok( context != 0xdeadbeef, "context unchanged\n" );
13369     ok( !len, "got %u\n", len );
13370     ok( !sid[0], "got %s\n", sid );
13371 
13372     guid[0] = 0;
13373     context = 0xdeadbeef;
13374     sid[0] = 0;
13375     len = sizeof(sid);
13376     r = pMsiEnumProductsExA( NULL, usersid, MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
13377     ok( r == ERROR_SUCCESS, "got %u\n", r );
13378     ok( guid[0], "empty guid\n" );
13379     ok( context != 0xdeadbeef, "context unchanged\n" );
13380     ok( !len, "got %u\n", len );
13381     ok( !sid[0], "got %s\n", sid );
13382 
13383     guid[0] = 0;
13384     context = 0xdeadbeef;
13385     sid[0] = 0;
13386     len = sizeof(sid);
13387     r = pMsiEnumProductsExA( NULL, "S-1-1-0", MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
13388     if (r == ERROR_ACCESS_DENIED)
13389     {
13390         skip( "insufficient rights\n" );
13391         goto done;
13392     }
13393     ok( r == ERROR_SUCCESS, "got %u\n", r );
13394     ok( guid[0], "empty guid\n" );
13395     ok( context != 0xdeadbeef, "context unchanged\n" );
13396     ok( !len, "got %u\n", len );
13397     ok( !sid[0], "got %s\n", sid );
13398 
13399     index = 0;
13400     guid[0] = 0;
13401     context = 0xdeadbeef;
13402     sid[0] = 0;
13403     len = sizeof(sid);
13404     found1 = found2 = found3 = FALSE;
13405     while (!pMsiEnumProductsExA( NULL, "S-1-1-0", MSIINSTALLCONTEXT_ALL, index, guid, &context, sid, &len ))
13406     {
13407         if (!strcmp( product1, guid ))
13408         {
13409             ok( context == MSIINSTALLCONTEXT_MACHINE, "got %u\n", context );
13410             ok( !sid[0], "got \"%s\"\n", sid );
13411             ok( !len, "unexpected length %u\n", len );
13412             found1 = TRUE;
13413         }
13414         if (!strcmp( product2, guid ))
13415         {
13416             ok( context == MSIINSTALLCONTEXT_USERMANAGED, "got %u\n", context );
13417             ok( sid[0], "empty sid\n" );
13418             ok( len == strlen(sid), "unexpected length %u\n", len );
13419             found2 = TRUE;
13420         }
13421         if (!strcmp( product3, guid ))
13422         {
13423             ok( context == MSIINSTALLCONTEXT_USERUNMANAGED, "got %u\n", context );
13424             ok( sid[0], "empty sid\n" );
13425             ok( len == strlen(sid), "unexpected length %u\n", len );
13426             found3 = TRUE;
13427         }
13428         if (found1 && found2 && found3) break;
13429         index++;
13430         guid[0] = 0;
13431         context = 0xdeadbeef;
13432         sid[0] = 0;
13433         len = sizeof(sid);
13434     }
13435     ok(found1, "product1 not found\n");
13436     ok(found2, "product2 not found\n");
13437     ok(found3, "product3 not found\n");
13438 
13439 done:
13440     delete_key( key1, "", access );
13441     delete_key( key2, "", access );
13442     delete_key( key3, "", access );
13443     RegCloseKey( key1 );
13444     RegCloseKey( key2 );
13445     RegCloseKey( key3 );
13446     LocalFree( usersid );
13447 }
13448 
13449 static void test_MsiEnumComponents(void)
13450 {
13451     UINT r;
13452     BOOL found1, found2;
13453     DWORD index;
13454     char comp1[39], comp2[39], guid[39];
13455     char comp_squashed1[33], comp_squashed2[33];
13456     char keypath1[MAX_PATH], keypath2[MAX_PATH];
13457     REGSAM access = KEY_ALL_ACCESS;
13458     char *usersid = get_user_sid();
13459     HKEY key1 = NULL, key2 = NULL;
13460 
13461     if (is_process_limited())
13462     {
13463         skip("process is limited\n");
13464         return;
13465     }
13466 
13467     create_test_guid( comp1, comp_squashed1 );
13468     create_test_guid( comp2, comp_squashed2 );
13469 
13470     if (is_wow64) access |= KEY_WOW64_64KEY;
13471 
13472     strcpy( keypath1, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
13473     strcat( keypath1, "S-1-5-18\\Components\\" );
13474     strcat( keypath1, comp_squashed1 );
13475 
13476     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
13477     if (r == ERROR_ACCESS_DENIED)
13478     {
13479         skip( "insufficient rights\n" );
13480         goto done;
13481     }
13482     ok( r == ERROR_SUCCESS, "got %u\n", r );
13483 
13484     strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
13485     strcat( keypath2, usersid );
13486     strcat( keypath2, "\\Components\\" );
13487     strcat( keypath2, comp_squashed2 );
13488 
13489     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
13490     if (r == ERROR_ACCESS_DENIED)
13491     {
13492         skip( "insufficient rights\n" );
13493         goto done;
13494     }
13495 
13496     r = MsiEnumComponentsA( 0, NULL );
13497     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13498 
13499     index = 0;
13500     guid[0] = 0;
13501     found1 = found2 = FALSE;
13502     while (!MsiEnumComponentsA( index, guid ))
13503     {
13504         if (!strcmp( guid, comp1 )) found1 = TRUE;
13505         if (!strcmp( guid, comp2 )) found2 = TRUE;
13506         ok( guid[0], "empty guid\n" );
13507         if (found1 && found2) break;
13508         guid[0] = 0;
13509         index++;
13510     }
13511     ok( found1, "comp1 not found\n" );
13512     ok( found2, "comp2 not found\n" );
13513 
13514 done:
13515     delete_key( key1, "", access );
13516     delete_key( key2, "", access );
13517     RegCloseKey( key1 );
13518     RegCloseKey( key2 );
13519     LocalFree( usersid );
13520 }
13521 
13522 static void test_MsiEnumComponentsEx(void)
13523 {
13524     UINT r;
13525     BOOL found1, found2;
13526     DWORD len, index;
13527     MSIINSTALLCONTEXT context;
13528     char comp1[39], comp2[39], guid[39], sid[128];
13529     char comp_squashed1[33], comp_squashed2[33];
13530     char keypath1[MAX_PATH], keypath2[MAX_PATH];
13531     HKEY key1 = NULL, key2 = NULL;
13532     REGSAM access = KEY_ALL_ACCESS;
13533     char *usersid = get_user_sid();
13534 
13535     if (!pMsiEnumComponentsExA)
13536     {
13537         win_skip( "MsiEnumComponentsExA not implemented\n" );
13538         return;
13539     }
13540     if (is_process_limited())
13541     {
13542         skip("process is limited\n");
13543         return;
13544     }
13545 
13546     create_test_guid( comp1, comp_squashed1 );
13547     create_test_guid( comp2, comp_squashed2 );
13548 
13549     if (is_wow64) access |= KEY_WOW64_64KEY;
13550 
13551     strcpy( keypath1, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
13552     strcat( keypath1, "S-1-5-18\\Components\\" );
13553     strcat( keypath1, comp_squashed1 );
13554 
13555     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
13556     if (r == ERROR_ACCESS_DENIED)
13557     {
13558         skip( "insufficient rights\n" );
13559         goto done;
13560     }
13561     ok( r == ERROR_SUCCESS, "got %u\n", r );
13562 
13563     strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
13564     strcat( keypath2, usersid );
13565     strcat( keypath2, "\\Components\\" );
13566     strcat( keypath2, comp_squashed2 );
13567 
13568     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
13569     if (r == ERROR_ACCESS_DENIED)
13570     {
13571         skip( "insufficient rights\n" );
13572         goto done;
13573     }
13574     ok( r == ERROR_SUCCESS, "got %u\n", r );
13575     r = RegSetValueExA( key2, comp_squashed2, 0, REG_SZ, (const BYTE *)"c:\\doesnotexist",
13576                         sizeof("c:\\doesnotexist"));
13577     ok( r == ERROR_SUCCESS, "got %u\n", r );
13578 
13579     index = 0;
13580     guid[0] = 0;
13581     context = 0xdeadbeef;
13582     sid[0] = 0;
13583     len = sizeof(sid);
13584     found1 = found2 = FALSE;
13585     while (!pMsiEnumComponentsExA( "S-1-1-0", MSIINSTALLCONTEXT_ALL, index, guid, &context, sid, &len ))
13586     {
13587         if (!strcmp( comp1, guid ))
13588         {
13589             ok( context == MSIINSTALLCONTEXT_MACHINE, "got %u\n", context );
13590             ok( !sid[0], "got \"%s\"\n", sid );
13591             ok( !len, "unexpected length %u\n", len );
13592             found1 = TRUE;
13593             if (found2) break;
13594         }
13595         if (!strcmp( comp2, guid ))
13596         {
13597             ok( context == MSIINSTALLCONTEXT_USERUNMANAGED, "got %u\n", context );
13598             ok( sid[0], "empty sid\n" );
13599             ok( len == strlen(sid), "unexpected length %u\n", len );
13600             found2 = TRUE;
13601             if (found1) break;
13602         }
13603         index++;
13604         guid[0] = 0;
13605         context = 0xdeadbeef;
13606         sid[0] = 0;
13607         len = sizeof(sid);
13608     }
13609     ok( found1, "comp1 not found\n" );
13610     ok( found2, "comp2 not found\n" );
13611 
13612     r = pMsiEnumComponentsExA( NULL, 0, 0, NULL, NULL, NULL, NULL );
13613     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13614 
13615     r = pMsiEnumComponentsExA( NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, NULL );
13616     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13617 
13618 done:
13619     RegDeleteValueA( key2, comp_squashed2 );
13620     delete_key( key1, "", access );
13621     delete_key( key2, "", access );
13622     RegCloseKey( key1 );
13623     RegCloseKey( key2 );
13624     LocalFree( usersid );
13625 }
13626 
13627 static void test_MsiConfigureProductEx(void)
13628 {
13629     UINT r;
13630     LONG res;
13631     DWORD type, size;
13632     HKEY props, source;
13633     CHAR keypath[MAX_PATH * 2], localpackage[MAX_PATH], packagename[MAX_PATH];
13634     REGSAM access = KEY_ALL_ACCESS;
13635 
13636     if (is_process_limited())
13637     {
13638         skip("process is limited\n");
13639         return;
13640     }
13641 
13642     CreateDirectoryA("msitest", NULL);
13643     create_file_data("msitest\\hydrogen", "hydrogen", 500);
13644     create_file_data("msitest\\helium", "helium", 500);
13645     create_file_data("msitest\\lithium", "lithium", 500);
13646 
13647     create_database(msifile, mcp_tables, ARRAY_SIZE(mcp_tables));
13648 
13649     if (is_wow64)
13650         access |= KEY_WOW64_64KEY;
13651 
13652     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
13653 
13654     /* NULL szProduct */
13655     r = MsiConfigureProductExA(NULL, INSTALLLEVEL_DEFAULT,
13656                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
13657     ok(r == ERROR_INVALID_PARAMETER,
13658        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
13659 
13660     /* empty szProduct */
13661     r = MsiConfigureProductExA("", INSTALLLEVEL_DEFAULT,
13662                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
13663     ok(r == ERROR_INVALID_PARAMETER,
13664        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
13665 
13666     /* garbage szProduct */
13667     r = MsiConfigureProductExA("garbage", INSTALLLEVEL_DEFAULT,
13668                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
13669     ok(r == ERROR_INVALID_PARAMETER,
13670        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
13671 
13672     /* guid without brackets */
13673     r = MsiConfigureProductExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
13674                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13675                                "PROPVAR=42");
13676     ok(r == ERROR_INVALID_PARAMETER,
13677        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
13678 
13679     /* guid with brackets */
13680     r = MsiConfigureProductExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
13681                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13682                                "PROPVAR=42");
13683     ok(r == ERROR_UNKNOWN_PRODUCT,
13684        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
13685 
13686     /* same length as guid, but random */
13687     r = MsiConfigureProductExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
13688                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13689                                "PROPVAR=42");
13690     ok(r == ERROR_UNKNOWN_PRODUCT,
13691        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
13692 
13693     /* product not installed yet */
13694     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
13695                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13696                                "PROPVAR=42");
13697     ok(r == ERROR_UNKNOWN_PRODUCT,
13698        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
13699 
13700     /* install the product, per-user unmanaged */
13701     r = MsiInstallProductA(msifile, "INSTALLLEVEL=10 PROPVAR=42");
13702     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
13703     {
13704         skip("Not enough rights to perform tests\n");
13705         goto error;
13706     }
13707     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13708     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13709     ok(pf_exists("msitest\\helium"), "File not installed\n");
13710     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13711     ok(pf_exists("msitest"), "File not installed\n");
13712 
13713     /* product is installed per-user managed, remove it */
13714     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13715                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13716                                "PROPVAR=42");
13717     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13718     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
13719     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
13720     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
13721     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
13722 
13723     /* product has been removed */
13724     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13725                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13726                                "PROPVAR=42");
13727     ok(r == ERROR_UNKNOWN_PRODUCT,
13728        "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
13729 
13730     /* install the product, machine */
13731     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
13732     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13733     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13734     ok(pf_exists("msitest\\helium"), "File not installed\n");
13735     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13736     ok(pf_exists("msitest"), "File not installed\n");
13737 
13738     /* product is installed machine, remove it */
13739     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13740                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13741                                "PROPVAR=42");
13742     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13743     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
13744     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
13745     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
13746     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
13747 
13748     /* product has been removed */
13749     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13750                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13751                                "PROPVAR=42");
13752     ok(r == ERROR_UNKNOWN_PRODUCT,
13753        "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
13754 
13755     /* install the product, machine */
13756     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
13757     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13758     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13759     ok(pf_exists("msitest\\helium"), "File not installed\n");
13760     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13761     ok(pf_exists("msitest"), "File not installed\n");
13762 
13763     DeleteFileA(msifile);
13764 
13765     /* msifile is removed */
13766     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13767                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13768                                "PROPVAR=42");
13769     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13770     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
13771     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
13772     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
13773     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
13774 
13775     create_database(msifile, mcp_tables, ARRAY_SIZE(mcp_tables));
13776 
13777     /* install the product, machine */
13778     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
13779     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13780     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13781     ok(pf_exists("msitest\\helium"), "File not installed\n");
13782     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13783     ok(pf_exists("msitest"), "File not installed\n");
13784 
13785     DeleteFileA(msifile);
13786 
13787     lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
13788     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
13789     lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\InstallProperties");
13790 
13791     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &props);
13792     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13793 
13794     type = REG_SZ;
13795     size = MAX_PATH;
13796     res = RegQueryValueExA(props, "LocalPackage", NULL, &type,
13797                            (LPBYTE)localpackage, &size);
13798     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13799 
13800     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
13801                          (const BYTE *)"C:\\idontexist.msi", 18);
13802     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13803 
13804     /* LocalPackage is used to find the cached msi package */
13805     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13806                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13807                                "PROPVAR=42");
13808     ok(r == ERROR_INSTALL_SOURCE_ABSENT,
13809        "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
13810     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13811     ok(pf_exists("msitest\\helium"), "File not installed\n");
13812     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13813     ok(pf_exists("msitest"), "File not installed\n");
13814 
13815     RegCloseKey(props);
13816     create_database(msifile, mcp_tables, ARRAY_SIZE(mcp_tables));
13817 
13818     /* LastUsedSource can be used as a last resort */
13819     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13820                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13821                                "PROPVAR=42");
13822     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13823     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
13824     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
13825     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
13826     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
13827     DeleteFileA( localpackage );
13828 
13829     /* install the product, machine */
13830     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
13831     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13832     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13833     ok(pf_exists("msitest\\helium"), "File not installed\n");
13834     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13835     ok(pf_exists("msitest"), "File not installed\n");
13836 
13837     lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
13838     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
13839     lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\InstallProperties");
13840 
13841     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &props);
13842     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13843 
13844     type = REG_SZ;
13845     size = MAX_PATH;
13846     res = RegQueryValueExA(props, "LocalPackage", NULL, &type,
13847                            (LPBYTE)localpackage, &size);
13848     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13849 
13850     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
13851                          (const BYTE *)"C:\\idontexist.msi", 18);
13852     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13853 
13854     lstrcpyA(keypath, "SOFTWARE\\Classes\\Installer\\Products\\");
13855     lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\SourceList");
13856 
13857     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &source);
13858     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13859 
13860     type = REG_SZ;
13861     size = MAX_PATH;
13862     res = RegQueryValueExA(source, "PackageName", NULL, &type,
13863                            (LPBYTE)packagename, &size);
13864     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13865 
13866     res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
13867                          (const BYTE *)"idontexist.msi", 15);
13868     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13869 
13870     /* SourceList is altered */
13871     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13872                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13873                                "PROPVAR=42");
13874     ok(r == ERROR_INSTALL_SOURCE_ABSENT,
13875        "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
13876     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13877     ok(pf_exists("msitest\\helium"), "File not installed\n");
13878     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13879     ok(pf_exists("msitest"), "File not installed\n");
13880 
13881     /* restore PackageName */
13882     res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
13883                          (const BYTE *)packagename, lstrlenA(packagename) + 1);
13884     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13885 
13886     /* restore LocalPackage */
13887     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
13888                          (const BYTE *)localpackage, lstrlenA(localpackage) + 1);
13889     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13890 
13891     /* finally remove the product */
13892     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13893                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13894                                "PROPVAR=42");
13895     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13896     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
13897     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
13898     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
13899     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
13900 
13901     RegCloseKey(source);
13902     RegCloseKey(props);
13903 
13904 error:
13905     DeleteFileA("msitest\\hydrogen");
13906     DeleteFileA("msitest\\helium");
13907     DeleteFileA("msitest\\lithium");
13908     RemoveDirectoryA("msitest");
13909     DeleteFileA(msifile);
13910 }
13911 
13912 static void test_MsiSetFeatureAttributes(void)
13913 {
13914     UINT r;
13915     DWORD attrs;
13916     char path[MAX_PATH];
13917     MSIHANDLE package;
13918 
13919     if (is_process_limited())
13920     {
13921         skip("process is limited\n");
13922         return;
13923     }
13924     create_database( msifile, tables, ARRAY_SIZE( tables ));
13925 
13926     strcpy( path, CURR_DIR );
13927     strcat( path, "\\" );
13928     strcat( path, msifile );
13929 
13930     r = MsiOpenPackageA( path, &package );
13931     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
13932     {
13933         skip("Not enough rights to perform tests\n");
13934         DeleteFileA( msifile );
13935         return;
13936     }
13937     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13938 
13939     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
13940     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %u\n", r);
13941 
13942     r = MsiDoActionA( package, "CostInitialize" );
13943     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13944 
13945     r = MsiSetFeatureAttributesA( 0, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
13946     ok(r == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", r);
13947 
13948     r = MsiSetFeatureAttributesA( package, "", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
13949     ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
13950 
13951     r = MsiSetFeatureAttributesA( package, NULL, INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
13952     ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
13953 
13954     r = MsiSetFeatureAttributesA( package, "One", 0 );
13955     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13956 
13957     attrs = 0xdeadbeef;
13958     r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL );
13959     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13960     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL,
13961        "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got 0x%08x\n", attrs);
13962 
13963     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
13964     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13965 
13966     attrs = 0;
13967     r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL );
13968     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13969     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL,
13970        "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got 0x%08x\n", attrs);
13971 
13972     r = MsiDoActionA( package, "FileCost" );
13973     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13974 
13975     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORSOURCE );
13976     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13977 
13978     attrs = 0;
13979     r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL );
13980     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13981     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORSOURCE,
13982        "expected INSTALLFEATUREATTRIBUTE_FAVORSOURCE, got 0x%08x\n", attrs);
13983 
13984     r = MsiDoActionA( package, "CostFinalize" );
13985     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13986 
13987     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
13988     ok(r == ERROR_FUNCTION_FAILED, "expected ERROR_FUNCTION_FAILED, got %u\n", r);
13989 
13990     MsiCloseHandle( package );
13991     DeleteFileA( msifile );
13992 }
13993 
13994 static void test_MsiGetFeatureInfo(void)
13995 {
13996     UINT r;
13997     MSIHANDLE package;
13998     char title[32], help[32], path[MAX_PATH];
13999     DWORD attrs, title_len, help_len;
14000 
14001     if (is_process_limited())
14002     {
14003         skip("process is limited\n");
14004         return;
14005     }
14006     create_database( msifile, tables, ARRAY_SIZE( tables ));
14007 
14008     strcpy( path, CURR_DIR );
14009     strcat( path, "\\" );
14010     strcat( path, msifile );
14011 
14012     r = MsiOpenPackageA( path, &package );
14013     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14014     {
14015         skip("Not enough rights to perform tests\n");
14016         DeleteFileA( msifile );
14017         return;
14018     }
14019     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14020 
14021     r = MsiGetFeatureInfoA( 0, NULL, NULL, NULL, NULL, NULL, NULL );
14022     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
14023 
14024     r = MsiGetFeatureInfoA( package, NULL, NULL, NULL, NULL, NULL, NULL );
14025     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
14026 
14027     r = MsiGetFeatureInfoA( package, "", NULL, NULL, NULL, NULL, NULL );
14028     ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
14029 
14030     r = MsiGetFeatureInfoA( package, "One", NULL, NULL, NULL, NULL, NULL );
14031     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14032 
14033     r = MsiGetFeatureInfoA( 0, "One", NULL, NULL, NULL, NULL, NULL );
14034     ok(r == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", r);
14035 
14036     title_len = help_len = 0;
14037     r = MsiGetFeatureInfoA( package, "One", NULL, NULL, &title_len, NULL, &help_len );
14038     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14039     ok(title_len == 3, "expected 3, got %u\n", title_len);
14040     ok(help_len == 3, "expected 3, got %u\n", help_len);
14041 
14042     title[0] = help[0] = 0;
14043     title_len = help_len = 0;
14044     r = MsiGetFeatureInfoA( package, "One", NULL, title, &title_len, help, &help_len );
14045     ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %u\n", r);
14046     ok(title_len == 3, "expected 3, got %u\n", title_len);
14047     ok(help_len == 3, "expected 3, got %u\n", help_len);
14048 
14049     attrs = 0;
14050     title[0] = help[0] = 0;
14051     title_len = sizeof(title);
14052     help_len = sizeof(help);
14053     r = MsiGetFeatureInfoA( package, "One", &attrs, title, &title_len, help, &help_len );
14054     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14055     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %u\n", attrs);
14056     ok(title_len == 3, "expected 3, got %u\n", title_len);
14057     ok(help_len == 3, "expected 3, got %u\n", help_len);
14058     ok(!strcmp(title, "One"), "expected \"One\", got \"%s\"\n", title);
14059     ok(!strcmp(help, "One"), "expected \"One\", got \"%s\"\n", help);
14060 
14061     attrs = 0;
14062     title[0] = help[0] = 0;
14063     title_len = sizeof(title);
14064     help_len = sizeof(help);
14065     r = MsiGetFeatureInfoA( package, "Two", &attrs, title, &title_len, help, &help_len );
14066     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14067     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %u\n", attrs);
14068     ok(!title_len, "expected 0, got %u\n", title_len);
14069     ok(!help_len, "expected 0, got %u\n", help_len);
14070     ok(!title[0], "expected \"\", got \"%s\"\n", title);
14071     ok(!help[0], "expected \"\", got \"%s\"\n", help);
14072 
14073     MsiCloseHandle( package );
14074     DeleteFileA( msifile );
14075 }
14076 
14077 static INT CALLBACK handler_a(LPVOID context, UINT type, LPCSTR msg)
14078 {
14079     return IDOK;
14080 }
14081 
14082 static INT CALLBACK handler_w(LPVOID context, UINT type, LPCWSTR msg)
14083 {
14084     return IDOK;
14085 }
14086 
14087 static INT CALLBACK handler_record(LPVOID context, UINT type, MSIHANDLE record)
14088 {
14089     return IDOK;
14090 }
14091 
14092 static void test_MsiSetInternalUI(void)
14093 {
14094     INSTALLUILEVEL level;
14095 
14096     level = MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
14097     ok(level == INSTALLUILEVEL_DEFAULT, "expected INSTALLUILEVEL_DEFAULT, got %d\n", level);
14098 
14099     level = MsiSetInternalUI(INSTALLUILEVEL_DEFAULT, NULL);
14100     ok(level == INSTALLUILEVEL_FULL, "expected INSTALLUILEVEL_FULL, got %d\n", level);
14101 
14102     level = MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE, NULL);
14103     ok(level == INSTALLUILEVEL_DEFAULT, "expected INSTALLUILEVEL_DEFAULT, got %d\n", level);
14104 
14105     level = MsiSetInternalUI(0xdeadbeef, NULL);
14106     ok(level == INSTALLUILEVEL_NOCHANGE, "expected INSTALLUILEVEL_NOCHANGE, got %d\n", level);
14107 }
14108 
14109 static void test_MsiSetExternalUI(void)
14110 {
14111     INSTALLUI_HANDLERA ret_a;
14112     INSTALLUI_HANDLERW ret_w;
14113     INSTALLUI_HANDLER_RECORD prev;
14114     UINT error;
14115 
14116     ret_a = MsiSetExternalUIA(handler_a, INSTALLLOGMODE_ERROR, NULL);
14117     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
14118 
14119     ret_a = MsiSetExternalUIA(NULL, 0, NULL);
14120     ok(ret_a == handler_a, "expected %p, got %p\n", handler_a, ret_a);
14121 
14122     /* Not present before Installer 3.1 */
14123     if (!pMsiSetExternalUIRecord) {
14124         win_skip("MsiSetExternalUIRecord is not available\n");
14125         return;
14126     }
14127 
14128     error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, &prev);
14129     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14130     ok(prev == NULL, "expected NULL, got %p\n", prev);
14131 
14132     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
14133     error = pMsiSetExternalUIRecord(NULL, INSTALLLOGMODE_ERROR, NULL, &prev);
14134     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14135     ok(prev == handler_record, "expected %p, got %p\n", handler_record, prev);
14136 
14137     ret_w = MsiSetExternalUIW(handler_w, INSTALLLOGMODE_ERROR, NULL);
14138     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
14139 
14140     ret_w = MsiSetExternalUIW(NULL, 0, NULL);
14141     ok(ret_w == handler_w, "expected %p, got %p\n", handler_w, ret_w);
14142 
14143     ret_a = MsiSetExternalUIA(handler_a, INSTALLLOGMODE_ERROR, NULL);
14144     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
14145 
14146     ret_w = MsiSetExternalUIW(handler_w, INSTALLLOGMODE_ERROR, NULL);
14147     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
14148 
14149     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
14150     error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, &prev);
14151     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14152     ok(prev == NULL, "expected NULL, got %p\n", prev);
14153 
14154     ret_a = MsiSetExternalUIA(NULL, 0, NULL);
14155     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
14156 
14157     ret_w = MsiSetExternalUIW(NULL, 0, NULL);
14158     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
14159 
14160     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
14161     error = pMsiSetExternalUIRecord(NULL, 0, NULL, &prev);
14162     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14163     ok(prev == handler_record, "expected %p, got %p\n", handler_record, prev);
14164 
14165     error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, NULL);
14166     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14167 
14168     error = pMsiSetExternalUIRecord(NULL, 0, NULL, NULL);
14169     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14170 }
14171 
14172 static void test_lastusedsource(void)
14173 {
14174     static const char prodcode[] = "{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}";
14175     char value[MAX_PATH], path[MAX_PATH];
14176     DWORD size;
14177     UINT r;
14178 
14179     if (!pMsiSourceListGetInfoA)
14180     {
14181         win_skip("MsiSourceListGetInfoA is not available\n");
14182         return;
14183     }
14184 
14185     CreateDirectoryA("msitest", NULL);
14186     create_file("maximus", 500);
14187     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
14188     DeleteFileA("maximus");
14189 
14190     create_database("msifile0.msi", lus0_tables, ARRAY_SIZE(lus0_tables));
14191     create_database("msifile1.msi", lus1_tables, ARRAY_SIZE(lus1_tables));
14192     create_database("msifile2.msi", lus2_tables, ARRAY_SIZE(lus2_tables));
14193 
14194     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
14195 
14196     /* no cabinet file */
14197 
14198     size = MAX_PATH;
14199     lstrcpyA(value, "aaa");
14200     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14201                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14202     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14203     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
14204 
14205     r = MsiInstallProductA("msifile0.msi", "PUBLISH_PRODUCT=1");
14206     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14207     {
14208         skip("Not enough rights to perform tests\n");
14209         goto error;
14210     }
14211     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14212 
14213     lstrcpyA(path, CURR_DIR);
14214     lstrcatA(path, "\\");
14215 
14216     size = MAX_PATH;
14217     lstrcpyA(value, "aaa");
14218     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14219                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14220     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14221     ok(!lstrcmpA(value, path), "expected \"%s\", got \"%s\"\n", path, value);
14222     ok(size == lstrlenA(path), "expected %d, got %d\n", lstrlenA(path), size);
14223 
14224     r = MsiInstallProductA("msifile0.msi", "REMOVE=ALL FULL=1");
14225     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14226 
14227     /* separate cabinet file */
14228 
14229     size = MAX_PATH;
14230     lstrcpyA(value, "aaa");
14231     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14232                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14233     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14234     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
14235 
14236     r = MsiInstallProductA("msifile1.msi", "PUBLISH_PRODUCT=1");
14237     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14238 
14239     lstrcpyA(path, CURR_DIR);
14240     lstrcatA(path, "\\");
14241 
14242     size = MAX_PATH;
14243     lstrcpyA(value, "aaa");
14244     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14245                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14246     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14247     ok(!lstrcmpA(value, path), "expected \"%s\", got \"%s\"\n", path, value);
14248     ok(size == lstrlenA(path), "expected %d, got %d\n", lstrlenA(path), size);
14249 
14250     r = MsiInstallProductA("msifile1.msi", "REMOVE=ALL FULL=1");
14251     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14252 
14253     size = MAX_PATH;
14254     lstrcpyA(value, "aaa");
14255     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14256                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14257     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14258     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
14259 
14260     /* embedded cabinet stream */
14261 
14262     add_cabinet_storage("msifile2.msi", "test1.cab");
14263 
14264     r = MsiInstallProductA("msifile2.msi", "PUBLISH_PRODUCT=1");
14265     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14266 
14267     size = MAX_PATH;
14268     lstrcpyA(value, "aaa");
14269     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14270                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14271     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14272     ok(!lstrcmpA(value, path), "expected \"%s\", got \"%s\"\n", path, value);
14273     ok(size == lstrlenA(path), "expected %d, got %d\n", lstrlenA(path), size);
14274 
14275     r = MsiInstallProductA("msifile2.msi", "REMOVE=ALL FULL=1");
14276     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14277 
14278     size = MAX_PATH;
14279     lstrcpyA(value, "aaa");
14280     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14281                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14282     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14283     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
14284 
14285 error:
14286     delete_cab_files();
14287     DeleteFileA("msitest\\maximus");
14288     RemoveDirectoryA("msitest");
14289     DeleteFileA("msifile0.msi");
14290     DeleteFileA("msifile1.msi");
14291     DeleteFileA("msifile2.msi");
14292 }
14293 
14294 static void test_setpropertyfolder(void)
14295 {
14296     UINT r;
14297 
14298     if (is_process_limited())
14299     {
14300         skip("process is limited\n");
14301         return;
14302     }
14303 
14304     CreateDirectoryA("msitest", NULL);
14305     create_file("msitest\\maximus", 500);
14306 
14307     create_database(msifile, spf_tables, ARRAY_SIZE(spf_tables));
14308 
14309     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
14310 
14311     r = MsiInstallProductA(msifile, NULL);
14312     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14313     {
14314         skip("Not enough rights to perform tests\n");
14315         goto error;
14316     }
14317     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14318     ok(delete_pf("msitest\\added\\added2\\maximus", TRUE), "File not installed\n");
14319     ok(delete_pf("msitest\\added\\added2", FALSE), "Directory not created\n");
14320     ok(delete_pf("msitest\\added", FALSE), "Directory not created\n");
14321     ok(delete_pf("msitest", FALSE), "Directory not created\n");
14322 
14323     CreateDirectoryA("parent", NULL);
14324     CreateDirectoryA("parent\\child", NULL);
14325     create_file("parent\\child\\maximus", 500);
14326 
14327     create_database(msifile, spf2_tables, ARRAY_SIZE(spf2_tables));
14328 
14329     r = MsiInstallProductA(msifile, "TARGETDIR=c:\\");
14330     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14331 
14332     ok(delete_pf("msitest\\maximus", TRUE), "file not installed\n");
14333     ok(delete_pf("msitest", FALSE), "directory not created\n");
14334 
14335     ok(DeleteFileA("c:\\parent\\child\\Shortcut.lnk"), "file not installed\n");
14336     ok(RemoveDirectoryA("c:\\parent\\child"), "directory not created\n");
14337     ok(RemoveDirectoryA("c:\\parent"), "directory not created\n");
14338 
14339     DeleteFileA("parent\\child\\maximus");
14340     RemoveDirectoryA("parent\\child");
14341     RemoveDirectoryA("parent");
14342 
14343 error:
14344     DeleteFileA(msifile);
14345     DeleteFileA("msitest\\maximus");
14346     RemoveDirectoryA("msitest");
14347 }
14348 
14349 static void test_sourcedir_props(void)
14350 {
14351     UINT r;
14352 
14353     if (is_process_limited())
14354     {
14355         skip("process is limited\n");
14356         return;
14357     }
14358 
14359     create_test_files();
14360     create_file("msitest\\sourcedir.txt", 1000);
14361     create_database(msifile, sd_tables, ARRAY_SIZE(sd_tables));
14362 
14363     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
14364 
14365     /* full UI, no ResolveSource action */
14366     r = MsiInstallProductA(msifile, NULL);
14367     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14368 
14369     r = MsiInstallProductA(msifile, "REMOVE=ALL");
14370     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14371 
14372     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
14373     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
14374 
14375     /* full UI, ResolveSource action */
14376     r = MsiInstallProductA(msifile, "ResolveSource=1");
14377     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14378 
14379     r = MsiInstallProductA(msifile, "REMOVE=ALL");
14380     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14381 
14382     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
14383     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
14384 
14385     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
14386 
14387     /* no UI, no ResolveSource action */
14388     r = MsiInstallProductA(msifile, NULL);
14389     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14390 
14391     r = MsiInstallProductA(msifile, "REMOVE=ALL");
14392     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14393 
14394     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
14395     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
14396 
14397     /* no UI, ResolveSource action */
14398     r = MsiInstallProductA(msifile, "ResolveSource=1");
14399     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14400 
14401     r = MsiInstallProductA(msifile, "REMOVE=ALL");
14402     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14403 
14404     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
14405     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
14406 
14407     DeleteFileA("msitest\\sourcedir.txt");
14408     delete_test_files();
14409     DeleteFileA(msifile);
14410 }
14411 
14412 static void test_concurrentinstall(void)
14413 {
14414     UINT r;
14415     CHAR path[MAX_PATH];
14416 
14417     if (is_process_limited())
14418     {
14419         skip("process is limited\n");
14420         return;
14421     }
14422 
14423     CreateDirectoryA("msitest", NULL);
14424     CreateDirectoryA("msitest\\msitest", NULL);
14425     create_file("msitest\\maximus", 500);
14426     create_file("msitest\\msitest\\augustus", 500);
14427 
14428     create_database(msifile, ci_tables, ARRAY_SIZE(ci_tables));
14429 
14430     lstrcpyA(path, CURR_DIR);
14431     lstrcatA(path, "\\msitest\\concurrent.msi");
14432     create_database(path, ci2_tables, ARRAY_SIZE(ci2_tables));
14433 
14434     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
14435 
14436     r = MsiInstallProductA(msifile, NULL);
14437     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14438     {
14439         skip("Not enough rights to perform tests\n");
14440         goto error;
14441     }
14442     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14443     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
14444     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
14445     ok(delete_pf("msitest", FALSE), "Directory not created\n");
14446 
14447     r = MsiConfigureProductA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", INSTALLLEVEL_DEFAULT,
14448                              INSTALLSTATE_ABSENT);
14449     ok(r == ERROR_SUCCESS, "got %u\n", r);
14450 
14451     r = MsiConfigureProductA("{FF4AFE9C-6AC2-44F9-A060-9EA6BD16C75E}", INSTALLLEVEL_DEFAULT,
14452                              INSTALLSTATE_ABSENT);
14453     ok(r == ERROR_SUCCESS, "got %u\n", r);
14454 
14455 error:
14456     DeleteFileA(path);
14457     DeleteFileA(msifile);
14458     DeleteFileA("msitest\\msitest\\augustus");
14459     DeleteFileA("msitest\\maximus");
14460     RemoveDirectoryA("msitest\\msitest");
14461     RemoveDirectoryA("msitest");
14462 }
14463 
14464 static void test_command_line_parsing(void)
14465 {
14466     UINT r;
14467     const char *cmd;
14468 
14469     if (is_process_limited())
14470     {
14471         skip("process is limited\n");
14472         return;
14473     }
14474 
14475     create_test_files();
14476     create_database(msifile, cl_tables, ARRAY_SIZE(cl_tables));
14477 
14478     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
14479 
14480     cmd = " ";
14481     r = MsiInstallProductA(msifile, cmd);
14482     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14483 
14484     cmd = "=";
14485     r = MsiInstallProductA(msifile, cmd);
14486     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14487 
14488     cmd = "==";
14489     r = MsiInstallProductA(msifile, cmd);
14490     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14491 
14492     cmd = "one";
14493     r = MsiInstallProductA(msifile, cmd);
14494     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14495 
14496     cmd = "=one";
14497     r = MsiInstallProductA(msifile, cmd);
14498     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14499 
14500     cmd = "P=";
14501     r = MsiInstallProductA(msifile, cmd);
14502     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14503 
14504     cmd = "  P=";
14505     r = MsiInstallProductA(msifile, cmd);
14506     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14507 
14508     cmd = "P=  ";
14509     r = MsiInstallProductA(msifile, cmd);
14510     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14511 
14512     cmd = "P=\"";
14513     r = MsiInstallProductA(msifile, cmd);
14514     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14515 
14516     cmd = "P=\"\"";
14517     r = MsiInstallProductA(msifile, cmd);
14518     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14519 
14520     cmd = "P=\"\"\"";
14521     r = MsiInstallProductA(msifile, cmd);
14522     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14523 
14524     cmd = "P=\"\"\"\"";
14525     r = MsiInstallProductA(msifile, cmd);
14526     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14527 
14528     cmd = "P=\" ";
14529     r = MsiInstallProductA(msifile, cmd);
14530     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14531 
14532     cmd = "P= \"";
14533     r = MsiInstallProductA(msifile, cmd);
14534     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14535 
14536     cmd = "P= \"\" ";
14537     r = MsiInstallProductA(msifile, cmd);
14538     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14539 
14540     cmd = "P=\"  \"";
14541     r = MsiInstallProductA(msifile, cmd);
14542     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14543 
14544     cmd = "P=one";
14545     r = MsiInstallProductA(msifile, cmd);
14546     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14547 
14548     cmd = "P= one";
14549     r = MsiInstallProductA(msifile, cmd);
14550     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14551 
14552     cmd = "P=\"one";
14553     r = MsiInstallProductA(msifile, cmd);
14554     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14555 
14556     cmd = "P=one\"";
14557     r = MsiInstallProductA(msifile, cmd);
14558     todo_wine ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14559 
14560     cmd = "P=\"one\"";
14561     r = MsiInstallProductA(msifile, cmd);
14562     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14563 
14564     cmd = "P= \"one\" ";
14565     r = MsiInstallProductA(msifile, cmd);
14566     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14567 
14568     cmd = "P=\"one\"\"";
14569     r = MsiInstallProductA(msifile, cmd);
14570     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14571 
14572     cmd = "P=\"\"one\"";
14573     r = MsiInstallProductA(msifile, cmd);
14574     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14575 
14576     cmd = "P=\"\"one\"\"";
14577     r = MsiInstallProductA(msifile, cmd);
14578     todo_wine ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14579 
14580     cmd = "P=\"one two\"";
14581     r = MsiInstallProductA(msifile, cmd);
14582     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14583 
14584     cmd = "P=\"\"\"one\"\" two\"";
14585     r = MsiInstallProductA(msifile, cmd);
14586     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14587 
14588     cmd = "P=\"\"\"one\"\" two\" Q=three";
14589     r = MsiInstallProductA(msifile, cmd);
14590     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14591 
14592     cmd = "P=\"\" Q=\"two\"";
14593     r = MsiInstallProductA(msifile, cmd);
14594     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14595 
14596     cmd = "P=\"one\" Q=\"two\"";
14597     r = MsiInstallProductA(msifile, cmd);
14598     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14599 
14600     cmd = "P=\"one=two\"";
14601     r = MsiInstallProductA(msifile, cmd);
14602     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14603 
14604     cmd = "Q=\"\" P=\"one\"";
14605     r = MsiInstallProductA(msifile, cmd);
14606     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14607 
14608     cmd = "P=\"\"\"one\"\"\" Q=\"two\"";
14609     r = MsiInstallProductA(msifile, cmd);
14610     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14611 
14612     cmd = "P=\"one \"\"two\"\"\" Q=\"three\"";
14613     r = MsiInstallProductA(msifile, cmd);
14614     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14615 
14616     cmd = "P=\"\"\"one\"\" two\" Q=\"three\"";
14617     r = MsiInstallProductA(msifile, cmd);
14618     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14619 
14620     DeleteFileA(msifile);
14621     delete_test_files();
14622 }
14623 
14624 START_TEST(msi)
14625 {
14626     DWORD len;
14627     char temp_path[MAX_PATH], prev_path[MAX_PATH];
14628 
14629 #ifdef __REACTOS__
14630     if (!winetest_interactive &&
14631         !strcmp(winetest_platform, "windows"))
14632     {
14633         skip("ROSTESTS-180: Skipping msi_winetest:msi because it hangs on WHS-Testbot. Set winetest_interactive to run it anyway.\n");
14634         return;
14635     }
14636 #endif
14637 
14638     init_functionpointers();
14639 
14640     if (pIsWow64Process)
14641         pIsWow64Process(GetCurrentProcess(), &is_wow64);
14642 
14643     GetCurrentDirectoryA(MAX_PATH, prev_path);
14644     GetTempPathA(MAX_PATH, temp_path);
14645     SetCurrentDirectoryA(temp_path);
14646 
14647     lstrcpyA(CURR_DIR, temp_path);
14648     len = lstrlenA(CURR_DIR);
14649 
14650     if(len && (CURR_DIR[len - 1] == '\\'))
14651         CURR_DIR[len - 1] = 0;
14652 
14653     ok(get_system_dirs(), "failed to retrieve system dirs\n");
14654 
14655     test_usefeature();
14656     test_null();
14657     test_getcomponentpath();
14658     test_MsiGetFileHash();
14659     test_MsiSetInternalUI();
14660     test_MsiSetExternalUI();
14661     test_MsiQueryProductState();
14662     test_MsiQueryFeatureState();
14663     test_MsiQueryComponentState();
14664     test_MsiGetComponentPath();
14665     test_MsiGetComponentPathEx();
14666     test_MsiProvideComponent();
14667     test_MsiGetProductCode();
14668     test_MsiEnumClients();
14669     test_MsiGetProductInfo();
14670     test_MsiGetProductInfoEx();
14671     test_MsiGetUserInfo();
14672     test_MsiOpenProduct();
14673     test_MsiEnumPatchesEx();
14674     test_MsiEnumPatches();
14675     test_MsiGetPatchInfoEx();
14676     test_MsiGetPatchInfo();
14677     test_MsiEnumProducts();
14678     test_MsiEnumProductsEx();
14679     test_MsiEnumComponents();
14680     test_MsiEnumComponentsEx();
14681     test_MsiGetFileVersion();
14682     test_MsiGetFileSignatureInformation();
14683     test_MsiConfigureProductEx();
14684     test_MsiSetFeatureAttributes();
14685     test_MsiGetFeatureInfo();
14686     test_lastusedsource();
14687     test_setpropertyfolder();
14688     test_sourcedir_props();
14689     if (pMsiGetComponentPathExA)
14690         test_concurrentinstall();
14691     test_command_line_parsing();
14692     test_MsiProvideQualifiedComponentEx();
14693 
14694     SetCurrentDirectoryA(prev_path);
14695 }
14696