xref: /reactos/modules/rostests/winetests/msi/msi.c (revision 7e22dc05)
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[] = L"winetest.msi";
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 + 72];
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         if (!(lpData = malloc(cbData))) skip("Out of memory\n");
970         else
971         {
972             r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
973             ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
974         }
975     }
976 
977     r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
978     if (r == ERROR_ACCESS_DENIED)
979     {
980         skip("Not enough rights to perform tests\n");
981         free(lpData);
982         RegCloseKey(hkey);
983         return;
984     }
985     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
986 
987     r = MsiGetProductInfoA("", "", NULL, NULL);
988     ok ( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
989 
990     if (lpData)
991     {
992         r = RegSetValueExA(hkey, NULL, 0, dwType, lpData, cbData);
993         ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
994         free(lpData);
995     }
996     else
997     {
998         r = RegDeleteValueA(hkey, NULL);
999         ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
1000     }
1001 
1002     r = RegCloseKey(hkey);
1003     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1004 
1005     /* empty attribute */
1006     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}",
1007                         0, NULL, 0, access, NULL, &hkey, NULL);
1008     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1009 
1010     r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
1011     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1012 
1013     r = MsiGetProductInfoA("{F1C3AF50-8B56-4A69-A00C-00773FE42F30}", "", NULL, NULL);
1014     ok ( r == ERROR_UNKNOWN_PROPERTY, "wrong error %d\n", r);
1015 
1016     r = RegCloseKey(hkey);
1017     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1018 
1019     r = delete_key(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}",
1020                    access & KEY_WOW64_64KEY);
1021     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1022 }
1023 
1024 static void test_getcomponentpath(void)
1025 {
1026     INSTALLSTATE r;
1027     char buffer[0x100];
1028     DWORD sz;
1029 
1030     if(!pMsiGetComponentPathA)
1031         return;
1032 
1033     r = pMsiGetComponentPathA( NULL, NULL, NULL, NULL );
1034     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1035 
1036     r = pMsiGetComponentPathA( "bogus", "bogus", NULL, NULL );
1037     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1038 
1039     r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", NULL, NULL );
1040     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1041 
1042     sz = sizeof buffer;
1043     buffer[0]=0;
1044     r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", buffer, &sz );
1045     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1046 
1047     r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C998E7}",
1048         "{00000000-0000-0000-0000-000000000000}", buffer, &sz );
1049     ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
1050 
1051     r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
1052         "{00000000-0000-0000-0000-00000000}", buffer, &sz );
1053     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1054 
1055     r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
1056         "{029E403D-A86A-1D11-5B5B0006799C897E}", buffer, &sz );
1057     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1058 
1059     r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C9987e}",
1060                             "{00000000-A68A-11d1-5B5B-0006799C897E}", buffer, &sz );
1061     ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
1062 }
1063 
1064 static void create_test_files(void)
1065 {
1066     CreateDirectoryA("msitest", NULL);
1067     create_file("msitest\\one.txt", 100);
1068     CreateDirectoryA("msitest\\first", NULL);
1069     create_file("msitest\\first\\two.txt", 100);
1070     CreateDirectoryA("msitest\\second", NULL);
1071     create_file("msitest\\second\\three.txt", 100);
1072 
1073     create_file("four.txt", 100);
1074     create_file("five.txt", 100);
1075     create_cab_file("msitest.cab", MEDIA_SIZE, "four.txt\0five.txt\0");
1076 
1077     create_file("msitest\\filename", 100);
1078     create_file("msitest\\service.exe", 100);
1079 
1080     DeleteFileA("four.txt");
1081     DeleteFileA("five.txt");
1082 }
1083 
1084 static void delete_test_files(void)
1085 {
1086     DeleteFileA("msitest.msi");
1087     DeleteFileA("msitest.cab");
1088     DeleteFileA("msitest\\second\\three.txt");
1089     DeleteFileA("msitest\\first\\two.txt");
1090     DeleteFileA("msitest\\one.txt");
1091     DeleteFileA("msitest\\service.exe");
1092     DeleteFileA("msitest\\filename");
1093     RemoveDirectoryA("msitest\\second");
1094     RemoveDirectoryA("msitest\\first");
1095     RemoveDirectoryA("msitest");
1096 }
1097 
1098 #define HASHSIZE sizeof(MSIFILEHASHINFO)
1099 
1100 static const struct
1101 {
1102     LPCSTR data;
1103     DWORD size;
1104     MSIFILEHASHINFO hash;
1105 } hash_data[] =
1106 {
1107     { "", 0,
1108       { HASHSIZE,
1109         { 0, 0, 0, 0 },
1110       },
1111     },
1112 
1113     { "abc", 0,
1114       { HASHSIZE,
1115         { 0x98500190, 0xb04fd23c, 0x7d3f96d6, 0x727fe128 },
1116       },
1117     },
1118 
1119     { "C:\\Program Files\\msitest\\caesar\n", 0,
1120       { HASHSIZE,
1121         { 0x2b566794, 0xfd42181b, 0x2514d6e4, 0x5768b4e2 },
1122       },
1123     },
1124 
1125     { "C:\\Program Files\\msitest\\caesar\n", 500,
1126       { HASHSIZE,
1127         { 0x58095058, 0x805efeff, 0x10f3483e, 0x0147d653 },
1128       },
1129     },
1130 };
1131 
1132 static void test_MsiGetFileHash(void)
1133 {
1134     const char name[] = "msitest.bin";
1135     UINT r;
1136     MSIFILEHASHINFO hash;
1137     DWORD i;
1138 
1139     if (!pMsiGetFileHashA)
1140     {
1141         win_skip("MsiGetFileHash not implemented\n");
1142         return;
1143     }
1144 
1145     hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
1146 
1147     /* szFilePath is NULL */
1148     r = pMsiGetFileHashA(NULL, 0, &hash);
1149     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1150 
1151     /* szFilePath is empty */
1152     r = pMsiGetFileHashA("", 0, &hash);
1153     ok(r == ERROR_PATH_NOT_FOUND || r == ERROR_BAD_PATHNAME,
1154        "Expected ERROR_PATH_NOT_FOUND or ERROR_BAD_PATHNAME, got %d\n", r);
1155 
1156     /* szFilePath is nonexistent */
1157     r = pMsiGetFileHashA(name, 0, &hash);
1158     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
1159 
1160     /* dwOptions is non-zero */
1161     r = pMsiGetFileHashA(name, 1, &hash);
1162     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1163 
1164     /* pHash.dwFileHashInfoSize is not correct */
1165     hash.dwFileHashInfoSize = 0;
1166     r = pMsiGetFileHashA(name, 0, &hash);
1167     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1168 
1169     /* pHash is NULL */
1170     r = pMsiGetFileHashA(name, 0, NULL);
1171     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1172 
1173     for (i = 0; i < ARRAY_SIZE(hash_data); i++)
1174     {
1175         int ret;
1176 
1177         create_file_data(name, hash_data[i].data, hash_data[i].size);
1178 
1179         memset(&hash, 0, sizeof(MSIFILEHASHINFO));
1180         hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
1181 
1182         r = pMsiGetFileHashA(name, 0, &hash);
1183         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1184 
1185         ret = memcmp(&hash, &hash_data[i].hash, HASHSIZE);
1186         ok(!ret, "Hash incorrect\n");
1187 
1188         DeleteFileA(name);
1189     }
1190 }
1191 
1192 /* copied from dlls/msi/registry.c */
1193 static BOOL squash_guid(LPCWSTR in, LPWSTR out)
1194 {
1195     DWORD i,n=1;
1196     GUID guid;
1197 
1198     if (FAILED(CLSIDFromString((LPCOLESTR)in, &guid)))
1199         return FALSE;
1200 
1201     for(i=0; i<8; i++)
1202         out[7-i] = in[n++];
1203     n++;
1204     for(i=0; i<4; i++)
1205         out[11-i] = in[n++];
1206     n++;
1207     for(i=0; i<4; i++)
1208         out[15-i] = in[n++];
1209     n++;
1210     for(i=0; i<2; i++)
1211     {
1212         out[17+i*2] = in[n++];
1213         out[16+i*2] = in[n++];
1214     }
1215     n++;
1216     for( ; i<8; i++)
1217     {
1218         out[17+i*2] = in[n++];
1219         out[16+i*2] = in[n++];
1220     }
1221     out[32]=0;
1222     return TRUE;
1223 }
1224 
1225 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
1226 {
1227     WCHAR guidW[GUID_SIZE];
1228     WCHAR squashedW[SQUASHED_GUID_SIZE];
1229     GUID guid;
1230     HRESULT hr;
1231     int size;
1232 
1233     hr = CoCreateGuid(&guid);
1234     ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
1235 
1236     size = StringFromGUID2(&guid, guidW, ARRAY_SIZE(guidW));
1237     ok(size == GUID_SIZE, "Expected %d, got %d.\n", GUID_SIZE, size);
1238 
1239     WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, GUID_SIZE, NULL, NULL);
1240     if (squashed)
1241     {
1242         squash_guid(guidW, squashedW);
1243         WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, SQUASHED_GUID_SIZE, NULL, NULL);
1244     }
1245 }
1246 
1247 static char *get_user_sid(void)
1248 {
1249     HANDLE token;
1250     DWORD size = 0;
1251     TOKEN_USER *user;
1252     char *usersid = NULL;
1253 
1254     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
1255     GetTokenInformation(token, TokenUser, NULL, size, &size);
1256 
1257     user = malloc(size);
1258     GetTokenInformation(token, TokenUser, user, size, &size);
1259     ConvertSidToStringSidA(user->User.Sid, &usersid);
1260     free(user);
1261 
1262     CloseHandle(token);
1263     return usersid;
1264 }
1265 
1266 static void test_MsiQueryProductState(void)
1267 {
1268     CHAR prodcode[MAX_PATH];
1269     CHAR prod_squashed[MAX_PATH];
1270     CHAR keypath[MAX_PATH*2];
1271     LPSTR usersid;
1272     INSTALLSTATE state;
1273     LONG res;
1274     HKEY userkey, localkey, props;
1275     HKEY prodkey;
1276     DWORD data, error;
1277     REGSAM access = KEY_ALL_ACCESS;
1278 
1279     create_test_guid(prodcode, prod_squashed);
1280     usersid = get_user_sid();
1281 
1282     if (is_wow64)
1283         access |= KEY_WOW64_64KEY;
1284 
1285     /* NULL prodcode */
1286     SetLastError(0xdeadbeef);
1287     state = MsiQueryProductStateA(NULL);
1288     error = GetLastError();
1289     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1290     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
1291 
1292     /* empty prodcode */
1293     SetLastError(0xdeadbeef);
1294     state = MsiQueryProductStateA("");
1295     error = GetLastError();
1296     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1297     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
1298 
1299     /* garbage prodcode */
1300     SetLastError(0xdeadbeef);
1301     state = MsiQueryProductStateA("garbage");
1302     error = GetLastError();
1303     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1304     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
1305 
1306     /* guid without brackets */
1307     SetLastError(0xdeadbeef);
1308     state = MsiQueryProductStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D");
1309     error = GetLastError();
1310     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1311     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
1312 
1313     /* guid with brackets */
1314     SetLastError(0xdeadbeef);
1315     state = MsiQueryProductStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}");
1316     error = GetLastError();
1317     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1318     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1319 
1320     /* same length as guid, but random */
1321     SetLastError(0xdeadbeef);
1322     state = MsiQueryProductStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93");
1323     error = GetLastError();
1324     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1325     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
1326 
1327     /* MSIINSTALLCONTEXT_USERUNMANAGED */
1328 
1329     SetLastError(0xdeadbeef);
1330     state = MsiQueryProductStateA(prodcode);
1331     error = GetLastError();
1332     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1333     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1334 
1335     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
1336     lstrcatA(keypath, prod_squashed);
1337 
1338     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
1339     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1340 
1341     /* user product key exists */
1342     SetLastError(0xdeadbeef);
1343     state = MsiQueryProductStateA(prodcode);
1344     error = GetLastError();
1345     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1346     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1347 
1348     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
1349     lstrcatA(keypath, prodcode);
1350 
1351     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1352     if (res == ERROR_ACCESS_DENIED)
1353     {
1354         skip("Not enough rights to perform tests\n");
1355         RegDeleteKeyA(userkey, "");
1356         RegCloseKey(userkey);
1357         LocalFree(usersid);
1358         return;
1359     }
1360     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1361 
1362     /* local uninstall key exists */
1363     SetLastError(0xdeadbeef);
1364     state = MsiQueryProductStateA(prodcode);
1365     error = GetLastError();
1366     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1367     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1368 
1369     data = 1;
1370     res = RegSetValueExA(localkey, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1371     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1372 
1373     /* WindowsInstaller value exists */
1374     SetLastError(0xdeadbeef);
1375     state = MsiQueryProductStateA(prodcode);
1376     error = GetLastError();
1377     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1378     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1379 
1380     RegDeleteValueA(localkey, "WindowsInstaller");
1381     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1382 
1383     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1384     lstrcatA(keypath, usersid);
1385     lstrcatA(keypath, "\\Products\\");
1386     lstrcatA(keypath, prod_squashed);
1387 
1388     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1389     if (res == ERROR_ACCESS_DENIED)
1390     {
1391         skip("Not enough rights to perform tests\n");
1392         RegDeleteKeyA(userkey, "");
1393         RegCloseKey(userkey);
1394         LocalFree(usersid);
1395         return;
1396     }
1397     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1398 
1399     /* local product key exists */
1400     SetLastError(0xdeadbeef);
1401     state = MsiQueryProductStateA(prodcode);
1402     error = GetLastError();
1403     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1404     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1405 
1406     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1407     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1408 
1409     /* install properties key exists */
1410     SetLastError(0xdeadbeef);
1411     state = MsiQueryProductStateA(prodcode);
1412     error = GetLastError();
1413     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1414     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1415 
1416     data = 1;
1417     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1418     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1419 
1420     /* WindowsInstaller value exists */
1421     SetLastError(0xdeadbeef);
1422     state = MsiQueryProductStateA(prodcode);
1423     error = GetLastError();
1424     if (state == INSTALLSTATE_ADVERTISED)
1425     {
1426         win_skip("broken result\n");
1427         RegDeleteValueA(props, "WindowsInstaller");
1428         delete_key(props, "", access & KEY_WOW64_64KEY);
1429         RegCloseKey(props);
1430         delete_key(localkey, "", access & KEY_WOW64_64KEY);
1431         RegCloseKey(localkey);
1432         RegDeleteKeyA(userkey, "");
1433         RegCloseKey(userkey);
1434         LocalFree(usersid);
1435         return;
1436     }
1437     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1438     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1439 
1440     data = 2;
1441     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1442     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1443 
1444     /* WindowsInstaller value is not 1 */
1445     SetLastError(0xdeadbeef);
1446     state = MsiQueryProductStateA(prodcode);
1447     error = GetLastError();
1448     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1449     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1450 
1451     RegDeleteKeyA(userkey, "");
1452 
1453     /* user product key does not exist */
1454     SetLastError(0xdeadbeef);
1455     state = MsiQueryProductStateA(prodcode);
1456     error = GetLastError();
1457     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1458     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1459 
1460     RegDeleteValueA(props, "WindowsInstaller");
1461     delete_key(props, "", access & KEY_WOW64_64KEY);
1462     RegCloseKey(props);
1463     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1464     RegCloseKey(localkey);
1465     RegDeleteKeyA(userkey, "");
1466     RegCloseKey(userkey);
1467 
1468     /* MSIINSTALLCONTEXT_USERMANAGED */
1469 
1470     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
1471     lstrcatA(keypath, usersid);
1472     lstrcatA(keypath, "\\Installer\\Products\\");
1473     lstrcatA(keypath, prod_squashed);
1474 
1475     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
1476     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1477 
1478     state = MsiQueryProductStateA(prodcode);
1479     ok(state == INSTALLSTATE_ADVERTISED,
1480        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1481 
1482     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1483     lstrcatA(keypath, usersid);
1484     lstrcatA(keypath, "\\Products\\");
1485     lstrcatA(keypath, prod_squashed);
1486 
1487     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1488     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1489 
1490     state = MsiQueryProductStateA(prodcode);
1491     ok(state == INSTALLSTATE_ADVERTISED,
1492        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1493 
1494     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1495     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1496 
1497     state = MsiQueryProductStateA(prodcode);
1498     ok(state == INSTALLSTATE_ADVERTISED,
1499        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1500 
1501     data = 1;
1502     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1503     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1504 
1505     /* WindowsInstaller value exists */
1506     state = MsiQueryProductStateA(prodcode);
1507     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1508 
1509     RegDeleteValueA(props, "WindowsInstaller");
1510     delete_key(props, "", access & KEY_WOW64_64KEY);
1511     RegCloseKey(props);
1512     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1513     RegCloseKey(localkey);
1514     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
1515     RegCloseKey(prodkey);
1516 
1517     /* MSIINSTALLCONTEXT_MACHINE */
1518 
1519     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
1520     lstrcatA(keypath, prod_squashed);
1521 
1522     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
1523     if (res == ERROR_ACCESS_DENIED)
1524     {
1525         skip( "insufficient rights\n" );
1526         LocalFree( usersid );
1527         return;
1528     }
1529     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1530 
1531     state = MsiQueryProductStateA(prodcode);
1532     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1533 
1534     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1535     lstrcatA(keypath, "S-1-5-18\\Products\\");
1536     lstrcatA(keypath, prod_squashed);
1537 
1538     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1539     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1540 
1541     state = MsiQueryProductStateA(prodcode);
1542     ok(state == INSTALLSTATE_ADVERTISED,
1543        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1544 
1545     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1546     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1547 
1548     state = MsiQueryProductStateA(prodcode);
1549     ok(state == INSTALLSTATE_ADVERTISED,
1550        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1551 
1552     data = 1;
1553     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1554     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1555 
1556     /* WindowsInstaller value exists */
1557     state = MsiQueryProductStateA(prodcode);
1558     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1559 
1560     RegDeleteValueA(props, "WindowsInstaller");
1561     delete_key(props, "", access & KEY_WOW64_64KEY);
1562     RegCloseKey(props);
1563     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1564     RegCloseKey(localkey);
1565     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
1566     RegCloseKey(prodkey);
1567 
1568     LocalFree(usersid);
1569 }
1570 
1571 static const char table_enc85[] =
1572 "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
1573 "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
1574 "yz{}~";
1575 
1576 /*
1577  *  Encodes a base85 guid given a GUID pointer
1578  *  Caller should provide a 21 character buffer for the encoded string.
1579  */
1580 static void encode_base85_guid( GUID *guid, LPWSTR str )
1581 {
1582     unsigned int x, *p, i;
1583 
1584     p = (unsigned int*) guid;
1585     for( i=0; i<4; i++ )
1586     {
1587         x = p[i];
1588         *str++ = table_enc85[x%85];
1589         x = x/85;
1590         *str++ = table_enc85[x%85];
1591         x = x/85;
1592         *str++ = table_enc85[x%85];
1593         x = x/85;
1594         *str++ = table_enc85[x%85];
1595         x = x/85;
1596         *str++ = table_enc85[x%85];
1597     }
1598     *str = 0;
1599 }
1600 
1601 static void compose_base85_guid(LPSTR component, LPSTR comp_base85, LPSTR squashed)
1602 {
1603     WCHAR guidW[MAX_PATH];
1604     WCHAR base85W[MAX_PATH];
1605     WCHAR squashedW[MAX_PATH];
1606     GUID guid;
1607     HRESULT hr;
1608     int size;
1609 
1610     hr = CoCreateGuid(&guid);
1611     ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
1612 
1613     size = StringFromGUID2(&guid, guidW, MAX_PATH);
1614     ok(size == 39, "Expected 39, got %d\n", size);
1615 
1616     WideCharToMultiByte(CP_ACP, 0, guidW, size, component, MAX_PATH, NULL, NULL);
1617     encode_base85_guid(&guid, base85W);
1618     WideCharToMultiByte(CP_ACP, 0, base85W, -1, comp_base85, MAX_PATH, NULL, NULL);
1619     squash_guid(guidW, squashedW);
1620     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
1621 }
1622 
1623 static void test_MsiQueryFeatureState(void)
1624 {
1625     HKEY userkey, localkey, compkey, compkey2;
1626     CHAR prodcode[MAX_PATH];
1627     CHAR prod_squashed[MAX_PATH];
1628     CHAR component[MAX_PATH];
1629     CHAR comp_base85[MAX_PATH];
1630     CHAR comp_squashed[MAX_PATH], comp_squashed2[MAX_PATH];
1631     CHAR keypath[MAX_PATH*2];
1632     INSTALLSTATE state;
1633     LPSTR usersid;
1634     LONG res;
1635     REGSAM access = KEY_ALL_ACCESS;
1636     DWORD error;
1637 
1638     create_test_guid(prodcode, prod_squashed);
1639     compose_base85_guid(component, comp_base85, comp_squashed);
1640     compose_base85_guid(component, comp_base85 + 20, comp_squashed2);
1641     usersid = get_user_sid();
1642 
1643     if (is_wow64)
1644         access |= KEY_WOW64_64KEY;
1645 
1646     /* NULL prodcode */
1647     SetLastError(0xdeadbeef);
1648     state = MsiQueryFeatureStateA(NULL, "feature");
1649     error = GetLastError();
1650     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1651     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
1652 
1653     /* empty prodcode */
1654     SetLastError(0xdeadbeef);
1655     state = MsiQueryFeatureStateA("", "feature");
1656     error = GetLastError();
1657     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1658     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
1659 
1660     /* garbage prodcode */
1661     SetLastError(0xdeadbeef);
1662     state = MsiQueryFeatureStateA("garbage", "feature");
1663     error = GetLastError();
1664     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1665     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
1666 
1667     /* guid without brackets */
1668     SetLastError(0xdeadbeef);
1669     state = MsiQueryFeatureStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", "feature");
1670     error = GetLastError();
1671     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1672     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
1673 
1674     /* guid with brackets */
1675     SetLastError(0xdeadbeef);
1676     state = MsiQueryFeatureStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", "feature");
1677     error = GetLastError();
1678     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1679     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1680 
1681     /* same length as guid, but random */
1682     SetLastError(0xdeadbeef);
1683     state = MsiQueryFeatureStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", "feature");
1684     error = GetLastError();
1685     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1686     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
1687 
1688     /* NULL szFeature */
1689     SetLastError(0xdeadbeef);
1690     state = MsiQueryFeatureStateA(prodcode, NULL);
1691     error = GetLastError();
1692     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1693     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
1694 
1695     /* empty szFeature */
1696     SetLastError(0xdeadbeef);
1697     state = MsiQueryFeatureStateA(prodcode, "");
1698     error = GetLastError();
1699     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1700     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1701 
1702     /* feature key does not exist yet */
1703     SetLastError(0xdeadbeef);
1704     state = MsiQueryFeatureStateA(prodcode, "feature");
1705     error = GetLastError();
1706     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1707     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1708 
1709     /* MSIINSTALLCONTEXT_USERUNMANAGED */
1710 
1711     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Features\\");
1712     lstrcatA(keypath, prod_squashed);
1713 
1714     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
1715     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1716 
1717     /* feature key exists */
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, "expected ERROR_SUCCESS, got %lu\n", error);
1723 
1724     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 2);
1725     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1726 
1727     /* feature value exists */
1728     SetLastError(0xdeadbeef);
1729     state = MsiQueryFeatureStateA(prodcode, "feature");
1730     error = GetLastError();
1731     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1732     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1733 
1734     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1735     lstrcatA(keypath, usersid);
1736     lstrcatA(keypath, "\\Products\\");
1737     lstrcatA(keypath, prod_squashed);
1738     lstrcatA(keypath, "\\Features");
1739 
1740     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1741     if (res == ERROR_ACCESS_DENIED)
1742     {
1743         skip("Not enough rights to perform tests\n");
1744         RegDeleteKeyA(userkey, "");
1745         RegCloseKey(userkey);
1746         LocalFree(usersid);
1747         return;
1748     }
1749     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1750 
1751     /* userdata features key exists */
1752     SetLastError(0xdeadbeef);
1753     state = MsiQueryFeatureStateA(prodcode, "feature");
1754     error = GetLastError();
1755     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1756     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1757 
1758     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
1759     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1760 
1761     SetLastError(0xdeadbeef);
1762     state = MsiQueryFeatureStateA(prodcode, "feature");
1763     error = GetLastError();
1764     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
1765     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1766 
1767     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
1768     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1769 
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, "expected ERROR_SUCCESS, got %lu\n", error);
1775 
1776     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
1777     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1778 
1779     SetLastError(0xdeadbeef);
1780     state = MsiQueryFeatureStateA(prodcode, "feature");
1781     error = GetLastError();
1782     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1783     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1784 
1785     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
1786     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1787 
1788     SetLastError(0xdeadbeef);
1789     state = MsiQueryFeatureStateA(prodcode, "feature");
1790     error = GetLastError();
1791     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1792     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1793 
1794     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1795     lstrcatA(keypath, usersid);
1796     lstrcatA(keypath, "\\Components\\");
1797     lstrcatA(keypath, comp_squashed);
1798 
1799     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
1800     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1801 
1802     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1803     lstrcatA(keypath, usersid);
1804     lstrcatA(keypath, "\\Components\\");
1805     lstrcatA(keypath, comp_squashed2);
1806 
1807     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
1808     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\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, "expected ERROR_SUCCESS, got %lu\n", error);
1815 
1816     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
1817     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1818 
1819     SetLastError(0xdeadbeef);
1820     state = MsiQueryFeatureStateA(prodcode, "feature");
1821     error = GetLastError();
1822     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1823     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1824 
1825     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
1826     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1827 
1828     SetLastError(0xdeadbeef);
1829     state = MsiQueryFeatureStateA(prodcode, "feature");
1830     error = GetLastError();
1831     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1832     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1833 
1834     res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
1835     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1836 
1837     /* INSTALLSTATE_LOCAL */
1838     SetLastError(0xdeadbeef);
1839     state = MsiQueryFeatureStateA(prodcode, "feature");
1840     error = GetLastError();
1841     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1842     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1843 
1844     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01\\", 4);
1845     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1846 
1847     /* INSTALLSTATE_SOURCE */
1848     SetLastError(0xdeadbeef);
1849     state = MsiQueryFeatureStateA(prodcode, "feature");
1850     error = GetLastError();
1851     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
1852     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1853 
1854     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
1855     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1856 
1857     /* bad INSTALLSTATE_SOURCE */
1858     SetLastError(0xdeadbeef);
1859     state = MsiQueryFeatureStateA(prodcode, "feature");
1860     error = GetLastError();
1861     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1862     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1863 
1864     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01a", 4);
1865     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1866 
1867     /* INSTALLSTATE_SOURCE */
1868     SetLastError(0xdeadbeef);
1869     state = MsiQueryFeatureStateA(prodcode, "feature");
1870     error = GetLastError();
1871     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
1872     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1873 
1874     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
1875     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1876 
1877     /* bad INSTALLSTATE_SOURCE */
1878     SetLastError(0xdeadbeef);
1879     state = MsiQueryFeatureStateA(prodcode, "feature");
1880     error = GetLastError();
1881     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1882     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1883 
1884     RegDeleteValueA(compkey, prod_squashed);
1885     RegDeleteValueA(compkey2, prod_squashed);
1886     delete_key(compkey, "", access & KEY_WOW64_64KEY);
1887     delete_key(compkey2, "", access & KEY_WOW64_64KEY);
1888     RegDeleteValueA(localkey, "feature");
1889     RegDeleteValueA(userkey, "feature");
1890     RegDeleteKeyA(userkey, "");
1891     RegCloseKey(compkey);
1892     RegCloseKey(compkey2);
1893     RegCloseKey(localkey);
1894     RegCloseKey(userkey);
1895 
1896     /* MSIINSTALLCONTEXT_USERMANAGED */
1897 
1898     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
1899     lstrcatA(keypath, usersid);
1900     lstrcatA(keypath, "\\Installer\\Features\\");
1901     lstrcatA(keypath, prod_squashed);
1902 
1903     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
1904     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1905 
1906     /* feature key exists */
1907     state = MsiQueryFeatureStateA(prodcode, "feature");
1908     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1909 
1910     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 1);
1911     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1912 
1913     /* feature value exists */
1914     state = MsiQueryFeatureStateA(prodcode, "feature");
1915     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1916 
1917     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1918     lstrcatA(keypath, usersid);
1919     lstrcatA(keypath, "\\Products\\");
1920     lstrcatA(keypath, prod_squashed);
1921     lstrcatA(keypath, "\\Features");
1922 
1923     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1924     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1925 
1926     /* userdata features key exists */
1927     state = MsiQueryFeatureStateA(prodcode, "feature");
1928     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1929 
1930     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
1931     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1932 
1933     state = MsiQueryFeatureStateA(prodcode, "feature");
1934     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
1935 
1936     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
1937     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1938 
1939     state = MsiQueryFeatureStateA(prodcode, "feature");
1940     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1941 
1942     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
1943     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1944 
1945     state = MsiQueryFeatureStateA(prodcode, "feature");
1946     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1947 
1948     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
1949     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1950 
1951     state = MsiQueryFeatureStateA(prodcode, "feature");
1952     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1953 
1954     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1955     lstrcatA(keypath, usersid);
1956     lstrcatA(keypath, "\\Components\\");
1957     lstrcatA(keypath, comp_squashed);
1958 
1959     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
1960     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1961 
1962     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1963     lstrcatA(keypath, usersid);
1964     lstrcatA(keypath, "\\Components\\");
1965     lstrcatA(keypath, comp_squashed2);
1966 
1967     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
1968     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1969 
1970     state = MsiQueryFeatureStateA(prodcode, "feature");
1971     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1972 
1973     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
1974     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1975 
1976     state = MsiQueryFeatureStateA(prodcode, "feature");
1977     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1978 
1979     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
1980     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1981 
1982     state = MsiQueryFeatureStateA(prodcode, "feature");
1983     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1984 
1985     res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
1986     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1987 
1988     state = MsiQueryFeatureStateA(prodcode, "feature");
1989     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1990 
1991     RegDeleteValueA(compkey, prod_squashed);
1992     RegDeleteValueA(compkey2, prod_squashed);
1993     delete_key(compkey, "", access & KEY_WOW64_64KEY);
1994     delete_key(compkey2, "", access & KEY_WOW64_64KEY);
1995     RegDeleteValueA(localkey, "feature");
1996     RegDeleteValueA(userkey, "feature");
1997     delete_key(userkey, "", access & KEY_WOW64_64KEY);
1998     RegCloseKey(compkey);
1999     RegCloseKey(compkey2);
2000     RegCloseKey(localkey);
2001     RegCloseKey(userkey);
2002 
2003     /* MSIINSTALLCONTEXT_MACHINE */
2004 
2005     lstrcpyA(keypath, "Software\\Classes\\Installer\\Features\\");
2006     lstrcatA(keypath, prod_squashed);
2007 
2008     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
2009     if (res == ERROR_ACCESS_DENIED)
2010     {
2011         skip( "insufficient rights\n" );
2012         LocalFree( usersid );
2013         return;
2014     }
2015     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2016 
2017     /* feature key exists */
2018     state = MsiQueryFeatureStateA(prodcode, "feature");
2019     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2020 
2021     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 1);
2022     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2023 
2024     /* feature value exists */
2025     state = MsiQueryFeatureStateA(prodcode, "feature");
2026     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2027 
2028     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2029     lstrcatA(keypath, "S-1-5-18\\Products\\");
2030     lstrcatA(keypath, prod_squashed);
2031     lstrcatA(keypath, "\\Features");
2032 
2033     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
2034     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2035 
2036     /* userdata features key exists */
2037     state = MsiQueryFeatureStateA(prodcode, "feature");
2038     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2039 
2040     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
2041     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2042 
2043     state = MsiQueryFeatureStateA(prodcode, "feature");
2044     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
2045 
2046     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
2047     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2048 
2049     state = MsiQueryFeatureStateA(prodcode, "feature");
2050     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2051 
2052     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
2053     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2054 
2055     state = MsiQueryFeatureStateA(prodcode, "feature");
2056     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2057 
2058     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
2059     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2060 
2061     state = MsiQueryFeatureStateA(prodcode, "feature");
2062     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2063 
2064     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2065     lstrcatA(keypath, "S-1-5-18\\Components\\");
2066     lstrcatA(keypath, comp_squashed);
2067 
2068     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2069     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2070 
2071     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2072     lstrcatA(keypath, "S-1-5-18\\Components\\");
2073     lstrcatA(keypath, comp_squashed2);
2074 
2075     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
2076     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2077 
2078     state = MsiQueryFeatureStateA(prodcode, "feature");
2079     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2080 
2081     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
2082     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2083 
2084     state = MsiQueryFeatureStateA(prodcode, "feature");
2085     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2086 
2087     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
2088     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2089 
2090     state = MsiQueryFeatureStateA(prodcode, "feature");
2091     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2092 
2093     res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
2094     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2095 
2096     state = MsiQueryFeatureStateA(prodcode, "feature");
2097     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2098 
2099     RegDeleteValueA(compkey, prod_squashed);
2100     RegDeleteValueA(compkey2, prod_squashed);
2101     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2102     delete_key(compkey2, "", access & KEY_WOW64_64KEY);
2103     RegDeleteValueA(localkey, "feature");
2104     RegDeleteValueA(userkey, "feature");
2105     delete_key(userkey, "", access & KEY_WOW64_64KEY);
2106     RegCloseKey(compkey);
2107     RegCloseKey(compkey2);
2108     RegCloseKey(localkey);
2109     RegCloseKey(userkey);
2110     LocalFree(usersid);
2111 }
2112 
2113 static void test_MsiQueryComponentState(void)
2114 {
2115     HKEY compkey, prodkey;
2116     CHAR prodcode[MAX_PATH];
2117     CHAR prod_squashed[MAX_PATH];
2118     CHAR component[MAX_PATH];
2119     CHAR comp_base85[MAX_PATH];
2120     CHAR comp_squashed[MAX_PATH];
2121     CHAR keypath[MAX_PATH];
2122     INSTALLSTATE state;
2123     LPSTR usersid;
2124     LONG res;
2125     UINT r;
2126     REGSAM access = KEY_ALL_ACCESS;
2127     DWORD error;
2128 
2129     static const INSTALLSTATE MAGIC_ERROR = 0xdeadbeef;
2130 
2131     if (!pMsiQueryComponentStateA)
2132     {
2133         win_skip("MsiQueryComponentStateA not implemented\n");
2134         return;
2135     }
2136 
2137     create_test_guid(prodcode, prod_squashed);
2138     compose_base85_guid(component, comp_base85, comp_squashed);
2139     usersid = get_user_sid();
2140 
2141     if (is_wow64)
2142         access |= KEY_WOW64_64KEY;
2143 
2144     /* NULL szProductCode */
2145     state = MAGIC_ERROR;
2146     SetLastError(0xdeadbeef);
2147     r = pMsiQueryComponentStateA(NULL, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2148     error = GetLastError();
2149     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2150     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2151     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2152 
2153     /* empty szProductCode */
2154     state = MAGIC_ERROR;
2155     SetLastError(0xdeadbeef);
2156     r = pMsiQueryComponentStateA("", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2157     error = GetLastError();
2158     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2159     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2160     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2161 
2162     /* random szProductCode */
2163     state = MAGIC_ERROR;
2164     SetLastError(0xdeadbeef);
2165     r = pMsiQueryComponentStateA("random", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2166     error = GetLastError();
2167     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2168     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2169     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2170 
2171     /* GUID-length szProductCode */
2172     state = MAGIC_ERROR;
2173     SetLastError(0xdeadbeef);
2174     r = pMsiQueryComponentStateA("DJANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KDE", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2175     error = GetLastError();
2176     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2177     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2178     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2179 
2180     /* GUID-length with brackets */
2181     state = MAGIC_ERROR;
2182     SetLastError(0xdeadbeef);
2183     r = pMsiQueryComponentStateA("{JANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KD}", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2184     error = GetLastError();
2185     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2186     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2187     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2188 
2189     /* actual GUID */
2190     state = MAGIC_ERROR;
2191     SetLastError(0xdeadbeef);
2192     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2193     error = GetLastError();
2194     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2195     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2196     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2197 
2198     state = MAGIC_ERROR;
2199     SetLastError(0xdeadbeef);
2200     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2201     error = GetLastError();
2202     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2203     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2204     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2205 
2206     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
2207     lstrcatA(keypath, prod_squashed);
2208 
2209     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2210     if (res == ERROR_ACCESS_DENIED)
2211     {
2212         skip("Not enough rights to perform tests\n");
2213         LocalFree(usersid);
2214         return;
2215     }
2216     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2217 
2218     state = MAGIC_ERROR;
2219     SetLastError(0xdeadbeef);
2220     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2221     error = GetLastError();
2222     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2223     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2224     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2225 
2226     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2227     RegCloseKey(prodkey);
2228 
2229     /* create local system product key */
2230     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\");
2231     lstrcatA(keypath, prod_squashed);
2232     lstrcatA(keypath, "\\InstallProperties");
2233 
2234     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2235     if (res == ERROR_ACCESS_DENIED)
2236     {
2237         skip("Not enough rights to perform tests\n");
2238         LocalFree(usersid);
2239         return;
2240     }
2241     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2242 
2243     /* local system product key exists */
2244     state = MAGIC_ERROR;
2245     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2246     error = GetLastError();
2247     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2248     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2249     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2250 
2251     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2252     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2253 
2254     /* LocalPackage value exists */
2255     state = MAGIC_ERROR;
2256     SetLastError(0xdeadbeef);
2257     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2258     error = GetLastError();
2259     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2260     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2261     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2262 
2263     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\");
2264     lstrcatA(keypath, comp_squashed);
2265 
2266     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2267     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2268 
2269     /* component key exists */
2270     state = MAGIC_ERROR;
2271     SetLastError(0xdeadbeef);
2272     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2273     error = GetLastError();
2274     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2275     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2276     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2277 
2278     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
2279     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2280 
2281     /* component\product exists */
2282     state = MAGIC_ERROR;
2283     SetLastError(0xdeadbeef);
2284     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2285     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2286     error = GetLastError();
2287     ok(state == INSTALLSTATE_NOTUSED || state == INSTALLSTATE_LOCAL,
2288        "Expected INSTALLSTATE_NOTUSED or INSTALLSTATE_LOCAL, got %d\n", state);
2289     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2290 
2291     /* NULL component, product exists */
2292     state = MAGIC_ERROR;
2293     SetLastError(0xdeadbeef);
2294     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, NULL, &state);
2295     error = GetLastError();
2296     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2297     ok(state == MAGIC_ERROR, "Expected state not changed, got %d\n", state);
2298     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2299 
2300     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
2301     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2302 
2303     /* INSTALLSTATE_LOCAL */
2304     state = MAGIC_ERROR;
2305     SetLastError(0xdeadbeef);
2306     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2307     error = GetLastError();
2308     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2309     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2310     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2311 
2312     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01\\", 4);
2313     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2314 
2315     /* INSTALLSTATE_SOURCE */
2316     state = MAGIC_ERROR;
2317     SetLastError(0xdeadbeef);
2318     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2319     error = GetLastError();
2320     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2321     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2322     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2323 
2324     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
2325     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2326 
2327     /* bad INSTALLSTATE_SOURCE */
2328     state = MAGIC_ERROR;
2329     SetLastError(0xdeadbeef);
2330     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2331     error = GetLastError();
2332     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2333     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2334     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2335 
2336     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01a", 4);
2337     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2338 
2339     /* INSTALLSTATE_SOURCE */
2340     state = MAGIC_ERROR;
2341     SetLastError(0xdeadbeef);
2342     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2343     error = GetLastError();
2344     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2345     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2346     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2347 
2348     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01:", 4);
2349     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2350 
2351     /* registry component */
2352     state = MAGIC_ERROR;
2353     SetLastError(0xdeadbeef);
2354     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2355     error = GetLastError();
2356     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2357     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2358     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2359 
2360     RegDeleteValueA(prodkey, "LocalPackage");
2361     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2362     RegDeleteValueA(compkey, prod_squashed);
2363     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2364     RegCloseKey(prodkey);
2365     RegCloseKey(compkey);
2366 
2367     /* MSIINSTALLCONTEXT_USERUNMANAGED */
2368 
2369     state = MAGIC_ERROR;
2370     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2371     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2372     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2373 
2374     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2375     lstrcatA(keypath, prod_squashed);
2376 
2377     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
2378     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2379 
2380     state = MAGIC_ERROR;
2381     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2382     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2383     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2384 
2385     RegDeleteKeyA(prodkey, "");
2386     RegCloseKey(prodkey);
2387 
2388     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2389     lstrcatA(keypath, usersid);
2390     lstrcatA(keypath, "\\Products\\");
2391     lstrcatA(keypath, prod_squashed);
2392     lstrcatA(keypath, "\\InstallProperties");
2393 
2394     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2395     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2396 
2397     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2398     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2399 
2400     RegCloseKey(prodkey);
2401 
2402     state = MAGIC_ERROR;
2403     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2404     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2405     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2406 
2407     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2408     lstrcatA(keypath, usersid);
2409     lstrcatA(keypath, "\\Components\\");
2410     lstrcatA(keypath, comp_squashed);
2411 
2412     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2413     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2414 
2415     /* component key exists */
2416     state = MAGIC_ERROR;
2417     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2418     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2419     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2420 
2421     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
2422     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2423 
2424     /* component\product exists */
2425     state = MAGIC_ERROR;
2426     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2427     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2428     ok(state == INSTALLSTATE_NOTUSED || state == INSTALLSTATE_LOCAL,
2429        "Expected INSTALLSTATE_NOTUSED or INSTALLSTATE_LOCAL, got %d\n", state);
2430 
2431     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
2432     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2433 
2434     state = MAGIC_ERROR;
2435     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2436     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2437     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2438 
2439     /* MSIINSTALLCONTEXT_USERMANAGED */
2440 
2441     state = MAGIC_ERROR;
2442     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2443     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2444     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2445 
2446     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2447     lstrcatA(keypath, prod_squashed);
2448 
2449     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
2450     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2451 
2452     state = MAGIC_ERROR;
2453     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2454     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2455     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2456 
2457     RegDeleteKeyA(prodkey, "");
2458     RegCloseKey(prodkey);
2459 
2460     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
2461     lstrcatA(keypath, usersid);
2462     lstrcatA(keypath, "\\Installer\\Products\\");
2463     lstrcatA(keypath, prod_squashed);
2464 
2465     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2466     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2467 
2468     state = MAGIC_ERROR;
2469     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2470     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2471     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2472 
2473     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2474     RegCloseKey(prodkey);
2475 
2476     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2477     lstrcatA(keypath, usersid);
2478     lstrcatA(keypath, "\\Products\\");
2479     lstrcatA(keypath, prod_squashed);
2480     lstrcatA(keypath, "\\InstallProperties");
2481 
2482     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2483     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2484 
2485     res = RegSetValueExA(prodkey, "ManagedLocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2486     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2487 
2488     state = MAGIC_ERROR;
2489     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2490     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2491     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2492 
2493     RegDeleteValueA(prodkey, "LocalPackage");
2494     RegDeleteValueA(prodkey, "ManagedLocalPackage");
2495     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2496     RegDeleteValueA(compkey, prod_squashed);
2497     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2498     RegCloseKey(prodkey);
2499     RegCloseKey(compkey);
2500     LocalFree(usersid);
2501 }
2502 
2503 static void test_MsiGetComponentPath(void)
2504 {
2505     HKEY compkey, prodkey, installprop;
2506     CHAR prodcode[MAX_PATH];
2507     CHAR prod_squashed[MAX_PATH];
2508     CHAR component[MAX_PATH];
2509     CHAR comp_base85[MAX_PATH];
2510     CHAR comp_squashed[MAX_PATH];
2511     CHAR keypath[MAX_PATH];
2512     CHAR path[MAX_PATH];
2513     INSTALLSTATE state;
2514     LPSTR usersid;
2515     DWORD size, val;
2516     REGSAM access = KEY_ALL_ACCESS;
2517     LONG res;
2518 
2519     create_test_guid(prodcode, prod_squashed);
2520     compose_base85_guid(component, comp_base85, comp_squashed);
2521     usersid = get_user_sid();
2522 
2523     if (is_wow64)
2524         access |= KEY_WOW64_64KEY;
2525 
2526     /* NULL szProduct */
2527     size = MAX_PATH;
2528     state = MsiGetComponentPathA(NULL, component, path, &size);
2529     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2530     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2531 
2532     /* NULL szComponent */
2533     size = MAX_PATH;
2534     state = MsiGetComponentPathA(prodcode, NULL, path, &size);
2535     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2536     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2537 
2538     size = MAX_PATH;
2539     state = MsiLocateComponentA(NULL, path, &size);
2540     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2541     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2542 
2543     /* NULL lpPathBuf */
2544     size = MAX_PATH;
2545     state = MsiGetComponentPathA(prodcode, component, NULL, &size);
2546     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2547     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2548 
2549     size = MAX_PATH;
2550     state = MsiLocateComponentA(component, NULL, &size);
2551     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2552     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2553 
2554     /* NULL pcchBuf */
2555     size = MAX_PATH;
2556     state = MsiGetComponentPathA(prodcode, component, path, NULL);
2557     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2558     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2559 
2560     size = MAX_PATH;
2561     state = MsiLocateComponentA(component, path, NULL);
2562     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2563     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2564 
2565     /* all params valid */
2566     size = MAX_PATH;
2567     state = MsiGetComponentPathA(prodcode, component, path, &size);
2568     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2569     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2570 
2571     size = MAX_PATH;
2572     state = MsiLocateComponentA(component, path, &size);
2573     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2574     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2575 
2576     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2577     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
2578     lstrcatA(keypath, comp_squashed);
2579 
2580     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2581     if (res == ERROR_ACCESS_DENIED)
2582     {
2583         skip("Not enough rights to perform tests\n");
2584         LocalFree(usersid);
2585         return;
2586     }
2587     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2588 
2589     /* local system component key exists */
2590     size = MAX_PATH;
2591     state = MsiGetComponentPathA(prodcode, component, path, &size);
2592     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2593     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2594 
2595     size = MAX_PATH;
2596     state = MsiLocateComponentA(component, path, &size);
2597     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2598     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2599 
2600     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2601     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2602 
2603     /* product value exists */
2604     path[0] = 0;
2605     size = MAX_PATH;
2606     state = MsiGetComponentPathA(prodcode, component, path, &size);
2607     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2608     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2609     ok(size == 10, "Expected 10, got %lu\n", size);
2610 
2611     path[0] = 0;
2612     size = MAX_PATH;
2613     state = MsiLocateComponentA(component, path, &size);
2614     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2615     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2616     ok(size == 10, "Expected 10, got %lu\n", size);
2617 
2618     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2619     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
2620     lstrcatA(keypath, prod_squashed);
2621     lstrcatA(keypath, "\\InstallProperties");
2622 
2623     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &installprop, NULL);
2624     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2625 
2626     val = 1;
2627     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
2628     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2629 
2630     /* install properties key exists */
2631     path[0] = 0;
2632     size = MAX_PATH;
2633     state = MsiGetComponentPathA(prodcode, component, path, &size);
2634     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2635     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2636     ok(size == 10, "Expected 10, got %lu\n", size);
2637 
2638     path[0] = 0;
2639     size = MAX_PATH;
2640     state = MsiLocateComponentA(component, path, &size);
2641     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2642     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2643     ok(size == 10, "Expected 10, got %lu\n", size);
2644 
2645     create_file("C:\\imapath", 11);
2646 
2647     /* file exists */
2648     path[0] = 'a';
2649     size = 0;
2650     state = MsiGetComponentPathA(prodcode, component, path, &size);
2651     ok(state == INSTALLSTATE_MOREDATA, "Expected INSTALLSTATE_MOREDATA, got %d\n", state);
2652     ok(path[0] == 'a', "got %s\n", path);
2653     ok(size == 10, "Expected 10, got %lu\n", size);
2654 
2655     path[0] = 0;
2656     size = MAX_PATH;
2657     state = MsiGetComponentPathA(prodcode, component, path, &size);
2658     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2659     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2660     ok(size == 10, "Expected 10, got %lu\n", size);
2661 
2662     size = 0;
2663     path[0] = 'a';
2664     state = MsiLocateComponentA(component, path, &size);
2665     ok(state == INSTALLSTATE_MOREDATA, "Expected INSTALLSTATE_MOREDATA, got %d\n", state);
2666     ok(path[0] == 'a', "got %s\n", path);
2667     ok(size == 10, "Expected 10, got %lu\n", size);
2668 
2669     path[0] = 0;
2670     size = MAX_PATH;
2671     state = MsiLocateComponentA(component, path, &size);
2672     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2673     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2674     ok(size == 10, "Expected 10, got %lu\n", size);
2675 
2676     RegDeleteValueA(compkey, prod_squashed);
2677     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2678     RegDeleteValueA(installprop, "WindowsInstaller");
2679     delete_key(installprop, "", access & KEY_WOW64_64KEY);
2680     RegCloseKey(compkey);
2681     RegCloseKey(installprop);
2682     DeleteFileA("C:\\imapath");
2683 
2684     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2685     lstrcatA(keypath, "Installer\\UserData\\");
2686     lstrcatA(keypath, usersid);
2687     lstrcatA(keypath, "\\Components\\");
2688     lstrcatA(keypath, comp_squashed);
2689 
2690     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2691     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2692 
2693     /* user managed component key exists */
2694     size = MAX_PATH;
2695     state = MsiGetComponentPathA(prodcode, component, path, &size);
2696     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2697     ok(size == MAX_PATH, "Expected size to be unchanged, got %ld\n", size);
2698 
2699     size = MAX_PATH;
2700     state = MsiLocateComponentA(component, path, &size);
2701     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2702     ok(size == MAX_PATH, "Expected size to be unchanged, got %ld\n", size);
2703 
2704     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2705     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2706 
2707     /* product value exists */
2708     path[0] = 0;
2709     size = MAX_PATH;
2710     state = MsiGetComponentPathA(prodcode, component, path, &size);
2711     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2712     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2713     ok(size == 10, "Expected 10, got %lu\n", size);
2714 
2715     path[0] = 0;
2716     size = MAX_PATH;
2717     state = MsiLocateComponentA(component, path, &size);
2718     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2719     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2720     ok(size == 10, "Expected 10, got %lu\n", size);
2721 
2722     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2723     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
2724     lstrcatA(keypath, prod_squashed);
2725     lstrcatA(keypath, "\\InstallProperties");
2726 
2727     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &installprop, NULL);
2728     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2729 
2730     val = 1;
2731     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
2732     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2733 
2734     /* install properties key exists */
2735     path[0] = 0;
2736     size = MAX_PATH;
2737     state = MsiGetComponentPathA(prodcode, component, path, &size);
2738     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2739     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2740     ok(size == 10, "Expected 10, got %lu\n", size);
2741 
2742     path[0] = 0;
2743     size = MAX_PATH;
2744     state = MsiLocateComponentA(component, path, &size);
2745     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2746     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2747     ok(size == 10, "Expected 10, got %lu\n", size);
2748 
2749     create_file("C:\\imapath", 11);
2750 
2751     /* file exists */
2752     path[0] = 0;
2753     size = MAX_PATH;
2754     state = MsiGetComponentPathA(prodcode, component, path, &size);
2755     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2756     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2757     ok(size == 10, "Expected 10, got %lu\n", size);
2758 
2759     path[0] = 0;
2760     size = MAX_PATH;
2761     state = MsiLocateComponentA(component, path, &size);
2762     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2763     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2764     ok(size == 10, "Expected 10, got %lu\n", size);
2765 
2766     RegDeleteValueA(compkey, prod_squashed);
2767     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2768     RegDeleteValueA(installprop, "WindowsInstaller");
2769     delete_key(installprop, "", access & KEY_WOW64_64KEY);
2770     RegCloseKey(compkey);
2771     RegCloseKey(installprop);
2772     DeleteFileA("C:\\imapath");
2773 
2774     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2775     lstrcatA(keypath, "Installer\\Managed\\");
2776     lstrcatA(keypath, usersid);
2777     lstrcatA(keypath, "\\Installer\\Products\\");
2778     lstrcatA(keypath, prod_squashed);
2779 
2780     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2781     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2782 
2783     /* user managed product key exists */
2784     size = MAX_PATH;
2785     state = MsiGetComponentPathA(prodcode, component, path, &size);
2786     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2787     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2788 
2789     size = MAX_PATH;
2790     state = MsiLocateComponentA(component, path, &size);
2791     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2792     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2793 
2794     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2795     lstrcatA(keypath, "Installer\\UserData\\");
2796     lstrcatA(keypath, usersid);
2797     lstrcatA(keypath, "\\Components\\");
2798     lstrcatA(keypath, comp_squashed);
2799 
2800     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2801     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2802 
2803     /* user managed component key exists */
2804     size = MAX_PATH;
2805     state = MsiGetComponentPathA(prodcode, component, path, &size);
2806     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2807     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2808 
2809     size = MAX_PATH;
2810     state = MsiLocateComponentA(component, path, &size);
2811     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2812     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2813 
2814     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2815     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2816 
2817     /* product value exists */
2818     path[0] = 0;
2819     size = MAX_PATH;
2820     state = MsiGetComponentPathA(prodcode, component, path, &size);
2821     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2822     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2823     ok(size == 10, "Expected 10, got %lu\n", size);
2824 
2825     path[0] = 0;
2826     size = MAX_PATH;
2827     state = MsiLocateComponentA(component, path, &size);
2828     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2829     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2830     ok(size == 10, "Expected 10, got %lu\n", size);
2831 
2832     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2833     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
2834     lstrcatA(keypath, prod_squashed);
2835     lstrcatA(keypath, "\\InstallProperties");
2836 
2837     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &installprop, NULL);
2838     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2839 
2840     val = 1;
2841     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
2842     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2843 
2844     /* install properties key exists */
2845     path[0] = 0;
2846     size = MAX_PATH;
2847     state = MsiGetComponentPathA(prodcode, component, path, &size);
2848     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2849     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2850     ok(size == 10, "Expected 10, got %lu\n", size);
2851 
2852     path[0] = 0;
2853     size = MAX_PATH;
2854     state = MsiLocateComponentA(component, path, &size);
2855     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2856     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2857     ok(size == 10, "Expected 10, got %lu\n", size);
2858 
2859     create_file("C:\\imapath", 11);
2860 
2861     /* file exists */
2862     path[0] = 0;
2863     size = MAX_PATH;
2864     state = MsiGetComponentPathA(prodcode, component, path, &size);
2865     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2866     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2867     ok(size == 10, "Expected 10, got %lu\n", size);
2868 
2869     path[0] = 0;
2870     size = MAX_PATH;
2871     state = MsiLocateComponentA(component, path, &size);
2872     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2873     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2874     ok(size == 10, "Expected 10, got %lu\n", size);
2875 
2876     RegDeleteValueA(compkey, prod_squashed);
2877     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2878     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2879     RegDeleteValueA(installprop, "WindowsInstaller");
2880     delete_key(installprop, "", access & KEY_WOW64_64KEY);
2881     RegCloseKey(prodkey);
2882     RegCloseKey(compkey);
2883     RegCloseKey(installprop);
2884     DeleteFileA("C:\\imapath");
2885 
2886     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2887     lstrcatA(keypath, prod_squashed);
2888 
2889     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
2890     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2891 
2892     /* user unmanaged product key exists */
2893     size = MAX_PATH;
2894     state = MsiGetComponentPathA(prodcode, component, path, &size);
2895     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2896     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2897 
2898     size = MAX_PATH;
2899     state = MsiLocateComponentA(component, path, &size);
2900     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2901     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2902 
2903     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2904     lstrcatA(keypath, "Installer\\UserData\\");
2905     lstrcatA(keypath, usersid);
2906     lstrcatA(keypath, "\\Components\\");
2907     lstrcatA(keypath, comp_squashed);
2908 
2909     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2910     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2911 
2912     /* user unmanaged component key exists */
2913     size = MAX_PATH;
2914     state = MsiGetComponentPathA(prodcode, component, path, &size);
2915     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2916     ok(size == MAX_PATH, "Expected size to be unchanged, got %ld\n", size);
2917 
2918     size = MAX_PATH;
2919     state = MsiLocateComponentA(component, path, &size);
2920     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2921     ok(size == MAX_PATH, "Expected size to be unchanged, got %ld\n", size);
2922 
2923     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2924     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2925 
2926     /* product value exists */
2927     path[0] = 0;
2928     size = MAX_PATH;
2929     state = MsiGetComponentPathA(prodcode, component, path, &size);
2930     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2931     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2932     ok(size == 10, "Expected 10, got %lu\n", size);
2933 
2934     path[0] = 0;
2935     size = MAX_PATH;
2936     state = MsiLocateComponentA(component, path, &size);
2937     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2938     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2939     ok(size == 10, "Expected 10, got %lu\n", size);
2940 
2941     create_file("C:\\imapath", 11);
2942 
2943     /* file exists */
2944     path[0] = 0;
2945     size = MAX_PATH;
2946     state = MsiGetComponentPathA(prodcode, component, path, &size);
2947     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2948     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2949     ok(size == 10, "Expected 10, got %lu\n", size);
2950 
2951     path[0] = 0;
2952     size = MAX_PATH;
2953     state = MsiLocateComponentA(component, path, &size);
2954     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2955     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2956     ok(size == 10, "Expected 10, got %lu\n", size);
2957 
2958     RegDeleteValueA(compkey, prod_squashed);
2959     RegDeleteKeyA(prodkey, "");
2960     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2961     RegCloseKey(prodkey);
2962     RegCloseKey(compkey);
2963     DeleteFileA("C:\\imapath");
2964 
2965     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
2966     lstrcatA(keypath, prod_squashed);
2967 
2968     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2969     if (res == ERROR_ACCESS_DENIED)
2970     {
2971         skip( "insufficient rights\n" );
2972         LocalFree( usersid );
2973         return;
2974     }
2975     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2976 
2977     /* local classes product key exists */
2978     size = MAX_PATH;
2979     state = MsiGetComponentPathA(prodcode, component, path, &size);
2980     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2981     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2982 
2983     size = MAX_PATH;
2984     state = MsiLocateComponentA(component, path, &size);
2985     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2986     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2987 
2988     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2989     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
2990     lstrcatA(keypath, comp_squashed);
2991 
2992     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2993     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2994 
2995     /* local user component key exists */
2996     size = MAX_PATH;
2997     state = MsiGetComponentPathA(prodcode, component, path, &size);
2998     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2999     ok(size == MAX_PATH, "Expected size to be unchanged, got %ld\n", size);
3000 
3001     size = MAX_PATH;
3002     state = MsiLocateComponentA(component, path, &size);
3003     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3004     ok(size == MAX_PATH, "Expected size to be unchanged, got %ld\n", size);
3005 
3006     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3007     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3008 
3009     /* product value exists */
3010     path[0] = 0;
3011     size = MAX_PATH;
3012     state = MsiGetComponentPathA(prodcode, component, path, &size);
3013     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3014     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3015     ok(size == 10, "Expected 10, got %lu\n", size);
3016 
3017     path[0] = 0;
3018     size = MAX_PATH;
3019     state = MsiLocateComponentA(component, path, &size);
3020     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3021     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3022     ok(size == 10, "Expected 10, got %lu\n", size);
3023 
3024     create_file("C:\\imapath", 11);
3025 
3026     /* file exists */
3027     path[0] = 0;
3028     size = MAX_PATH;
3029     state = MsiGetComponentPathA(prodcode, component, path, &size);
3030     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3031     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3032     ok(size == 10, "Expected 10, got %lu\n", size);
3033 
3034     path[0] = 0;
3035     size = MAX_PATH;
3036     state = MsiLocateComponentA(component, path, &size);
3037     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3038     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3039     ok(size == 10, "Expected 10, got %lu\n", size);
3040 
3041     RegDeleteValueA(compkey, prod_squashed);
3042     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3043     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3044     RegCloseKey(prodkey);
3045     RegCloseKey(compkey);
3046     DeleteFileA("C:\\imapath");
3047     LocalFree(usersid);
3048 }
3049 
3050 static void test_MsiGetComponentPathEx(void)
3051 {
3052     HKEY key_comp, key_installprop, key_prod;
3053     char prod[MAX_PATH], prod_squashed[MAX_PATH];
3054     char comp[MAX_PATH], comp_base85[MAX_PATH], comp_squashed[MAX_PATH];
3055     char path[MAX_PATH], path_key[MAX_PATH], *usersid;
3056     INSTALLSTATE state;
3057     DWORD size, val;
3058     REGSAM access = KEY_ALL_ACCESS;
3059     LONG res;
3060 
3061     if (!pMsiGetComponentPathExA)
3062     {
3063         win_skip( "MsiGetComponentPathExA not present\n" );
3064         return;
3065     }
3066 
3067     if (is_wow64) access |= KEY_WOW64_64KEY;
3068 
3069     create_test_guid( prod, prod_squashed );
3070     compose_base85_guid( comp, comp_base85, comp_squashed );
3071     usersid = get_user_sid();
3072 
3073     /* NULL product */
3074     size = MAX_PATH;
3075     state = pMsiGetComponentPathExA( NULL, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3076     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
3077     todo_wine ok( !size, "got %lu\n", size );
3078 
3079     /* NULL component */
3080     size = MAX_PATH;
3081     state = pMsiGetComponentPathExA( prod, NULL, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3082     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
3083     todo_wine ok( !size, "got %lu\n", size );
3084 
3085     /* non-NULL usersid, MSIINSTALLCONTEXT_MACHINE */
3086     size = MAX_PATH;
3087     state = pMsiGetComponentPathExA( prod, comp, usersid, MSIINSTALLCONTEXT_MACHINE, path, &size);
3088     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
3089     todo_wine ok( !size, "got %lu\n", size );
3090 
3091     /* NULL buf */
3092     size = MAX_PATH;
3093     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, NULL, &size );
3094     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3095     todo_wine ok( size == MAX_PATH * 2, "got %lu\n", size );
3096 
3097     /* NULL buflen */
3098     size = MAX_PATH;
3099     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, NULL );
3100     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
3101     ok( size == MAX_PATH, "got %lu\n", size );
3102 
3103     /* all params valid */
3104     size = MAX_PATH;
3105     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3106     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3107     todo_wine ok( !size, "got %lu\n", size );
3108 
3109     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3110     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Components\\" );
3111     lstrcatA( path_key, comp_squashed );
3112 
3113     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3114     if (res == ERROR_ACCESS_DENIED)
3115     {
3116         skip( "insufficient rights\n" );
3117         LocalFree( usersid );
3118         return;
3119     }
3120     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3121 
3122     /* local system component key exists */
3123     size = MAX_PATH;
3124     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3125     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3126 
3127     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3128     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3129 
3130     /* product value exists */
3131     path[0] = 0;
3132     size = MAX_PATH;
3133     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3134     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3135     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3136     ok( size == 20, "got %lu\n", size );
3137 
3138     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3139     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Products\\" );
3140     lstrcatA( path_key, prod_squashed );
3141     lstrcatA( path_key, "\\InstallProperties" );
3142 
3143     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_installprop, NULL );
3144     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3145 
3146     val = 1;
3147     res = RegSetValueExA( key_installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(val) );
3148     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3149 
3150     /* install properties key exists */
3151     path[0] = 0;
3152     size = MAX_PATH;
3153     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3154     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3155     ok( !lstrcmpA( path, "c:\\testcomponentpath"), "got %s\n", path );
3156     ok( size == 20, "got %lu\n", size );
3157 
3158     create_file( "c:\\testcomponentpath", 21 );
3159 
3160     /* file exists */
3161     path[0] = 0;
3162     size = 0;
3163     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3164     ok( state == INSTALLSTATE_MOREDATA, "got %d\n", state );
3165     ok( !path[0], "got %s\n", path );
3166     todo_wine ok( size == 40, "got %lu\n", size );
3167 
3168     path[0] = 0;
3169     size = MAX_PATH;
3170     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3171     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3172     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3173     ok( size == 20, "got %lu\n", size );
3174 
3175     RegDeleteValueA( key_comp, prod_squashed );
3176     delete_key( key_comp, "", access & KEY_WOW64_64KEY );
3177     RegDeleteValueA( key_installprop, "WindowsInstaller" );
3178     delete_key( key_installprop, "", access & KEY_WOW64_64KEY );
3179     RegCloseKey( key_comp );
3180     RegCloseKey( key_installprop );
3181     DeleteFileA( "c:\\testcomponentpath" );
3182 
3183     lstrcpyA( path_key, "Software\\Microsoft\\Installer\\Products\\" );
3184     lstrcatA( path_key, prod_squashed );
3185 
3186     res = RegCreateKeyA( HKEY_CURRENT_USER, path_key, &key_prod );
3187     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3188 
3189     /* user unmanaged product key exists */
3190     size = MAX_PATH;
3191     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3192     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3193     todo_wine ok(!size, "got %lu\n", size);
3194 
3195     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3196     lstrcatA( path_key, "Installer\\UserData\\" );
3197     lstrcatA( path_key, usersid );
3198     lstrcatA( path_key, "\\Components\\" );
3199     lstrcatA( path_key, comp_squashed );
3200 
3201     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3202     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3203 
3204     /* user unmanaged component key exists */
3205     size = MAX_PATH;
3206     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3207     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3208     todo_wine ok(!size, "got %lu\n", size);
3209 
3210     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3211     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3212 
3213     /* product value exists */
3214     path[0] = 0;
3215     size = MAX_PATH;
3216     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3217     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3218     ok( !lstrcmpA( path, "c:\\testcomponentpath"), "got %s\n", path );
3219     ok( size == 20, "got %lu\n", size );
3220 
3221     create_file( "c:\\testcomponentpath", 21 );
3222 
3223     /* file exists */
3224     path[0] = 0;
3225     size = MAX_PATH;
3226     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3227     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3228     ok( !lstrcmpA( path, "c:\\testcomponentpath"), "got %s\n", path );
3229     ok( size == 20, "got %lu\n", size );
3230 
3231     RegDeleteValueA( key_comp, prod_squashed );
3232     RegDeleteKeyA( key_prod, "" );
3233     delete_key( key_comp, "", access & KEY_WOW64_64KEY );
3234     RegCloseKey( key_prod );
3235     RegCloseKey( key_comp );
3236     DeleteFileA( "c:\\testcomponentpath" );
3237 
3238     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3239     lstrcatA( path_key, "Installer\\Managed\\" );
3240     lstrcatA( path_key, usersid );
3241     lstrcatA( path_key, "\\Installer\\Products\\" );
3242     lstrcatA( path_key, prod_squashed );
3243 
3244     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_prod, NULL );
3245     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3246 
3247     /* user managed product key exists */
3248     size = MAX_PATH;
3249     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3250     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3251 
3252     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3253     lstrcatA( path_key, "Installer\\UserData\\" );
3254     lstrcatA( path_key, usersid );
3255     lstrcatA( path_key, "\\Components\\" );
3256     lstrcatA( path_key, comp_squashed );
3257 
3258     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3259     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3260 
3261     /* user managed component key exists */
3262     size = MAX_PATH;
3263     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3264     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3265 
3266     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3267     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3268 
3269     /* product value exists */
3270     path[0] = 0;
3271     size = MAX_PATH;
3272     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3273     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3274     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3275     ok( size == 20, "got %lu\n", size );
3276 
3277     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3278     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Products\\" );
3279     lstrcatA( path_key, prod_squashed );
3280     lstrcatA( path_key, "\\InstallProperties" );
3281 
3282     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_installprop, NULL );
3283     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3284 
3285     val = 1;
3286     res = RegSetValueExA( key_installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(val) );
3287     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3288 
3289     /* install properties key exists */
3290     path[0] = 0;
3291     size = MAX_PATH;
3292     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3293     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3294     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3295     ok( size == 20, "got %lu\n", size );
3296 
3297     create_file( "c:\\testcomponentpath", 21 );
3298 
3299     /* file exists */
3300     path[0] = 0;
3301     size = MAX_PATH;
3302     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3303     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3304     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3305     ok( size == 20, "got %lu\n", size );
3306 
3307     RegDeleteValueA( key_comp, prod_squashed );
3308     delete_key( key_prod, "", access & KEY_WOW64_64KEY );
3309     delete_key( key_comp, "", access & KEY_WOW64_64KEY );
3310     RegDeleteValueA( key_installprop, "WindowsInstaller" );
3311     delete_key( key_installprop, "", access & KEY_WOW64_64KEY );
3312     RegCloseKey( key_prod );
3313     RegCloseKey( key_comp );
3314     RegCloseKey( key_installprop );
3315     DeleteFileA( "c:\\testcomponentpath" );
3316     lstrcpyA( path_key, "Software\\Classes\\Installer\\Products\\" );
3317     lstrcatA( path_key, prod_squashed );
3318 
3319     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_prod, NULL );
3320     if (res == ERROR_ACCESS_DENIED)
3321     {
3322         skip( "insufficient rights\n" );
3323         LocalFree( usersid );
3324         return;
3325     }
3326     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3327 
3328     /* local classes product key exists */
3329     size = MAX_PATH;
3330     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3331     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3332     todo_wine ok(!size, "got %lu\n", size);
3333 
3334     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3335     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Components\\" );
3336     lstrcatA( path_key, comp_squashed );
3337 
3338     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE,  path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3339     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3340 
3341     /* local user component key exists */
3342     size = MAX_PATH;
3343     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3344     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3345     todo_wine ok(!size, "got %lu\n", size);
3346 
3347     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3348     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3349 
3350     /* product value exists */
3351     path[0] = 0;
3352     size = MAX_PATH;
3353     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3354     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3355     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3356     ok( size == 20, "got %lu\n", size );
3357 
3358     create_file( "c:\\testcomponentpath", 21 );
3359 
3360     /* file exists */
3361     path[0] = 0;
3362     size = MAX_PATH;
3363     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3364     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3365     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3366     ok( size == 20, "got %lu\n", size );
3367 
3368     RegDeleteValueA( key_comp, prod_squashed );
3369     delete_key( key_prod, "", access & KEY_WOW64_64KEY );
3370     delete_key( key_comp, "", access & KEY_WOW64_64KEY );
3371     RegCloseKey( key_prod );
3372     RegCloseKey( key_comp );
3373     DeleteFileA( "c:\\testcomponentpath" );
3374     LocalFree( usersid );
3375 }
3376 
3377 static void test_MsiProvideComponent(void)
3378 {
3379     INSTALLSTATE state;
3380     char buf[0x100];
3381     WCHAR bufW[0x100];
3382     DWORD len, len2;
3383     UINT r;
3384 
3385     if (is_process_limited())
3386     {
3387         skip("process is limited\n");
3388         return;
3389     }
3390 
3391     create_test_files();
3392     create_file("msitest\\sourcedir.txt", 1000);
3393     create_database(msifile, sd_tables, ARRAY_SIZE(sd_tables));
3394 
3395     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3396 
3397     buf[0] = 0;
3398     len = sizeof(buf);
3399     r = pMsiProvideComponentA("{90120000-0070-0000-0000-4000000FF1CE}",
3400                               "{17961602-C4E2-482E-800A-DF6E627549CF}",
3401                               "ProductFiles", INSTALLMODE_NODETECTION, buf, &len);
3402     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
3403 
3404     r = MsiInstallProductA(msifile, NULL);
3405     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3406 
3407     state = MsiQueryFeatureStateA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir");
3408     ok(state == INSTALLSTATE_LOCAL, "got %d\n", state);
3409 
3410     buf[0] = 0;
3411     len = sizeof(buf);
3412     r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir",
3413                               "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
3414                               INSTALLMODE_NODETECTION, buf, &len);
3415     ok(r == ERROR_SUCCESS, "got %u\n", r);
3416     ok(buf[0], "empty path\n");
3417     ok(len == lstrlenA(buf), "got %lu\n", len);
3418 
3419     len2 = 0;
3420     r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir",
3421                               "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
3422                               INSTALLMODE_NODETECTION, NULL, &len2);
3423     ok(r == ERROR_SUCCESS, "got %u\n", r);
3424     ok(len2 == len, "got %lu\n", len2);
3425 
3426     len2 = 0;
3427     r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir",
3428                               "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
3429                               INSTALLMODE_NODETECTION, buf, &len2);
3430     ok(r == ERROR_MORE_DATA, "got %u\n", r);
3431     ok(len2 == len, "got %lu\n", len2);
3432 
3433     /* wide version */
3434 
3435     bufW[0] = 0;
3436     len = sizeof(buf);
3437     r = pMsiProvideComponentW(L"{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", L"sourcedir",
3438                               L"{DD422F92-3ED8-49B5-A0B7-F266F98357DF}", INSTALLMODE_NODETECTION, bufW, &len);
3439     ok(r == ERROR_SUCCESS, "got %u\n", r);
3440     ok(bufW[0], "empty path\n");
3441     ok(len == lstrlenW(bufW), "got %lu\n", len);
3442 
3443     len2 = 0;
3444     r = pMsiProvideComponentW(L"{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", L"sourcedir",
3445                               L"{DD422F92-3ED8-49B5-A0B7-F266F98357DF}", INSTALLMODE_NODETECTION, NULL, &len2);
3446     ok(r == ERROR_SUCCESS, "got %u\n", r);
3447     ok(len2 == len, "got %lu\n", len2);
3448 
3449     len2 = 0;
3450     r = pMsiProvideComponentW(L"{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", L"sourcedir",
3451                               L"{DD422F92-3ED8-49B5-A0B7-F266F98357DF}", INSTALLMODE_NODETECTION, bufW, &len2);
3452     ok(r == ERROR_MORE_DATA, "got %u\n", r);
3453     ok(len2 == len, "got %lu\n", len2);
3454 
3455     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3456     ok(r == ERROR_SUCCESS, "got %u\n", r);
3457 
3458     DeleteFileA("msitest\\sourcedir.txt");
3459     delete_test_files();
3460     DeleteFileA(msifile);
3461 }
3462 
3463 static void test_MsiProvideQualifiedComponentEx(void)
3464 {
3465     UINT r;
3466     INSTALLSTATE state;
3467     char comp[39], comp_squashed[33], comp2[39], comp2_base85[21], comp2_squashed[33];
3468     char prod[39], prod_base85[21], prod_squashed[33];
3469     char desc[MAX_PATH], buf[MAX_PATH], keypath[MAX_PATH], path[MAX_PATH];
3470     DWORD len = sizeof(buf);
3471     REGSAM access = KEY_ALL_ACCESS;
3472     HKEY hkey, hkey2, hkey3, hkey4, hkey5;
3473     LONG res;
3474 
3475     if (is_process_limited())
3476     {
3477         skip( "process is limited\n" );
3478         return;
3479     }
3480 
3481     create_test_guid( comp, comp_squashed );
3482     compose_base85_guid( comp2, comp2_base85, comp2_squashed );
3483     compose_base85_guid( prod, prod_base85, prod_squashed );
3484 
3485     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3486     ok( r == ERROR_UNKNOWN_COMPONENT, "got %u\n", r );
3487 
3488     lstrcpyA( keypath, "Software\\Classes\\Installer\\Components\\" );
3489     lstrcatA( keypath, comp_squashed );
3490 
3491     if (is_wow64) access |= KEY_WOW64_64KEY;
3492     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey, NULL );
3493     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3494 
3495     lstrcpyA( desc, prod_base85 );
3496     memcpy( desc + lstrlenA(desc), "feature<\0", sizeof("feature<\0") );
3497     res = RegSetValueExA( hkey, "qualifier", 0, REG_MULTI_SZ, (const BYTE *)desc,
3498                           lstrlenA(prod_base85) + sizeof("feature<\0") );
3499     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3500 
3501     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3502     ok( r == ERROR_UNKNOWN_PRODUCT, "got %u\n", r );
3503 
3504     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, NULL, 0, 0, buf, &len );
3505     ok( r == ERROR_UNKNOWN_PRODUCT, "got %u\n", r );
3506 
3507     state = MsiQueryProductStateA( prod );
3508     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3509 
3510     lstrcpyA( keypath, "Software\\Classes\\Installer\\Products\\" );
3511     lstrcatA( keypath, prod_squashed );
3512 
3513     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey2, NULL );
3514     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3515 
3516     state = MsiQueryProductStateA( prod );
3517     ok( state == INSTALLSTATE_ADVERTISED, "got %d\n", state );
3518 
3519     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3520     todo_wine ok( r == ERROR_UNKNOWN_FEATURE, "got %u\n", r );
3521 
3522     lstrcpyA( keypath, "Software\\Classes\\Installer\\Features\\" );
3523     lstrcatA( keypath, prod_squashed );
3524 
3525     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey3, NULL );
3526     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3527 
3528     state = MsiQueryFeatureStateA( prod, "feature" );
3529     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3530 
3531     res = RegSetValueExA( hkey3, "feature", 0, REG_SZ, (const BYTE *)"", 1 );
3532     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3533 
3534     state = MsiQueryFeatureStateA( prod, "feature" );
3535     ok( state == INSTALLSTATE_ADVERTISED, "got %d\n", state );
3536 
3537     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3538     ok( r == ERROR_FILE_NOT_FOUND, "got %u\n", r );
3539 
3540     len = sizeof(buf);
3541     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, NULL, 0, 0, buf, &len );
3542     ok( r == ERROR_FILE_NOT_FOUND, "got %u\n", r );
3543 
3544     lstrcpyA( keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\" );
3545     lstrcatA( keypath, prod_squashed );
3546     lstrcatA( keypath, "\\Features" );
3547 
3548     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey4, NULL );
3549     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3550 
3551     res = RegSetValueExA( hkey4, "feature", 0, REG_SZ, (const BYTE *)comp2_base85, sizeof(comp2_base85) );
3552     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3553 
3554     state = MsiQueryFeatureStateA( prod, "feature" );
3555     ok( state == INSTALLSTATE_ADVERTISED, "got %d\n", state );
3556 
3557     lstrcpyA( keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\" );
3558     lstrcatA( keypath, comp2_squashed );
3559 
3560     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey5, NULL );
3561     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3562 
3563     res = RegSetValueExA( hkey5, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\nosuchfile", sizeof("c:\\nosuchfile") );
3564     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3565 
3566     state = MsiQueryFeatureStateA( prod, "feature" );
3567     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3568 
3569     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3570     ok( r == ERROR_FILE_NOT_FOUND, "got %u\n", r );
3571 
3572     GetCurrentDirectoryA( MAX_PATH, path );
3573     lstrcatA( path, "\\msitest" );
3574     CreateDirectoryA( path, NULL );
3575     lstrcatA( path, "\\test.txt" );
3576     create_file_data( path, "test", 100 );
3577 
3578     res = RegSetValueExA( hkey5, prod_squashed, 0, REG_SZ, (const BYTE *)path, lstrlenA(path) + 1 );
3579     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3580 
3581     buf[0] = 0;
3582     len = sizeof(buf);
3583     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3584     ok( r == ERROR_SUCCESS, "got %u\n", r );
3585     ok( len == lstrlenA(path), "got %lu\n", len );
3586     ok( !lstrcmpA( path, buf ), "got '%s'\n", buf );
3587 
3588     DeleteFileA( "msitest\\text.txt" );
3589     RemoveDirectoryA( "msitest" );
3590 
3591     delete_key( hkey5, "", access & KEY_WOW64_64KEY );
3592     RegCloseKey( hkey5 );
3593     delete_key( hkey4, "", access & KEY_WOW64_64KEY );
3594     RegCloseKey( hkey4 );
3595     delete_key( hkey3, "", access & KEY_WOW64_64KEY );
3596     RegCloseKey( hkey3 );
3597     delete_key( hkey2, "", access & KEY_WOW64_64KEY );
3598     RegCloseKey( hkey2 );
3599     delete_key( hkey, "", access & KEY_WOW64_64KEY );
3600     RegCloseKey( hkey );
3601 }
3602 
3603 static void test_MsiGetProductCode(void)
3604 {
3605     HKEY compkey, prodkey;
3606     CHAR prodcode[MAX_PATH];
3607     CHAR prod_squashed[MAX_PATH];
3608     CHAR prodcode2[MAX_PATH];
3609     CHAR prod2_squashed[MAX_PATH];
3610     CHAR component[MAX_PATH];
3611     CHAR comp_base85[MAX_PATH];
3612     CHAR comp_squashed[MAX_PATH];
3613     CHAR keypath[MAX_PATH];
3614     CHAR product[MAX_PATH];
3615     LPSTR usersid;
3616     LONG res;
3617     UINT r;
3618     REGSAM access = KEY_ALL_ACCESS;
3619 
3620     create_test_guid(prodcode, prod_squashed);
3621     create_test_guid(prodcode2, prod2_squashed);
3622     compose_base85_guid(component, comp_base85, comp_squashed);
3623     usersid = get_user_sid();
3624 
3625     if (is_wow64)
3626         access |= KEY_WOW64_64KEY;
3627 
3628     /* szComponent is NULL */
3629     lstrcpyA(product, "prod");
3630     r = MsiGetProductCodeA(NULL, product);
3631     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3632     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3633 
3634     /* szComponent is empty */
3635     lstrcpyA(product, "prod");
3636     r = MsiGetProductCodeA("", product);
3637     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3638     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3639 
3640     /* garbage szComponent */
3641     lstrcpyA(product, "prod");
3642     r = MsiGetProductCodeA("garbage", product);
3643     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3644     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3645 
3646     /* guid without brackets */
3647     lstrcpyA(product, "prod");
3648     r = MsiGetProductCodeA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", product);
3649     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3650     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3651 
3652     /* guid with brackets */
3653     lstrcpyA(product, "prod");
3654     r = MsiGetProductCodeA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", product);
3655     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3656     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3657 
3658     /* same length as guid, but random */
3659     lstrcpyA(product, "prod");
3660     r = MsiGetProductCodeA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", product);
3661     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3662     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3663 
3664     /* all params correct, szComponent not published */
3665     lstrcpyA(product, "prod");
3666     r = MsiGetProductCodeA(component, product);
3667     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3668     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3669 
3670     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3671     lstrcatA(keypath, "Installer\\UserData\\");
3672     lstrcatA(keypath, usersid);
3673     lstrcatA(keypath, "\\Components\\");
3674     lstrcatA(keypath, comp_squashed);
3675 
3676     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3677     if (res == ERROR_ACCESS_DENIED)
3678     {
3679         skip("Not enough rights to perform tests\n");
3680         LocalFree(usersid);
3681         return;
3682     }
3683     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3684 
3685     /* user unmanaged component key exists */
3686     lstrcpyA(product, "prod");
3687     r = MsiGetProductCodeA(component, product);
3688     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3689     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3690 
3691     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3692     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3693 
3694     /* product value exists */
3695     lstrcpyA(product, "prod");
3696     r = MsiGetProductCodeA(component, product);
3697     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3698     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3699 
3700     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
3701     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3702 
3703     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3704     lstrcatA(keypath, "Installer\\Managed\\");
3705     lstrcatA(keypath, usersid);
3706     lstrcatA(keypath, "\\Installer\\Products\\");
3707     lstrcatA(keypath, prod_squashed);
3708 
3709     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3710     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3711 
3712     /* user managed product key of first product exists */
3713     lstrcpyA(product, "prod");
3714     r = MsiGetProductCodeA(component, product);
3715     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3716     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3717 
3718     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3719     RegCloseKey(prodkey);
3720 
3721     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
3722     lstrcatA(keypath, prod_squashed);
3723 
3724     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
3725     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3726 
3727     /* user unmanaged product key exists */
3728     lstrcpyA(product, "prod");
3729     r = MsiGetProductCodeA(component, product);
3730     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3731     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3732 
3733     RegDeleteKeyA(prodkey, "");
3734     RegCloseKey(prodkey);
3735 
3736     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
3737     lstrcatA(keypath, prod_squashed);
3738 
3739     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3740     if (res == ERROR_ACCESS_DENIED)
3741     {
3742         skip( "insufficient rights\n" );
3743         LocalFree( usersid );
3744         return;
3745     }
3746     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3747 
3748     /* local classes product key exists */
3749     lstrcpyA(product, "prod");
3750     r = MsiGetProductCodeA(component, product);
3751     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3752     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3753 
3754     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3755     RegCloseKey(prodkey);
3756 
3757     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3758     lstrcatA(keypath, "Installer\\Managed\\");
3759     lstrcatA(keypath, usersid);
3760     lstrcatA(keypath, "\\Installer\\Products\\");
3761     lstrcatA(keypath, prod2_squashed);
3762 
3763     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3764     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3765 
3766     /* user managed product key of second product 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, prodcode2), "Expected %s, got %s\n", prodcode2, product);
3771 
3772     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3773     RegCloseKey(prodkey);
3774     RegDeleteValueA(compkey, prod_squashed);
3775     RegDeleteValueA(compkey, prod2_squashed);
3776     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3777     RegCloseKey(compkey);
3778 
3779     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3780     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
3781     lstrcatA(keypath, comp_squashed);
3782 
3783     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3784     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3785 
3786     /* local user component key exists */
3787     lstrcpyA(product, "prod");
3788     r = MsiGetProductCodeA(component, product);
3789     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3790     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3791 
3792     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3793     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3794 
3795     /* product value exists */
3796     lstrcpyA(product, "prod");
3797     r = MsiGetProductCodeA(component, product);
3798     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3799     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3800 
3801     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
3802     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3803 
3804     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3805     lstrcatA(keypath, "Installer\\Managed\\");
3806     lstrcatA(keypath, usersid);
3807     lstrcatA(keypath, "\\Installer\\Products\\");
3808     lstrcatA(keypath, prod_squashed);
3809 
3810     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3811     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3812 
3813     /* user managed product key of first product exists */
3814     lstrcpyA(product, "prod");
3815     r = MsiGetProductCodeA(component, product);
3816     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3817     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3818 
3819     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3820     RegCloseKey(prodkey);
3821 
3822     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
3823     lstrcatA(keypath, prod_squashed);
3824 
3825     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
3826     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3827 
3828     /* user unmanaged product key exists */
3829     lstrcpyA(product, "prod");
3830     r = MsiGetProductCodeA(component, product);
3831     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3832     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3833 
3834     RegDeleteKeyA(prodkey, "");
3835     RegCloseKey(prodkey);
3836 
3837     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
3838     lstrcatA(keypath, prod_squashed);
3839 
3840     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3841     if (res == ERROR_ACCESS_DENIED)
3842     {
3843         skip( "insufficient rights\n" );
3844         LocalFree( usersid );
3845         return;
3846     }
3847     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3848 
3849     /* local classes product key exists */
3850     lstrcpyA(product, "prod");
3851     r = MsiGetProductCodeA(component, product);
3852     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3853     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3854 
3855     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3856     RegCloseKey(prodkey);
3857 
3858     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3859     lstrcatA(keypath, "Installer\\Managed\\");
3860     lstrcatA(keypath, usersid);
3861     lstrcatA(keypath, "\\Installer\\Products\\");
3862     lstrcatA(keypath, prod2_squashed);
3863 
3864     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3865     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3866 
3867     /* user managed product key of second product 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, prodcode2), "Expected %s, got %s\n", prodcode2, product);
3872 
3873     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3874     RegCloseKey(prodkey);
3875     RegDeleteValueA(compkey, prod_squashed);
3876     RegDeleteValueA(compkey, prod2_squashed);
3877     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3878     RegCloseKey(compkey);
3879     LocalFree(usersid);
3880 }
3881 
3882 static void test_MsiEnumClients(void)
3883 {
3884     HKEY compkey;
3885     CHAR prodcode[MAX_PATH];
3886     CHAR prod_squashed[MAX_PATH];
3887     CHAR prodcode2[MAX_PATH];
3888     CHAR prod2_squashed[MAX_PATH];
3889     CHAR component[MAX_PATH];
3890     CHAR comp_base85[MAX_PATH];
3891     CHAR comp_squashed[MAX_PATH];
3892     CHAR product[MAX_PATH];
3893     CHAR keypath[MAX_PATH];
3894     LPSTR usersid;
3895     LONG res;
3896     UINT r;
3897     REGSAM access = KEY_ALL_ACCESS;
3898 
3899     create_test_guid(prodcode, prod_squashed);
3900     create_test_guid(prodcode2, prod2_squashed);
3901     compose_base85_guid(component, comp_base85, comp_squashed);
3902     usersid = get_user_sid();
3903 
3904     if (is_wow64)
3905         access |= KEY_WOW64_64KEY;
3906 
3907     /* NULL szComponent */
3908     product[0] = '\0';
3909     r = MsiEnumClientsA(NULL, 0, product);
3910     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3911     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3912 
3913     /* empty szComponent */
3914     product[0] = '\0';
3915     r = MsiEnumClientsA("", 0, product);
3916     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3917     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3918 
3919     /* NULL lpProductBuf */
3920     r = MsiEnumClientsA(component, 0, NULL);
3921     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3922 
3923     /* all params correct, component missing */
3924     product[0] = '\0';
3925     r = MsiEnumClientsA(component, 0, product);
3926     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3927     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3928 
3929     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3930     lstrcatA(keypath, "Installer\\UserData\\");
3931     lstrcatA(keypath, usersid);
3932     lstrcatA(keypath, "\\Components\\");
3933     lstrcatA(keypath, comp_squashed);
3934 
3935     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3936     if (res == ERROR_ACCESS_DENIED)
3937     {
3938         skip("Not enough rights to perform tests\n");
3939         LocalFree(usersid);
3940         return;
3941     }
3942     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3943 
3944     /* user unmanaged component key exists */
3945     product[0] = '\0';
3946     r = MsiEnumClientsA(component, 0, product);
3947     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3948     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3949 
3950     /* index > 0, no products exist */
3951     product[0] = '\0';
3952     r = MsiEnumClientsA(component, 1, product);
3953     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3954     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3955 
3956     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3957     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3958 
3959     /* product value exists */
3960     r = MsiEnumClientsA(component, 0, product);
3961     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3962     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3963 
3964     /* try index 0 again */
3965     product[0] = '\0';
3966     r = MsiEnumClientsA(component, 0, product);
3967     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3968     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3969 
3970     /* try index 1, second product value does not exist */
3971     product[0] = '\0';
3972     r = MsiEnumClientsA(component, 1, product);
3973     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3974     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3975 
3976     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
3977     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3978 
3979     /* try index 1, second product value does exist */
3980     product[0] = '\0';
3981     r = MsiEnumClientsA(component, 1, product);
3982     todo_wine
3983     {
3984         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3985         ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3986     }
3987 
3988     /* start the enumeration over */
3989     product[0] = '\0';
3990     r = MsiEnumClientsA(component, 0, product);
3991     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3992     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
3993        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
3994 
3995     /* correctly query second product */
3996     product[0] = '\0';
3997     r = MsiEnumClientsA(component, 1, product);
3998     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3999     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
4000        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
4001 
4002     RegDeleteValueA(compkey, prod_squashed);
4003     RegDeleteValueA(compkey, prod2_squashed);
4004     delete_key(compkey, "", access & KEY_WOW64_64KEY);
4005     RegCloseKey(compkey);
4006 
4007     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4008     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
4009     lstrcatA(keypath, comp_squashed);
4010 
4011     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
4012     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4013 
4014     /* user local component key exists */
4015     product[0] = '\0';
4016     r = MsiEnumClientsA(component, 0, product);
4017     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
4018     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4019 
4020     /* index > 0, no products exist */
4021     product[0] = '\0';
4022     r = MsiEnumClientsA(component, 1, product);
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     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
4027     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4028 
4029     /* product value exists */
4030     product[0] = '\0';
4031     r = MsiEnumClientsA(component, 0, product);
4032     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4033     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4034 
4035     /* try index 0 again */
4036     product[0] = '\0';
4037     r = MsiEnumClientsA(component, 0, product);
4038     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4039 
4040     /* try index 1, second product value does not exist */
4041     product[0] = '\0';
4042     r = MsiEnumClientsA(component, 1, product);
4043     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4044     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4045 
4046     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
4047     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4048 
4049     /* try index 1, second product value does exist */
4050     product[0] = '\0';
4051     r = MsiEnumClientsA(component, 1, product);
4052     todo_wine
4053     {
4054         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4055         ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4056     }
4057 
4058     /* start the enumeration over */
4059     product[0] = '\0';
4060     r = MsiEnumClientsA(component, 0, product);
4061     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4062     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
4063        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
4064 
4065     /* correctly query second product */
4066     product[0] = '\0';
4067     r = MsiEnumClientsA(component, 1, product);
4068     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4069     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
4070        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
4071 
4072     RegDeleteValueA(compkey, prod_squashed);
4073     RegDeleteValueA(compkey, prod2_squashed);
4074     delete_key(compkey, "", access & KEY_WOW64_64KEY);
4075     RegCloseKey(compkey);
4076     LocalFree(usersid);
4077 }
4078 
4079 static void get_version_info(LPSTR path, LPSTR *vercheck, LPDWORD verchecksz,
4080                              LPSTR *langcheck, LPDWORD langchecksz)
4081 {
4082     LPSTR version;
4083     VS_FIXEDFILEINFO *ffi;
4084     DWORD size = GetFileVersionInfoSizeA(path, NULL);
4085     UINT len;
4086     USHORT *lang;
4087 
4088     version = malloc(size);
4089     GetFileVersionInfoA(path, 0, size, version);
4090 
4091     VerQueryValueA(version, "\\", (LPVOID *)&ffi, &len);
4092     *vercheck = malloc(MAX_PATH);
4093     sprintf(*vercheck, "%d.%d.%d.%d", HIWORD(ffi->dwFileVersionMS),
4094             LOWORD(ffi->dwFileVersionMS), HIWORD(ffi->dwFileVersionLS),
4095             LOWORD(ffi->dwFileVersionLS));
4096     *verchecksz = lstrlenA(*vercheck);
4097 
4098     VerQueryValueA(version, "\\VarFileInfo\\Translation", (void **)&lang, &len);
4099     *langcheck = malloc(MAX_PATH);
4100     sprintf(*langcheck, "%d", *lang);
4101     *langchecksz = lstrlenA(*langcheck);
4102 
4103     free(version);
4104 }
4105 
4106 static void test_MsiGetFileVersion(void)
4107 {
4108     UINT r;
4109     DWORD versz, langsz;
4110     char version[MAX_PATH];
4111     char lang[MAX_PATH];
4112     char path[MAX_PATH];
4113     LPSTR vercheck, langcheck;
4114     DWORD verchecksz, langchecksz;
4115 
4116     /* NULL szFilePath */
4117     r = MsiGetFileVersionA(NULL, NULL, NULL, NULL, NULL);
4118     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4119 
4120     versz = MAX_PATH;
4121     langsz = MAX_PATH;
4122     lstrcpyA(version, "version");
4123     lstrcpyA(lang, "lang");
4124     r = MsiGetFileVersionA(NULL, version, &versz, lang, &langsz);
4125     ok(r == ERROR_INVALID_PARAMETER,
4126        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4127     ok(!lstrcmpA(version, "version"),
4128        "Expected version to be unchanged, got %s\n", version);
4129     ok(versz == MAX_PATH, "got %lu\n", versz);
4130     ok(!lstrcmpA(lang, "lang"),
4131        "Expected lang to be unchanged, got %s\n", lang);
4132     ok(langsz == MAX_PATH, "got %lu\n", langsz);
4133 
4134     /* empty szFilePath */
4135     r = MsiGetFileVersionA("", NULL, NULL, NULL, NULL);
4136     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4137 
4138     versz = MAX_PATH;
4139     langsz = MAX_PATH;
4140     lstrcpyA(version, "version");
4141     lstrcpyA(lang, "lang");
4142     r = MsiGetFileVersionA("", version, &versz, lang, &langsz);
4143     ok(r == ERROR_FILE_NOT_FOUND,
4144        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4145     ok(!lstrcmpA(version, "version"),
4146        "Expected version to be unchanged, got %s\n", version);
4147     ok(versz == MAX_PATH, "got %lu\n", versz);
4148     ok(!lstrcmpA(lang, "lang"),
4149        "Expected lang to be unchanged, got %s\n", lang);
4150     ok(langsz == MAX_PATH, "got %lu\n", langsz);
4151 
4152     /* nonexistent szFilePath */
4153     versz = MAX_PATH;
4154     langsz = MAX_PATH;
4155     lstrcpyA(version, "version");
4156     lstrcpyA(lang, "lang");
4157     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
4158     ok(r == ERROR_FILE_NOT_FOUND,
4159        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4160     ok(!lstrcmpA(version, "version"),
4161        "Expected version to be unchanged, got %s\n", version);
4162     ok(versz == MAX_PATH, "got %lu\n", versz);
4163     ok(!lstrcmpA(lang, "lang"),
4164        "Expected lang to be unchanged, got %s\n", lang);
4165     ok(langsz == MAX_PATH, "got %lu\n", langsz);
4166 
4167     /* nonexistent szFilePath, valid lpVersionBuf, NULL pcchVersionBuf */
4168     versz = MAX_PATH;
4169     langsz = MAX_PATH;
4170     lstrcpyA(version, "version");
4171     lstrcpyA(lang, "lang");
4172     r = MsiGetFileVersionA("nonexistent", version, NULL, lang, &langsz);
4173     ok(r == ERROR_INVALID_PARAMETER,
4174        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4175     ok(!lstrcmpA(version, "version"),
4176        "Expected version to be unchanged, got %s\n", version);
4177     ok(versz == MAX_PATH, "got %lu\n", versz);
4178     ok(!lstrcmpA(lang, "lang"),
4179        "Expected lang to be unchanged, got %s\n", lang);
4180     ok(langsz == MAX_PATH, "got %lu\n", langsz);
4181 
4182     /* nonexistent szFilePath, valid lpLangBuf, NULL pcchLangBuf */
4183     versz = MAX_PATH;
4184     langsz = MAX_PATH;
4185     lstrcpyA(version, "version");
4186     lstrcpyA(lang, "lang");
4187     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, NULL);
4188     ok(r == ERROR_INVALID_PARAMETER,
4189        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4190     ok(!lstrcmpA(version, "version"),
4191        "Expected version to be unchanged, got %s\n", version);
4192     ok(versz == MAX_PATH, "got %lu\n", versz);
4193     ok(!lstrcmpA(lang, "lang"),
4194        "Expected lang to be unchanged, got %s\n", lang);
4195     ok(langsz == MAX_PATH, "got %lu\n", langsz);
4196 
4197     /* nonexistent szFilePath, valid lpVersionBuf, pcchVersionBuf is zero */
4198     versz = 0;
4199     langsz = MAX_PATH;
4200     lstrcpyA(version, "version");
4201     lstrcpyA(lang, "lang");
4202     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
4203     ok(r == ERROR_FILE_NOT_FOUND,
4204        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4205     ok(!lstrcmpA(version, "version"),
4206        "Expected version to be unchanged, got %s\n", version);
4207     ok(versz == 0, "Expected 0, got %lu\n", versz);
4208     ok(!lstrcmpA(lang, "lang"),
4209        "Expected lang to be unchanged, got %s\n", lang);
4210     ok(langsz == MAX_PATH, "got %lu\n", langsz);
4211 
4212     /* nonexistent szFilePath, valid lpLangBuf, pcchLangBuf is zero */
4213     versz = MAX_PATH;
4214     langsz = 0;
4215     lstrcpyA(version, "version");
4216     lstrcpyA(lang, "lang");
4217     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
4218     ok(r == ERROR_FILE_NOT_FOUND,
4219        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4220     ok(!lstrcmpA(version, "version"),
4221        "Expected version to be unchanged, got %s\n", version);
4222     ok(versz == MAX_PATH, "got %lu\n", versz);
4223     ok(!lstrcmpA(lang, "lang"),
4224        "Expected lang to be unchanged, got %s\n", lang);
4225     ok(langsz == 0, "Expected 0, got %lu\n", langsz);
4226 
4227     /* nonexistent szFilePath, rest NULL */
4228     r = MsiGetFileVersionA("nonexistent", NULL, NULL, NULL, NULL);
4229     ok(r == ERROR_FILE_NOT_FOUND,
4230        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4231 
4232     create_file("ver.txt", 20);
4233 
4234     /* file exists, no version information */
4235     r = MsiGetFileVersionA("ver.txt", NULL, NULL, NULL, NULL);
4236     ok(r == ERROR_FILE_INVALID, "Expected ERROR_FILE_INVALID, got %d\n", r);
4237 
4238     versz = MAX_PATH;
4239     langsz = MAX_PATH;
4240     lstrcpyA(version, "version");
4241     lstrcpyA(lang, "lang");
4242     r = MsiGetFileVersionA("ver.txt", version, &versz, lang, &langsz);
4243     ok(versz == MAX_PATH, "got %lu\n", versz);
4244     ok(!lstrcmpA(version, "version"),
4245        "Expected version to be unchanged, got %s\n", version);
4246     ok(langsz == MAX_PATH, "got %lu\n", langsz);
4247     ok(!lstrcmpA(lang, "lang"),
4248        "Expected lang to be unchanged, got %s\n", lang);
4249     ok(r == ERROR_FILE_INVALID,
4250        "Expected ERROR_FILE_INVALID, got %d\n", r);
4251 
4252     DeleteFileA("ver.txt");
4253 
4254     /* relative path, has version information */
4255     versz = MAX_PATH;
4256     langsz = MAX_PATH;
4257     lstrcpyA(version, "version");
4258     lstrcpyA(lang, "lang");
4259     r = MsiGetFileVersionA("kernel32.dll", version, &versz, lang, &langsz);
4260     todo_wine
4261     {
4262         ok(r == ERROR_FILE_NOT_FOUND,
4263            "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4264         ok(!lstrcmpA(version, "version"),
4265            "Expected version to be unchanged, got %s\n", version);
4266         ok(versz == MAX_PATH, "got %lu\n", versz);
4267         ok(!lstrcmpA(lang, "lang"),
4268            "Expected lang to be unchanged, got %s\n", lang);
4269         ok(langsz == MAX_PATH, "got %lu\n", langsz);
4270     }
4271 
4272     GetSystemDirectoryA(path, MAX_PATH);
4273     lstrcatA(path, "\\kernel32.dll");
4274 
4275     get_version_info(path, &vercheck, &verchecksz, &langcheck, &langchecksz);
4276 
4277     /* absolute path, has version information */
4278     versz = MAX_PATH;
4279     langsz = MAX_PATH;
4280     lstrcpyA(version, "version");
4281     lstrcpyA(lang, "lang");
4282     r = MsiGetFileVersionA(path, version, &versz, lang, &langsz);
4283     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4284     if (langchecksz && !langsz)
4285     {
4286         win_skip("broken MsiGetFileVersionA detected\n");
4287         free(vercheck);
4288         free(langcheck);
4289         return;
4290     }
4291     ok(versz == verchecksz, "Expected %lu, got %lu\n", verchecksz, versz);
4292     ok(strstr(lang, langcheck) != NULL, "Expected \"%s\" in \"%s\"\n", langcheck, lang);
4293     ok(!lstrcmpA(version, vercheck),
4294         "Expected %s, got %s\n", vercheck, version);
4295 
4296     /* only check version */
4297     versz = MAX_PATH;
4298     lstrcpyA(version, "version");
4299     r = MsiGetFileVersionA(path, version, &versz, NULL, NULL);
4300     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4301     ok(versz == verchecksz, "Expected %lu, got %lu\n", verchecksz, versz);
4302     ok(!lstrcmpA(version, vercheck), "Expected %s, got %s\n", vercheck, version);
4303 
4304     /* only check language */
4305     langsz = MAX_PATH;
4306     lstrcpyA(lang, "lang");
4307     r = MsiGetFileVersionA(path, NULL, NULL, lang, &langsz);
4308     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4309     ok(strstr(lang, langcheck) != NULL, "Expected \"%s\" in \"%s\"\n", langcheck, lang);
4310 
4311     /* check neither version nor language */
4312     r = MsiGetFileVersionA(path, NULL, NULL, NULL, NULL);
4313     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4314 
4315     /* get pcchVersionBuf */
4316     versz = MAX_PATH;
4317     r = MsiGetFileVersionA(path, NULL, &versz, NULL, NULL);
4318     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4319     ok(versz == verchecksz, "Expected %lu, got %lu\n", verchecksz, versz);
4320 
4321     /* get pcchLangBuf */
4322     langsz = MAX_PATH;
4323     r = MsiGetFileVersionA(path, NULL, NULL, NULL, &langsz);
4324     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4325     ok(langsz >= langchecksz, "Expected %lu >= %lu\n", langsz, langchecksz);
4326 
4327     /* pcchVersionBuf not big enough */
4328     versz = 5;
4329     lstrcpyA(version, "version");
4330     r = MsiGetFileVersionA(path, version, &versz, NULL, NULL);
4331     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4332     ok(!strncmp(version, vercheck, 4),
4333        "Expected first 4 characters of \"%s\", got \"%s\"\n", vercheck, version);
4334     ok(versz == verchecksz, "Expected %lu, got %lu\n", verchecksz, versz);
4335 
4336     /* pcchLangBuf not big enough */
4337     langsz = 4;
4338     lstrcpyA(lang, "lang");
4339     r = MsiGetFileVersionA(path, NULL, NULL, lang, &langsz);
4340     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4341     ok(lstrcmpA(lang, "lang"), "lang not set\n");
4342     ok(langsz >= langchecksz, "Expected %lu >= %lu\n", langsz, langchecksz);
4343 
4344     /* pcchVersionBuf big enough, pcchLangBuf not big enough */
4345     versz = MAX_PATH;
4346     langsz = 0;
4347     lstrcpyA(version, "version");
4348     r = MsiGetFileVersionA(path, version, &versz, NULL, &langsz);
4349     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4350     ok(versz == verchecksz, "Expected %lu, got %lu\n", verchecksz, versz);
4351     ok(!lstrcmpA(version, vercheck), "Expected \"%s\", got \"%s\"\n", vercheck, version);
4352     ok(langsz >= langchecksz && langsz < MAX_PATH, "Expected %lu >= %lu\n", langsz, langchecksz);
4353 
4354     /* pcchVersionBuf not big enough, pcchLangBuf big enough */
4355     versz = 5;
4356     langsz = MAX_PATH;
4357     lstrcpyA(lang, "lang");
4358     r = MsiGetFileVersionA(path, NULL, &versz, lang, &langsz);
4359     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4360     ok(versz == verchecksz, "Expected %lu, got %lu\n", verchecksz, versz);
4361     ok(langsz >= langchecksz && langsz < MAX_PATH, "Expected %lu >= %lu\n", langsz, langchecksz);
4362     ok(strstr(lang, langcheck) != NULL, "expected %s in %s\n", langcheck, lang);
4363 
4364     /* NULL pcchVersionBuf and pcchLangBuf */
4365     r = MsiGetFileVersionA(path, version, NULL, lang, NULL);
4366     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4367 
4368     /* All NULL except szFilePath */
4369     r = MsiGetFileVersionA(path, NULL, NULL, NULL, NULL);
4370     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4371 
4372     free(vercheck);
4373     free(langcheck);
4374 }
4375 
4376 static void test_MsiGetProductInfo(void)
4377 {
4378     UINT r;
4379     LONG res;
4380     HKEY propkey, source;
4381     HKEY prodkey, localkey;
4382     CHAR prodcode[MAX_PATH];
4383     CHAR prod_squashed[MAX_PATH];
4384     CHAR packcode[MAX_PATH];
4385     CHAR pack_squashed[MAX_PATH];
4386     CHAR buf[MAX_PATH];
4387     CHAR keypath[MAX_PATH];
4388     LPSTR usersid;
4389     DWORD sz, val = 42;
4390     REGSAM access = KEY_ALL_ACCESS;
4391 
4392     create_test_guid(prodcode, prod_squashed);
4393     create_test_guid(packcode, pack_squashed);
4394     usersid = get_user_sid();
4395 
4396     if (is_wow64)
4397         access |= KEY_WOW64_64KEY;
4398 
4399     /* NULL szProduct */
4400     sz = MAX_PATH;
4401     lstrcpyA(buf, "apple");
4402     r = MsiGetProductInfoA(NULL, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4403     ok(r == ERROR_INVALID_PARAMETER,
4404        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4405     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4406     ok(sz == MAX_PATH, "got %lu\n", sz);
4407 
4408     /* empty szProduct */
4409     sz = MAX_PATH;
4410     lstrcpyA(buf, "apple");
4411     r = MsiGetProductInfoA("", INSTALLPROPERTY_HELPLINKA, buf, &sz);
4412     ok(r == ERROR_INVALID_PARAMETER,
4413        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4414     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4415     ok(sz == MAX_PATH, "got %lu\n", sz);
4416 
4417     /* garbage szProduct */
4418     sz = MAX_PATH;
4419     lstrcpyA(buf, "apple");
4420     r = MsiGetProductInfoA("garbage", INSTALLPROPERTY_HELPLINKA, buf, &sz);
4421     ok(r == ERROR_INVALID_PARAMETER,
4422        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4423     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4424     ok(sz == MAX_PATH, "got %lu\n", sz);
4425 
4426     /* guid without brackets */
4427     sz = MAX_PATH;
4428     lstrcpyA(buf, "apple");
4429     r = MsiGetProductInfoA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
4430                            INSTALLPROPERTY_HELPLINKA, buf, &sz);
4431     ok(r == ERROR_INVALID_PARAMETER,
4432        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4433     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4434     ok(sz == MAX_PATH, "got %lu\n", sz);
4435 
4436     /* guid with brackets */
4437     sz = MAX_PATH;
4438     lstrcpyA(buf, "apple");
4439     r = MsiGetProductInfoA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
4440                            INSTALLPROPERTY_HELPLINKA, buf, &sz);
4441     ok(r == ERROR_UNKNOWN_PRODUCT,
4442        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4443     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4444     ok(sz == MAX_PATH, "got %lu\n", sz);
4445 
4446     /* same length as guid, but random */
4447     sz = MAX_PATH;
4448     lstrcpyA(buf, "apple");
4449     r = MsiGetProductInfoA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
4450                            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, "got %lu\n", sz);
4455 
4456     /* not installed, NULL szAttribute */
4457     sz = MAX_PATH;
4458     lstrcpyA(buf, "apple");
4459     r = MsiGetProductInfoA(prodcode, NULL, 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, "got %lu\n", sz);
4464 
4465     /* not installed, NULL lpValueBuf */
4466     sz = MAX_PATH;
4467     lstrcpyA(buf, "apple");
4468     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, &sz);
4469     ok(r == ERROR_UNKNOWN_PRODUCT,
4470        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4471     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4472     ok(sz == MAX_PATH, "got %lu\n", sz);
4473 
4474     /* not installed, NULL pcchValueBuf */
4475     sz = MAX_PATH;
4476     lstrcpyA(buf, "apple");
4477     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, NULL);
4478     ok(r == ERROR_INVALID_PARAMETER,
4479        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4480     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4481     ok(sz == MAX_PATH, "got %lu\n", sz);
4482 
4483     /* created guid cannot possibly be an installed product code */
4484     sz = MAX_PATH;
4485     lstrcpyA(buf, "apple");
4486     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4487     ok(r == ERROR_UNKNOWN_PRODUCT,
4488        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4489     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4490     ok(sz == MAX_PATH, "got %lu\n", sz);
4491 
4492     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
4493     lstrcatA(keypath, usersid);
4494     lstrcatA(keypath, "\\Installer\\Products\\");
4495     lstrcatA(keypath, prod_squashed);
4496 
4497     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4498     if (res == ERROR_ACCESS_DENIED)
4499     {
4500         skip("Not enough rights to perform tests\n");
4501         LocalFree(usersid);
4502         return;
4503     }
4504     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4505 
4506     /* managed product code exists */
4507     sz = MAX_PATH;
4508     lstrcpyA(buf, "apple");
4509     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4510     ok(r == ERROR_UNKNOWN_PROPERTY,
4511        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4512     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4513     ok(sz == MAX_PATH, "got %lu\n", sz);
4514 
4515     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4516     RegCloseKey(prodkey);
4517 
4518     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
4519     lstrcatA(keypath, usersid);
4520     lstrcatA(keypath, "\\Products\\");
4521     lstrcatA(keypath, prod_squashed);
4522 
4523     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
4524     if (res == ERROR_ACCESS_DENIED)
4525     {
4526         skip("Not enough rights to perform tests\n");
4527         LocalFree(usersid);
4528         return;
4529     }
4530     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4531 
4532     /* local user product code exists */
4533     sz = MAX_PATH;
4534     lstrcpyA(buf, "apple");
4535     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4536     ok(r == ERROR_UNKNOWN_PRODUCT,
4537        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4538     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4539     ok(sz == MAX_PATH, "got %lu\n", sz);
4540 
4541     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
4542     lstrcatA(keypath, usersid);
4543     lstrcatA(keypath, "\\Installer\\Products\\");
4544     lstrcatA(keypath, prod_squashed);
4545 
4546     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4547     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4548 
4549     /* both local and managed product code exist */
4550     sz = MAX_PATH;
4551     lstrcpyA(buf, "apple");
4552     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4553     ok(r == ERROR_UNKNOWN_PROPERTY,
4554        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4555     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4556     ok(sz == MAX_PATH, "%lu\n", sz);
4557 
4558     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
4559     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4560 
4561     /* InstallProperties key exists */
4562     sz = MAX_PATH;
4563     lstrcpyA(buf, "apple");
4564     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4565     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4566     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4567     ok(sz == 0, "Expected 0, got %lu\n", sz);
4568 
4569     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
4570     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4571 
4572     /* HelpLink value exists */
4573     sz = MAX_PATH;
4574     lstrcpyA(buf, "apple");
4575     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4576     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4577     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
4578     ok(sz == 4, "Expected 4, got %lu\n", sz);
4579 
4580     /* pcchBuf is NULL */
4581     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, NULL);
4582     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4583 
4584     /* lpValueBuf is NULL */
4585     sz = MAX_PATH;
4586     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, &sz);
4587     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4588     ok(sz == 4, "Expected 4, got %lu\n", sz);
4589 
4590     /* lpValueBuf is NULL, pcchValueBuf is too small */
4591     sz = 2;
4592     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, &sz);
4593     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4594     ok(sz == 4, "Expected 4, got %lu\n", sz);
4595 
4596     /* lpValueBuf is non-NULL, pcchValueBuf is too small */
4597     sz = 2;
4598     lstrcpyA(buf, "apple");
4599     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4600     ok(!lstrcmpA(buf, "apple"), "Expected buf to remain unchanged, got \"%s\"\n", buf);
4601     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4602     ok(sz == 4, "Expected 4, got %lu\n", sz);
4603 
4604     /* lpValueBuf is non-NULL, pcchValueBuf is exactly 4 */
4605     sz = 4;
4606     lstrcpyA(buf, "apple");
4607     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4608     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4609     ok(!lstrcmpA(buf, "apple"),
4610        "Expected buf to remain unchanged, got \"%s\"\n", buf);
4611     ok(sz == 4, "Expected 4, got %lu\n", sz);
4612 
4613     res = RegSetValueExA(propkey, "IMadeThis", 0, REG_SZ, (LPBYTE)"random", 7);
4614     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4615 
4616     /* random property not supported by MSI, value exists */
4617     sz = MAX_PATH;
4618     lstrcpyA(buf, "apple");
4619     r = MsiGetProductInfoA(prodcode, "IMadeThis", buf, &sz);
4620     ok(r == ERROR_UNKNOWN_PROPERTY,
4621        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4622     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4623     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
4624 
4625     RegDeleteValueA(propkey, "IMadeThis");
4626     RegDeleteValueA(propkey, "HelpLink");
4627     delete_key(propkey, "", access & KEY_WOW64_64KEY);
4628     delete_key(localkey, "", access & KEY_WOW64_64KEY);
4629     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4630     RegCloseKey(propkey);
4631     RegCloseKey(localkey);
4632     RegCloseKey(prodkey);
4633 
4634     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
4635     lstrcatA(keypath, prod_squashed);
4636 
4637     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
4638     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4639 
4640     /* user product key exists */
4641     sz = MAX_PATH;
4642     lstrcpyA(buf, "apple");
4643     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4644     ok(r == ERROR_UNKNOWN_PROPERTY,
4645        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4646     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4647     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
4648 
4649     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
4650     lstrcatA(keypath, usersid);
4651     lstrcatA(keypath, "\\Products\\");
4652     lstrcatA(keypath, prod_squashed);
4653 
4654     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
4655     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4656 
4657     /* local user product key exists */
4658     sz = MAX_PATH;
4659     lstrcpyA(buf, "apple");
4660     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4661     ok(r == ERROR_UNKNOWN_PROPERTY,
4662        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4663     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4664     ok(sz == MAX_PATH, "got %lu\n", sz);
4665 
4666     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
4667     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4668 
4669     /* InstallProperties key exists */
4670     sz = MAX_PATH;
4671     lstrcpyA(buf, "apple");
4672     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4673     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4674     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4675     ok(sz == 0, "Expected 0, got %lu\n", sz);
4676 
4677     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
4678     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4679 
4680     /* HelpLink value exists */
4681     sz = MAX_PATH;
4682     lstrcpyA(buf, "apple");
4683     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4684     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4685     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
4686     ok(sz == 4, "Expected 4, got %lu\n", sz);
4687 
4688     RegDeleteValueA(propkey, "HelpLink");
4689     delete_key(propkey, "", access & KEY_WOW64_64KEY);
4690     delete_key(localkey, "", access & KEY_WOW64_64KEY);
4691     RegDeleteKeyA(prodkey, "");
4692     RegCloseKey(propkey);
4693     RegCloseKey(localkey);
4694     RegCloseKey(prodkey);
4695 
4696     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
4697     lstrcatA(keypath, prod_squashed);
4698 
4699     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4700     if (res == ERROR_ACCESS_DENIED)
4701     {
4702         skip( "insufficient rights\n" );
4703         LocalFree( usersid );
4704         return;
4705     }
4706     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4707 
4708     /* classes product key exists */
4709     sz = MAX_PATH;
4710     lstrcpyA(buf, "apple");
4711     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4712     ok(r == ERROR_UNKNOWN_PROPERTY,
4713        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4714     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4715     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
4716 
4717     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
4718     lstrcatA(keypath, usersid);
4719     lstrcatA(keypath, "\\Products\\");
4720     lstrcatA(keypath, prod_squashed);
4721 
4722     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
4723     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4724 
4725     /* local user product key exists */
4726     sz = MAX_PATH;
4727     lstrcpyA(buf, "apple");
4728     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4729     ok(r == ERROR_UNKNOWN_PROPERTY,
4730        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4731     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4732     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
4733 
4734     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
4735     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4736 
4737     /* InstallProperties key exists */
4738     sz = MAX_PATH;
4739     lstrcpyA(buf, "apple");
4740     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4741     ok(r == ERROR_UNKNOWN_PROPERTY,
4742        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4743     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4744     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
4745 
4746     delete_key(propkey, "", access & KEY_WOW64_64KEY);
4747     delete_key(localkey, "", access & KEY_WOW64_64KEY);
4748     RegCloseKey(propkey);
4749     RegCloseKey(localkey);
4750 
4751     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
4752     lstrcatA(keypath, "S-1-5-18\\\\Products\\");
4753     lstrcatA(keypath, prod_squashed);
4754 
4755     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
4756     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4757 
4758     /* Local System product key exists */
4759     sz = MAX_PATH;
4760     lstrcpyA(buf, "apple");
4761     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4762     ok(r == ERROR_UNKNOWN_PROPERTY,
4763         "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4764     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4765     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
4766 
4767     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
4768     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4769 
4770     /* InstallProperties key exists */
4771     sz = MAX_PATH;
4772     lstrcpyA(buf, "apple");
4773     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4774     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4775     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4776     ok(sz == 0, "Expected 0, got %lu\n", sz);
4777 
4778     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
4779     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4780 
4781     /* HelpLink value exists */
4782     sz = MAX_PATH;
4783     lstrcpyA(buf, "apple");
4784     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4785     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4786     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
4787     ok(sz == 4, "Expected 4, got %lu\n", sz);
4788 
4789     res = RegSetValueExA(propkey, "HelpLink", 0, REG_DWORD,
4790                          (const BYTE *)&val, sizeof(DWORD));
4791     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4792 
4793     /* HelpLink type is REG_DWORD */
4794     sz = MAX_PATH;
4795     lstrcpyA(buf, "apple");
4796     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4797     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4798     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4799     ok(sz == 2, "Expected 2, got %lu\n", sz);
4800 
4801     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
4802     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4803 
4804     /* DisplayName value exists */
4805     sz = MAX_PATH;
4806     lstrcpyA(buf, "apple");
4807     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
4808     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4809     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
4810     ok(sz == 4, "Expected 4, got %lu\n", sz);
4811 
4812     res = RegSetValueExA(propkey, "DisplayName", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
4813     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4814 
4815     /* DisplayName type is REG_DWORD */
4816     sz = MAX_PATH;
4817     lstrcpyA(buf, "apple");
4818     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
4819     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4820     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4821     ok(sz == 2, "Expected 2, got %lu\n", sz);
4822 
4823     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"1.1.1", 6);
4824     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4825 
4826     /* DisplayVersion value exists */
4827     sz = MAX_PATH;
4828     lstrcpyA(buf, "apple");
4829     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
4830     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4831     ok(!lstrcmpA(buf, "1.1.1"), "Expected \"1.1.1\", got \"%s\"\n", buf);
4832     ok(sz == 5, "Expected 5, got %lu\n", sz);
4833 
4834     res = RegSetValueExA(propkey, "DisplayVersion", 0,
4835                          REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
4836     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4837 
4838     /* DisplayVersion type is REG_DWORD */
4839     sz = MAX_PATH;
4840     lstrcpyA(buf, "apple");
4841     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
4842     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4843     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4844     ok(sz == 2, "Expected 2, got %lu\n", sz);
4845 
4846     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"tele", 5);
4847     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4848 
4849     /* HelpTelephone value exists */
4850     sz = MAX_PATH;
4851     lstrcpyA(buf, "apple");
4852     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
4853     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4854     ok(!lstrcmpA(buf, "tele"), "Expected \"tele\", got \"%s\"\n", buf);
4855     ok(sz == 4, "Expected 4, got %lu\n", sz);
4856 
4857     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_DWORD,
4858                          (const BYTE *)&val, sizeof(DWORD));
4859     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4860 
4861     /* HelpTelephone type is REG_DWORD */
4862     sz = MAX_PATH;
4863     lstrcpyA(buf, "apple");
4864     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
4865     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4866     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4867     ok(sz == 2, "Expected 2, got %lu\n", sz);
4868 
4869     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
4870     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4871 
4872     /* InstallLocation value exists */
4873     sz = MAX_PATH;
4874     lstrcpyA(buf, "apple");
4875     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
4876     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4877     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
4878     ok(sz == 3, "Expected 3, got %lu\n", sz);
4879 
4880     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_DWORD,
4881                          (const BYTE *)&val, sizeof(DWORD));
4882     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4883 
4884     /* InstallLocation type is REG_DWORD */
4885     sz = MAX_PATH;
4886     lstrcpyA(buf, "apple");
4887     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
4888     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4889     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4890     ok(sz == 2, "Expected 2, got %lu\n", sz);
4891 
4892     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
4893     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4894 
4895     /* InstallSource value exists */
4896     sz = MAX_PATH;
4897     lstrcpyA(buf, "apple");
4898     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
4899     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4900     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
4901     ok(sz == 6, "Expected 6, got %lu\n", sz);
4902 
4903     res = RegSetValueExA(propkey, "InstallSource", 0, REG_DWORD,
4904                          (const BYTE *)&val, sizeof(DWORD));
4905     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4906 
4907     /* InstallSource type is REG_DWORD */
4908     sz = MAX_PATH;
4909     lstrcpyA(buf, "apple");
4910     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
4911     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4912     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4913     ok(sz == 2, "Expected 2, got %lu\n", sz);
4914 
4915     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
4916     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4917 
4918     /* InstallDate value exists */
4919     sz = MAX_PATH;
4920     lstrcpyA(buf, "apple");
4921     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
4922     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4923     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
4924     ok(sz == 4, "Expected 4, got %lu\n", sz);
4925 
4926     res = RegSetValueExA(propkey, "InstallDate", 0, REG_DWORD,
4927                          (const BYTE *)&val, sizeof(DWORD));
4928     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4929 
4930     /* InstallDate type is REG_DWORD */
4931     sz = MAX_PATH;
4932     lstrcpyA(buf, "apple");
4933     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
4934     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4935     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4936     ok(sz == 2, "Expected 2, got %lu\n", sz);
4937 
4938     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
4939     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4940 
4941     /* Publisher value exists */
4942     sz = MAX_PATH;
4943     lstrcpyA(buf, "apple");
4944     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PUBLISHERA, buf, &sz);
4945     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4946     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
4947     ok(sz == 3, "Expected 3, got %lu\n", sz);
4948 
4949     res = RegSetValueExA(propkey, "Publisher", 0, REG_DWORD,
4950                          (const BYTE *)&val, sizeof(DWORD));
4951     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4952 
4953     /* Publisher type is REG_DWORD */
4954     sz = MAX_PATH;
4955     lstrcpyA(buf, "apple");
4956     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PUBLISHERA, buf, &sz);
4957     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4958     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4959     ok(sz == 2, "Expected 2, got %lu\n", sz);
4960 
4961     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"pack", 5);
4962     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4963 
4964     /* LocalPackage value exists */
4965     sz = MAX_PATH;
4966     lstrcpyA(buf, "apple");
4967     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
4968     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4969     ok(!lstrcmpA(buf, "pack"), "Expected \"pack\", got \"%s\"\n", buf);
4970     ok(sz == 4, "Expected 4, got %lu\n", sz);
4971 
4972     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_DWORD,
4973                          (const BYTE *)&val, sizeof(DWORD));
4974     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4975 
4976     /* LocalPackage type is REG_DWORD */
4977     sz = MAX_PATH;
4978     lstrcpyA(buf, "apple");
4979     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
4980     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4981     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4982     ok(sz == 2, "Expected 2, got %lu\n", sz);
4983 
4984     res = RegSetValueExA(propkey, "UrlInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
4985     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4986 
4987     /* UrlInfoAbout value exists */
4988     sz = MAX_PATH;
4989     lstrcpyA(buf, "apple");
4990     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
4991     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4992     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
4993     ok(sz == 5, "Expected 5, got %lu\n", sz);
4994 
4995     res = RegSetValueExA(propkey, "UrlInfoAbout", 0, REG_DWORD,
4996                          (const BYTE *)&val, sizeof(DWORD));
4997     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4998 
4999     /* UrlInfoAbout type is REG_DWORD */
5000     sz = MAX_PATH;
5001     lstrcpyA(buf, "apple");
5002     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
5003     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5004     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5005     ok(sz == 2, "Expected 2, got %lu\n", sz);
5006 
5007     res = RegSetValueExA(propkey, "UrlUpdateInfo", 0, REG_SZ, (LPBYTE)"info", 5);
5008     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5009 
5010     /* UrlUpdateInfo value exists */
5011     sz = MAX_PATH;
5012     lstrcpyA(buf, "apple");
5013     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
5014     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5015     ok(!lstrcmpA(buf, "info"), "Expected \"info\", got \"%s\"\n", buf);
5016     ok(sz == 4, "Expected 4, got %lu\n", sz);
5017 
5018     res = RegSetValueExA(propkey, "UrlUpdateInfo", 0, REG_DWORD,
5019                          (const BYTE *)&val, sizeof(DWORD));
5020     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5021 
5022     /* UrlUpdateInfo type is REG_DWORD */
5023     sz = MAX_PATH;
5024     lstrcpyA(buf, "apple");
5025     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
5026     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5027     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5028     ok(sz == 2, "Expected 2, got %lu\n", sz);
5029 
5030     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"1", 2);
5031     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5032 
5033     /* VersionMinor value exists */
5034     sz = MAX_PATH;
5035     lstrcpyA(buf, "apple");
5036     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
5037     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5038     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
5039     ok(sz == 1, "Expected 1, got %lu\n", sz);
5040 
5041     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_DWORD,
5042                          (const BYTE *)&val, sizeof(DWORD));
5043     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5044 
5045     /* VersionMinor type is REG_DWORD */
5046     sz = MAX_PATH;
5047     lstrcpyA(buf, "apple");
5048     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
5049     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5050     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5051     ok(sz == 2, "Expected 2, got %lu\n", sz);
5052 
5053     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"1", 2);
5054     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5055 
5056     /* VersionMajor value exists */
5057     sz = MAX_PATH;
5058     lstrcpyA(buf, "apple");
5059     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
5060     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5061     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
5062     ok(sz == 1, "Expected 1, got %lu\n", sz);
5063 
5064     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_DWORD,
5065                          (const BYTE *)&val, sizeof(DWORD));
5066     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5067 
5068     /* VersionMajor type is REG_DWORD */
5069     sz = MAX_PATH;
5070     lstrcpyA(buf, "apple");
5071     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
5072     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5073     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5074     ok(sz == 2, "Expected 2, got %lu\n", sz);
5075 
5076     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
5077     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5078 
5079     /* ProductID value exists */
5080     sz = MAX_PATH;
5081     lstrcpyA(buf, "apple");
5082     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
5083     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5084     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
5085     ok(sz == 2, "Expected 2, got %lu\n", sz);
5086 
5087     res = RegSetValueExA(propkey, "ProductID", 0, REG_DWORD,
5088                          (const BYTE *)&val, sizeof(DWORD));
5089     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5090 
5091     /* ProductID type is REG_DWORD */
5092     sz = MAX_PATH;
5093     lstrcpyA(buf, "apple");
5094     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
5095     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5096     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5097     ok(sz == 2, "Expected 2, got %lu\n", sz);
5098 
5099     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
5100     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5101 
5102     /* RegCompany value exists */
5103     sz = MAX_PATH;
5104     lstrcpyA(buf, "apple");
5105     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
5106     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5107     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
5108     ok(sz == 4, "Expected 4, got %lu\n", sz);
5109 
5110     res = RegSetValueExA(propkey, "RegCompany", 0, REG_DWORD,
5111                          (const BYTE *)&val, sizeof(DWORD));
5112     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5113 
5114     /* RegCompany type is REG_DWORD */
5115     sz = MAX_PATH;
5116     lstrcpyA(buf, "apple");
5117     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
5118     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5119     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5120     ok(sz == 2, "Expected 2, got %lu\n", sz);
5121 
5122     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"own", 4);
5123     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5124 
5125     /* RegOwner value exists */
5126     sz = MAX_PATH;
5127     lstrcpyA(buf, "apple");
5128     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGOWNERA, buf, &sz);
5129     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5130     ok(!lstrcmpA(buf, "own"), "Expected \"own\", got \"%s\"\n", buf);
5131     ok(sz == 3, "Expected 3, got %lu\n", sz);
5132 
5133     res = RegSetValueExA(propkey, "RegOwner", 0, REG_DWORD,
5134                          (const BYTE *)&val, sizeof(DWORD));
5135     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5136 
5137     /* RegOwner type is REG_DWORD */
5138     sz = MAX_PATH;
5139     lstrcpyA(buf, "apple");
5140     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGOWNERA, buf, &sz);
5141     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5142     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5143     ok(sz == 2, "Expected 2, got %lu\n", sz);
5144 
5145     res = RegSetValueExA(propkey, "InstanceType", 0, REG_SZ, (LPBYTE)"type", 5);
5146     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5147 
5148     /* InstanceType value exists */
5149     sz = MAX_PATH;
5150     lstrcpyA(buf, "apple");
5151     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5152     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5153     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5154     ok(sz == 0, "Expected 0, got %lu\n", sz);
5155 
5156     res = RegSetValueExA(propkey, "InstanceType", 0, REG_DWORD,
5157                          (const BYTE *)&val, sizeof(DWORD));
5158     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5159 
5160     /* InstanceType type is REG_DWORD */
5161     sz = MAX_PATH;
5162     lstrcpyA(buf, "apple");
5163     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5164     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5165     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5166     ok(sz == 0, "Expected 0, got %lu\n", sz);
5167 
5168     res = RegSetValueExA(prodkey, "InstanceType", 0, REG_SZ, (LPBYTE)"type", 5);
5169     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5170 
5171     /* InstanceType value exists */
5172     sz = MAX_PATH;
5173     lstrcpyA(buf, "apple");
5174     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5175     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5176     ok(!lstrcmpA(buf, "type"), "Expected \"type\", got \"%s\"\n", buf);
5177     ok(sz == 4, "Expected 4, got %lu\n", sz);
5178 
5179     res = RegSetValueExA(prodkey, "InstanceType", 0, REG_DWORD,
5180                          (const BYTE *)&val, sizeof(DWORD));
5181     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5182 
5183     /* InstanceType type is REG_DWORD */
5184     sz = MAX_PATH;
5185     lstrcpyA(buf, "apple");
5186     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5187     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5188     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5189     ok(sz == 2, "Expected 2, got %lu\n", sz);
5190 
5191     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"tforms", 7);
5192     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5193 
5194     /* Transforms value exists */
5195     sz = MAX_PATH;
5196     lstrcpyA(buf, "apple");
5197     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5198     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5199     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5200     ok(sz == 0, "Expected 0, got %lu\n", sz);
5201 
5202     res = RegSetValueExA(propkey, "Transforms", 0, REG_DWORD,
5203                          (const BYTE *)&val, sizeof(DWORD));
5204     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5205 
5206     /* Transforms type is REG_DWORD */
5207     sz = MAX_PATH;
5208     lstrcpyA(buf, "apple");
5209     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5210     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5211     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5212     ok(sz == 0, "Expected 0, got %lu\n", sz);
5213 
5214     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"tforms", 7);
5215     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5216 
5217     /* Transforms value exists */
5218     sz = MAX_PATH;
5219     lstrcpyA(buf, "apple");
5220     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5221     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5222     ok(!lstrcmpA(buf, "tforms"), "Expected \"tforms\", got \"%s\"\n", buf);
5223     ok(sz == 6, "Expected 6, got %lu\n", sz);
5224 
5225     res = RegSetValueExA(prodkey, "Transforms", 0, REG_DWORD,
5226                          (const BYTE *)&val, sizeof(DWORD));
5227     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5228 
5229     /* Transforms type is REG_DWORD */
5230     sz = MAX_PATH;
5231     lstrcpyA(buf, "apple");
5232     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5233     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5234     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5235     ok(sz == 2, "Expected 2, got %lu\n", sz);
5236 
5237     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
5238     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5239 
5240     /* Language value exists */
5241     sz = MAX_PATH;
5242     lstrcpyA(buf, "apple");
5243     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5244     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5245     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5246     ok(sz == 0, "Expected 0, got %lu\n", sz);
5247 
5248     res = RegSetValueExA(propkey, "Language", 0, REG_DWORD,
5249                          (const BYTE *)&val, sizeof(DWORD));
5250     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5251 
5252     /* Language type is REG_DWORD */
5253     sz = MAX_PATH;
5254     lstrcpyA(buf, "apple");
5255     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5256     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5257     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5258     ok(sz == 0, "Expected 0, got %lu\n", sz);
5259 
5260     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
5261     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5262 
5263     /* Language value exists */
5264     sz = MAX_PATH;
5265     lstrcpyA(buf, "apple");
5266     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5267     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5268     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
5269     ok(sz == 4, "Expected 4, got %lu\n", sz);
5270 
5271     res = RegSetValueExA(prodkey, "Language", 0, REG_DWORD,
5272                          (const BYTE *)&val, sizeof(DWORD));
5273     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5274 
5275     /* Language type is REG_DWORD */
5276     sz = MAX_PATH;
5277     lstrcpyA(buf, "apple");
5278     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5279     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5280     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5281     ok(sz == 2, "Expected 2, got %lu\n", sz);
5282 
5283     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
5284     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5285 
5286     /* ProductName value exists */
5287     sz = MAX_PATH;
5288     lstrcpyA(buf, "apple");
5289     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5290     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5291     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5292     ok(sz == 0, "Expected 0, got %lu\n", sz);
5293 
5294     res = RegSetValueExA(propkey, "ProductName", 0, REG_DWORD,
5295                          (const BYTE *)&val, sizeof(DWORD));
5296     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5297 
5298     /* ProductName type is REG_DWORD */
5299     sz = MAX_PATH;
5300     lstrcpyA(buf, "apple");
5301     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5302     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5303     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5304     ok(sz == 0, "Expected 0, got %lu\n", sz);
5305 
5306     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
5307     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5308 
5309     /* ProductName value exists */
5310     sz = MAX_PATH;
5311     lstrcpyA(buf, "apple");
5312     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5313     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5314     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
5315     ok(sz == 4, "Expected 4, got %lu\n", sz);
5316 
5317     res = RegSetValueExA(prodkey, "ProductName", 0, REG_DWORD,
5318                          (const BYTE *)&val, sizeof(DWORD));
5319     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5320 
5321     /* ProductName type is REG_DWORD */
5322     sz = MAX_PATH;
5323     lstrcpyA(buf, "apple");
5324     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5325     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5326     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5327     ok(sz == 2, "Expected 2, got %lu\n", sz);
5328 
5329     res = RegSetValueExA(propkey, "Assignment", 0, REG_SZ, (LPBYTE)"at", 3);
5330     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5331 
5332     /* Assignment value exists */
5333     sz = MAX_PATH;
5334     lstrcpyA(buf, "apple");
5335     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5336     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5337     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5338     ok(sz == 0, "Expected 0, got %lu\n", sz);
5339 
5340     res = RegSetValueExA(propkey, "Assignment", 0, REG_DWORD,
5341                          (const BYTE *)&val, sizeof(DWORD));
5342     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5343 
5344     /* Assignment type is REG_DWORD */
5345     sz = MAX_PATH;
5346     lstrcpyA(buf, "apple");
5347     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5348     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5349     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5350     ok(sz == 0, "Expected 0, got %lu\n", sz);
5351 
5352     res = RegSetValueExA(prodkey, "Assignment", 0, REG_SZ, (LPBYTE)"at", 3);
5353     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5354 
5355     /* Assignment value exists */
5356     sz = MAX_PATH;
5357     lstrcpyA(buf, "apple");
5358     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5359     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5360     ok(!lstrcmpA(buf, "at"), "Expected \"at\", got \"%s\"\n", buf);
5361     ok(sz == 2, "Expected 2, got %lu\n", sz);
5362 
5363     res = RegSetValueExA(prodkey, "Assignment", 0, REG_DWORD,
5364                          (const BYTE *)&val, sizeof(DWORD));
5365     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5366 
5367     /* Assignment type is REG_DWORD */
5368     sz = MAX_PATH;
5369     lstrcpyA(buf, "apple");
5370     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5371     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5372     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5373     ok(sz == 2, "Expected 2, got %lu\n", sz);
5374 
5375     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
5376     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5377 
5378     /* PackageCode value exists */
5379     sz = MAX_PATH;
5380     lstrcpyA(buf, "apple");
5381     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5382     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5383     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5384     ok(sz == 0, "Expected 0, got %lu\n", sz);
5385 
5386     res = RegSetValueExA(propkey, "PackageCode", 0, REG_DWORD,
5387                          (const BYTE *)&val, sizeof(DWORD));
5388     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5389 
5390     /* PackageCode type is REG_DWORD */
5391     sz = MAX_PATH;
5392     lstrcpyA(buf, "apple");
5393     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5394     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5395     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5396     ok(sz == 0, "Expected 0, got %lu\n", sz);
5397 
5398     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
5399     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5400 
5401     /* PackageCode value exists */
5402     sz = MAX_PATH;
5403     lstrcpyA(buf, "apple");
5404     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5405     ok(r == ERROR_BAD_CONFIGURATION,
5406        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
5407     ok(!lstrcmpA(buf, "code"), "Expected \"code\", got \"%s\"\n", buf);
5408     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5409 
5410     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_DWORD,
5411                          (const BYTE *)&val, sizeof(DWORD));
5412     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5413 
5414     /* PackageCode type is REG_DWORD */
5415     sz = MAX_PATH;
5416     lstrcpyA(buf, "apple");
5417     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5418     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5419     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5420     ok(sz == 2, "Expected 2, got %lu\n", sz);
5421 
5422     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)pack_squashed, 33);
5423     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5424 
5425     /* PackageCode value exists */
5426     sz = MAX_PATH;
5427     lstrcpyA(buf, "apple");
5428     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5429     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5430     ok(!lstrcmpA(buf, packcode), "Expected \"%s\", got \"%s\"\n", packcode, buf);
5431     ok(sz == 38, "Expected 38, got %lu\n", sz);
5432 
5433     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
5434     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5435 
5436     /* Version value exists */
5437     sz = MAX_PATH;
5438     lstrcpyA(buf, "apple");
5439     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5440     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5441     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5442     ok(sz == 0, "Expected 0, got %lu\n", sz);
5443 
5444     res = RegSetValueExA(propkey, "Version", 0, REG_DWORD,
5445                          (const BYTE *)&val, sizeof(DWORD));
5446     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5447 
5448     /* Version type is REG_DWORD */
5449     sz = MAX_PATH;
5450     lstrcpyA(buf, "apple");
5451     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5452     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5453     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5454     ok(sz == 0, "Expected 0, got %lu\n", sz);
5455 
5456     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
5457     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5458 
5459     /* Version value exists */
5460     sz = MAX_PATH;
5461     lstrcpyA(buf, "apple");
5462     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5463     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5464     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
5465     ok(sz == 3, "Expected 3, got %lu\n", sz);
5466 
5467     res = RegSetValueExA(prodkey, "Version", 0, REG_DWORD,
5468                          (const BYTE *)&val, sizeof(DWORD));
5469     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5470 
5471     /* Version type is REG_DWORD */
5472     sz = MAX_PATH;
5473     lstrcpyA(buf, "apple");
5474     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5475     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5476     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5477     ok(sz == 2, "Expected 2, got %lu\n", sz);
5478 
5479     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"ico", 4);
5480     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5481 
5482     /* ProductIcon value exists */
5483     sz = MAX_PATH;
5484     lstrcpyA(buf, "apple");
5485     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5486     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5487     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5488     ok(sz == 0, "Expected 0, got %lu\n", sz);
5489 
5490     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_DWORD,
5491                          (const BYTE *)&val, sizeof(DWORD));
5492     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5493 
5494     /* ProductIcon type is REG_DWORD */
5495     sz = MAX_PATH;
5496     lstrcpyA(buf, "apple");
5497     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5498     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5499     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5500     ok(sz == 0, "Expected 0, got %lu\n", sz);
5501 
5502     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"ico", 4);
5503     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5504 
5505     /* ProductIcon value exists */
5506     sz = MAX_PATH;
5507     lstrcpyA(buf, "apple");
5508     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5509     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5510     ok(!lstrcmpA(buf, "ico"), "Expected \"ico\", got \"%s\"\n", buf);
5511     ok(sz == 3, "Expected 3, got %lu\n", sz);
5512 
5513     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_DWORD,
5514                          (const BYTE *)&val, sizeof(DWORD));
5515     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5516 
5517     /* ProductIcon type is REG_DWORD */
5518     sz = MAX_PATH;
5519     lstrcpyA(buf, "apple");
5520     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5521     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5522     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5523     ok(sz == 2, "Expected 2, got %lu\n", sz);
5524 
5525     /* SourceList key does not exist */
5526     sz = MAX_PATH;
5527     lstrcpyA(buf, "apple");
5528     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5529     ok(r == ERROR_UNKNOWN_PRODUCT,
5530        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5531     ok(!lstrcmpA(buf, "apple"),
5532        "Expected buf to be unchanged, got \"%s\"\n", buf);
5533     ok(sz == MAX_PATH, "Expected sz to be unchanged, got %lu\n", sz);
5534 
5535     res = RegCreateKeyExA(prodkey, "SourceList", 0, NULL, 0, access, NULL, &source, NULL);
5536     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5537 
5538     /* SourceList key exists, but PackageName val does not exist */
5539     sz = MAX_PATH;
5540     lstrcpyA(buf, "apple");
5541     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5542     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5543     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5544     ok(sz == 0, "Expected 0, got %lu\n", sz);
5545 
5546     res = RegSetValueExA(source, "PackageName", 0, REG_SZ, (LPBYTE)"packname", 9);
5547     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5548 
5549     /* PackageName val exists */
5550     sz = MAX_PATH;
5551     lstrcpyA(buf, "apple");
5552     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5553     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5554     ok(!lstrcmpA(buf, "packname"), "Expected \"packname\", got \"%s\"\n", buf);
5555     ok(sz == 8, "Expected 8, got %lu\n", sz);
5556 
5557     res = RegSetValueExA(source, "PackageName", 0, REG_DWORD,
5558                          (const BYTE *)&val, sizeof(DWORD));
5559     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5560 
5561     /* PackageName type is REG_DWORD */
5562     sz = MAX_PATH;
5563     lstrcpyA(buf, "apple");
5564     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5565     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5566     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5567     ok(sz == 2, "Expected 2, got %lu\n", sz);
5568 
5569     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
5570     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5571 
5572     /* Authorized value exists */
5573     sz = MAX_PATH;
5574     lstrcpyA(buf, "apple");
5575     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5576     if (r != ERROR_UNKNOWN_PROPERTY)
5577     {
5578         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5579         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5580         ok(sz == 0, "Expected 0, got %lu\n", sz);
5581     }
5582 
5583     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_DWORD,
5584                          (const BYTE *)&val, sizeof(DWORD));
5585     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5586 
5587     /* AuthorizedLUAApp type is REG_DWORD */
5588     sz = MAX_PATH;
5589     lstrcpyA(buf, "apple");
5590     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5591     if (r != ERROR_UNKNOWN_PROPERTY)
5592     {
5593         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5594         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5595         ok(sz == 0, "Expected 0, got %lu\n", sz);
5596     }
5597 
5598     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
5599     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5600 
5601     /* Authorized value exists */
5602     sz = MAX_PATH;
5603     lstrcpyA(buf, "apple");
5604     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5605     if (r != ERROR_UNKNOWN_PROPERTY)
5606     {
5607         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5608         ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
5609         ok(sz == 4, "Expected 4, got %lu\n", sz);
5610     }
5611 
5612     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_DWORD,
5613                          (const BYTE *)&val, sizeof(DWORD));
5614     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5615 
5616     /* AuthorizedLUAApp type is REG_DWORD */
5617     sz = MAX_PATH;
5618     lstrcpyA(buf, "apple");
5619     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5620     if (r != ERROR_UNKNOWN_PROPERTY)
5621     {
5622         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5623         ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5624         ok(sz == 2, "Expected 2, got %lu\n", sz);
5625     }
5626 
5627     RegDeleteValueA(propkey, "HelpLink");
5628     RegDeleteValueA(propkey, "DisplayName");
5629     RegDeleteValueA(propkey, "DisplayVersion");
5630     RegDeleteValueA(propkey, "HelpTelephone");
5631     RegDeleteValueA(propkey, "InstallLocation");
5632     RegDeleteValueA(propkey, "InstallSource");
5633     RegDeleteValueA(propkey, "InstallDate");
5634     RegDeleteValueA(propkey, "Publisher");
5635     RegDeleteValueA(propkey, "LocalPackage");
5636     RegDeleteValueA(propkey, "UrlInfoAbout");
5637     RegDeleteValueA(propkey, "UrlUpdateInfo");
5638     RegDeleteValueA(propkey, "VersionMinor");
5639     RegDeleteValueA(propkey, "VersionMajor");
5640     RegDeleteValueA(propkey, "ProductID");
5641     RegDeleteValueA(propkey, "RegCompany");
5642     RegDeleteValueA(propkey, "RegOwner");
5643     RegDeleteValueA(propkey, "InstanceType");
5644     RegDeleteValueA(propkey, "Transforms");
5645     RegDeleteValueA(propkey, "Language");
5646     RegDeleteValueA(propkey, "ProductName");
5647     RegDeleteValueA(propkey, "Assignment");
5648     RegDeleteValueA(propkey, "PackageCode");
5649     RegDeleteValueA(propkey, "Version");
5650     RegDeleteValueA(propkey, "ProductIcon");
5651     RegDeleteValueA(propkey, "AuthorizedLUAApp");
5652     delete_key(propkey, "", access & KEY_WOW64_64KEY);
5653     delete_key(localkey, "", access & KEY_WOW64_64KEY);
5654     RegDeleteValueA(prodkey, "InstanceType");
5655     RegDeleteValueA(prodkey, "Transforms");
5656     RegDeleteValueA(prodkey, "Language");
5657     RegDeleteValueA(prodkey, "ProductName");
5658     RegDeleteValueA(prodkey, "Assignment");
5659     RegDeleteValueA(prodkey, "PackageCode");
5660     RegDeleteValueA(prodkey, "Version");
5661     RegDeleteValueA(prodkey, "ProductIcon");
5662     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
5663     RegDeleteValueA(source, "PackageName");
5664     delete_key(source, "", access & KEY_WOW64_64KEY);
5665     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
5666     RegCloseKey(propkey);
5667     RegCloseKey(localkey);
5668     RegCloseKey(source);
5669     RegCloseKey(prodkey);
5670     LocalFree(usersid);
5671 }
5672 
5673 static void test_MsiGetProductInfoEx(void)
5674 {
5675     UINT r;
5676     LONG res;
5677     HKEY propkey, userkey;
5678     HKEY prodkey, localkey;
5679     CHAR prodcode[MAX_PATH];
5680     CHAR prod_squashed[MAX_PATH];
5681     CHAR packcode[MAX_PATH];
5682     CHAR pack_squashed[MAX_PATH];
5683     CHAR buf[MAX_PATH];
5684     CHAR keypath[MAX_PATH];
5685     LPSTR usersid;
5686     DWORD sz;
5687     REGSAM access = KEY_ALL_ACCESS;
5688 
5689     if (!pMsiGetProductInfoExA)
5690     {
5691         win_skip("MsiGetProductInfoExA is not available\n");
5692         return;
5693     }
5694 
5695     create_test_guid(prodcode, prod_squashed);
5696     create_test_guid(packcode, pack_squashed);
5697     usersid = get_user_sid();
5698 
5699     if (is_wow64)
5700         access |= KEY_WOW64_64KEY;
5701 
5702     /* NULL szProductCode */
5703     sz = MAX_PATH;
5704     lstrcpyA(buf, "apple");
5705     r = pMsiGetProductInfoExA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
5706                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5707     ok(r == ERROR_INVALID_PARAMETER,
5708        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5709     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5710     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5711 
5712     /* empty szProductCode */
5713     sz = MAX_PATH;
5714     lstrcpyA(buf, "apple");
5715     r = pMsiGetProductInfoExA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
5716                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5717     ok(r == ERROR_INVALID_PARAMETER,
5718        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5719     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5720     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5721 
5722     /* garbage szProductCode */
5723     sz = MAX_PATH;
5724     lstrcpyA(buf, "apple");
5725     r = pMsiGetProductInfoExA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
5726                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5727     ok(r == ERROR_INVALID_PARAMETER,
5728        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5729     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5730     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5731 
5732     /* guid without brackets */
5733     sz = MAX_PATH;
5734     lstrcpyA(buf, "apple");
5735     r = pMsiGetProductInfoExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", usersid,
5736                               MSIINSTALLCONTEXT_USERUNMANAGED,
5737                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5738     ok(r == ERROR_INVALID_PARAMETER,
5739        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5740     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5741     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5742 
5743     /* guid with brackets */
5744     sz = MAX_PATH;
5745     lstrcpyA(buf, "apple");
5746     r = pMsiGetProductInfoExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", usersid,
5747                               MSIINSTALLCONTEXT_USERUNMANAGED,
5748                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5749     ok(r == ERROR_UNKNOWN_PRODUCT,
5750        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5751     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5752     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5753 
5754     /* szValue is non-NULL while pcchValue is NULL */
5755     lstrcpyA(buf, "apple");
5756     r = pMsiGetProductInfoExA(prodcode, usersid,
5757                               MSIINSTALLCONTEXT_USERUNMANAGED,
5758                               INSTALLPROPERTY_PRODUCTSTATEA, buf, NULL);
5759     ok(r == ERROR_INVALID_PARAMETER,
5760        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5761     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5762 
5763     /* dwContext is out of range */
5764     sz = MAX_PATH;
5765     lstrcpyA(buf, "apple");
5766     r = pMsiGetProductInfoExA(prodcode, usersid, 42,
5767                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5768     ok(r == ERROR_INVALID_PARAMETER,
5769        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5770     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5771     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5772 
5773     /* szProperty is NULL */
5774     sz = MAX_PATH;
5775     lstrcpyA(buf, "apple");
5776     r = pMsiGetProductInfoExA(prodcode, usersid,
5777                               MSIINSTALLCONTEXT_USERUNMANAGED,
5778                               NULL, buf, &sz);
5779     ok(r == ERROR_INVALID_PARAMETER,
5780        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5781     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5782     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5783 
5784     /* szProperty is empty */
5785     sz = MAX_PATH;
5786     lstrcpyA(buf, "apple");
5787     r = pMsiGetProductInfoExA(prodcode, usersid,
5788                               MSIINSTALLCONTEXT_USERUNMANAGED,
5789                               "", buf, &sz);
5790     ok(r == ERROR_INVALID_PARAMETER,
5791        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5792     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5793     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5794 
5795     /* szProperty is not a valid property */
5796     sz = MAX_PATH;
5797     lstrcpyA(buf, "apple");
5798     r = pMsiGetProductInfoExA(prodcode, usersid,
5799                               MSIINSTALLCONTEXT_USERUNMANAGED,
5800                               "notvalid", buf, &sz);
5801     ok(r == ERROR_UNKNOWN_PRODUCT,
5802        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5803     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5804     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5805 
5806     /* same length as guid, but random */
5807     sz = MAX_PATH;
5808     lstrcpyA(buf, "apple");
5809     r = pMsiGetProductInfoExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", usersid,
5810                               MSIINSTALLCONTEXT_USERUNMANAGED,
5811                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5812     ok(r == ERROR_INVALID_PARAMETER,
5813        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5814     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5815     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5816 
5817     /* MSIINSTALLCONTEXT_USERUNMANAGED */
5818 
5819     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
5820     lstrcatA(keypath, usersid);
5821     lstrcatA(keypath, "\\Products\\");
5822     lstrcatA(keypath, prod_squashed);
5823 
5824     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
5825     if (res == ERROR_ACCESS_DENIED)
5826     {
5827         skip("Not enough rights to perform tests\n");
5828         LocalFree(usersid);
5829         return;
5830     }
5831     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5832 
5833     /* local user product key exists */
5834     sz = MAX_PATH;
5835     lstrcpyA(buf, "apple");
5836     r = pMsiGetProductInfoExA(prodcode, usersid,
5837                               MSIINSTALLCONTEXT_USERUNMANAGED,
5838                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5839     ok(r == ERROR_UNKNOWN_PRODUCT,
5840        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5841     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5842     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5843 
5844     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
5845     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5846 
5847     /* InstallProperties key exists */
5848     sz = MAX_PATH;
5849     lstrcpyA(buf, "apple");
5850     r = pMsiGetProductInfoExA(prodcode, usersid,
5851                               MSIINSTALLCONTEXT_USERUNMANAGED,
5852                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5853     ok(r == ERROR_UNKNOWN_PRODUCT,
5854        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5855     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5856     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5857 
5858     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
5859     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5860 
5861     /* LocalPackage value exists */
5862     sz = MAX_PATH;
5863     lstrcpyA(buf, "apple");
5864     r = pMsiGetProductInfoExA(prodcode, usersid,
5865                               MSIINSTALLCONTEXT_USERUNMANAGED,
5866                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5867     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5868     ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
5869     ok(sz == 1, "Expected 1, got %lu\n", sz);
5870 
5871     RegDeleteValueA(propkey, "LocalPackage");
5872 
5873     /* LocalPackage value must exist */
5874     sz = MAX_PATH;
5875     lstrcpyA(buf, "apple");
5876     r = pMsiGetProductInfoExA(prodcode, usersid,
5877                               MSIINSTALLCONTEXT_USERUNMANAGED,
5878                               INSTALLPROPERTY_HELPLINKA, 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 %lu\n", sz);
5883 
5884     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
5885     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5886 
5887     /* LocalPackage exists, but HelpLink does not exist */
5888     sz = MAX_PATH;
5889     lstrcpyA(buf, "apple");
5890     r = pMsiGetProductInfoExA(prodcode, usersid,
5891                               MSIINSTALLCONTEXT_USERUNMANAGED,
5892                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
5893     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5894     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5895     ok(sz == 0, "Expected 0, got %lu\n", sz);
5896 
5897     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
5898     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5899 
5900     /* HelpLink value exists */
5901     sz = MAX_PATH;
5902     lstrcpyA(buf, "apple");
5903     r = pMsiGetProductInfoExA(prodcode, usersid,
5904                               MSIINSTALLCONTEXT_USERUNMANAGED,
5905                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
5906     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5907     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
5908     ok(sz == 4, "Expected 4, got %lu\n", sz);
5909 
5910     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
5911     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5912 
5913     /* HelpTelephone value exists */
5914     sz = MAX_PATH;
5915     lstrcpyA(buf, "apple");
5916     r = pMsiGetProductInfoExA(prodcode, usersid,
5917                               MSIINSTALLCONTEXT_USERUNMANAGED,
5918                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
5919     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5920     ok(!lstrcmpA(buf, "phone"), "Expected \"phone\", got \"%s\"\n", buf);
5921     ok(sz == 5, "Expected 5, got %lu\n", sz);
5922 
5923     /* szValue and pcchValue are NULL */
5924     r = pMsiGetProductInfoExA(prodcode, usersid,
5925                               MSIINSTALLCONTEXT_USERUNMANAGED,
5926                               INSTALLPROPERTY_HELPTELEPHONEA, NULL, NULL);
5927     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5928 
5929     /* pcchValue is exactly 5 */
5930     sz = 5;
5931     lstrcpyA(buf, "apple");
5932     r = pMsiGetProductInfoExA(prodcode, usersid,
5933                               MSIINSTALLCONTEXT_USERUNMANAGED,
5934                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
5935     ok(r == ERROR_MORE_DATA,
5936        "Expected ERROR_MORE_DATA, got %d\n", r);
5937     ok(sz == 10, "Expected 10, got %lu\n", sz);
5938 
5939     /* szValue is NULL, pcchValue is exactly 5 */
5940     sz = 5;
5941     r = pMsiGetProductInfoExA(prodcode, usersid,
5942                               MSIINSTALLCONTEXT_USERUNMANAGED,
5943                               INSTALLPROPERTY_HELPTELEPHONEA, NULL, &sz);
5944     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5945     ok(sz == 10, "Expected 10, got %lu\n", sz);
5946 
5947     /* szValue is NULL, pcchValue is MAX_PATH */
5948     sz = MAX_PATH;
5949     r = pMsiGetProductInfoExA(prodcode, usersid,
5950                               MSIINSTALLCONTEXT_USERUNMANAGED,
5951                               INSTALLPROPERTY_HELPTELEPHONEA, NULL, &sz);
5952     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5953     ok(sz == 10, "Expected 10, got %lu\n", sz);
5954 
5955     /* pcchValue is exactly 0 */
5956     sz = 0;
5957     lstrcpyA(buf, "apple");
5958     r = pMsiGetProductInfoExA(prodcode, usersid,
5959                               MSIINSTALLCONTEXT_USERUNMANAGED,
5960                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
5961     ok(r == ERROR_MORE_DATA,
5962        "Expected ERROR_MORE_DATA, got %d\n", r);
5963     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
5964     ok(sz == 10, "Expected 10, got %lu\n", sz);
5965 
5966     res = RegSetValueExA(propkey, "notvalid", 0, REG_SZ, (LPBYTE)"invalid", 8);
5967     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5968 
5969     /* szProperty is not a valid property */
5970     sz = MAX_PATH;
5971     lstrcpyA(buf, "apple");
5972     r = pMsiGetProductInfoExA(prodcode, usersid,
5973                               MSIINSTALLCONTEXT_USERUNMANAGED,
5974                               "notvalid", buf, &sz);
5975     ok(r == ERROR_UNKNOWN_PROPERTY,
5976        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5977     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5978     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5979 
5980     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
5981     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5982 
5983     /* InstallDate value exists */
5984     sz = MAX_PATH;
5985     lstrcpyA(buf, "apple");
5986     r = pMsiGetProductInfoExA(prodcode, usersid,
5987                               MSIINSTALLCONTEXT_USERUNMANAGED,
5988                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
5989     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5990     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
5991     ok(sz == 4, "Expected 4, got %lu\n", sz);
5992 
5993     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
5994     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5995 
5996     /* DisplayName value exists */
5997     sz = MAX_PATH;
5998     lstrcpyA(buf, "apple");
5999     r = pMsiGetProductInfoExA(prodcode, usersid,
6000                               MSIINSTALLCONTEXT_USERUNMANAGED,
6001                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
6002     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6003     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
6004     ok(sz == 4, "Expected 4, got %lu\n", sz);
6005 
6006     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
6007     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6008 
6009     /* InstallLocation value exists */
6010     sz = MAX_PATH;
6011     lstrcpyA(buf, "apple");
6012     r = pMsiGetProductInfoExA(prodcode, usersid,
6013                               MSIINSTALLCONTEXT_USERUNMANAGED,
6014                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
6015     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6016     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
6017     ok(sz == 3, "Expected 3, got %lu\n", sz);
6018 
6019     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
6020     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6021 
6022     /* InstallSource value exists */
6023     sz = MAX_PATH;
6024     lstrcpyA(buf, "apple");
6025     r = pMsiGetProductInfoExA(prodcode, usersid,
6026                               MSIINSTALLCONTEXT_USERUNMANAGED,
6027                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
6028     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6029     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
6030     ok(sz == 6, "Expected 6, got %lu\n", sz);
6031 
6032     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6033     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6034 
6035     /* LocalPackage value exists */
6036     sz = MAX_PATH;
6037     lstrcpyA(buf, "apple");
6038     r = pMsiGetProductInfoExA(prodcode, usersid,
6039                               MSIINSTALLCONTEXT_USERUNMANAGED,
6040                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
6041     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6042     ok(!lstrcmpA(buf, "local"), "Expected \"local\", got \"%s\"\n", buf);
6043     ok(sz == 5, "Expected 5, got %lu\n", sz);
6044 
6045     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
6046     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6047 
6048     /* Publisher value exists */
6049     sz = MAX_PATH;
6050     lstrcpyA(buf, "apple");
6051     r = pMsiGetProductInfoExA(prodcode, usersid,
6052                               MSIINSTALLCONTEXT_USERUNMANAGED,
6053                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
6054     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6055     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
6056     ok(sz == 3, "Expected 3, got %lu\n", sz);
6057 
6058     res = RegSetValueExA(propkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
6059     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6060 
6061     /* URLInfoAbout value exists */
6062     sz = MAX_PATH;
6063     lstrcpyA(buf, "apple");
6064     r = pMsiGetProductInfoExA(prodcode, usersid,
6065                               MSIINSTALLCONTEXT_USERUNMANAGED,
6066                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
6067     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6068     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
6069     ok(sz == 5, "Expected 5, got %lu\n", sz);
6070 
6071     res = RegSetValueExA(propkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
6072     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6073 
6074     /* URLUpdateInfo value exists */
6075     sz = MAX_PATH;
6076     lstrcpyA(buf, "apple");
6077     r = pMsiGetProductInfoExA(prodcode, usersid,
6078                               MSIINSTALLCONTEXT_USERUNMANAGED,
6079                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
6080     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6081     ok(!lstrcmpA(buf, "update"), "Expected \"update\", got \"%s\"\n", buf);
6082     ok(sz == 6, "Expected 6, got %lu\n", sz);
6083 
6084     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
6085     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6086 
6087     /* VersionMinor value exists */
6088     sz = MAX_PATH;
6089     lstrcpyA(buf, "apple");
6090     r = pMsiGetProductInfoExA(prodcode, usersid,
6091                               MSIINSTALLCONTEXT_USERUNMANAGED,
6092                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
6093     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6094     ok(!lstrcmpA(buf, "2"), "Expected \"2\", got \"%s\"\n", buf);
6095     ok(sz == 1, "Expected 1, got %lu\n", sz);
6096 
6097     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
6098     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6099 
6100     /* VersionMajor value exists */
6101     sz = MAX_PATH;
6102     lstrcpyA(buf, "apple");
6103     r = pMsiGetProductInfoExA(prodcode, usersid,
6104                               MSIINSTALLCONTEXT_USERUNMANAGED,
6105                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
6106     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6107     ok(!lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
6108     ok(sz == 1, "Expected 1, got %lu\n", sz);
6109 
6110     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
6111     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6112 
6113     /* DisplayVersion value exists */
6114     sz = MAX_PATH;
6115     lstrcpyA(buf, "apple");
6116     r = pMsiGetProductInfoExA(prodcode, usersid,
6117                               MSIINSTALLCONTEXT_USERUNMANAGED,
6118                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
6119     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6120     ok(!lstrcmpA(buf, "3.2.1"), "Expected \"3.2.1\", got \"%s\"\n", buf);
6121     ok(sz == 5, "Expected 5, got %lu\n", sz);
6122 
6123     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
6124     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6125 
6126     /* ProductID value exists */
6127     sz = MAX_PATH;
6128     lstrcpyA(buf, "apple");
6129     r = pMsiGetProductInfoExA(prodcode, usersid,
6130                               MSIINSTALLCONTEXT_USERUNMANAGED,
6131                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
6132     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6133     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
6134     ok(sz == 2, "Expected 2, got %lu\n", sz);
6135 
6136     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
6137     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6138 
6139     /* RegCompany value exists */
6140     sz = MAX_PATH;
6141     lstrcpyA(buf, "apple");
6142     r = pMsiGetProductInfoExA(prodcode, usersid,
6143                               MSIINSTALLCONTEXT_USERUNMANAGED,
6144                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
6145     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6146     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
6147     ok(sz == 4, "Expected 4, got %lu\n", sz);
6148 
6149     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
6150     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6151 
6152     /* RegOwner value exists */
6153     sz = MAX_PATH;
6154     lstrcpyA(buf, "apple");
6155     r = pMsiGetProductInfoExA(prodcode, usersid,
6156                               MSIINSTALLCONTEXT_USERUNMANAGED,
6157                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
6158     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6159     ok(!lstrcmpA(buf, "owner"), "Expected \"owner\", got \"%s\"\n", buf);
6160     ok(sz == 5, "Expected 5, got %lu\n", sz);
6161 
6162     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
6163     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6164 
6165     /* Transforms value exists */
6166     sz = MAX_PATH;
6167     lstrcpyA(buf, "apple");
6168     r = pMsiGetProductInfoExA(prodcode, usersid,
6169                               MSIINSTALLCONTEXT_USERUNMANAGED,
6170                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
6171     ok(r == ERROR_UNKNOWN_PRODUCT,
6172        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6173     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6174     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6175 
6176     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
6177     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6178 
6179     /* Language value exists */
6180     sz = MAX_PATH;
6181     lstrcpyA(buf, "apple");
6182     r = pMsiGetProductInfoExA(prodcode, usersid,
6183                               MSIINSTALLCONTEXT_USERUNMANAGED,
6184                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
6185     ok(r == ERROR_UNKNOWN_PRODUCT,
6186        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6187     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6188     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6189 
6190     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
6191     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6192 
6193     /* ProductName value exists */
6194     sz = MAX_PATH;
6195     lstrcpyA(buf, "apple");
6196     r = pMsiGetProductInfoExA(prodcode, usersid,
6197                               MSIINSTALLCONTEXT_USERUNMANAGED,
6198                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
6199     ok(r == ERROR_UNKNOWN_PRODUCT,
6200        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6201     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6202     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6203 
6204     res = RegSetValueExA(propkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
6205     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6206 
6207     /* FIXME */
6208 
6209     /* AssignmentType value exists */
6210     sz = MAX_PATH;
6211     lstrcpyA(buf, "apple");
6212     r = pMsiGetProductInfoExA(prodcode, usersid,
6213                               MSIINSTALLCONTEXT_USERUNMANAGED,
6214                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
6215     ok(r == ERROR_UNKNOWN_PRODUCT,
6216        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6217     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6218     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6219 
6220     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
6221     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6222 
6223     /* PackageCode value exists */
6224     sz = MAX_PATH;
6225     lstrcpyA(buf, "apple");
6226     r = pMsiGetProductInfoExA(prodcode, usersid,
6227                               MSIINSTALLCONTEXT_USERUNMANAGED,
6228                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
6229     ok(r == ERROR_UNKNOWN_PRODUCT,
6230        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6231     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6232     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6233 
6234     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
6235     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6236 
6237     /* Version value exists */
6238     sz = MAX_PATH;
6239     lstrcpyA(buf, "apple");
6240     r = pMsiGetProductInfoExA(prodcode, usersid,
6241                               MSIINSTALLCONTEXT_USERUNMANAGED,
6242                               INSTALLPROPERTY_VERSIONA, buf, &sz);
6243     ok(r == ERROR_UNKNOWN_PRODUCT,
6244        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6245     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6246     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6247 
6248     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
6249     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6250 
6251     /* ProductIcon value exists */
6252     sz = MAX_PATH;
6253     lstrcpyA(buf, "apple");
6254     r = pMsiGetProductInfoExA(prodcode, usersid,
6255                               MSIINSTALLCONTEXT_USERUNMANAGED,
6256                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
6257     ok(r == ERROR_UNKNOWN_PRODUCT,
6258        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6259     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6260     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6261 
6262     res = RegSetValueExA(propkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
6263     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6264 
6265     /* PackageName value exists */
6266     sz = MAX_PATH;
6267     lstrcpyA(buf, "apple");
6268     r = pMsiGetProductInfoExA(prodcode, usersid,
6269                               MSIINSTALLCONTEXT_USERUNMANAGED,
6270                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
6271     ok(r == ERROR_UNKNOWN_PRODUCT,
6272        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6273     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6274     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6275 
6276     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
6277     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6278 
6279     /* AuthorizedLUAApp value exists */
6280     sz = MAX_PATH;
6281     lstrcpyA(buf, "apple");
6282     r = pMsiGetProductInfoExA(prodcode, usersid,
6283                               MSIINSTALLCONTEXT_USERUNMANAGED,
6284                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
6285     ok(r == ERROR_UNKNOWN_PRODUCT,
6286        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6287     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6288     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6289 
6290     RegDeleteValueA(propkey, "AuthorizedLUAApp");
6291     RegDeleteValueA(propkey, "PackageName");
6292     RegDeleteValueA(propkey, "ProductIcon");
6293     RegDeleteValueA(propkey, "Version");
6294     RegDeleteValueA(propkey, "PackageCode");
6295     RegDeleteValueA(propkey, "AssignmentType");
6296     RegDeleteValueA(propkey, "ProductName");
6297     RegDeleteValueA(propkey, "Language");
6298     RegDeleteValueA(propkey, "Transforms");
6299     RegDeleteValueA(propkey, "RegOwner");
6300     RegDeleteValueA(propkey, "RegCompany");
6301     RegDeleteValueA(propkey, "ProductID");
6302     RegDeleteValueA(propkey, "DisplayVersion");
6303     RegDeleteValueA(propkey, "VersionMajor");
6304     RegDeleteValueA(propkey, "VersionMinor");
6305     RegDeleteValueA(propkey, "URLUpdateInfo");
6306     RegDeleteValueA(propkey, "URLInfoAbout");
6307     RegDeleteValueA(propkey, "Publisher");
6308     RegDeleteValueA(propkey, "LocalPackage");
6309     RegDeleteValueA(propkey, "InstallSource");
6310     RegDeleteValueA(propkey, "InstallLocation");
6311     RegDeleteValueA(propkey, "DisplayName");
6312     RegDeleteValueA(propkey, "InstallDate");
6313     RegDeleteValueA(propkey, "HelpTelephone");
6314     RegDeleteValueA(propkey, "HelpLink");
6315     RegDeleteValueA(propkey, "LocalPackage");
6316     RegDeleteKeyA(propkey, "");
6317     RegCloseKey(propkey);
6318     RegDeleteKeyA(localkey, "");
6319     RegCloseKey(localkey);
6320 
6321     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
6322     lstrcatA(keypath, usersid);
6323     lstrcatA(keypath, "\\Installer\\Products\\");
6324     lstrcatA(keypath, prod_squashed);
6325 
6326     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
6327     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6328 
6329     /* user product key exists */
6330     sz = MAX_PATH;
6331     lstrcpyA(buf, "apple");
6332     r = pMsiGetProductInfoExA(prodcode, usersid,
6333                               MSIINSTALLCONTEXT_USERUNMANAGED,
6334                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6335     ok(r == ERROR_UNKNOWN_PRODUCT,
6336        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6337     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6338     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6339 
6340     RegDeleteKeyA(userkey, "");
6341     RegCloseKey(userkey);
6342 
6343     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
6344     lstrcatA(keypath, prod_squashed);
6345 
6346     res = RegCreateKeyExA(HKEY_CURRENT_USER, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
6347     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6348 
6349     sz = MAX_PATH;
6350     lstrcpyA(buf, "apple");
6351     r = pMsiGetProductInfoExA(prodcode, usersid,
6352                               MSIINSTALLCONTEXT_USERUNMANAGED,
6353                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6354     ok(r == ERROR_SUCCESS || broken(r == ERROR_UNKNOWN_PRODUCT), "Expected ERROR_SUCCESS, got %d\n", r);
6355     if (r == ERROR_UNKNOWN_PRODUCT)
6356     {
6357         win_skip("skipping remaining tests for MsiGetProductInfoEx\n");
6358         delete_key(prodkey, "", access);
6359         RegCloseKey(prodkey);
6360         return;
6361     }
6362     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
6363     ok(sz == 1, "Expected 1, got %lu\n", sz);
6364 
6365     res = RegSetValueExA(prodkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
6366     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6367 
6368     /* HelpLink value exists */
6369     sz = MAX_PATH;
6370     lstrcpyA(buf, "apple");
6371     r = pMsiGetProductInfoExA(prodcode, usersid,
6372                               MSIINSTALLCONTEXT_USERUNMANAGED,
6373                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
6374     ok(r == ERROR_UNKNOWN_PROPERTY,
6375        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6376     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6377     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6378 
6379     res = RegSetValueExA(prodkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
6380     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6381 
6382     /* HelpTelephone value exists */
6383     sz = MAX_PATH;
6384     lstrcpyA(buf, "apple");
6385     r = pMsiGetProductInfoExA(prodcode, usersid,
6386                               MSIINSTALLCONTEXT_USERUNMANAGED,
6387                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
6388     ok(r == ERROR_UNKNOWN_PROPERTY,
6389        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6390     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6391     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6392 
6393     res = RegSetValueExA(prodkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
6394     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6395 
6396     /* InstallDate value exists */
6397     sz = MAX_PATH;
6398     lstrcpyA(buf, "apple");
6399     r = pMsiGetProductInfoExA(prodcode, usersid,
6400                               MSIINSTALLCONTEXT_USERUNMANAGED,
6401                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
6402     ok(r == ERROR_UNKNOWN_PROPERTY,
6403        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6404     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6405     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6406 
6407     res = RegSetValueExA(prodkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
6408     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6409 
6410     /* DisplayName value exists */
6411     sz = MAX_PATH;
6412     lstrcpyA(buf, "apple");
6413     r = pMsiGetProductInfoExA(prodcode, usersid,
6414                               MSIINSTALLCONTEXT_USERUNMANAGED,
6415                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
6416     ok(r == ERROR_UNKNOWN_PROPERTY,
6417        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6418     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6419     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6420 
6421     res = RegSetValueExA(prodkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
6422     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6423 
6424     /* InstallLocation value exists */
6425     sz = MAX_PATH;
6426     lstrcpyA(buf, "apple");
6427     r = pMsiGetProductInfoExA(prodcode, usersid,
6428                               MSIINSTALLCONTEXT_USERUNMANAGED,
6429                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
6430     ok(r == ERROR_UNKNOWN_PROPERTY,
6431        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6432     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6433     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6434 
6435     res = RegSetValueExA(prodkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
6436     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6437 
6438     /* InstallSource value exists */
6439     sz = MAX_PATH;
6440     lstrcpyA(buf, "apple");
6441     r = pMsiGetProductInfoExA(prodcode, usersid,
6442                               MSIINSTALLCONTEXT_USERUNMANAGED,
6443                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
6444     ok(r == ERROR_UNKNOWN_PROPERTY,
6445        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6446     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6447     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6448 
6449     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6450     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6451 
6452     /* LocalPackage value exists */
6453     sz = MAX_PATH;
6454     lstrcpyA(buf, "apple");
6455     r = pMsiGetProductInfoExA(prodcode, usersid,
6456                               MSIINSTALLCONTEXT_USERUNMANAGED,
6457                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
6458     ok(r == ERROR_UNKNOWN_PROPERTY,
6459        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6460     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6461     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6462 
6463     res = RegSetValueExA(prodkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
6464     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6465 
6466     /* Publisher value exists */
6467     sz = MAX_PATH;
6468     lstrcpyA(buf, "apple");
6469     r = pMsiGetProductInfoExA(prodcode, usersid,
6470                               MSIINSTALLCONTEXT_USERUNMANAGED,
6471                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
6472     ok(r == ERROR_UNKNOWN_PROPERTY,
6473        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6474     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6475     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6476 
6477     res = RegSetValueExA(prodkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
6478     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6479 
6480     /* URLInfoAbout value exists */
6481     sz = MAX_PATH;
6482     lstrcpyA(buf, "apple");
6483     r = pMsiGetProductInfoExA(prodcode, usersid,
6484                               MSIINSTALLCONTEXT_USERUNMANAGED,
6485                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
6486     ok(r == ERROR_UNKNOWN_PROPERTY,
6487        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6488     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6489     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6490 
6491     res = RegSetValueExA(prodkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
6492     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6493 
6494     /* URLUpdateInfo value exists */
6495     sz = MAX_PATH;
6496     lstrcpyA(buf, "apple");
6497     r = pMsiGetProductInfoExA(prodcode, usersid,
6498                               MSIINSTALLCONTEXT_USERUNMANAGED,
6499                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
6500     ok(r == ERROR_UNKNOWN_PROPERTY,
6501        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6502     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6503     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6504 
6505     res = RegSetValueExA(prodkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
6506     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6507 
6508     /* VersionMinor value exists */
6509     sz = MAX_PATH;
6510     lstrcpyA(buf, "apple");
6511     r = pMsiGetProductInfoExA(prodcode, usersid,
6512                               MSIINSTALLCONTEXT_USERUNMANAGED,
6513                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
6514     ok(r == ERROR_UNKNOWN_PROPERTY,
6515        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6516     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6517     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6518 
6519     res = RegSetValueExA(prodkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
6520     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6521 
6522     /* VersionMajor value exists */
6523     sz = MAX_PATH;
6524     lstrcpyA(buf, "apple");
6525     r = pMsiGetProductInfoExA(prodcode, usersid,
6526                               MSIINSTALLCONTEXT_USERUNMANAGED,
6527                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
6528     ok(r == ERROR_UNKNOWN_PROPERTY,
6529        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6530     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6531     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6532 
6533     res = RegSetValueExA(prodkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
6534     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6535 
6536     /* DisplayVersion value exists */
6537     sz = MAX_PATH;
6538     lstrcpyA(buf, "apple");
6539     r = pMsiGetProductInfoExA(prodcode, usersid,
6540                               MSIINSTALLCONTEXT_USERUNMANAGED,
6541                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
6542     ok(r == ERROR_UNKNOWN_PROPERTY,
6543        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6544     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6545     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6546 
6547     res = RegSetValueExA(prodkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
6548     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6549 
6550     /* ProductID value exists */
6551     sz = MAX_PATH;
6552     lstrcpyA(buf, "apple");
6553     r = pMsiGetProductInfoExA(prodcode, usersid,
6554                               MSIINSTALLCONTEXT_USERUNMANAGED,
6555                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
6556     ok(r == ERROR_UNKNOWN_PROPERTY,
6557        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6558     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6559     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6560 
6561     res = RegSetValueExA(prodkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
6562     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6563 
6564     /* RegCompany value exists */
6565     sz = MAX_PATH;
6566     lstrcpyA(buf, "apple");
6567     r = pMsiGetProductInfoExA(prodcode, usersid,
6568                               MSIINSTALLCONTEXT_USERUNMANAGED,
6569                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
6570     ok(r == ERROR_UNKNOWN_PROPERTY,
6571        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6572     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6573     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6574 
6575     res = RegSetValueExA(prodkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
6576     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6577 
6578     /* RegOwner value exists */
6579     sz = MAX_PATH;
6580     lstrcpyA(buf, "apple");
6581     r = pMsiGetProductInfoExA(prodcode, usersid,
6582                               MSIINSTALLCONTEXT_USERUNMANAGED,
6583                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
6584     ok(r == ERROR_UNKNOWN_PROPERTY,
6585        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6586     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6587     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6588 
6589     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
6590     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6591 
6592     /* Transforms value exists */
6593     sz = MAX_PATH;
6594     lstrcpyA(buf, "apple");
6595     r = pMsiGetProductInfoExA(prodcode, usersid,
6596                               MSIINSTALLCONTEXT_USERUNMANAGED,
6597                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
6598     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6599     ok(!lstrcmpA(buf, "trans"), "Expected \"trans\", got \"%s\"\n", buf);
6600     ok(sz == 5, "Expected 5, got %lu\n", sz);
6601 
6602     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
6603     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6604 
6605     /* Language value exists */
6606     sz = MAX_PATH;
6607     lstrcpyA(buf, "apple");
6608     r = pMsiGetProductInfoExA(prodcode, usersid,
6609                               MSIINSTALLCONTEXT_USERUNMANAGED,
6610                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
6611     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6612     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
6613     ok(sz == 4, "Expected 4, got %lu\n", sz);
6614 
6615     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
6616     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6617 
6618     /* ProductName value exists */
6619     sz = MAX_PATH;
6620     lstrcpyA(buf, "apple");
6621     r = pMsiGetProductInfoExA(prodcode, usersid,
6622                               MSIINSTALLCONTEXT_USERUNMANAGED,
6623                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
6624     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6625     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
6626     ok(sz == 4, "Expected 4, got %lu\n", sz);
6627 
6628     res = RegSetValueExA(prodkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
6629     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6630 
6631     /* FIXME */
6632 
6633     /* AssignmentType value exists */
6634     sz = MAX_PATH;
6635     lstrcpyA(buf, "apple");
6636     r = pMsiGetProductInfoExA(prodcode, usersid,
6637                               MSIINSTALLCONTEXT_USERUNMANAGED,
6638                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
6639     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6640     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
6641     ok(sz == 0, "Expected 0, got %lu\n", sz);
6642 
6643     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
6644     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6645 
6646     /* FIXME */
6647 
6648     /* PackageCode value exists */
6649     sz = MAX_PATH;
6650     lstrcpyA(buf, "apple");
6651     r = pMsiGetProductInfoExA(prodcode, usersid,
6652                               MSIINSTALLCONTEXT_USERUNMANAGED,
6653                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
6654     todo_wine
6655     {
6656         ok(r == ERROR_BAD_CONFIGURATION,
6657            "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
6658         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6659         ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6660     }
6661 
6662     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
6663     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6664 
6665     /* Version value exists */
6666     sz = MAX_PATH;
6667     lstrcpyA(buf, "apple");
6668     r = pMsiGetProductInfoExA(prodcode, usersid,
6669                               MSIINSTALLCONTEXT_USERUNMANAGED,
6670                               INSTALLPROPERTY_VERSIONA, buf, &sz);
6671     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6672     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
6673     ok(sz == 3, "Expected 3, got %lu\n", sz);
6674 
6675     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
6676     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6677 
6678     /* ProductIcon value exists */
6679     sz = MAX_PATH;
6680     lstrcpyA(buf, "apple");
6681     r = pMsiGetProductInfoExA(prodcode, usersid,
6682                               MSIINSTALLCONTEXT_USERUNMANAGED,
6683                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
6684     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6685     ok(!lstrcmpA(buf, "icon"), "Expected \"icon\", got \"%s\"\n", buf);
6686     ok(sz == 4, "Expected 4, got %lu\n", sz);
6687 
6688     res = RegSetValueExA(prodkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
6689     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6690 
6691     /* PackageName value exists */
6692     sz = MAX_PATH;
6693     lstrcpyA(buf, "apple");
6694     r = pMsiGetProductInfoExA(prodcode, usersid,
6695                               MSIINSTALLCONTEXT_USERUNMANAGED,
6696                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
6697     todo_wine
6698     {
6699         ok(r == ERROR_UNKNOWN_PRODUCT,
6700            "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6701         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6702         ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6703     }
6704 
6705     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
6706     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6707 
6708     /* AuthorizedLUAApp value exists */
6709     sz = MAX_PATH;
6710     lstrcpyA(buf, "apple");
6711     r = pMsiGetProductInfoExA(prodcode, usersid,
6712                               MSIINSTALLCONTEXT_USERUNMANAGED,
6713                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
6714     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6715     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
6716     ok(sz == 4, "Expected 4, got %lu\n", sz);
6717 
6718     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
6719     RegDeleteValueA(prodkey, "PackageName");
6720     RegDeleteValueA(prodkey, "ProductIcon");
6721     RegDeleteValueA(prodkey, "Version");
6722     RegDeleteValueA(prodkey, "PackageCode");
6723     RegDeleteValueA(prodkey, "AssignmentType");
6724     RegDeleteValueA(prodkey, "ProductName");
6725     RegDeleteValueA(prodkey, "Language");
6726     RegDeleteValueA(prodkey, "Transforms");
6727     RegDeleteValueA(prodkey, "RegOwner");
6728     RegDeleteValueA(prodkey, "RegCompany");
6729     RegDeleteValueA(prodkey, "ProductID");
6730     RegDeleteValueA(prodkey, "DisplayVersion");
6731     RegDeleteValueA(prodkey, "VersionMajor");
6732     RegDeleteValueA(prodkey, "VersionMinor");
6733     RegDeleteValueA(prodkey, "URLUpdateInfo");
6734     RegDeleteValueA(prodkey, "URLInfoAbout");
6735     RegDeleteValueA(prodkey, "Publisher");
6736     RegDeleteValueA(prodkey, "LocalPackage");
6737     RegDeleteValueA(prodkey, "InstallSource");
6738     RegDeleteValueA(prodkey, "InstallLocation");
6739     RegDeleteValueA(prodkey, "DisplayName");
6740     RegDeleteValueA(prodkey, "InstallDate");
6741     RegDeleteValueA(prodkey, "HelpTelephone");
6742     RegDeleteValueA(prodkey, "HelpLink");
6743     RegDeleteValueA(prodkey, "LocalPackage");
6744     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
6745     RegCloseKey(prodkey);
6746 
6747     /* MSIINSTALLCONTEXT_USERMANAGED */
6748 
6749     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
6750     lstrcatA(keypath, usersid);
6751     lstrcatA(keypath, "\\Products\\");
6752     lstrcatA(keypath, prod_squashed);
6753 
6754     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
6755     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6756 
6757     /* local user product key exists */
6758     sz = MAX_PATH;
6759     lstrcpyA(buf, "apple");
6760     r = pMsiGetProductInfoExA(prodcode, usersid,
6761                               MSIINSTALLCONTEXT_USERMANAGED,
6762                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6763     ok(r == ERROR_UNKNOWN_PRODUCT,
6764        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6765     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6766     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6767 
6768     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
6769     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6770 
6771     /* InstallProperties key exists */
6772     sz = MAX_PATH;
6773     lstrcpyA(buf, "apple");
6774     r = pMsiGetProductInfoExA(prodcode, usersid,
6775                               MSIINSTALLCONTEXT_USERMANAGED,
6776                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6777     ok(r == ERROR_UNKNOWN_PRODUCT,
6778        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6779     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6780     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6781 
6782     res = RegSetValueExA(propkey, "ManagedLocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6783     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6784 
6785     /* ManagedLocalPackage value exists */
6786     sz = MAX_PATH;
6787     lstrcpyA(buf, "apple");
6788     r = pMsiGetProductInfoExA(prodcode, usersid,
6789                               MSIINSTALLCONTEXT_USERMANAGED,
6790                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6791     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6792     ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
6793     ok(sz == 1, "Expected 1, got %lu\n", sz);
6794 
6795     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
6796     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6797 
6798     /* HelpLink value exists */
6799     sz = MAX_PATH;
6800     lstrcpyA(buf, "apple");
6801     r = pMsiGetProductInfoExA(prodcode, usersid,
6802                               MSIINSTALLCONTEXT_USERMANAGED,
6803                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
6804     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6805     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
6806     ok(sz == 4, "Expected 4, got %lu\n", sz);
6807 
6808     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
6809     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6810 
6811     /* HelpTelephone value exists */
6812     sz = MAX_PATH;
6813     lstrcpyA(buf, "apple");
6814     r = pMsiGetProductInfoExA(prodcode, usersid,
6815                               MSIINSTALLCONTEXT_USERMANAGED,
6816                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
6817     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6818     ok(!lstrcmpA(buf, "phone"), "Expected \"phone\", got \"%s\"\n", buf);
6819     ok(sz == 5, "Expected 5, got %lu\n", sz);
6820 
6821     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
6822     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6823 
6824     /* InstallDate value exists */
6825     sz = MAX_PATH;
6826     lstrcpyA(buf, "apple");
6827     r = pMsiGetProductInfoExA(prodcode, usersid,
6828                               MSIINSTALLCONTEXT_USERMANAGED,
6829                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
6830     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6831     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
6832     ok(sz == 4, "Expected 4, got %lu\n", sz);
6833 
6834     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
6835     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6836 
6837     /* DisplayName value exists */
6838     sz = MAX_PATH;
6839     lstrcpyA(buf, "apple");
6840     r = pMsiGetProductInfoExA(prodcode, usersid,
6841                               MSIINSTALLCONTEXT_USERMANAGED,
6842                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
6843     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6844     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
6845     ok(sz == 4, "Expected 4, got %lu\n", sz);
6846 
6847     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
6848     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6849 
6850     /* InstallLocation value exists */
6851     sz = MAX_PATH;
6852     lstrcpyA(buf, "apple");
6853     r = pMsiGetProductInfoExA(prodcode, usersid,
6854                               MSIINSTALLCONTEXT_USERMANAGED,
6855                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
6856     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6857     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
6858     ok(sz == 3, "Expected 3, got %lu\n", sz);
6859 
6860     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
6861     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6862 
6863     /* InstallSource value exists */
6864     sz = MAX_PATH;
6865     lstrcpyA(buf, "apple");
6866     r = pMsiGetProductInfoExA(prodcode, usersid,
6867                               MSIINSTALLCONTEXT_USERMANAGED,
6868                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
6869     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6870     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
6871     ok(sz == 6, "Expected 6, got %lu\n", sz);
6872 
6873     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6874     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6875 
6876     /* LocalPackage value exists */
6877     sz = MAX_PATH;
6878     lstrcpyA(buf, "apple");
6879     r = pMsiGetProductInfoExA(prodcode, usersid,
6880                               MSIINSTALLCONTEXT_USERMANAGED,
6881                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
6882     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6883     ok(!lstrcmpA(buf, "local"), "Expected \"local\", got \"%s\"\n", buf);
6884     ok(sz == 5, "Expected 5, got %lu\n", sz);
6885 
6886     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
6887     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6888 
6889     /* Publisher value exists */
6890     sz = MAX_PATH;
6891     lstrcpyA(buf, "apple");
6892     r = pMsiGetProductInfoExA(prodcode, usersid,
6893                               MSIINSTALLCONTEXT_USERMANAGED,
6894                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
6895     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6896     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
6897     ok(sz == 3, "Expected 3, got %lu\n", sz);
6898 
6899     res = RegSetValueExA(propkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
6900     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6901 
6902     /* URLInfoAbout value exists */
6903     sz = MAX_PATH;
6904     lstrcpyA(buf, "apple");
6905     r = pMsiGetProductInfoExA(prodcode, usersid,
6906                               MSIINSTALLCONTEXT_USERMANAGED,
6907                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
6908     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6909     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
6910     ok(sz == 5, "Expected 5, got %lu\n", sz);
6911 
6912     res = RegSetValueExA(propkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
6913     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6914 
6915     /* URLUpdateInfo value exists */
6916     sz = MAX_PATH;
6917     lstrcpyA(buf, "apple");
6918     r = pMsiGetProductInfoExA(prodcode, usersid,
6919                               MSIINSTALLCONTEXT_USERMANAGED,
6920                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
6921     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6922     ok(!lstrcmpA(buf, "update"), "Expected \"update\", got \"%s\"\n", buf);
6923     ok(sz == 6, "Expected 6, got %lu\n", sz);
6924 
6925     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
6926     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6927 
6928     /* VersionMinor value exists */
6929     sz = MAX_PATH;
6930     lstrcpyA(buf, "apple");
6931     r = pMsiGetProductInfoExA(prodcode, usersid,
6932                               MSIINSTALLCONTEXT_USERMANAGED,
6933                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
6934     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6935     ok(!lstrcmpA(buf, "2"), "Expected \"2\", got \"%s\"\n", buf);
6936     ok(sz == 1, "Expected 1, got %lu\n", sz);
6937 
6938     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
6939     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6940 
6941     /* VersionMajor value exists */
6942     sz = MAX_PATH;
6943     lstrcpyA(buf, "apple");
6944     r = pMsiGetProductInfoExA(prodcode, usersid,
6945                               MSIINSTALLCONTEXT_USERMANAGED,
6946                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
6947     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6948     ok(!lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
6949     ok(sz == 1, "Expected 1, got %lu\n", sz);
6950 
6951     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
6952     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6953 
6954     /* DisplayVersion value exists */
6955     sz = MAX_PATH;
6956     lstrcpyA(buf, "apple");
6957     r = pMsiGetProductInfoExA(prodcode, usersid,
6958                               MSIINSTALLCONTEXT_USERMANAGED,
6959                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
6960     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6961     ok(!lstrcmpA(buf, "3.2.1"), "Expected \"3.2.1\", got \"%s\"\n", buf);
6962     ok(sz == 5, "Expected 5, got %lu\n", sz);
6963 
6964     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
6965     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6966 
6967     /* ProductID value exists */
6968     sz = MAX_PATH;
6969     lstrcpyA(buf, "apple");
6970     r = pMsiGetProductInfoExA(prodcode, usersid,
6971                               MSIINSTALLCONTEXT_USERMANAGED,
6972                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
6973     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6974     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
6975     ok(sz == 2, "Expected 2, got %lu\n", sz);
6976 
6977     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
6978     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6979 
6980     /* RegCompany value exists */
6981     sz = MAX_PATH;
6982     lstrcpyA(buf, "apple");
6983     r = pMsiGetProductInfoExA(prodcode, usersid,
6984                               MSIINSTALLCONTEXT_USERMANAGED,
6985                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
6986     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6987     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
6988     ok(sz == 4, "Expected 4, got %lu\n", sz);
6989 
6990     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
6991     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6992 
6993     /* RegOwner value exists */
6994     sz = MAX_PATH;
6995     lstrcpyA(buf, "apple");
6996     r = pMsiGetProductInfoExA(prodcode, usersid,
6997                               MSIINSTALLCONTEXT_USERMANAGED,
6998                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
6999     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7000     ok(!lstrcmpA(buf, "owner"), "Expected \"owner\", got \"%s\"\n", buf);
7001     ok(sz == 5, "Expected 5, got %lu\n", sz);
7002 
7003     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
7004     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7005 
7006     /* Transforms value exists */
7007     sz = MAX_PATH;
7008     lstrcpyA(buf, "apple");
7009     r = pMsiGetProductInfoExA(prodcode, usersid,
7010                               MSIINSTALLCONTEXT_USERMANAGED,
7011                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
7012     ok(r == ERROR_UNKNOWN_PRODUCT,
7013        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7014     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7015     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7016 
7017     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
7018     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7019 
7020     /* Language value exists */
7021     sz = MAX_PATH;
7022     lstrcpyA(buf, "apple");
7023     r = pMsiGetProductInfoExA(prodcode, usersid,
7024                               MSIINSTALLCONTEXT_USERMANAGED,
7025                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
7026     ok(r == ERROR_UNKNOWN_PRODUCT,
7027        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7028     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7029     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7030 
7031     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
7032     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7033 
7034     /* ProductName value exists */
7035     sz = MAX_PATH;
7036     lstrcpyA(buf, "apple");
7037     r = pMsiGetProductInfoExA(prodcode, usersid,
7038                               MSIINSTALLCONTEXT_USERMANAGED,
7039                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
7040     ok(r == ERROR_UNKNOWN_PRODUCT,
7041        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7042     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7043     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7044 
7045     res = RegSetValueExA(propkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
7046     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7047 
7048     /* FIXME */
7049 
7050     /* AssignmentType value exists */
7051     sz = MAX_PATH;
7052     lstrcpyA(buf, "apple");
7053     r = pMsiGetProductInfoExA(prodcode, usersid,
7054                               MSIINSTALLCONTEXT_USERMANAGED,
7055                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
7056     ok(r == ERROR_UNKNOWN_PRODUCT,
7057        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7058     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7059     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7060 
7061     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
7062     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7063 
7064     /* PackageCode value exists */
7065     sz = MAX_PATH;
7066     lstrcpyA(buf, "apple");
7067     r = pMsiGetProductInfoExA(prodcode, usersid,
7068                               MSIINSTALLCONTEXT_USERMANAGED,
7069                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
7070     ok(r == ERROR_UNKNOWN_PRODUCT,
7071        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7072     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7073     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7074 
7075     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
7076     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7077 
7078     /* Version value exists */
7079     sz = MAX_PATH;
7080     lstrcpyA(buf, "apple");
7081     r = pMsiGetProductInfoExA(prodcode, usersid,
7082                               MSIINSTALLCONTEXT_USERMANAGED,
7083                               INSTALLPROPERTY_VERSIONA, buf, &sz);
7084     ok(r == ERROR_UNKNOWN_PRODUCT,
7085        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7086     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7087     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7088 
7089     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
7090     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7091 
7092     /* ProductIcon value exists */
7093     sz = MAX_PATH;
7094     lstrcpyA(buf, "apple");
7095     r = pMsiGetProductInfoExA(prodcode, usersid,
7096                               MSIINSTALLCONTEXT_USERMANAGED,
7097                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
7098     ok(r == ERROR_UNKNOWN_PRODUCT,
7099        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7100     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7101     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7102 
7103     res = RegSetValueExA(propkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
7104     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7105 
7106     /* PackageName value exists */
7107     sz = MAX_PATH;
7108     lstrcpyA(buf, "apple");
7109     r = pMsiGetProductInfoExA(prodcode, usersid,
7110                               MSIINSTALLCONTEXT_USERMANAGED,
7111                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
7112     ok(r == ERROR_UNKNOWN_PRODUCT,
7113        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7114     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7115     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7116 
7117     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
7118     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7119 
7120     /* AuthorizedLUAApp value exists */
7121     sz = MAX_PATH;
7122     lstrcpyA(buf, "apple");
7123     r = pMsiGetProductInfoExA(prodcode, usersid,
7124                               MSIINSTALLCONTEXT_USERMANAGED,
7125                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
7126     ok(r == ERROR_UNKNOWN_PRODUCT,
7127        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7128     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7129     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7130 
7131     RegDeleteValueA(propkey, "AuthorizedLUAApp");
7132     RegDeleteValueA(propkey, "PackageName");
7133     RegDeleteValueA(propkey, "ProductIcon");
7134     RegDeleteValueA(propkey, "Version");
7135     RegDeleteValueA(propkey, "PackageCode");
7136     RegDeleteValueA(propkey, "AssignmentType");
7137     RegDeleteValueA(propkey, "ProductName");
7138     RegDeleteValueA(propkey, "Language");
7139     RegDeleteValueA(propkey, "Transforms");
7140     RegDeleteValueA(propkey, "RegOwner");
7141     RegDeleteValueA(propkey, "RegCompany");
7142     RegDeleteValueA(propkey, "ProductID");
7143     RegDeleteValueA(propkey, "DisplayVersion");
7144     RegDeleteValueA(propkey, "VersionMajor");
7145     RegDeleteValueA(propkey, "VersionMinor");
7146     RegDeleteValueA(propkey, "URLUpdateInfo");
7147     RegDeleteValueA(propkey, "URLInfoAbout");
7148     RegDeleteValueA(propkey, "Publisher");
7149     RegDeleteValueA(propkey, "LocalPackage");
7150     RegDeleteValueA(propkey, "InstallSource");
7151     RegDeleteValueA(propkey, "InstallLocation");
7152     RegDeleteValueA(propkey, "DisplayName");
7153     RegDeleteValueA(propkey, "InstallDate");
7154     RegDeleteValueA(propkey, "HelpTelephone");
7155     RegDeleteValueA(propkey, "HelpLink");
7156     RegDeleteValueA(propkey, "ManagedLocalPackage");
7157     delete_key(propkey, "", access & KEY_WOW64_64KEY);
7158     RegCloseKey(propkey);
7159     delete_key(localkey, "", access & KEY_WOW64_64KEY);
7160     RegCloseKey(localkey);
7161 
7162     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
7163     lstrcatA(keypath, usersid);
7164     lstrcatA(keypath, "\\Installer\\Products\\");
7165     lstrcatA(keypath, prod_squashed);
7166 
7167     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
7168     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7169 
7170     /* user product key exists */
7171     sz = MAX_PATH;
7172     lstrcpyA(buf, "apple");
7173     r = pMsiGetProductInfoExA(prodcode, usersid,
7174                               MSIINSTALLCONTEXT_USERMANAGED,
7175                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7176     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7177     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
7178     ok(sz == 1, "Expected 1, got %lu\n", sz);
7179 
7180     delete_key(userkey, "", access & KEY_WOW64_64KEY);
7181     RegCloseKey(userkey);
7182 
7183     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
7184     lstrcatA(keypath, prod_squashed);
7185 
7186     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
7187     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7188 
7189     /* current user product key exists */
7190     sz = MAX_PATH;
7191     lstrcpyA(buf, "apple");
7192     r = pMsiGetProductInfoExA(prodcode, usersid,
7193                               MSIINSTALLCONTEXT_USERMANAGED,
7194                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7195     ok(r == ERROR_UNKNOWN_PRODUCT,
7196        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7197     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7198     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7199 
7200     res = RegSetValueExA(prodkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
7201     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7202 
7203     /* HelpLink value exists, user product key does not exist */
7204     sz = MAX_PATH;
7205     lstrcpyA(buf, "apple");
7206     r = pMsiGetProductInfoExA(prodcode, usersid,
7207                               MSIINSTALLCONTEXT_USERMANAGED,
7208                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
7209     ok(r == ERROR_UNKNOWN_PRODUCT,
7210        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7211     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7212     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7213 
7214     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
7215     lstrcatA(keypath, usersid);
7216     lstrcatA(keypath, "\\Installer\\Products\\");
7217     lstrcatA(keypath, prod_squashed);
7218 
7219     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
7220     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7221 
7222     res = RegSetValueExA(userkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
7223     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7224 
7225     /* HelpLink value exists, user product key does exist */
7226     sz = MAX_PATH;
7227     lstrcpyA(buf, "apple");
7228     r = pMsiGetProductInfoExA(prodcode, usersid,
7229                               MSIINSTALLCONTEXT_USERMANAGED,
7230                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
7231     ok(r == ERROR_UNKNOWN_PROPERTY,
7232        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7233     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7234     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7235 
7236     res = RegSetValueExA(userkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
7237     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7238 
7239     /* HelpTelephone value exists */
7240     sz = MAX_PATH;
7241     lstrcpyA(buf, "apple");
7242     r = pMsiGetProductInfoExA(prodcode, usersid,
7243                               MSIINSTALLCONTEXT_USERMANAGED,
7244                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
7245     ok(r == ERROR_UNKNOWN_PROPERTY,
7246        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7247     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7248     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7249 
7250     res = RegSetValueExA(userkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
7251     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7252 
7253     /* InstallDate value exists */
7254     sz = MAX_PATH;
7255     lstrcpyA(buf, "apple");
7256     r = pMsiGetProductInfoExA(prodcode, usersid,
7257                               MSIINSTALLCONTEXT_USERMANAGED,
7258                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
7259     ok(r == ERROR_UNKNOWN_PROPERTY,
7260        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7261     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7262     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7263 
7264     res = RegSetValueExA(userkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
7265     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7266 
7267     /* DisplayName value exists */
7268     sz = MAX_PATH;
7269     lstrcpyA(buf, "apple");
7270     r = pMsiGetProductInfoExA(prodcode, usersid,
7271                               MSIINSTALLCONTEXT_USERMANAGED,
7272                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
7273     ok(r == ERROR_UNKNOWN_PROPERTY,
7274        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7275     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7276     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7277 
7278     res = RegSetValueExA(userkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
7279     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7280 
7281     /* InstallLocation value exists */
7282     sz = MAX_PATH;
7283     lstrcpyA(buf, "apple");
7284     r = pMsiGetProductInfoExA(prodcode, usersid,
7285                               MSIINSTALLCONTEXT_USERMANAGED,
7286                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
7287     ok(r == ERROR_UNKNOWN_PROPERTY,
7288        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7289     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7290     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7291 
7292     res = RegSetValueExA(userkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
7293     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7294 
7295     /* InstallSource value exists */
7296     sz = MAX_PATH;
7297     lstrcpyA(buf, "apple");
7298     r = pMsiGetProductInfoExA(prodcode, usersid,
7299                               MSIINSTALLCONTEXT_USERMANAGED,
7300                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
7301     ok(r == ERROR_UNKNOWN_PROPERTY,
7302        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7303     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7304     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7305 
7306     res = RegSetValueExA(userkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
7307     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7308 
7309     /* LocalPackage value exists */
7310     sz = MAX_PATH;
7311     lstrcpyA(buf, "apple");
7312     r = pMsiGetProductInfoExA(prodcode, usersid,
7313                               MSIINSTALLCONTEXT_USERMANAGED,
7314                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
7315     ok(r == ERROR_UNKNOWN_PROPERTY,
7316        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7317     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7318     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7319 
7320     res = RegSetValueExA(userkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
7321     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7322 
7323     /* Publisher value exists */
7324     sz = MAX_PATH;
7325     lstrcpyA(buf, "apple");
7326     r = pMsiGetProductInfoExA(prodcode, usersid,
7327                               MSIINSTALLCONTEXT_USERMANAGED,
7328                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
7329     ok(r == ERROR_UNKNOWN_PROPERTY,
7330        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7331     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7332     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7333 
7334     res = RegSetValueExA(userkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
7335     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7336 
7337     /* URLInfoAbout value exists */
7338     sz = MAX_PATH;
7339     lstrcpyA(buf, "apple");
7340     r = pMsiGetProductInfoExA(prodcode, usersid,
7341                               MSIINSTALLCONTEXT_USERMANAGED,
7342                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
7343     ok(r == ERROR_UNKNOWN_PROPERTY,
7344        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7345     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7346     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7347 
7348     res = RegSetValueExA(userkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
7349     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7350 
7351     /* URLUpdateInfo value exists */
7352     sz = MAX_PATH;
7353     lstrcpyA(buf, "apple");
7354     r = pMsiGetProductInfoExA(prodcode, usersid,
7355                               MSIINSTALLCONTEXT_USERMANAGED,
7356                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
7357     ok(r == ERROR_UNKNOWN_PROPERTY,
7358        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7359     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7360     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7361 
7362     res = RegSetValueExA(userkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
7363     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7364 
7365     /* VersionMinor value exists */
7366     sz = MAX_PATH;
7367     lstrcpyA(buf, "apple");
7368     r = pMsiGetProductInfoExA(prodcode, usersid,
7369                               MSIINSTALLCONTEXT_USERMANAGED,
7370                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
7371     ok(r == ERROR_UNKNOWN_PROPERTY,
7372        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7373     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7374     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7375 
7376     res = RegSetValueExA(userkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
7377     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7378 
7379     /* VersionMajor value exists */
7380     sz = MAX_PATH;
7381     lstrcpyA(buf, "apple");
7382     r = pMsiGetProductInfoExA(prodcode, usersid,
7383                               MSIINSTALLCONTEXT_USERMANAGED,
7384                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
7385     ok(r == ERROR_UNKNOWN_PROPERTY,
7386        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7387     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7388     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7389 
7390     res = RegSetValueExA(userkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
7391     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7392 
7393     /* DisplayVersion value exists */
7394     sz = MAX_PATH;
7395     lstrcpyA(buf, "apple");
7396     r = pMsiGetProductInfoExA(prodcode, usersid,
7397                               MSIINSTALLCONTEXT_USERMANAGED,
7398                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
7399     ok(r == ERROR_UNKNOWN_PROPERTY,
7400        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7401     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7402     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7403 
7404     res = RegSetValueExA(userkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
7405     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7406 
7407     /* ProductID value exists */
7408     sz = MAX_PATH;
7409     lstrcpyA(buf, "apple");
7410     r = pMsiGetProductInfoExA(prodcode, usersid,
7411                               MSIINSTALLCONTEXT_USERMANAGED,
7412                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
7413     ok(r == ERROR_UNKNOWN_PROPERTY,
7414        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7415     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7416     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7417 
7418     res = RegSetValueExA(userkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
7419     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7420 
7421     /* RegCompany value exists */
7422     sz = MAX_PATH;
7423     lstrcpyA(buf, "apple");
7424     r = pMsiGetProductInfoExA(prodcode, usersid,
7425                               MSIINSTALLCONTEXT_USERMANAGED,
7426                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
7427     ok(r == ERROR_UNKNOWN_PROPERTY,
7428        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7429     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7430     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7431 
7432     res = RegSetValueExA(userkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
7433     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7434 
7435     /* RegOwner value exists */
7436     sz = MAX_PATH;
7437     lstrcpyA(buf, "apple");
7438     r = pMsiGetProductInfoExA(prodcode, usersid,
7439                               MSIINSTALLCONTEXT_USERMANAGED,
7440                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
7441     ok(r == ERROR_UNKNOWN_PROPERTY,
7442        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7443     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7444     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7445 
7446     res = RegSetValueExA(userkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
7447     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7448 
7449     /* Transforms value exists */
7450     sz = MAX_PATH;
7451     lstrcpyA(buf, "apple");
7452     r = pMsiGetProductInfoExA(prodcode, usersid,
7453                               MSIINSTALLCONTEXT_USERMANAGED,
7454                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
7455     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7456     ok(!lstrcmpA(buf, "trans"), "Expected \"trans\", got \"%s\"\n", buf);
7457     ok(sz == 5, "Expected 5, got %lu\n", sz);
7458 
7459     res = RegSetValueExA(userkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
7460     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7461 
7462     /* Language value exists */
7463     sz = MAX_PATH;
7464     lstrcpyA(buf, "apple");
7465     r = pMsiGetProductInfoExA(prodcode, usersid,
7466                               MSIINSTALLCONTEXT_USERMANAGED,
7467                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
7468     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7469     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
7470     ok(sz == 4, "Expected 4, got %lu\n", sz);
7471 
7472     res = RegSetValueExA(userkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
7473     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7474 
7475     /* ProductName value exists */
7476     sz = MAX_PATH;
7477     lstrcpyA(buf, "apple");
7478     r = pMsiGetProductInfoExA(prodcode, usersid,
7479                               MSIINSTALLCONTEXT_USERMANAGED,
7480                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
7481     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7482     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
7483     ok(sz == 4, "Expected 4, got %lu\n", sz);
7484 
7485     res = RegSetValueExA(userkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
7486     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7487 
7488     /* FIXME */
7489 
7490     /* AssignmentType value exists */
7491     sz = MAX_PATH;
7492     lstrcpyA(buf, "apple");
7493     r = pMsiGetProductInfoExA(prodcode, usersid,
7494                               MSIINSTALLCONTEXT_USERMANAGED,
7495                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
7496     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7497     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7498     ok(sz == 0, "Expected 0, got %lu\n", sz);
7499 
7500     res = RegSetValueExA(userkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
7501     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7502 
7503     /* FIXME */
7504 
7505     /* PackageCode value exists */
7506     sz = MAX_PATH;
7507     lstrcpyA(buf, "apple");
7508     r = pMsiGetProductInfoExA(prodcode, usersid,
7509                               MSIINSTALLCONTEXT_USERMANAGED,
7510                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
7511     todo_wine
7512     {
7513         ok(r == ERROR_BAD_CONFIGURATION,
7514            "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
7515         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7516         ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7517     }
7518 
7519     res = RegSetValueExA(userkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
7520     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7521 
7522     /* Version value exists */
7523     sz = MAX_PATH;
7524     lstrcpyA(buf, "apple");
7525     r = pMsiGetProductInfoExA(prodcode, usersid,
7526                               MSIINSTALLCONTEXT_USERMANAGED,
7527                               INSTALLPROPERTY_VERSIONA, buf, &sz);
7528     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7529     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
7530     ok(sz == 3, "Expected 3, got %lu\n", sz);
7531 
7532     res = RegSetValueExA(userkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
7533     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7534 
7535     /* ProductIcon value exists */
7536     sz = MAX_PATH;
7537     lstrcpyA(buf, "apple");
7538     r = pMsiGetProductInfoExA(prodcode, usersid,
7539                               MSIINSTALLCONTEXT_USERMANAGED,
7540                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
7541     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7542     ok(!lstrcmpA(buf, "icon"), "Expected \"icon\", got \"%s\"\n", buf);
7543     ok(sz == 4, "Expected 4, got %lu\n", sz);
7544 
7545     res = RegSetValueExA(userkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
7546     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7547 
7548     /* PackageName value exists */
7549     sz = MAX_PATH;
7550     lstrcpyA(buf, "apple");
7551     r = pMsiGetProductInfoExA(prodcode, usersid,
7552                               MSIINSTALLCONTEXT_USERMANAGED,
7553                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
7554     todo_wine
7555     {
7556         ok(r == ERROR_UNKNOWN_PRODUCT,
7557            "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7558         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7559         ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7560     }
7561 
7562     res = RegSetValueExA(userkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
7563     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7564 
7565     /* AuthorizedLUAApp value exists */
7566     sz = MAX_PATH;
7567     lstrcpyA(buf, "apple");
7568     r = pMsiGetProductInfoExA(prodcode, usersid,
7569                               MSIINSTALLCONTEXT_USERMANAGED,
7570                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
7571     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7572     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
7573     ok(sz == 4, "Expected 4, got %lu\n", sz);
7574 
7575     RegDeleteValueA(userkey, "AuthorizedLUAApp");
7576     RegDeleteValueA(userkey, "PackageName");
7577     RegDeleteValueA(userkey, "ProductIcon");
7578     RegDeleteValueA(userkey, "Version");
7579     RegDeleteValueA(userkey, "PackageCode");
7580     RegDeleteValueA(userkey, "AssignmentType");
7581     RegDeleteValueA(userkey, "ProductName");
7582     RegDeleteValueA(userkey, "Language");
7583     RegDeleteValueA(userkey, "Transforms");
7584     RegDeleteValueA(userkey, "RegOwner");
7585     RegDeleteValueA(userkey, "RegCompany");
7586     RegDeleteValueA(userkey, "ProductID");
7587     RegDeleteValueA(userkey, "DisplayVersion");
7588     RegDeleteValueA(userkey, "VersionMajor");
7589     RegDeleteValueA(userkey, "VersionMinor");
7590     RegDeleteValueA(userkey, "URLUpdateInfo");
7591     RegDeleteValueA(userkey, "URLInfoAbout");
7592     RegDeleteValueA(userkey, "Publisher");
7593     RegDeleteValueA(userkey, "LocalPackage");
7594     RegDeleteValueA(userkey, "InstallSource");
7595     RegDeleteValueA(userkey, "InstallLocation");
7596     RegDeleteValueA(userkey, "DisplayName");
7597     RegDeleteValueA(userkey, "InstallDate");
7598     RegDeleteValueA(userkey, "HelpTelephone");
7599     RegDeleteValueA(userkey, "HelpLink");
7600     delete_key(userkey, "", access & KEY_WOW64_64KEY);
7601     RegCloseKey(userkey);
7602     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
7603     RegCloseKey(prodkey);
7604 
7605     /* MSIINSTALLCONTEXT_MACHINE */
7606 
7607     /* szUserSid is non-NULL */
7608     sz = MAX_PATH;
7609     lstrcpyA(buf, "apple");
7610     r = pMsiGetProductInfoExA(prodcode, usersid,
7611                               MSIINSTALLCONTEXT_MACHINE,
7612                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7613     ok(r == ERROR_INVALID_PARAMETER,
7614        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
7615     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7616     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7617 
7618     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\");
7619     lstrcatA(keypath, prod_squashed);
7620 
7621     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
7622     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7623 
7624     /* local system product key exists */
7625     sz = MAX_PATH;
7626     lstrcpyA(buf, "apple");
7627     r = pMsiGetProductInfoExA(prodcode, NULL,
7628                               MSIINSTALLCONTEXT_MACHINE,
7629                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7630     ok(r == ERROR_UNKNOWN_PRODUCT,
7631        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7632     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7633     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7634 
7635     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
7636     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7637 
7638     /* InstallProperties key exists */
7639     sz = MAX_PATH;
7640     lstrcpyA(buf, "apple");
7641     r = pMsiGetProductInfoExA(prodcode, NULL,
7642                               MSIINSTALLCONTEXT_MACHINE,
7643                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7644     ok(r == ERROR_UNKNOWN_PRODUCT,
7645        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7646     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7647     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7648 
7649     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
7650     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7651 
7652     /* LocalPackage value exists */
7653     sz = MAX_PATH;
7654     lstrcpyA(buf, "apple");
7655     r = pMsiGetProductInfoExA(prodcode, NULL,
7656                               MSIINSTALLCONTEXT_MACHINE,
7657                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7658     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7659     ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
7660     ok(sz == 1, "Expected 1, got %lu\n", sz);
7661 
7662     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
7663     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7664 
7665     /* HelpLink value exists */
7666     sz = MAX_PATH;
7667     lstrcpyA(buf, "apple");
7668     r = pMsiGetProductInfoExA(prodcode, NULL,
7669                               MSIINSTALLCONTEXT_MACHINE,
7670                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
7671     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7672     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
7673     ok(sz == 4, "Expected 4, got %lu\n", sz);
7674 
7675     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
7676     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7677 
7678     /* HelpTelephone value exists */
7679     sz = MAX_PATH;
7680     lstrcpyA(buf, "apple");
7681     r = pMsiGetProductInfoExA(prodcode, NULL,
7682                               MSIINSTALLCONTEXT_MACHINE,
7683                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
7684     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7685     ok(!lstrcmpA(buf, "phone"), "Expected \"phone\", got \"%s\"\n", buf);
7686     ok(sz == 5, "Expected 5, got %lu\n", sz);
7687 
7688     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
7689     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7690 
7691     /* InstallDate value exists */
7692     sz = MAX_PATH;
7693     lstrcpyA(buf, "apple");
7694     r = pMsiGetProductInfoExA(prodcode, NULL,
7695                               MSIINSTALLCONTEXT_MACHINE,
7696                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
7697     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7698     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
7699     ok(sz == 4, "Expected 4, got %lu\n", sz);
7700 
7701     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
7702     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7703 
7704     /* DisplayName value exists */
7705     sz = MAX_PATH;
7706     lstrcpyA(buf, "apple");
7707     r = pMsiGetProductInfoExA(prodcode, NULL,
7708                               MSIINSTALLCONTEXT_MACHINE,
7709                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
7710     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7711     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
7712     ok(sz == 4, "Expected 4, got %lu\n", sz);
7713 
7714     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
7715     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7716 
7717     /* InstallLocation value exists */
7718     sz = MAX_PATH;
7719     lstrcpyA(buf, "apple");
7720     r = pMsiGetProductInfoExA(prodcode, NULL,
7721                               MSIINSTALLCONTEXT_MACHINE,
7722                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
7723     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7724     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
7725     ok(sz == 3, "Expected 3, got %lu\n", sz);
7726 
7727     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
7728     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7729 
7730     /* InstallSource value exists */
7731     sz = MAX_PATH;
7732     lstrcpyA(buf, "apple");
7733     r = pMsiGetProductInfoExA(prodcode, NULL,
7734                               MSIINSTALLCONTEXT_MACHINE,
7735                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
7736     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7737     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
7738     ok(sz == 6, "Expected 6, got %lu\n", sz);
7739 
7740     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
7741     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7742 
7743     /* LocalPackage value exists */
7744     sz = MAX_PATH;
7745     lstrcpyA(buf, "apple");
7746     r = pMsiGetProductInfoExA(prodcode, NULL,
7747                               MSIINSTALLCONTEXT_MACHINE,
7748                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
7749     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7750     ok(!lstrcmpA(buf, "local"), "Expected \"local\", got \"%s\"\n", buf);
7751     ok(sz == 5, "Expected 5, got %lu\n", sz);
7752 
7753     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
7754     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7755 
7756     /* Publisher value exists */
7757     sz = MAX_PATH;
7758     lstrcpyA(buf, "apple");
7759     r = pMsiGetProductInfoExA(prodcode, NULL,
7760                               MSIINSTALLCONTEXT_MACHINE,
7761                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
7762     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7763     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
7764     ok(sz == 3, "Expected 3, got %lu\n", sz);
7765 
7766     res = RegSetValueExA(propkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
7767     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7768 
7769     /* URLInfoAbout value exists */
7770     sz = MAX_PATH;
7771     lstrcpyA(buf, "apple");
7772     r = pMsiGetProductInfoExA(prodcode, NULL,
7773                               MSIINSTALLCONTEXT_MACHINE,
7774                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
7775     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7776     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
7777     ok(sz == 5, "Expected 5, got %lu\n", sz);
7778 
7779     res = RegSetValueExA(propkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
7780     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7781 
7782     /* URLUpdateInfo value exists */
7783     sz = MAX_PATH;
7784     lstrcpyA(buf, "apple");
7785     r = pMsiGetProductInfoExA(prodcode, NULL,
7786                               MSIINSTALLCONTEXT_MACHINE,
7787                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
7788     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7789     ok(!lstrcmpA(buf, "update"), "Expected \"update\", got \"%s\"\n", buf);
7790     ok(sz == 6, "Expected 6, got %lu\n", sz);
7791 
7792     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
7793     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7794 
7795     /* VersionMinor value exists */
7796     sz = MAX_PATH;
7797     lstrcpyA(buf, "apple");
7798     r = pMsiGetProductInfoExA(prodcode, NULL,
7799                               MSIINSTALLCONTEXT_MACHINE,
7800                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
7801     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7802     ok(!lstrcmpA(buf, "2"), "Expected \"2\", got \"%s\"\n", buf);
7803     ok(sz == 1, "Expected 1, got %lu\n", sz);
7804 
7805     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
7806     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7807 
7808     /* VersionMajor value exists */
7809     sz = MAX_PATH;
7810     lstrcpyA(buf, "apple");
7811     r = pMsiGetProductInfoExA(prodcode, NULL,
7812                               MSIINSTALLCONTEXT_MACHINE,
7813                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
7814     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7815     ok(!lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
7816     ok(sz == 1, "Expected 1, got %lu\n", sz);
7817 
7818     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
7819     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7820 
7821     /* DisplayVersion value exists */
7822     sz = MAX_PATH;
7823     lstrcpyA(buf, "apple");
7824     r = pMsiGetProductInfoExA(prodcode, NULL,
7825                               MSIINSTALLCONTEXT_MACHINE,
7826                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
7827     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7828     ok(!lstrcmpA(buf, "3.2.1"), "Expected \"3.2.1\", got \"%s\"\n", buf);
7829     ok(sz == 5, "Expected 5, got %lu\n", sz);
7830 
7831     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
7832     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7833 
7834     /* ProductID value exists */
7835     sz = MAX_PATH;
7836     lstrcpyA(buf, "apple");
7837     r = pMsiGetProductInfoExA(prodcode, NULL,
7838                               MSIINSTALLCONTEXT_MACHINE,
7839                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
7840     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7841     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
7842     ok(sz == 2, "Expected 2, got %lu\n", sz);
7843 
7844     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
7845     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7846 
7847     /* RegCompany value exists */
7848     sz = MAX_PATH;
7849     lstrcpyA(buf, "apple");
7850     r = pMsiGetProductInfoExA(prodcode, NULL,
7851                               MSIINSTALLCONTEXT_MACHINE,
7852                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
7853     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7854     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
7855     ok(sz == 4, "Expected 4, got %lu\n", sz);
7856 
7857     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
7858     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7859 
7860     /* RegOwner value exists */
7861     sz = MAX_PATH;
7862     lstrcpyA(buf, "apple");
7863     r = pMsiGetProductInfoExA(prodcode, NULL,
7864                               MSIINSTALLCONTEXT_MACHINE,
7865                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
7866     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7867     ok(!lstrcmpA(buf, "owner"), "Expected \"owner\", got \"%s\"\n", buf);
7868     ok(sz == 5, "Expected 5, got %lu\n", sz);
7869 
7870     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
7871     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7872 
7873     /* Transforms value exists */
7874     sz = MAX_PATH;
7875     lstrcpyA(buf, "apple");
7876     r = pMsiGetProductInfoExA(prodcode, NULL,
7877                               MSIINSTALLCONTEXT_MACHINE,
7878                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
7879     ok(r == ERROR_UNKNOWN_PRODUCT,
7880        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7881     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7882     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7883 
7884     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
7885     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7886 
7887     /* Language value exists */
7888     sz = MAX_PATH;
7889     lstrcpyA(buf, "apple");
7890     r = pMsiGetProductInfoExA(prodcode, NULL,
7891                               MSIINSTALLCONTEXT_MACHINE,
7892                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
7893     ok(r == ERROR_UNKNOWN_PRODUCT,
7894        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7895     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7896     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7897 
7898     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
7899     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7900 
7901     /* ProductName value exists */
7902     sz = MAX_PATH;
7903     lstrcpyA(buf, "apple");
7904     r = pMsiGetProductInfoExA(prodcode, NULL,
7905                               MSIINSTALLCONTEXT_MACHINE,
7906                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
7907     ok(r == ERROR_UNKNOWN_PRODUCT,
7908        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7909     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7910     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7911 
7912     res = RegSetValueExA(propkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
7913     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7914 
7915     /* FIXME */
7916 
7917     /* AssignmentType value exists */
7918     sz = MAX_PATH;
7919     lstrcpyA(buf, "apple");
7920     r = pMsiGetProductInfoExA(prodcode, NULL,
7921                               MSIINSTALLCONTEXT_MACHINE,
7922                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
7923     ok(r == ERROR_UNKNOWN_PRODUCT,
7924        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7925     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7926     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7927 
7928     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
7929     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7930 
7931     /* PackageCode value exists */
7932     sz = MAX_PATH;
7933     lstrcpyA(buf, "apple");
7934     r = pMsiGetProductInfoExA(prodcode, NULL,
7935                               MSIINSTALLCONTEXT_MACHINE,
7936                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
7937     ok(r == ERROR_UNKNOWN_PRODUCT,
7938        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7939     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7940     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7941 
7942     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
7943     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7944 
7945     /* Version value exists */
7946     sz = MAX_PATH;
7947     lstrcpyA(buf, "apple");
7948     r = pMsiGetProductInfoExA(prodcode, NULL,
7949                               MSIINSTALLCONTEXT_MACHINE,
7950                               INSTALLPROPERTY_VERSIONA, buf, &sz);
7951     ok(r == ERROR_UNKNOWN_PRODUCT,
7952        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7953     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7954     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7955 
7956     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
7957     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7958 
7959     /* ProductIcon value exists */
7960     sz = MAX_PATH;
7961     lstrcpyA(buf, "apple");
7962     r = pMsiGetProductInfoExA(prodcode, NULL,
7963                               MSIINSTALLCONTEXT_MACHINE,
7964                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
7965     ok(r == ERROR_UNKNOWN_PRODUCT,
7966        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7967     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7968     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7969 
7970     res = RegSetValueExA(propkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
7971     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7972 
7973     /* PackageName value exists */
7974     sz = MAX_PATH;
7975     lstrcpyA(buf, "apple");
7976     r = pMsiGetProductInfoExA(prodcode, NULL,
7977                               MSIINSTALLCONTEXT_MACHINE,
7978                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
7979     ok(r == ERROR_UNKNOWN_PRODUCT,
7980        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7981     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7982     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7983 
7984     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
7985     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7986 
7987     /* AuthorizedLUAApp value exists */
7988     sz = MAX_PATH;
7989     lstrcpyA(buf, "apple");
7990     r = pMsiGetProductInfoExA(prodcode, NULL,
7991                               MSIINSTALLCONTEXT_MACHINE,
7992                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
7993     ok(r == ERROR_UNKNOWN_PRODUCT,
7994        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7995     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7996     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7997 
7998     RegDeleteValueA(propkey, "AuthorizedLUAApp");
7999     RegDeleteValueA(propkey, "PackageName");
8000     RegDeleteValueA(propkey, "ProductIcon");
8001     RegDeleteValueA(propkey, "Version");
8002     RegDeleteValueA(propkey, "PackageCode");
8003     RegDeleteValueA(propkey, "AssignmentType");
8004     RegDeleteValueA(propkey, "ProductName");
8005     RegDeleteValueA(propkey, "Language");
8006     RegDeleteValueA(propkey, "Transforms");
8007     RegDeleteValueA(propkey, "RegOwner");
8008     RegDeleteValueA(propkey, "RegCompany");
8009     RegDeleteValueA(propkey, "ProductID");
8010     RegDeleteValueA(propkey, "DisplayVersion");
8011     RegDeleteValueA(propkey, "VersionMajor");
8012     RegDeleteValueA(propkey, "VersionMinor");
8013     RegDeleteValueA(propkey, "URLUpdateInfo");
8014     RegDeleteValueA(propkey, "URLInfoAbout");
8015     RegDeleteValueA(propkey, "Publisher");
8016     RegDeleteValueA(propkey, "LocalPackage");
8017     RegDeleteValueA(propkey, "InstallSource");
8018     RegDeleteValueA(propkey, "InstallLocation");
8019     RegDeleteValueA(propkey, "DisplayName");
8020     RegDeleteValueA(propkey, "InstallDate");
8021     RegDeleteValueA(propkey, "HelpTelephone");
8022     RegDeleteValueA(propkey, "HelpLink");
8023     RegDeleteValueA(propkey, "LocalPackage");
8024     delete_key(propkey, "", access & KEY_WOW64_64KEY);
8025     RegCloseKey(propkey);
8026     delete_key(localkey, "", access & KEY_WOW64_64KEY);
8027     RegCloseKey(localkey);
8028 
8029     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
8030     lstrcatA(keypath, prod_squashed);
8031 
8032     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8033     if (res == ERROR_ACCESS_DENIED)
8034     {
8035         skip( "insufficient rights\n" );
8036         LocalFree( usersid );
8037         return;
8038     }
8039     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8040 
8041     /* local classes product key exists */
8042     sz = MAX_PATH;
8043     lstrcpyA(buf, "apple");
8044     r = pMsiGetProductInfoExA(prodcode, NULL,
8045                               MSIINSTALLCONTEXT_MACHINE,
8046                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
8047     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8048     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
8049     ok(sz == 1, "Expected 1, got %lu\n", sz);
8050 
8051     res = RegSetValueExA(prodkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
8052     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8053 
8054     /* HelpLink value exists */
8055     sz = MAX_PATH;
8056     lstrcpyA(buf, "apple");
8057     r = pMsiGetProductInfoExA(prodcode, NULL,
8058                               MSIINSTALLCONTEXT_MACHINE,
8059                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
8060     ok(r == ERROR_UNKNOWN_PROPERTY,
8061        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8062     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8063     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
8064 
8065     res = RegSetValueExA(prodkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
8066     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8067 
8068     /* HelpTelephone value exists */
8069     sz = MAX_PATH;
8070     lstrcpyA(buf, "apple");
8071     r = pMsiGetProductInfoExA(prodcode, NULL,
8072                               MSIINSTALLCONTEXT_MACHINE,
8073                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
8074     ok(r == ERROR_UNKNOWN_PROPERTY,
8075        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8076     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8077     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
8078 
8079     res = RegSetValueExA(prodkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
8080     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8081 
8082     /* InstallDate value exists */
8083     sz = MAX_PATH;
8084     lstrcpyA(buf, "apple");
8085     r = pMsiGetProductInfoExA(prodcode, NULL,
8086                               MSIINSTALLCONTEXT_MACHINE,
8087                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
8088     ok(r == ERROR_UNKNOWN_PROPERTY,
8089        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8090     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8091     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
8092 
8093     res = RegSetValueExA(prodkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
8094     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8095 
8096     /* DisplayName value exists */
8097     sz = MAX_PATH;
8098     lstrcpyA(buf, "apple");
8099     r = pMsiGetProductInfoExA(prodcode, NULL,
8100                               MSIINSTALLCONTEXT_MACHINE,
8101                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
8102     ok(r == ERROR_UNKNOWN_PROPERTY,
8103        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8104     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8105     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
8106 
8107     res = RegSetValueExA(prodkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
8108     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8109 
8110     /* InstallLocation value exists */
8111     sz = MAX_PATH;
8112     lstrcpyA(buf, "apple");
8113     r = pMsiGetProductInfoExA(prodcode, NULL,
8114                               MSIINSTALLCONTEXT_MACHINE,
8115                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
8116     ok(r == ERROR_UNKNOWN_PROPERTY,
8117        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8118     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8119     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
8120 
8121     res = RegSetValueExA(prodkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
8122     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8123 
8124     /* InstallSource value exists */
8125     sz = MAX_PATH;
8126     lstrcpyA(buf, "apple");
8127     r = pMsiGetProductInfoExA(prodcode, NULL,
8128                               MSIINSTALLCONTEXT_MACHINE,
8129                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
8130     ok(r == ERROR_UNKNOWN_PROPERTY,
8131        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8132     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8133     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
8134 
8135     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
8136     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8137 
8138     /* LocalPackage value exists */
8139     sz = MAX_PATH;
8140     lstrcpyA(buf, "apple");
8141     r = pMsiGetProductInfoExA(prodcode, NULL,
8142                               MSIINSTALLCONTEXT_MACHINE,
8143                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
8144     ok(r == ERROR_UNKNOWN_PROPERTY,
8145        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8146     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8147     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
8148 
8149     res = RegSetValueExA(prodkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
8150     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8151 
8152     /* Publisher value exists */
8153     sz = MAX_PATH;
8154     lstrcpyA(buf, "apple");
8155     r = pMsiGetProductInfoExA(prodcode, NULL,
8156                               MSIINSTALLCONTEXT_MACHINE,
8157                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
8158     ok(r == ERROR_UNKNOWN_PROPERTY,
8159        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8160     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8161     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
8162 
8163     res = RegSetValueExA(prodkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
8164     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8165 
8166     /* URLInfoAbout value exists */
8167     sz = MAX_PATH;
8168     lstrcpyA(buf, "apple");
8169     r = pMsiGetProductInfoExA(prodcode, NULL,
8170                               MSIINSTALLCONTEXT_MACHINE,
8171                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
8172     ok(r == ERROR_UNKNOWN_PROPERTY,
8173        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8174     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8175     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
8176 
8177     res = RegSetValueExA(prodkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
8178     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8179 
8180     /* URLUpdateInfo value exists */
8181     sz = MAX_PATH;
8182     lstrcpyA(buf, "apple");
8183     r = pMsiGetProductInfoExA(prodcode, NULL,
8184                               MSIINSTALLCONTEXT_MACHINE,
8185                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
8186     ok(r == ERROR_UNKNOWN_PROPERTY,
8187        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8188     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8189     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
8190 
8191     res = RegSetValueExA(prodkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
8192     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8193 
8194     /* VersionMinor value exists */
8195     sz = MAX_PATH;
8196     lstrcpyA(buf, "apple");
8197     r = pMsiGetProductInfoExA(prodcode, NULL,
8198                               MSIINSTALLCONTEXT_MACHINE,
8199                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
8200     ok(r == ERROR_UNKNOWN_PROPERTY,
8201        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8202     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8203     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
8204 
8205     res = RegSetValueExA(prodkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
8206     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8207 
8208     /* VersionMajor value exists */
8209     sz = MAX_PATH;
8210     lstrcpyA(buf, "apple");
8211     r = pMsiGetProductInfoExA(prodcode, NULL,
8212                               MSIINSTALLCONTEXT_MACHINE,
8213                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
8214     ok(r == ERROR_UNKNOWN_PROPERTY,
8215        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8216     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8217     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
8218 
8219     res = RegSetValueExA(prodkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
8220     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8221 
8222     /* DisplayVersion value exists */
8223     sz = MAX_PATH;
8224     lstrcpyA(buf, "apple");
8225     r = pMsiGetProductInfoExA(prodcode, NULL,
8226                               MSIINSTALLCONTEXT_MACHINE,
8227                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
8228     ok(r == ERROR_UNKNOWN_PROPERTY,
8229        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8230     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8231     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
8232 
8233     res = RegSetValueExA(prodkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
8234     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8235 
8236     /* ProductID value exists */
8237     sz = MAX_PATH;
8238     lstrcpyA(buf, "apple");
8239     r = pMsiGetProductInfoExA(prodcode, NULL,
8240                               MSIINSTALLCONTEXT_MACHINE,
8241                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
8242     ok(r == ERROR_UNKNOWN_PROPERTY,
8243        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8244     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8245     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
8246 
8247     res = RegSetValueExA(prodkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
8248     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8249 
8250     /* RegCompany value exists */
8251     sz = MAX_PATH;
8252     lstrcpyA(buf, "apple");
8253     r = pMsiGetProductInfoExA(prodcode, NULL,
8254                               MSIINSTALLCONTEXT_MACHINE,
8255                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
8256     ok(r == ERROR_UNKNOWN_PROPERTY,
8257        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8258     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8259     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
8260 
8261     res = RegSetValueExA(prodkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
8262     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8263 
8264     /* RegOwner value exists */
8265     sz = MAX_PATH;
8266     lstrcpyA(buf, "apple");
8267     r = pMsiGetProductInfoExA(prodcode, NULL,
8268                               MSIINSTALLCONTEXT_MACHINE,
8269                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
8270     ok(r == ERROR_UNKNOWN_PROPERTY,
8271        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8272     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8273     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
8274 
8275     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
8276     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8277 
8278     /* Transforms value exists */
8279     sz = MAX_PATH;
8280     lstrcpyA(buf, "apple");
8281     r = pMsiGetProductInfoExA(prodcode, NULL,
8282                               MSIINSTALLCONTEXT_MACHINE,
8283                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
8284     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8285     ok(!lstrcmpA(buf, "trans"), "Expected \"trans\", got \"%s\"\n", buf);
8286     ok(sz == 5, "Expected 5, got %lu\n", sz);
8287 
8288     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
8289     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8290 
8291     /* Language value exists */
8292     sz = MAX_PATH;
8293     lstrcpyA(buf, "apple");
8294     r = pMsiGetProductInfoExA(prodcode, NULL,
8295                               MSIINSTALLCONTEXT_MACHINE,
8296                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
8297     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8298     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
8299     ok(sz == 4, "Expected 4, got %lu\n", sz);
8300 
8301     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
8302     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8303 
8304     /* ProductName value exists */
8305     sz = MAX_PATH;
8306     lstrcpyA(buf, "apple");
8307     r = pMsiGetProductInfoExA(prodcode, NULL,
8308                               MSIINSTALLCONTEXT_MACHINE,
8309                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
8310     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8311     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
8312     ok(sz == 4, "Expected 4, got %lu\n", sz);
8313 
8314     res = RegSetValueExA(prodkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
8315     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8316 
8317     /* FIXME */
8318 
8319     /* AssignmentType value exists */
8320     sz = MAX_PATH;
8321     lstrcpyA(buf, "apple");
8322     r = pMsiGetProductInfoExA(prodcode, NULL,
8323                               MSIINSTALLCONTEXT_MACHINE,
8324                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
8325     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8326     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
8327     ok(sz == 0, "Expected 0, got %lu\n", sz);
8328 
8329     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
8330     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8331 
8332     /* FIXME */
8333 
8334     /* PackageCode value exists */
8335     sz = MAX_PATH;
8336     lstrcpyA(buf, "apple");
8337     r = pMsiGetProductInfoExA(prodcode, NULL,
8338                               MSIINSTALLCONTEXT_MACHINE,
8339                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
8340     todo_wine
8341     {
8342         ok(r == ERROR_BAD_CONFIGURATION,
8343            "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
8344         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8345         ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
8346     }
8347 
8348     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
8349     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8350 
8351     /* Version value exists */
8352     sz = MAX_PATH;
8353     lstrcpyA(buf, "apple");
8354     r = pMsiGetProductInfoExA(prodcode, NULL,
8355                               MSIINSTALLCONTEXT_MACHINE,
8356                               INSTALLPROPERTY_VERSIONA, buf, &sz);
8357     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8358     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
8359     ok(sz == 3, "Expected 3, got %lu\n", sz);
8360 
8361     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
8362     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8363 
8364     /* ProductIcon value exists */
8365     sz = MAX_PATH;
8366     lstrcpyA(buf, "apple");
8367     r = pMsiGetProductInfoExA(prodcode, NULL,
8368                               MSIINSTALLCONTEXT_MACHINE,
8369                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
8370     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8371     ok(!lstrcmpA(buf, "icon"), "Expected \"icon\", got \"%s\"\n", buf);
8372     ok(sz == 4, "Expected 4, got %lu\n", sz);
8373 
8374     res = RegSetValueExA(prodkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
8375     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8376 
8377     /* PackageName value exists */
8378     sz = MAX_PATH;
8379     lstrcpyA(buf, "apple");
8380     r = pMsiGetProductInfoExA(prodcode, NULL,
8381                               MSIINSTALLCONTEXT_MACHINE,
8382                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
8383     todo_wine
8384     {
8385         ok(r == ERROR_UNKNOWN_PRODUCT,
8386            "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8387         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8388         ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
8389     }
8390 
8391     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
8392     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8393 
8394     /* AuthorizedLUAApp value exists */
8395     sz = MAX_PATH;
8396     lstrcpyA(buf, "apple");
8397     r = pMsiGetProductInfoExA(prodcode, NULL,
8398                               MSIINSTALLCONTEXT_MACHINE,
8399                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
8400     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8401     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
8402     ok(sz == 4, "Expected 4, got %lu\n", sz);
8403 
8404     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
8405     RegDeleteValueA(prodkey, "PackageName");
8406     RegDeleteValueA(prodkey, "ProductIcon");
8407     RegDeleteValueA(prodkey, "Version");
8408     RegDeleteValueA(prodkey, "PackageCode");
8409     RegDeleteValueA(prodkey, "AssignmentType");
8410     RegDeleteValueA(prodkey, "ProductName");
8411     RegDeleteValueA(prodkey, "Language");
8412     RegDeleteValueA(prodkey, "Transforms");
8413     RegDeleteValueA(prodkey, "RegOwner");
8414     RegDeleteValueA(prodkey, "RegCompany");
8415     RegDeleteValueA(prodkey, "ProductID");
8416     RegDeleteValueA(prodkey, "DisplayVersion");
8417     RegDeleteValueA(prodkey, "VersionMajor");
8418     RegDeleteValueA(prodkey, "VersionMinor");
8419     RegDeleteValueA(prodkey, "URLUpdateInfo");
8420     RegDeleteValueA(prodkey, "URLInfoAbout");
8421     RegDeleteValueA(prodkey, "Publisher");
8422     RegDeleteValueA(prodkey, "LocalPackage");
8423     RegDeleteValueA(prodkey, "InstallSource");
8424     RegDeleteValueA(prodkey, "InstallLocation");
8425     RegDeleteValueA(prodkey, "DisplayName");
8426     RegDeleteValueA(prodkey, "InstallDate");
8427     RegDeleteValueA(prodkey, "HelpTelephone");
8428     RegDeleteValueA(prodkey, "HelpLink");
8429     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
8430     RegCloseKey(prodkey);
8431     LocalFree(usersid);
8432 }
8433 
8434 #define INIT_USERINFO() \
8435     lstrcpyA(user, "apple"); \
8436     lstrcpyA(org, "orange"); \
8437     lstrcpyA(serial, "banana"); \
8438     usersz = orgsz = serialsz = MAX_PATH;
8439 
8440 static void test_MsiGetUserInfo(void)
8441 {
8442     USERINFOSTATE state;
8443     CHAR user[MAX_PATH];
8444     CHAR org[MAX_PATH];
8445     CHAR serial[MAX_PATH];
8446     DWORD usersz, orgsz, serialsz;
8447     CHAR keypath[MAX_PATH * 2];
8448     CHAR prodcode[MAX_PATH];
8449     CHAR prod_squashed[MAX_PATH];
8450     HKEY prodkey, userprod, props;
8451     LPSTR usersid;
8452     LONG res;
8453     REGSAM access = KEY_ALL_ACCESS;
8454 
8455     create_test_guid(prodcode, prod_squashed);
8456     usersid = get_user_sid();
8457 
8458     if (is_wow64)
8459         access |= KEY_WOW64_64KEY;
8460 
8461     /* NULL szProduct */
8462     INIT_USERINFO();
8463     state = MsiGetUserInfoA(NULL, user, &usersz, org, &orgsz, serial, &serialsz);
8464     ok(state == USERINFOSTATE_INVALIDARG,
8465        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8466     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8467     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8468     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8469     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8470     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8471     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8472 
8473     /* empty szProductCode */
8474     INIT_USERINFO();
8475     state = MsiGetUserInfoA("", user, &usersz, org, &orgsz, serial, &serialsz);
8476     ok(state == USERINFOSTATE_INVALIDARG,
8477        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8478     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8479     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8480     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8481     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8482     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8483     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8484 
8485     /* garbage szProductCode */
8486     INIT_USERINFO();
8487     state = MsiGetUserInfoA("garbage", user, &usersz, org, &orgsz, serial, &serialsz);
8488     ok(state == USERINFOSTATE_INVALIDARG,
8489        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8490     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8491     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8492     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8493     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8494     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8495     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8496 
8497     /* guid without brackets */
8498     INIT_USERINFO();
8499     state = MsiGetUserInfoA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
8500                             user, &usersz, org, &orgsz, serial, &serialsz);
8501     ok(state == USERINFOSTATE_INVALIDARG,
8502        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8503     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8504     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8505     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8506     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8507     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8508     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8509 
8510     /* guid with brackets */
8511     INIT_USERINFO();
8512     state = MsiGetUserInfoA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
8513                             user, &usersz, org, &orgsz, serial, &serialsz);
8514     ok(state == USERINFOSTATE_UNKNOWN,
8515        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8516     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8517     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8518     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8519     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8520     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8521     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8522 
8523     /* NULL lpUserNameBuf */
8524     INIT_USERINFO();
8525     state = MsiGetUserInfoA(prodcode, NULL, &usersz, org, &orgsz, serial, &serialsz);
8526     ok(state == USERINFOSTATE_UNKNOWN,
8527        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8528     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8529     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8530     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8531     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8532     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8533 
8534     /* NULL pcchUserNameBuf */
8535     INIT_USERINFO();
8536     state = MsiGetUserInfoA(prodcode, user, NULL, org, &orgsz, serial, &serialsz);
8537     ok(state == USERINFOSTATE_INVALIDARG,
8538        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8539     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8540     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8541     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8542     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8543     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8544 
8545     /* both lpUserNameBuf and pcchUserNameBuf NULL */
8546     INIT_USERINFO();
8547     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
8548     ok(state == USERINFOSTATE_UNKNOWN,
8549        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8550     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8551     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8552     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8553     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8554 
8555     /* NULL lpOrgNameBuf */
8556     INIT_USERINFO();
8557     state = MsiGetUserInfoA(prodcode, user, &usersz, NULL, &orgsz, serial, &serialsz);
8558     ok(state == USERINFOSTATE_UNKNOWN,
8559        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8560     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8561     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8562     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8563     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8564     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8565 
8566     /* NULL pcchOrgNameBuf */
8567     INIT_USERINFO();
8568     state = MsiGetUserInfoA(prodcode, user, &usersz, org, NULL, serial, &serialsz);
8569     ok(state == USERINFOSTATE_INVALIDARG,
8570        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8571     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8572     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8573     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8574     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8575     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8576 
8577     /* both lpOrgNameBuf and pcchOrgNameBuf NULL */
8578     INIT_USERINFO();
8579     state = MsiGetUserInfoA(prodcode, user, &usersz, NULL, NULL, serial, &serialsz);
8580     ok(state == USERINFOSTATE_UNKNOWN,
8581        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8582     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8583     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8584     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8585     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8586 
8587     /* NULL lpSerialBuf */
8588     INIT_USERINFO();
8589     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, NULL, &serialsz);
8590     ok(state == USERINFOSTATE_UNKNOWN,
8591        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8592     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8593     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8594     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8595     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8596     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8597 
8598     /* NULL pcchSerialBuf */
8599     INIT_USERINFO();
8600     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, NULL);
8601     ok(state == USERINFOSTATE_INVALIDARG,
8602        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8603     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8604     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8605     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8606     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8607     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8608 
8609     /* both lpSerialBuf and pcchSerialBuf NULL */
8610     INIT_USERINFO();
8611     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, NULL, NULL);
8612     ok(state == USERINFOSTATE_UNKNOWN,
8613        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8614     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8615     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8616     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8617     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8618 
8619     /* MSIINSTALLCONTEXT_USERMANAGED */
8620 
8621     /* create local system product key */
8622     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
8623     lstrcatA(keypath, usersid);
8624     lstrcatA(keypath, "\\Installer\\Products\\");
8625     lstrcatA(keypath, prod_squashed);
8626 
8627     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8628     if (res == ERROR_ACCESS_DENIED)
8629     {
8630         skip("Not enough rights to perform tests\n");
8631         LocalFree(usersid);
8632         return;
8633     }
8634     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8635 
8636     /* managed product key exists */
8637     INIT_USERINFO();
8638     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8639     ok(state == USERINFOSTATE_ABSENT,
8640        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8641     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8642     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8643     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8644     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8645     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8646     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8647 
8648     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8649     lstrcatA(keypath, "Installer\\UserData\\");
8650     lstrcatA(keypath, usersid);
8651     lstrcatA(keypath, "\\Products\\");
8652     lstrcatA(keypath, prod_squashed);
8653 
8654     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL);
8655     if (res == ERROR_ACCESS_DENIED)
8656     {
8657         skip("Not enough rights to perform tests\n");
8658         LocalFree(usersid);
8659         return;
8660     }
8661     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8662 
8663     res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8664     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8665 
8666     /* InstallProperties key exists */
8667     INIT_USERINFO();
8668     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8669     ok(state == USERINFOSTATE_ABSENT,
8670        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8671     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8672     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8673     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8674     ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", usersz);
8675     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8676     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8677 
8678     /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */
8679     INIT_USERINFO();
8680     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
8681     ok(state == USERINFOSTATE_ABSENT,
8682        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8683     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
8684     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8685     ok(orgsz == 0, "Expected 0, got %lu\n", orgsz);
8686     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", serialsz);
8687 
8688     /* RegOwner, RegCompany don't exist, out params are NULL */
8689     INIT_USERINFO();
8690     state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz);
8691     ok(state == USERINFOSTATE_ABSENT,
8692        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8693     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8694     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", serialsz);
8695 
8696     res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
8697     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8698 
8699     /* RegOwner value exists */
8700     INIT_USERINFO();
8701     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8702     ok(state == USERINFOSTATE_ABSENT,
8703        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8704     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8705     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
8706     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8707     ok(usersz == 5, "Expected 5, got %lu\n", usersz);
8708     ok(orgsz == 0, "Expected 0, got %lu\n", orgsz);
8709     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", serialsz);
8710 
8711     res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8);
8712     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8713 
8714     /* RegCompany value exists */
8715     INIT_USERINFO();
8716     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8717     ok(state == USERINFOSTATE_ABSENT,
8718        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8719     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8720     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8721     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8722     ok(usersz == 5, "Expected 5, got %lu\n", usersz);
8723     ok(orgsz == 7, "Expected 7, got %lu\n", orgsz);
8724     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", serialsz);
8725 
8726     res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3);
8727     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8728 
8729     /* ProductID value exists */
8730     INIT_USERINFO();
8731     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8732     ok(state == USERINFOSTATE_PRESENT,
8733        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
8734     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8735     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8736     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
8737     ok(usersz == 5, "Expected 5, got %lu\n", usersz);
8738     ok(orgsz == 7, "Expected 7, got %lu\n", orgsz);
8739     ok(serialsz == 2, "Expected 2, got %lu\n", serialsz);
8740 
8741     /* pcchUserNameBuf is too small */
8742     INIT_USERINFO();
8743     usersz = 0;
8744     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8745     ok(state == USERINFOSTATE_MOREDATA,
8746        "Expected USERINFOSTATE_MOREDATA, got %d\n", state);
8747     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8748     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8749     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8750     ok(usersz == 5, "Expected 5, got %lu\n", usersz);
8751     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8752     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8753 
8754     /* pcchUserNameBuf has no room for NULL terminator */
8755     INIT_USERINFO();
8756     usersz = 5;
8757     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8758     ok(state == USERINFOSTATE_MOREDATA,
8759        "Expected USERINFOSTATE_MOREDATA, got %d\n", state);
8760     todo_wine
8761     {
8762         ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8763     }
8764     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8765     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8766     ok(usersz == 5, "Expected 5, got %lu\n", usersz);
8767     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8768     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8769 
8770     /* pcchUserNameBuf is too small, lpUserNameBuf is NULL */
8771     INIT_USERINFO();
8772     usersz = 0;
8773     state = MsiGetUserInfoA(prodcode, NULL, &usersz, org, &orgsz, serial, &serialsz);
8774     ok(state == USERINFOSTATE_PRESENT,
8775        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
8776     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8777     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8778     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
8779     ok(usersz == 5, "Expected 5, got %lu\n", usersz);
8780     ok(orgsz == 7, "Expected 7, got %lu\n", orgsz);
8781     ok(serialsz == 2, "Expected 2, got %lu\n", serialsz);
8782 
8783     RegDeleteValueA(props, "ProductID");
8784     RegDeleteValueA(props, "RegCompany");
8785     RegDeleteValueA(props, "RegOwner");
8786     delete_key(props, "", access & KEY_WOW64_64KEY);
8787     RegCloseKey(props);
8788     delete_key(userprod, "", access & KEY_WOW64_64KEY);
8789     RegCloseKey(userprod);
8790     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
8791     RegCloseKey(prodkey);
8792 
8793     /* MSIINSTALLCONTEXT_USERUNMANAGED */
8794 
8795     /* create local system product key */
8796     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
8797     lstrcatA(keypath, prod_squashed);
8798 
8799     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
8800     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8801 
8802     /* product key exists */
8803     INIT_USERINFO();
8804     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8805     ok(state == USERINFOSTATE_ABSENT,
8806        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8807     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8808     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8809     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8810     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8811     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8812     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8813 
8814     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8815     lstrcatA(keypath, "Installer\\UserData\\");
8816     lstrcatA(keypath, usersid);
8817     lstrcatA(keypath, "\\Products\\");
8818     lstrcatA(keypath, prod_squashed);
8819 
8820     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL);
8821     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8822 
8823     res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8824     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8825 
8826     /* InstallProperties key exists */
8827     INIT_USERINFO();
8828     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8829     ok(state == USERINFOSTATE_ABSENT,
8830        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8831     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8832     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8833     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8834     ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", usersz);
8835     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8836     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8837 
8838     /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */
8839     INIT_USERINFO();
8840     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
8841     ok(state == USERINFOSTATE_ABSENT,
8842        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8843     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
8844     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8845     ok(orgsz == 0, "Expected 0, got %lu\n", orgsz);
8846     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", serialsz);
8847 
8848     /* RegOwner, RegCompany don't exist, out params are NULL */
8849     INIT_USERINFO();
8850     state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz);
8851     ok(state == USERINFOSTATE_ABSENT,
8852        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8853     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8854     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", serialsz);
8855 
8856     res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
8857     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8858 
8859     /* RegOwner value exists */
8860     INIT_USERINFO();
8861     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8862     ok(state == USERINFOSTATE_ABSENT,
8863        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8864     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8865     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
8866     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8867     ok(usersz == 5, "Expected 5, got %lu\n", usersz);
8868     ok(orgsz == 0, "Expected 0, got %lu\n", orgsz);
8869     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", serialsz);
8870 
8871     res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8);
8872     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8873 
8874     /* RegCompany value exists */
8875     INIT_USERINFO();
8876     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8877     ok(state == USERINFOSTATE_ABSENT,
8878        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8879     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8880     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8881     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8882     ok(usersz == 5, "Expected 5, got %lu\n", usersz);
8883     ok(orgsz == 7, "Expected 7, got %lu\n", orgsz);
8884     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", serialsz);
8885 
8886     res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3);
8887     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8888 
8889     /* ProductID value exists */
8890     INIT_USERINFO();
8891     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8892     ok(state == USERINFOSTATE_PRESENT,
8893        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
8894     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8895     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8896     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
8897     ok(usersz == 5, "Expected 5, got %lu\n", usersz);
8898     ok(orgsz == 7, "Expected 7, got %lu\n", orgsz);
8899     ok(serialsz == 2, "Expected 2, got %lu\n", serialsz);
8900 
8901     RegDeleteValueA(props, "ProductID");
8902     RegDeleteValueA(props, "RegCompany");
8903     RegDeleteValueA(props, "RegOwner");
8904     delete_key(props, "", access & KEY_WOW64_64KEY);
8905     RegCloseKey(props);
8906     delete_key(userprod, "", access & KEY_WOW64_64KEY);
8907     RegCloseKey(userprod);
8908     RegDeleteKeyA(prodkey, "");
8909     RegCloseKey(prodkey);
8910 
8911     /* MSIINSTALLCONTEXT_MACHINE */
8912 
8913     /* create local system product key */
8914     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
8915     lstrcatA(keypath, prod_squashed);
8916 
8917     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8918     if (res == ERROR_ACCESS_DENIED)
8919     {
8920         skip( "insufficient rights\n" );
8921         LocalFree( usersid );
8922         return;
8923     }
8924     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8925 
8926     /* product key exists */
8927     INIT_USERINFO();
8928     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8929     ok(state == USERINFOSTATE_ABSENT,
8930        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8931     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8932     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8933     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8934     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8935     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8936     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8937 
8938     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8939     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18");
8940     lstrcatA(keypath, "\\Products\\");
8941     lstrcatA(keypath, prod_squashed);
8942 
8943     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL);
8944     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8945 
8946     res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8947     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8948 
8949     /* InstallProperties key exists */
8950     INIT_USERINFO();
8951     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8952     ok(state == USERINFOSTATE_ABSENT,
8953        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8954     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8955     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8956     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8957     ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", usersz);
8958     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8959     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8960 
8961     /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */
8962     INIT_USERINFO();
8963     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
8964     ok(state == USERINFOSTATE_ABSENT,
8965        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8966     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
8967     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8968     ok(orgsz == 0, "Expected 0, got %lu\n", orgsz);
8969     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", serialsz);
8970 
8971     /* RegOwner, RegCompany don't exist, out params are NULL */
8972     INIT_USERINFO();
8973     state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz);
8974     ok(state == USERINFOSTATE_ABSENT,
8975        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8976     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8977     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", serialsz);
8978 
8979     res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
8980     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8981 
8982     /* RegOwner value exists */
8983     INIT_USERINFO();
8984     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8985     ok(state == USERINFOSTATE_ABSENT,
8986        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8987     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8988     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
8989     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8990     ok(usersz == 5, "Expected 5, got %lu\n", usersz);
8991     ok(orgsz == 0, "Expected 0, got %lu\n", orgsz);
8992     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", serialsz);
8993 
8994     res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8);
8995     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8996 
8997     /* RegCompany value exists */
8998     INIT_USERINFO();
8999     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9000     ok(state == USERINFOSTATE_ABSENT,
9001        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9002     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9003     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9004     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9005     ok(usersz == 5, "Expected 5, got %lu\n", usersz);
9006     ok(orgsz == 7, "Expected 7, got %lu\n", orgsz);
9007     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", serialsz);
9008 
9009     res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3);
9010     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9011 
9012     /* ProductID value exists */
9013     INIT_USERINFO();
9014     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9015     ok(state == USERINFOSTATE_PRESENT,
9016        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
9017     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9018     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9019     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
9020     ok(usersz == 5, "Expected 5, got %lu\n", usersz);
9021     ok(orgsz == 7, "Expected 7, got %lu\n", orgsz);
9022     ok(serialsz == 2, "Expected 2, got %lu\n", serialsz);
9023 
9024     RegDeleteValueA(props, "ProductID");
9025     RegDeleteValueA(props, "RegCompany");
9026     RegDeleteValueA(props, "RegOwner");
9027     delete_key(props, "", access & KEY_WOW64_64KEY);
9028     RegCloseKey(props);
9029     delete_key(userprod, "", access & KEY_WOW64_64KEY);
9030     RegCloseKey(userprod);
9031     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
9032     RegCloseKey(prodkey);
9033     LocalFree(usersid);
9034 }
9035 
9036 static void test_MsiOpenProduct(void)
9037 {
9038     MSIHANDLE hprod, hdb;
9039     CHAR val[MAX_PATH];
9040     CHAR path[MAX_PATH];
9041     CHAR keypath[MAX_PATH*2];
9042     CHAR prodcode[MAX_PATH];
9043     CHAR prod_squashed[MAX_PATH];
9044     HKEY prodkey, userkey, props;
9045     LPSTR usersid;
9046     DWORD size;
9047     LONG res;
9048     UINT r;
9049     REGSAM access = KEY_ALL_ACCESS;
9050 
9051     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
9052 
9053     GetCurrentDirectoryA(MAX_PATH, path);
9054     lstrcatA(path, "\\");
9055 
9056     create_test_guid(prodcode, prod_squashed);
9057     usersid = get_user_sid();
9058 
9059     if (is_wow64)
9060         access |= KEY_WOW64_64KEY;
9061 
9062     hdb = create_package_db(prodcode);
9063     MsiCloseHandle(hdb);
9064 
9065     /* NULL szProduct */
9066     hprod = 0xdeadbeef;
9067     r = MsiOpenProductA(NULL, &hprod);
9068     ok(r == ERROR_INVALID_PARAMETER,
9069        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9070     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9071 
9072     /* empty szProduct */
9073     hprod = 0xdeadbeef;
9074     r = MsiOpenProductA("", &hprod);
9075     ok(r == ERROR_INVALID_PARAMETER,
9076        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9077     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9078 
9079     /* garbage szProduct */
9080     hprod = 0xdeadbeef;
9081     r = MsiOpenProductA("garbage", &hprod);
9082     ok(r == ERROR_INVALID_PARAMETER,
9083        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9084     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9085 
9086     /* guid without brackets */
9087     hprod = 0xdeadbeef;
9088     r = MsiOpenProductA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", &hprod);
9089     ok(r == ERROR_INVALID_PARAMETER,
9090        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9091     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9092 
9093     /* guid with brackets */
9094     hprod = 0xdeadbeef;
9095     r = MsiOpenProductA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", &hprod);
9096     ok(r == ERROR_UNKNOWN_PRODUCT,
9097        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9098     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9099 
9100     /* same length as guid, but random */
9101     hprod = 0xdeadbeef;
9102     r = MsiOpenProductA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", &hprod);
9103     ok(r == ERROR_INVALID_PARAMETER,
9104        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9105     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9106 
9107     /* hProduct is NULL */
9108     hprod = 0xdeadbeef;
9109     r = MsiOpenProductA(prodcode, NULL);
9110     ok(r == ERROR_INVALID_PARAMETER,
9111        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9112     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9113 
9114     /* MSIINSTALLCONTEXT_USERMANAGED */
9115 
9116     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9117     lstrcatA(keypath, "Installer\\Managed\\");
9118     lstrcatA(keypath, usersid);
9119     lstrcatA(keypath, "\\Installer\\Products\\");
9120     lstrcatA(keypath, prod_squashed);
9121 
9122     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
9123     if (res == ERROR_ACCESS_DENIED)
9124     {
9125         skip("Not enough rights to perform tests\n");
9126         LocalFree(usersid);
9127         return;
9128     }
9129     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9130 
9131     /* managed product key exists */
9132     hprod = 0xdeadbeef;
9133     r = MsiOpenProductA(prodcode, &hprod);
9134     ok(r == ERROR_UNKNOWN_PRODUCT,
9135        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9136     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9137 
9138     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9139     lstrcatA(keypath, "Installer\\UserData\\");
9140     lstrcatA(keypath, usersid);
9141     lstrcatA(keypath, "\\Products\\");
9142     lstrcatA(keypath, prod_squashed);
9143 
9144     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
9145     if (res == ERROR_ACCESS_DENIED)
9146     {
9147         skip("Not enough rights to perform tests\n");
9148         LocalFree(usersid);
9149         return;
9150     }
9151     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9152 
9153     /* user product key exists */
9154     hprod = 0xdeadbeef;
9155     r = MsiOpenProductA(prodcode, &hprod);
9156     ok(r == ERROR_UNKNOWN_PRODUCT,
9157        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9158     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9159 
9160     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9161     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9162 
9163     /* InstallProperties key exists */
9164     hprod = 0xdeadbeef;
9165     r = MsiOpenProductA(prodcode, &hprod);
9166     ok(r == ERROR_UNKNOWN_PRODUCT,
9167        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9168     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9169 
9170     lstrcpyA(val, path);
9171     lstrcatA(val, "\\winetest.msi");
9172     res = RegSetValueExA(props, "ManagedLocalPackage", 0, REG_SZ,
9173                          (const BYTE *)val, lstrlenA(val) + 1);
9174     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9175 
9176     /* ManagedLocalPackage value exists */
9177     hprod = 0xdeadbeef;
9178     r = MsiOpenProductA(prodcode, &hprod);
9179     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9180     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
9181 
9182     size = MAX_PATH;
9183     r = MsiGetPropertyA(hprod, "ProductCode", val, &size);
9184     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9185     ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val);
9186     ok(size == lstrlenA(prodcode), "Expected %d, got %lu\n", lstrlenA(prodcode), size);
9187 
9188     MsiCloseHandle(hprod);
9189 
9190     RegDeleteValueA(props, "ManagedLocalPackage");
9191     delete_key(props, "", access & KEY_WOW64_64KEY);
9192     RegCloseKey(props);
9193     delete_key(userkey, "", access & KEY_WOW64_64KEY);
9194     RegCloseKey(userkey);
9195     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
9196     RegCloseKey(prodkey);
9197 
9198     /* MSIINSTALLCONTEXT_USERUNMANAGED */
9199 
9200     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
9201     lstrcatA(keypath, prod_squashed);
9202 
9203     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
9204     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9205 
9206     /* unmanaged product key exists */
9207     hprod = 0xdeadbeef;
9208     r = MsiOpenProductA(prodcode, &hprod);
9209     ok(r == ERROR_UNKNOWN_PRODUCT,
9210        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9211     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9212 
9213     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9214     lstrcatA(keypath, "Installer\\UserData\\");
9215     lstrcatA(keypath, usersid);
9216     lstrcatA(keypath, "\\Products\\");
9217     lstrcatA(keypath, prod_squashed);
9218 
9219     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
9220     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9221 
9222     /* user product key exists */
9223     hprod = 0xdeadbeef;
9224     r = MsiOpenProductA(prodcode, &hprod);
9225     ok(r == ERROR_UNKNOWN_PRODUCT,
9226        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9227     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9228 
9229     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9230     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9231 
9232     /* InstallProperties key exists */
9233     hprod = 0xdeadbeef;
9234     r = MsiOpenProductA(prodcode, &hprod);
9235     ok(r == ERROR_UNKNOWN_PRODUCT,
9236        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9237     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9238 
9239     lstrcpyA(val, path);
9240     lstrcatA(val, "\\winetest.msi");
9241     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
9242                          (const BYTE *)val, lstrlenA(val) + 1);
9243     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9244 
9245     /* LocalPackage value exists */
9246     hprod = 0xdeadbeef;
9247     r = MsiOpenProductA(prodcode, &hprod);
9248     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9249     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
9250 
9251     size = MAX_PATH;
9252     r = MsiGetPropertyA(hprod, "ProductCode", val, &size);
9253     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9254     ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val);
9255     ok(size == lstrlenA(prodcode), "Expected %d, got %lu\n", lstrlenA(prodcode), size);
9256 
9257     MsiCloseHandle(hprod);
9258 
9259     RegDeleteValueA(props, "LocalPackage");
9260     delete_key(props, "", access & KEY_WOW64_64KEY);
9261     RegCloseKey(props);
9262     delete_key(userkey, "", access & KEY_WOW64_64KEY);
9263     RegCloseKey(userkey);
9264     RegDeleteKeyA(prodkey, "");
9265     RegCloseKey(prodkey);
9266 
9267     /* MSIINSTALLCONTEXT_MACHINE */
9268 
9269     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
9270     lstrcatA(keypath, prod_squashed);
9271 
9272     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
9273     if (res == ERROR_ACCESS_DENIED)
9274     {
9275         skip( "insufficient rights\n" );
9276         LocalFree( usersid );
9277         return;
9278     }
9279     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9280 
9281     /* managed product key exists */
9282     hprod = 0xdeadbeef;
9283     r = MsiOpenProductA(prodcode, &hprod);
9284     ok(r == ERROR_UNKNOWN_PRODUCT,
9285        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9286     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9287 
9288     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9289     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
9290     lstrcatA(keypath, prod_squashed);
9291 
9292     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
9293     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9294 
9295     /* user product key exists */
9296     hprod = 0xdeadbeef;
9297     r = MsiOpenProductA(prodcode, &hprod);
9298     ok(r == ERROR_UNKNOWN_PRODUCT,
9299        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9300     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9301 
9302     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9303     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9304 
9305     /* InstallProperties key exists */
9306     hprod = 0xdeadbeef;
9307     r = MsiOpenProductA(prodcode, &hprod);
9308     ok(r == ERROR_UNKNOWN_PRODUCT,
9309        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9310     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9311 
9312     lstrcpyA(val, path);
9313     lstrcatA(val, "\\winetest.msi");
9314     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
9315                          (const BYTE *)val, lstrlenA(val) + 1);
9316     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9317 
9318     /* LocalPackage value exists */
9319     hprod = 0xdeadbeef;
9320     r = MsiOpenProductA(prodcode, &hprod);
9321     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9322     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
9323 
9324     size = MAX_PATH;
9325     r = MsiGetPropertyA(hprod, "ProductCode", val, &size);
9326     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9327     ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val);
9328     ok(size == lstrlenA(prodcode), "Expected %d, got %lu\n", lstrlenA(prodcode), size);
9329 
9330     MsiCloseHandle(hprod);
9331 
9332     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
9333                          (const BYTE *)"winetest.msi", 13);
9334     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9335 
9336     lstrcpyA(val, path);
9337     lstrcatA(val, "\\winetest.msi");
9338     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
9339                          (const BYTE *)val, lstrlenA(val) + 1);
9340     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9341 
9342     DeleteFileA(msifile);
9343 
9344     /* local package does not exist */
9345     hprod = 0xdeadbeef;
9346     r = MsiOpenProductA(prodcode, &hprod);
9347     ok(r == ERROR_UNKNOWN_PRODUCT,
9348        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9349     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9350 
9351     RegDeleteValueA(props, "LocalPackage");
9352     delete_key(props, "", access & KEY_WOW64_64KEY);
9353     RegCloseKey(props);
9354     delete_key(userkey, "", access & KEY_WOW64_64KEY);
9355     RegCloseKey(userkey);
9356     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
9357     RegCloseKey(prodkey);
9358 
9359     DeleteFileA(msifile);
9360     LocalFree(usersid);
9361 }
9362 
9363 static void test_MsiEnumPatchesEx_usermanaged(LPCSTR usersid, LPCSTR expectedsid)
9364 {
9365     MSIINSTALLCONTEXT context;
9366     CHAR keypath[MAX_PATH], patch[MAX_PATH];
9367     CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
9368     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
9369     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
9370     HKEY prodkey, patches, udprod, udpatch, hpatch;
9371     DWORD size, data;
9372     LONG res;
9373     UINT r;
9374     REGSAM access = KEY_ALL_ACCESS;
9375 
9376     create_test_guid(prodcode, prod_squashed);
9377     create_test_guid(patch, patch_squashed);
9378 
9379     if (is_wow64)
9380         access |= KEY_WOW64_64KEY;
9381 
9382     /* MSIPATCHSTATE_APPLIED */
9383 
9384     lstrcpyA(patchcode, "apple");
9385     lstrcpyA(targetprod, "banana");
9386     context = 0xdeadbeef;
9387     lstrcpyA(targetsid, "kiwi");
9388     size = MAX_PATH;
9389     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9390                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9391                            &context, targetsid, &size);
9392     if (r == ERROR_ACCESS_DENIED)
9393     {
9394         skip("Not enough rights to perform tests\n");
9395         return;
9396     }
9397     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9398     ok(!lstrcmpA(patchcode, "apple"),
9399        "Expected patchcode to be unchanged, got %s\n", patchcode);
9400     ok(!lstrcmpA(targetprod, "banana"),
9401        "Expected targetprod to be unchanged, got %s\n", targetprod);
9402     ok(context == 0xdeadbeef,
9403        "Expected context to be unchanged, got %d\n", context);
9404     ok(!lstrcmpA(targetsid, "kiwi"),
9405        "Expected targetsid to be unchanged, got %s\n", targetsid);
9406     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9407 
9408     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
9409     lstrcatA(keypath, expectedsid);
9410     lstrcatA(keypath, "\\Installer\\Products\\");
9411     lstrcatA(keypath, prod_squashed);
9412 
9413     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
9414     if (res == ERROR_ACCESS_DENIED)
9415     {
9416         skip("Not enough rights to perform tests\n");
9417         return;
9418     }
9419     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9420 
9421     /* managed product key exists */
9422     lstrcpyA(patchcode, "apple");
9423     lstrcpyA(targetprod, "banana");
9424     context = 0xdeadbeef;
9425     lstrcpyA(targetsid, "kiwi");
9426     size = MAX_PATH;
9427     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9428                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9429                            &context, targetsid, &size);
9430     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9431     ok(!lstrcmpA(patchcode, "apple"),
9432        "Expected patchcode to be unchanged, got %s\n", patchcode);
9433     ok(!lstrcmpA(targetprod, "banana"),
9434        "Expected targetprod to be unchanged, got %s\n", targetprod);
9435     ok(context == 0xdeadbeef,
9436        "Expected context to be unchanged, got %d\n", context);
9437     ok(!lstrcmpA(targetsid, "kiwi"),
9438        "Expected targetsid to be unchanged, got %s\n", targetsid);
9439     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9440 
9441     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
9442     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9443 
9444     /* patches key exists */
9445     lstrcpyA(patchcode, "apple");
9446     lstrcpyA(targetprod, "banana");
9447     context = 0xdeadbeef;
9448     lstrcpyA(targetsid, "kiwi");
9449     size = MAX_PATH;
9450     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9451                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9452                            &context, targetsid, &size);
9453     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9454     ok(!lstrcmpA(patchcode, "apple"),
9455        "Expected patchcode to be unchanged, got %s\n", patchcode);
9456     ok(!lstrcmpA(targetprod, "banana"),
9457        "Expected targetprod to be unchanged, got %s\n", targetprod);
9458     ok(context == 0xdeadbeef,
9459        "Expected context to be unchanged, got %d\n", context);
9460     ok(!lstrcmpA(targetsid, "kiwi"),
9461        "Expected targetsid to be unchanged, got %s\n", targetsid);
9462     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9463 
9464     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
9465                          (const BYTE *)patch_squashed,
9466                          lstrlenA(patch_squashed) + 1);
9467     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9468 
9469     /* Patches value exists, is not REG_MULTI_SZ */
9470     lstrcpyA(patchcode, "apple");
9471     lstrcpyA(targetprod, "banana");
9472     context = 0xdeadbeef;
9473     lstrcpyA(targetsid, "kiwi");
9474     size = MAX_PATH;
9475     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9476                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9477                            &context, targetsid, &size);
9478     ok(r == ERROR_BAD_CONFIGURATION,
9479        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9480     ok(!lstrcmpA(patchcode, "apple"),
9481        "Expected patchcode to be unchanged, got %s\n", patchcode);
9482     ok(!lstrcmpA(targetprod, "banana"),
9483        "Expected targetprod to be unchanged, got %s\n", targetprod);
9484     ok(context == 0xdeadbeef,
9485        "Expected context to be unchanged, got %d\n", context);
9486     ok(!lstrcmpA(targetsid, "kiwi"),
9487        "Expected targetsid to be unchanged, got %s\n", targetsid);
9488     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9489 
9490     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
9491                          (const BYTE *)"a\0b\0c\0\0", 7);
9492     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9493 
9494     /* Patches value exists, is not a squashed guid */
9495     lstrcpyA(patchcode, "apple");
9496     lstrcpyA(targetprod, "banana");
9497     context = 0xdeadbeef;
9498     lstrcpyA(targetsid, "kiwi");
9499     size = MAX_PATH;
9500     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9501                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9502                            &context, targetsid, &size);
9503     ok(r == ERROR_BAD_CONFIGURATION,
9504        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9505     ok(!lstrcmpA(patchcode, "apple"),
9506        "Expected patchcode to be unchanged, got %s\n", patchcode);
9507     ok(!lstrcmpA(targetprod, "banana"),
9508        "Expected targetprod to be unchanged, got %s\n", targetprod);
9509     ok(context == 0xdeadbeef,
9510        "Expected context to be unchanged, got %d\n", context);
9511     ok(!lstrcmpA(targetsid, "kiwi"),
9512        "Expected targetsid to be unchanged, got %s\n", targetsid);
9513     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9514 
9515     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
9516     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
9517                          (const BYTE *)patch_squashed,
9518                          lstrlenA(patch_squashed) + 2);
9519     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9520 
9521     /* Patches value exists */
9522     lstrcpyA(patchcode, "apple");
9523     lstrcpyA(targetprod, "banana");
9524     context = 0xdeadbeef;
9525     lstrcpyA(targetsid, "kiwi");
9526     size = MAX_PATH;
9527     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9528                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9529                            &context, targetsid, &size);
9530     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9531     ok(!lstrcmpA(patchcode, "apple"),
9532        "Expected patchcode to be unchanged, got %s\n", patchcode);
9533     ok(!lstrcmpA(targetprod, "banana"),
9534        "Expected targetprod to be unchanged, got %s\n", targetprod);
9535     ok(context == 0xdeadbeef,
9536        "Expected context to be unchanged, got %d\n", context);
9537     ok(!lstrcmpA(targetsid, "kiwi"),
9538        "Expected targetsid to be unchanged, got %s\n", targetsid);
9539     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9540 
9541     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
9542                          (const BYTE *)"whatever", 9);
9543     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9544 
9545     /* patch squashed value exists */
9546     lstrcpyA(patchcode, "apple");
9547     lstrcpyA(targetprod, "banana");
9548     context = 0xdeadbeef;
9549     lstrcpyA(targetsid, "kiwi");
9550     size = MAX_PATH;
9551     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9552                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9553                            &context, targetsid, &size);
9554     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9555     ok(!lstrcmpA(patchcode, patch),
9556        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9557     ok(!lstrcmpA(targetprod, prodcode),
9558        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9559     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9560        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9561     ok(!lstrcmpA(targetsid, expectedsid),
9562        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9563     ok(size == lstrlenA(expectedsid),
9564        "Expected %d, got %lu\n", lstrlenA(expectedsid), size);
9565 
9566     /* increase the index */
9567     lstrcpyA(patchcode, "apple");
9568     lstrcpyA(targetprod, "banana");
9569     context = 0xdeadbeef;
9570     lstrcpyA(targetsid, "kiwi");
9571     size = MAX_PATH;
9572     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9573                            MSIPATCHSTATE_APPLIED, 1, patchcode, targetprod,
9574                            &context, targetsid, &size);
9575     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9576     ok(!lstrcmpA(patchcode, "apple"),
9577        "Expected patchcode to be unchanged, got %s\n", patchcode);
9578     ok(!lstrcmpA(targetprod, "banana"),
9579        "Expected targetprod to be unchanged, got %s\n", targetprod);
9580     ok(context == 0xdeadbeef,
9581        "Expected context to be unchanged, got %d\n", context);
9582     ok(!lstrcmpA(targetsid, "kiwi"),
9583        "Expected targetsid to be unchanged, got %s\n", targetsid);
9584     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9585 
9586     /* increase again */
9587     lstrcpyA(patchcode, "apple");
9588     lstrcpyA(targetprod, "banana");
9589     context = 0xdeadbeef;
9590     lstrcpyA(targetsid, "kiwi");
9591     size = MAX_PATH;
9592     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9593                            MSIPATCHSTATE_APPLIED, 2, patchcode, targetprod,
9594                            &context, targetsid, &size);
9595     ok(r == ERROR_INVALID_PARAMETER,
9596        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9597     ok(!lstrcmpA(patchcode, "apple"),
9598        "Expected patchcode to be unchanged, got %s\n", patchcode);
9599     ok(!lstrcmpA(targetprod, "banana"),
9600        "Expected targetprod to be unchanged, got %s\n", targetprod);
9601     ok(context == 0xdeadbeef,
9602        "Expected context to be unchanged, got %d\n", context);
9603     ok(!lstrcmpA(targetsid, "kiwi"),
9604        "Expected targetsid to be unchanged, got %s\n", targetsid);
9605     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9606 
9607     /* szPatchCode is NULL */
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, 0, NULL, targetprod,
9614                            &context, targetsid, &size);
9615     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9616     ok(!lstrcmpA(targetprod, prodcode),
9617        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9618     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9619        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9620     ok(!lstrcmpA(targetsid, expectedsid),
9621        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9622     ok(size == lstrlenA(expectedsid),
9623        "Expected %d, got %lu\n", lstrlenA(expectedsid), size);
9624 
9625     /* szTargetProductCode is NULL */
9626     lstrcpyA(patchcode, "apple");
9627     context = 0xdeadbeef;
9628     lstrcpyA(targetsid, "kiwi");
9629     size = MAX_PATH;
9630     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9631                            MSIPATCHSTATE_APPLIED, 0, patchcode, NULL,
9632                            &context, targetsid, &size);
9633     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9634     ok(!lstrcmpA(patchcode, patch),
9635        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9636     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9637        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9638     ok(!lstrcmpA(targetsid, expectedsid),
9639        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9640     ok(size == lstrlenA(expectedsid),
9641        "Expected %d, got %lu\n", lstrlenA(expectedsid), size);
9642 
9643     /* pdwTargetProductContext is NULL */
9644     lstrcpyA(patchcode, "apple");
9645     lstrcpyA(targetprod, "banana");
9646     lstrcpyA(targetsid, "kiwi");
9647     size = MAX_PATH;
9648     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9649                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9650                            NULL, targetsid, &size);
9651     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9652     ok(!lstrcmpA(patchcode, patch),
9653        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9654     ok(!lstrcmpA(targetprod, prodcode),
9655        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9656     ok(!lstrcmpA(targetsid, expectedsid),
9657        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9658     ok(size == lstrlenA(expectedsid),
9659        "Expected %d, got %lu\n", lstrlenA(expectedsid), size);
9660 
9661     /* szTargetUserSid is NULL */
9662     lstrcpyA(patchcode, "apple");
9663     lstrcpyA(targetprod, "banana");
9664     context = 0xdeadbeef;
9665     size = MAX_PATH;
9666     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9667                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9668                            &context, NULL, &size);
9669     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9670     ok(!lstrcmpA(patchcode, patch),
9671        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9672     ok(!lstrcmpA(targetprod, prodcode),
9673        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9674     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9675        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9676     ok(size == lstrlenA(expectedsid) * sizeof(WCHAR),
9677        "Expected %d*sizeof(WCHAR), got %lu\n", lstrlenA(expectedsid), size);
9678 
9679     /* pcchTargetUserSid is exactly the length of szTargetUserSid */
9680     lstrcpyA(patchcode, "apple");
9681     lstrcpyA(targetprod, "banana");
9682     context = 0xdeadbeef;
9683     lstrcpyA(targetsid, "kiwi");
9684     size = lstrlenA(expectedsid);
9685     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9686                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9687                            &context, targetsid, &size);
9688     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
9689     ok(!lstrcmpA(patchcode, patch),
9690        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9691     ok(!lstrcmpA(targetprod, prodcode),
9692        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9693     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9694        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9695     ok(!strncmp(targetsid, expectedsid, lstrlenA(expectedsid) - 1),
9696        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9697     ok(size == lstrlenA(expectedsid) * sizeof(WCHAR),
9698        "Expected %d*sizeof(WCHAR), got %lu\n", lstrlenA(expectedsid), size);
9699 
9700     /* pcchTargetUserSid has enough room for NULL terminator */
9701     lstrcpyA(patchcode, "apple");
9702     lstrcpyA(targetprod, "banana");
9703     context = 0xdeadbeef;
9704     lstrcpyA(targetsid, "kiwi");
9705     size = lstrlenA(expectedsid) + 1;
9706     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9707                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9708                            &context, targetsid, &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(!lstrcmpA(targetsid, expectedsid),
9717        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9718     ok(size == lstrlenA(expectedsid),
9719        "Expected %d, got %lu\n", lstrlenA(expectedsid), size);
9720 
9721     /* both szTargetuserSid and pcchTargetUserSid are NULL */
9722     lstrcpyA(patchcode, "apple");
9723     lstrcpyA(targetprod, "banana");
9724     context = 0xdeadbeef;
9725     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9726                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9727                            &context, NULL, NULL);
9728     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, 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 
9736     /* MSIPATCHSTATE_SUPERSEDED */
9737 
9738     lstrcpyA(patchcode, "apple");
9739     lstrcpyA(targetprod, "banana");
9740     context = 0xdeadbeef;
9741     lstrcpyA(targetsid, "kiwi");
9742     size = MAX_PATH;
9743     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9744                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
9745                            &context, targetsid, &size);
9746     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9747     ok(!lstrcmpA(patchcode, "apple"),
9748        "Expected patchcode to be unchanged, got %s\n", patchcode);
9749     ok(!lstrcmpA(targetprod, "banana"),
9750        "Expected targetprod to be unchanged, got %s\n", targetprod);
9751     ok(context == 0xdeadbeef,
9752        "Expected context to be unchanged, got %d\n", context);
9753     ok(!lstrcmpA(targetsid, "kiwi"),
9754        "Expected targetsid to be unchanged, got %s\n", targetsid);
9755     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9756 
9757     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
9758     lstrcatA(keypath, expectedsid);
9759     lstrcatA(keypath, "\\Products\\");
9760     lstrcatA(keypath, prod_squashed);
9761 
9762     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
9763     if (res == ERROR_ACCESS_DENIED)
9764     {
9765         skip("Not enough rights to perform tests\n");
9766         return;
9767     }
9768     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9769 
9770     /* UserData product key exists */
9771     lstrcpyA(patchcode, "apple");
9772     lstrcpyA(targetprod, "banana");
9773     context = 0xdeadbeef;
9774     lstrcpyA(targetsid, "kiwi");
9775     size = MAX_PATH;
9776     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9777                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
9778                            &context, targetsid, &size);
9779     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9780     ok(!lstrcmpA(patchcode, "apple"),
9781        "Expected patchcode to be unchanged, got %s\n", patchcode);
9782     ok(!lstrcmpA(targetprod, "banana"),
9783        "Expected targetprod to be unchanged, got %s\n", targetprod);
9784     ok(context == 0xdeadbeef,
9785        "Expected context to be unchanged, got %d\n", context);
9786     ok(!lstrcmpA(targetsid, "kiwi"),
9787        "Expected targetsid to be unchanged, got %s\n", targetsid);
9788     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9789 
9790     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
9791     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9792 
9793     /* UserData patches key exists */
9794     lstrcpyA(patchcode, "apple");
9795     lstrcpyA(targetprod, "banana");
9796     context = 0xdeadbeef;
9797     lstrcpyA(targetsid, "kiwi");
9798     size = MAX_PATH;
9799     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9800                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
9801                            &context, targetsid, &size);
9802     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9803     ok(!lstrcmpA(patchcode, "apple"),
9804        "Expected patchcode to be unchanged, got %s\n", patchcode);
9805     ok(!lstrcmpA(targetprod, "banana"),
9806        "Expected targetprod to be unchanged, got %s\n", targetprod);
9807     ok(context == 0xdeadbeef,
9808        "Expected context to be unchanged, got %d\n", context);
9809     ok(!lstrcmpA(targetsid, "kiwi"),
9810        "Expected targetsid to be unchanged, got %s\n", targetsid);
9811     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9812 
9813     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
9814     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9815 
9816     /* specific UserData patch key exists */
9817     lstrcpyA(patchcode, "apple");
9818     lstrcpyA(targetprod, "banana");
9819     context = 0xdeadbeef;
9820     lstrcpyA(targetsid, "kiwi");
9821     size = MAX_PATH;
9822     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9823                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
9824                            &context, targetsid, &size);
9825     ok(r == ERROR_BAD_CONFIGURATION,
9826        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9827     ok(!lstrcmpA(patchcode, "apple"),
9828        "Expected patchcode to be unchanged, got %s\n", patchcode);
9829     ok(!lstrcmpA(targetprod, "banana"),
9830        "Expected targetprod to be unchanged, got %s\n", targetprod);
9831     ok(context == 0xdeadbeef,
9832        "Expected context to be unchanged, got %d\n", context);
9833     ok(!lstrcmpA(targetsid, "kiwi"),
9834        "Expected targetsid to be unchanged, got %s\n", targetsid);
9835     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9836 
9837     data = MSIPATCHSTATE_SUPERSEDED;
9838     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
9839                          (const BYTE *)&data, sizeof(DWORD));
9840     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9841 
9842     /* State value exists */
9843     lstrcpyA(patchcode, "apple");
9844     lstrcpyA(targetprod, "banana");
9845     context = 0xdeadbeef;
9846     lstrcpyA(targetsid, "kiwi");
9847     size = MAX_PATH;
9848     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9849                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
9850                            &context, targetsid, &size);
9851     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9852     ok(!lstrcmpA(patchcode, patch),
9853        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9854     ok(!lstrcmpA(targetprod, prodcode),
9855        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9856     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9857        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9858     ok(!lstrcmpA(targetsid, expectedsid),
9859        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9860     ok(size == lstrlenA(expectedsid),
9861        "Expected %d, got %lu\n", lstrlenA(expectedsid), size);
9862 
9863     /* MSIPATCHSTATE_OBSOLETED */
9864 
9865     lstrcpyA(patchcode, "apple");
9866     lstrcpyA(targetprod, "banana");
9867     context = 0xdeadbeef;
9868     lstrcpyA(targetsid, "kiwi");
9869     size = MAX_PATH;
9870     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9871                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
9872                            &context, targetsid, &size);
9873     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9874     ok(!lstrcmpA(patchcode, "apple"),
9875        "Expected patchcode to be unchanged, got %s\n", patchcode);
9876     ok(!lstrcmpA(targetprod, "banana"),
9877        "Expected targetprod to be unchanged, got %s\n", targetprod);
9878     ok(context == 0xdeadbeef,
9879        "Expected context to be unchanged, got %d\n", context);
9880     ok(!lstrcmpA(targetsid, "kiwi"),
9881        "Expected targetsid to be unchanged, got %s\n", targetsid);
9882     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9883 
9884     data = MSIPATCHSTATE_OBSOLETED;
9885     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
9886                          (const BYTE *)&data, sizeof(DWORD));
9887     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9888 
9889     /* State value is obsoleted */
9890     lstrcpyA(patchcode, "apple");
9891     lstrcpyA(targetprod, "banana");
9892     context = 0xdeadbeef;
9893     lstrcpyA(targetsid, "kiwi");
9894     size = MAX_PATH;
9895     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9896                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
9897                            &context, targetsid, &size);
9898     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9899     ok(!lstrcmpA(patchcode, patch),
9900        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9901     ok(!lstrcmpA(targetprod, prodcode),
9902        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9903     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9904        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9905     ok(!lstrcmpA(targetsid, expectedsid),
9906        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9907     ok(size == lstrlenA(expectedsid),
9908        "Expected %d, got %lu\n", lstrlenA(expectedsid), size);
9909 
9910     /* MSIPATCHSTATE_REGISTERED */
9911     /* FIXME */
9912 
9913     /* MSIPATCHSTATE_ALL */
9914 
9915     /* 1st */
9916     lstrcpyA(patchcode, "apple");
9917     lstrcpyA(targetprod, "banana");
9918     context = 0xdeadbeef;
9919     lstrcpyA(targetsid, "kiwi");
9920     size = MAX_PATH;
9921     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9922                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
9923                            &context, targetsid, &size);
9924     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9925     ok(!lstrcmpA(patchcode, patch),
9926        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9927     ok(!lstrcmpA(targetprod, prodcode),
9928        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9929     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9930        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9931     ok(!lstrcmpA(targetsid, expectedsid),
9932        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9933     ok(size == lstrlenA(expectedsid),
9934        "Expected %d, got %lu\n", lstrlenA(expectedsid), size);
9935 
9936     /* same patch in multiple places, only one is enumerated */
9937     lstrcpyA(patchcode, "apple");
9938     lstrcpyA(targetprod, "banana");
9939     context = 0xdeadbeef;
9940     lstrcpyA(targetsid, "kiwi");
9941     size = MAX_PATH;
9942     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9943                            MSIPATCHSTATE_ALL, 1, patchcode, targetprod,
9944                            &context, targetsid, &size);
9945     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9946     ok(!lstrcmpA(patchcode, "apple"),
9947        "Expected patchcode to be unchanged, got %s\n", patchcode);
9948     ok(!lstrcmpA(targetprod, "banana"),
9949        "Expected targetprod to be unchanged, got %s\n", targetprod);
9950     ok(context == 0xdeadbeef,
9951        "Expected context to be unchanged, got %d\n", context);
9952     ok(!lstrcmpA(targetsid, "kiwi"),
9953        "Expected targetsid to be unchanged, got %s\n", targetsid);
9954     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9955 
9956     RegDeleteValueA(hpatch, "State");
9957     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
9958     RegCloseKey(hpatch);
9959     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
9960     RegCloseKey(udpatch);
9961     delete_key(udprod, "", access & KEY_WOW64_64KEY);
9962     RegCloseKey(udprod);
9963     RegDeleteValueA(patches, "Patches");
9964     delete_key(patches, "", access & KEY_WOW64_64KEY);
9965     RegCloseKey(patches);
9966     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
9967     RegCloseKey(prodkey);
9968 }
9969 
9970 static void test_MsiEnumPatchesEx_userunmanaged(LPCSTR usersid, LPCSTR expectedsid)
9971 {
9972     MSIINSTALLCONTEXT context;
9973     CHAR keypath[MAX_PATH], patch[MAX_PATH];
9974     CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
9975     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
9976     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
9977     HKEY prodkey, patches, udprod, udpatch;
9978     HKEY userkey, hpatch;
9979     DWORD size, data;
9980     LONG res;
9981     UINT r;
9982     REGSAM access = KEY_ALL_ACCESS;
9983 
9984     create_test_guid(prodcode, prod_squashed);
9985     create_test_guid(patch, patch_squashed);
9986 
9987     if (is_wow64)
9988         access |= KEY_WOW64_64KEY;
9989 
9990     /* MSIPATCHSTATE_APPLIED */
9991 
9992     lstrcpyA(patchcode, "apple");
9993     lstrcpyA(targetprod, "banana");
9994     context = 0xdeadbeef;
9995     lstrcpyA(targetsid, "kiwi");
9996     size = MAX_PATH;
9997     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9998                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9999                            &context, targetsid, &size);
10000     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10001     ok(!lstrcmpA(patchcode, "apple"),
10002        "Expected patchcode to be unchanged, got %s\n", patchcode);
10003     ok(!lstrcmpA(targetprod, "banana"),
10004        "Expected targetprod to be unchanged, got %s\n", targetprod);
10005     ok(context == 0xdeadbeef,
10006        "Expected context to be unchanged, got %d\n", context);
10007     ok(!lstrcmpA(targetsid, "kiwi"),
10008        "Expected targetsid to be unchanged, got %s\n", targetsid);
10009     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10010 
10011     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
10012     lstrcatA(keypath, prod_squashed);
10013 
10014     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
10015     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10016 
10017     /* current user product key exists */
10018     lstrcpyA(patchcode, "apple");
10019     lstrcpyA(targetprod, "banana");
10020     context = 0xdeadbeef;
10021     lstrcpyA(targetsid, "kiwi");
10022     size = MAX_PATH;
10023     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10024                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10025                            &context, targetsid, &size);
10026     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10027     ok(!lstrcmpA(patchcode, "apple"),
10028        "Expected patchcode to be unchanged, got %s\n", patchcode);
10029     ok(!lstrcmpA(targetprod, "banana"),
10030        "Expected targetprod to be unchanged, got %s\n", targetprod);
10031     ok(context == 0xdeadbeef,
10032        "Expected context to be unchanged, got %d\n", context);
10033     ok(!lstrcmpA(targetsid, "kiwi"),
10034        "Expected targetsid to be unchanged, got %s\n", targetsid);
10035     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10036 
10037     res = RegCreateKeyA(prodkey, "Patches", &patches);
10038     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10039 
10040     /* Patches key exists */
10041     lstrcpyA(patchcode, "apple");
10042     lstrcpyA(targetprod, "banana");
10043     context = 0xdeadbeef;
10044     lstrcpyA(targetsid, "kiwi");
10045     size = MAX_PATH;
10046     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10047                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10048                            &context, targetsid, &size);
10049     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10050     ok(!lstrcmpA(patchcode, "apple"),
10051        "Expected patchcode to be unchanged, got %s\n", patchcode);
10052     ok(!lstrcmpA(targetprod, "banana"),
10053        "Expected targetprod to be unchanged, got %s\n", targetprod);
10054     ok(context == 0xdeadbeef,
10055        "Expected context to be unchanged, got %d\n", context);
10056     ok(!lstrcmpA(targetsid, "kiwi"),
10057        "Expected targetsid to be unchanged, got %s\n", targetsid);
10058     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10059 
10060     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
10061                          (const BYTE *)patch_squashed,
10062                          lstrlenA(patch_squashed) + 1);
10063     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10064 
10065     /* Patches value exists, is not REG_MULTI_SZ */
10066     lstrcpyA(patchcode, "apple");
10067     lstrcpyA(targetprod, "banana");
10068     context = 0xdeadbeef;
10069     lstrcpyA(targetsid, "kiwi");
10070     size = MAX_PATH;
10071     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10072                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10073                            &context, targetsid, &size);
10074     ok(r == ERROR_BAD_CONFIGURATION,
10075        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10076     ok(!lstrcmpA(patchcode, "apple"),
10077        "Expected patchcode to be unchanged, got %s\n", patchcode);
10078     ok(!lstrcmpA(targetprod, "banana"),
10079        "Expected targetprod to be unchanged, got %s\n", targetprod);
10080     ok(context == 0xdeadbeef,
10081        "Expected context to be unchanged, got %d\n", context);
10082     ok(!lstrcmpA(targetsid, "kiwi"),
10083        "Expected targetsid to be unchanged, got %s\n", targetsid);
10084     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10085 
10086     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10087                          (const BYTE *)"a\0b\0c\0\0", 7);
10088     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10089 
10090     /* Patches value exists, is not a squashed guid */
10091     lstrcpyA(patchcode, "apple");
10092     lstrcpyA(targetprod, "banana");
10093     context = 0xdeadbeef;
10094     lstrcpyA(targetsid, "kiwi");
10095     size = MAX_PATH;
10096     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10097                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10098                            &context, targetsid, &size);
10099     ok(r == ERROR_BAD_CONFIGURATION,
10100        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10101     ok(!lstrcmpA(patchcode, "apple"),
10102        "Expected patchcode to be unchanged, got %s\n", patchcode);
10103     ok(!lstrcmpA(targetprod, "banana"),
10104        "Expected targetprod to be unchanged, got %s\n", targetprod);
10105     ok(context == 0xdeadbeef,
10106        "Expected context to be unchanged, got %d\n", context);
10107     ok(!lstrcmpA(targetsid, "kiwi"),
10108        "Expected targetsid to be unchanged, got %s\n", targetsid);
10109     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10110 
10111     patch_squashed[lstrlenA(patch_squashed) + 1] = 0;
10112     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10113                          (const BYTE *)patch_squashed,
10114                          lstrlenA(patch_squashed) + 2);
10115     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10116 
10117     /* Patches value exists */
10118     lstrcpyA(patchcode, "apple");
10119     lstrcpyA(targetprod, "banana");
10120     context = 0xdeadbeef;
10121     lstrcpyA(targetsid, "kiwi");
10122     size = MAX_PATH;
10123     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10124                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10125                            &context, targetsid, &size);
10126     ok(r == ERROR_NO_MORE_ITEMS ||
10127        broken(r == ERROR_BAD_CONFIGURATION), /* Windows Installer 3.0 */
10128        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10129     ok(!lstrcmpA(patchcode, "apple"),
10130        "Expected patchcode to be unchanged, got %s\n", patchcode);
10131     ok(!lstrcmpA(targetprod, "banana"),
10132        "Expected targetprod to be unchanged, got %s\n", targetprod);
10133     ok(context == 0xdeadbeef,
10134        "Expected context to be unchanged, got %d\n", context);
10135     ok(!lstrcmpA(targetsid, "kiwi"),
10136        "Expected targetsid to be unchanged, got %s\n", targetsid);
10137     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10138 
10139     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
10140                          (const BYTE *)"whatever", 9);
10141     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10142 
10143     /* patch code value exists */
10144     lstrcpyA(patchcode, "apple");
10145     lstrcpyA(targetprod, "banana");
10146     context = 0xdeadbeef;
10147     lstrcpyA(targetsid, "kiwi");
10148     size = MAX_PATH;
10149     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10150                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10151                            &context, targetsid, &size);
10152     ok(r == ERROR_NO_MORE_ITEMS ||
10153        broken(r == ERROR_BAD_CONFIGURATION), /* Windows Installer 3.0 */
10154        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10155     ok(!lstrcmpA(patchcode, "apple"),
10156        "Expected patchcode to be unchanged, got %s\n", patchcode);
10157     ok(!lstrcmpA(targetprod, "banana"),
10158        "Expected targetprod to be unchanged, got %s\n", targetprod);
10159     ok(context == 0xdeadbeef,
10160        "Expected context to be unchanged, got %d\n", context);
10161     ok(!lstrcmpA(targetsid, "kiwi"),
10162        "Expected targetsid to be unchanged, got %s\n", targetsid);
10163     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10164 
10165     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
10166     lstrcatA(keypath, expectedsid);
10167     lstrcatA(keypath, "\\Patches\\");
10168     lstrcatA(keypath, patch_squashed);
10169 
10170     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
10171     if (res == ERROR_ACCESS_DENIED)
10172     {
10173         skip("Not enough rights to perform tests\n");
10174         goto error;
10175     }
10176     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10177 
10178     /* userdata patch key exists */
10179     lstrcpyA(patchcode, "apple");
10180     lstrcpyA(targetprod, "banana");
10181     context = 0xdeadbeef;
10182     lstrcpyA(targetsid, "kiwi");
10183     size = MAX_PATH;
10184     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10185                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10186                            &context, targetsid, &size);
10187     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10188     ok(!lstrcmpA(patchcode, patch),
10189        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10190     ok(!lstrcmpA(targetprod, prodcode),
10191        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10192     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
10193        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
10194     ok(!lstrcmpA(targetsid, expectedsid),
10195        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10196     ok(size == lstrlenA(expectedsid),
10197        "Expected %d, got %lu\n", lstrlenA(expectedsid), size);
10198 
10199     /* MSIPATCHSTATE_SUPERSEDED */
10200 
10201     lstrcpyA(patchcode, "apple");
10202     lstrcpyA(targetprod, "banana");
10203     context = 0xdeadbeef;
10204     lstrcpyA(targetsid, "kiwi");
10205     size = MAX_PATH;
10206     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10207                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10208                            &context, targetsid, &size);
10209     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10210     ok(!lstrcmpA(patchcode, "apple"),
10211        "Expected patchcode to be unchanged, got %s\n", patchcode);
10212     ok(!lstrcmpA(targetprod, "banana"),
10213        "Expected targetprod to be unchanged, got %s\n", targetprod);
10214     ok(context == 0xdeadbeef,
10215        "Expected context to be unchanged, got %d\n", context);
10216     ok(!lstrcmpA(targetsid, "kiwi"),
10217        "Expected targetsid to be unchanged, got %s\n", targetsid);
10218     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10219 
10220     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
10221     lstrcatA(keypath, expectedsid);
10222     lstrcatA(keypath, "\\Products\\");
10223     lstrcatA(keypath, prod_squashed);
10224 
10225     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
10226     if (res == ERROR_ACCESS_DENIED)
10227     {
10228         skip("Not enough rights to perform tests\n");
10229         goto error;
10230     }
10231     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10232 
10233     /* UserData product key exists */
10234     lstrcpyA(patchcode, "apple");
10235     lstrcpyA(targetprod, "banana");
10236     context = 0xdeadbeef;
10237     lstrcpyA(targetsid, "kiwi");
10238     size = MAX_PATH;
10239     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10240                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10241                            &context, targetsid, &size);
10242     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10243     ok(!lstrcmpA(patchcode, "apple"),
10244        "Expected patchcode to be unchanged, got %s\n", patchcode);
10245     ok(!lstrcmpA(targetprod, "banana"),
10246        "Expected targetprod to be unchanged, got %s\n", targetprod);
10247     ok(context == 0xdeadbeef,
10248        "Expected context to be unchanged, got %d\n", context);
10249     ok(!lstrcmpA(targetsid, "kiwi"),
10250        "Expected targetsid to be unchanged, got %s\n", targetsid);
10251     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10252 
10253     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
10254     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10255 
10256     /* UserData patches key exists */
10257     lstrcpyA(patchcode, "apple");
10258     lstrcpyA(targetprod, "banana");
10259     context = 0xdeadbeef;
10260     lstrcpyA(targetsid, "kiwi");
10261     size = MAX_PATH;
10262     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10263                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10264                            &context, targetsid, &size);
10265     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10266     ok(!lstrcmpA(patchcode, "apple"),
10267        "Expected patchcode to be unchanged, got %s\n", patchcode);
10268     ok(!lstrcmpA(targetprod, "banana"),
10269        "Expected targetprod to be unchanged, got %s\n", targetprod);
10270     ok(context == 0xdeadbeef,
10271        "Expected context to be unchanged, got %d\n", context);
10272     ok(!lstrcmpA(targetsid, "kiwi"),
10273        "Expected targetsid to be unchanged, got %s\n", targetsid);
10274     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10275 
10276     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
10277     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10278 
10279     /* specific UserData patch key exists */
10280     lstrcpyA(patchcode, "apple");
10281     lstrcpyA(targetprod, "banana");
10282     context = 0xdeadbeef;
10283     lstrcpyA(targetsid, "kiwi");
10284     size = MAX_PATH;
10285     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10286                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10287                            &context, targetsid, &size);
10288     ok(r == ERROR_BAD_CONFIGURATION,
10289        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10290     ok(!lstrcmpA(patchcode, "apple"),
10291        "Expected patchcode to be unchanged, got %s\n", patchcode);
10292     ok(!lstrcmpA(targetprod, "banana"),
10293        "Expected targetprod to be unchanged, got %s\n", targetprod);
10294     ok(context == 0xdeadbeef,
10295        "Expected context to be unchanged, got %d\n", context);
10296     ok(!lstrcmpA(targetsid, "kiwi"),
10297        "Expected targetsid to be unchanged, got %s\n", targetsid);
10298     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10299 
10300     data = MSIPATCHSTATE_SUPERSEDED;
10301     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10302                          (const BYTE *)&data, sizeof(DWORD));
10303     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10304 
10305     /* State value exists */
10306     lstrcpyA(patchcode, "apple");
10307     lstrcpyA(targetprod, "banana");
10308     context = 0xdeadbeef;
10309     lstrcpyA(targetsid, "kiwi");
10310     size = MAX_PATH;
10311     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10312                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10313                            &context, targetsid, &size);
10314     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10315     ok(!lstrcmpA(patchcode, patch),
10316        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10317     ok(!lstrcmpA(targetprod, prodcode),
10318        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10319     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
10320        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
10321     ok(!lstrcmpA(targetsid, expectedsid),
10322        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10323     ok(size == lstrlenA(expectedsid),
10324        "Expected %d, got %lu\n", lstrlenA(expectedsid), size);
10325 
10326     /* MSIPATCHSTATE_OBSOLETED */
10327 
10328     lstrcpyA(patchcode, "apple");
10329     lstrcpyA(targetprod, "banana");
10330     context = 0xdeadbeef;
10331     lstrcpyA(targetsid, "kiwi");
10332     size = MAX_PATH;
10333     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10334                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
10335                            &context, targetsid, &size);
10336     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10337     ok(!lstrcmpA(patchcode, "apple"),
10338        "Expected patchcode to be unchanged, got %s\n", patchcode);
10339     ok(!lstrcmpA(targetprod, "banana"),
10340        "Expected targetprod to be unchanged, got %s\n", targetprod);
10341     ok(context == 0xdeadbeef,
10342        "Expected context to be unchanged, got %d\n", context);
10343     ok(!lstrcmpA(targetsid, "kiwi"),
10344        "Expected targetsid to be unchanged, got %s\n", targetsid);
10345     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10346 
10347     data = MSIPATCHSTATE_OBSOLETED;
10348     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10349                          (const BYTE *)&data, sizeof(DWORD));
10350     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10351 
10352     /* State value is obsoleted */
10353     lstrcpyA(patchcode, "apple");
10354     lstrcpyA(targetprod, "banana");
10355     context = 0xdeadbeef;
10356     lstrcpyA(targetsid, "kiwi");
10357     size = MAX_PATH;
10358     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10359                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
10360                            &context, targetsid, &size);
10361     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10362     ok(!lstrcmpA(patchcode, patch),
10363        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10364     ok(!lstrcmpA(targetprod, prodcode),
10365        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10366     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
10367        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
10368     ok(!lstrcmpA(targetsid, expectedsid),
10369        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10370     ok(size == lstrlenA(expectedsid),
10371        "Expected %d, got %lu\n", lstrlenA(expectedsid), size);
10372 
10373     /* MSIPATCHSTATE_REGISTERED */
10374     /* FIXME */
10375 
10376     /* MSIPATCHSTATE_ALL */
10377 
10378     /* 1st */
10379     lstrcpyA(patchcode, "apple");
10380     lstrcpyA(targetprod, "banana");
10381     context = 0xdeadbeef;
10382     lstrcpyA(targetsid, "kiwi");
10383     size = MAX_PATH;
10384     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10385                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
10386                            &context, targetsid, &size);
10387     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10388     ok(!lstrcmpA(patchcode, patch),
10389        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10390     ok(!lstrcmpA(targetprod, prodcode),
10391        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10392     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
10393        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
10394     ok(!lstrcmpA(targetsid, expectedsid),
10395        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10396     ok(size == lstrlenA(expectedsid),
10397        "Expected %d, got %lu\n", lstrlenA(expectedsid), size);
10398 
10399     /* same patch in multiple places, only one is enumerated */
10400     lstrcpyA(patchcode, "apple");
10401     lstrcpyA(targetprod, "banana");
10402     context = 0xdeadbeef;
10403     lstrcpyA(targetsid, "kiwi");
10404     size = MAX_PATH;
10405     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10406                            MSIPATCHSTATE_ALL, 1, patchcode, targetprod,
10407                            &context, targetsid, &size);
10408     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10409     ok(!lstrcmpA(patchcode, "apple"),
10410        "Expected patchcode to be unchanged, got %s\n", patchcode);
10411     ok(!lstrcmpA(targetprod, "banana"),
10412        "Expected targetprod to be unchanged, got %s\n", targetprod);
10413     ok(context == 0xdeadbeef,
10414        "Expected context to be unchanged, got %d\n", context);
10415     ok(!lstrcmpA(targetsid, "kiwi"),
10416        "Expected targetsid to be unchanged, got %s\n", targetsid);
10417     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10418 
10419     RegDeleteValueA(hpatch, "State");
10420     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
10421     RegCloseKey(hpatch);
10422     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
10423     RegCloseKey(udpatch);
10424     delete_key(udprod, "", access & KEY_WOW64_64KEY);
10425     RegCloseKey(udprod);
10426     delete_key(userkey, "", access & KEY_WOW64_64KEY);
10427     RegCloseKey(userkey);
10428     RegDeleteValueA(patches, patch_squashed);
10429     RegDeleteValueA(patches, "Patches");
10430 
10431 error:
10432     RegDeleteKeyA(patches, "");
10433     RegCloseKey(patches);
10434     RegDeleteKeyA(prodkey, "");
10435     RegCloseKey(prodkey);
10436 }
10437 
10438 static void test_MsiEnumPatchesEx_machine(void)
10439 {
10440     CHAR keypath[MAX_PATH], patch[MAX_PATH];
10441     CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
10442     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
10443     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
10444     HKEY prodkey, patches, udprod, udpatch;
10445     HKEY hpatch;
10446     MSIINSTALLCONTEXT context;
10447     DWORD size, data;
10448     LONG res;
10449     UINT r;
10450     REGSAM access = KEY_ALL_ACCESS;
10451 
10452     create_test_guid(prodcode, prod_squashed);
10453     create_test_guid(patch, patch_squashed);
10454 
10455     if (is_wow64)
10456         access |= KEY_WOW64_64KEY;
10457 
10458     /* MSIPATCHSTATE_APPLIED */
10459 
10460     lstrcpyA(patchcode, "apple");
10461     lstrcpyA(targetprod, "banana");
10462     context = 0xdeadbeef;
10463     lstrcpyA(targetsid, "kiwi");
10464     size = MAX_PATH;
10465     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10466                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10467                            &context, targetsid, &size);
10468     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10469     ok(!lstrcmpA(patchcode, "apple"),
10470        "Expected patchcode to be unchanged, got %s\n", patchcode);
10471     ok(!lstrcmpA(targetprod, "banana"),
10472        "Expected targetprod to be unchanged, got %s\n", targetprod);
10473     ok(context == 0xdeadbeef,
10474        "Expected context to be unchanged, got %d\n", context);
10475     ok(!lstrcmpA(targetsid, "kiwi"),
10476        "Expected targetsid to be unchanged, got %s\n", targetsid);
10477     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10478 
10479     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
10480     lstrcatA(keypath, prod_squashed);
10481 
10482     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
10483     if (res == ERROR_ACCESS_DENIED)
10484     {
10485         skip("Not enough rights to perform tests\n");
10486         return;
10487     }
10488     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10489 
10490     /* local product key exists */
10491     lstrcpyA(patchcode, "apple");
10492     lstrcpyA(targetprod, "banana");
10493     context = 0xdeadbeef;
10494     lstrcpyA(targetsid, "kiwi");
10495     size = MAX_PATH;
10496     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10497                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10498                            &context, targetsid, &size);
10499     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10500     ok(!lstrcmpA(patchcode, "apple"),
10501        "Expected patchcode to be unchanged, got %s\n", patchcode);
10502     ok(!lstrcmpA(targetprod, "banana"),
10503        "Expected targetprod to be unchanged, got %s\n", targetprod);
10504     ok(context == 0xdeadbeef,
10505        "Expected context to be unchanged, got %d\n", context);
10506     ok(!lstrcmpA(targetsid, "kiwi"),
10507        "Expected targetsid to be unchanged, got %s\n", targetsid);
10508     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10509 
10510     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
10511     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10512 
10513     /* Patches key exists */
10514     lstrcpyA(patchcode, "apple");
10515     lstrcpyA(targetprod, "banana");
10516     context = 0xdeadbeef;
10517     lstrcpyA(targetsid, "kiwi");
10518     size = MAX_PATH;
10519     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10520                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10521                            &context, targetsid, &size);
10522     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10523     ok(!lstrcmpA(patchcode, "apple"),
10524        "Expected patchcode to be unchanged, got %s\n", patchcode);
10525     ok(!lstrcmpA(targetprod, "banana"),
10526        "Expected targetprod to be unchanged, got %s\n", targetprod);
10527     ok(context == 0xdeadbeef,
10528        "Expected context to be unchanged, got %d\n", context);
10529     ok(!lstrcmpA(targetsid, "kiwi"),
10530        "Expected targetsid to be unchanged, got %s\n", targetsid);
10531     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10532 
10533     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
10534                          (const BYTE *)patch_squashed,
10535                          lstrlenA(patch_squashed) + 1);
10536     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10537 
10538     /* Patches value exists, is not REG_MULTI_SZ */
10539     lstrcpyA(patchcode, "apple");
10540     lstrcpyA(targetprod, "banana");
10541     context = 0xdeadbeef;
10542     lstrcpyA(targetsid, "kiwi");
10543     size = MAX_PATH;
10544     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10545                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10546                            &context, targetsid, &size);
10547     ok(r == ERROR_BAD_CONFIGURATION,
10548        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10549     ok(!lstrcmpA(patchcode, "apple"),
10550        "Expected patchcode to be unchanged, got %s\n", patchcode);
10551     ok(!lstrcmpA(targetprod, "banana"),
10552        "Expected targetprod to be unchanged, got %s\n", targetprod);
10553     ok(context == 0xdeadbeef,
10554        "Expected context to be unchanged, got %d\n", context);
10555     ok(!lstrcmpA(targetsid, "kiwi"),
10556        "Expected targetsid to be unchanged, got %s\n", targetsid);
10557     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10558 
10559     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10560                          (const BYTE *)"a\0b\0c\0\0", 7);
10561     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10562 
10563     /* Patches value exists, is not a squashed guid */
10564     lstrcpyA(patchcode, "apple");
10565     lstrcpyA(targetprod, "banana");
10566     context = 0xdeadbeef;
10567     lstrcpyA(targetsid, "kiwi");
10568     size = MAX_PATH;
10569     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10570                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10571                            &context, targetsid, &size);
10572     ok(r == ERROR_BAD_CONFIGURATION,
10573        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10574     ok(!lstrcmpA(patchcode, "apple"),
10575        "Expected patchcode to be unchanged, got %s\n", patchcode);
10576     ok(!lstrcmpA(targetprod, "banana"),
10577        "Expected targetprod to be unchanged, got %s\n", targetprod);
10578     ok(context == 0xdeadbeef,
10579        "Expected context to be unchanged, got %d\n", context);
10580     ok(!lstrcmpA(targetsid, "kiwi"),
10581        "Expected targetsid to be unchanged, got %s\n", targetsid);
10582     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10583 
10584     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
10585     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10586                          (const BYTE *)patch_squashed,
10587                          lstrlenA(patch_squashed) + 2);
10588     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10589 
10590     /* Patches value exists */
10591     lstrcpyA(patchcode, "apple");
10592     lstrcpyA(targetprod, "banana");
10593     context = 0xdeadbeef;
10594     lstrcpyA(targetsid, "kiwi");
10595     size = MAX_PATH;
10596     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10597                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10598                            &context, targetsid, &size);
10599     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10600     ok(!lstrcmpA(patchcode, "apple"),
10601        "Expected patchcode to be unchanged, got %s\n", patchcode);
10602     ok(!lstrcmpA(targetprod, "banana"),
10603        "Expected targetprod to be unchanged, got %s\n", targetprod);
10604     ok(context == 0xdeadbeef,
10605        "Expected context to be unchanged, got %d\n", context);
10606     ok(!lstrcmpA(targetsid, "kiwi"),
10607        "Expected targetsid to be unchanged, got %s\n", targetsid);
10608     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10609 
10610     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
10611                          (const BYTE *)"whatever", 9);
10612     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10613 
10614     /* patch code value exists */
10615     lstrcpyA(patchcode, "apple");
10616     lstrcpyA(targetprod, "banana");
10617     context = 0xdeadbeef;
10618     lstrcpyA(targetsid, "kiwi");
10619     size = MAX_PATH;
10620     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10621                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10622                            &context, targetsid, &size);
10623     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10624     ok(!lstrcmpA(patchcode, patch),
10625        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10626     ok(!lstrcmpA(targetprod, prodcode),
10627        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10628     ok(context == MSIINSTALLCONTEXT_MACHINE,
10629        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10630     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
10631     ok(size == 0, "Expected 0, got %lu\n", size);
10632 
10633     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
10634     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
10635     lstrcatA(keypath, prod_squashed);
10636 
10637     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
10638     if (res == ERROR_ACCESS_DENIED)
10639     {
10640         skip("Not enough rights to perform tests\n");
10641         goto done;
10642     }
10643     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10644 
10645     /* local UserData product key exists */
10646     lstrcpyA(patchcode, "apple");
10647     lstrcpyA(targetprod, "banana");
10648     context = 0xdeadbeef;
10649     lstrcpyA(targetsid, "kiwi");
10650     size = MAX_PATH;
10651     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10652                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10653                            &context, targetsid, &size);
10654     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10655     ok(!lstrcmpA(patchcode, patch),
10656        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10657     ok(!lstrcmpA(targetprod, prodcode),
10658        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10659     ok(context == MSIINSTALLCONTEXT_MACHINE,
10660        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10661     ok(!lstrcmpA(targetsid, ""),
10662        "Expected \"\", got \"%s\"\n", targetsid);
10663     ok(size == 0, "Expected 0, got %lu\n", size);
10664 
10665     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
10666     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10667 
10668     /* local UserData Patches key exists */
10669     lstrcpyA(patchcode, "apple");
10670     lstrcpyA(targetprod, "banana");
10671     context = 0xdeadbeef;
10672     lstrcpyA(targetsid, "kiwi");
10673     size = MAX_PATH;
10674     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10675                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10676                            &context, targetsid, &size);
10677     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10678     ok(!lstrcmpA(patchcode, patch),
10679        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10680     ok(!lstrcmpA(targetprod, prodcode),
10681        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10682     ok(context == MSIINSTALLCONTEXT_MACHINE,
10683        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10684     ok(!lstrcmpA(targetsid, ""),
10685        "Expected \"\", got \"%s\"\n", targetsid);
10686     ok(size == 0, "Expected 0, got %lu\n", size);
10687 
10688     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
10689     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10690 
10691     /* local UserData Product patch key exists */
10692     lstrcpyA(patchcode, "apple");
10693     lstrcpyA(targetprod, "banana");
10694     context = 0xdeadbeef;
10695     lstrcpyA(targetsid, "kiwi");
10696     size = MAX_PATH;
10697     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10698                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10699                            &context, targetsid, &size);
10700     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10701     ok(!lstrcmpA(patchcode, "apple"),
10702        "Expected patchcode to be unchanged, got %s\n", patchcode);
10703     ok(!lstrcmpA(targetprod, "banana"),
10704        "Expected targetprod to be unchanged, got %s\n", targetprod);
10705     ok(context == 0xdeadbeef,
10706        "Expected context to be unchanged, got %d\n", context);
10707     ok(!lstrcmpA(targetsid, "kiwi"),
10708        "Expected targetsid to be unchanged, got %s\n", targetsid);
10709     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10710 
10711     data = MSIPATCHSTATE_APPLIED;
10712     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10713                          (const BYTE *)&data, sizeof(DWORD));
10714     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10715 
10716     /* State value exists */
10717     lstrcpyA(patchcode, "apple");
10718     lstrcpyA(targetprod, "banana");
10719     context = 0xdeadbeef;
10720     lstrcpyA(targetsid, "kiwi");
10721     size = MAX_PATH;
10722     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10723                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10724                            &context, targetsid, &size);
10725     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10726     ok(!lstrcmpA(patchcode, patch),
10727        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10728     ok(!lstrcmpA(targetprod, prodcode),
10729        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10730     ok(context == MSIINSTALLCONTEXT_MACHINE,
10731        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10732     ok(!lstrcmpA(targetsid, ""),
10733        "Expected \"\", got \"%s\"\n", targetsid);
10734     ok(size == 0, "Expected 0, got %lu\n", size);
10735 
10736     /* MSIPATCHSTATE_SUPERSEDED */
10737 
10738     lstrcpyA(patchcode, "apple");
10739     lstrcpyA(targetprod, "banana");
10740     context = 0xdeadbeef;
10741     lstrcpyA(targetsid, "kiwi");
10742     size = MAX_PATH;
10743     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10744                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10745                            &context, targetsid, &size);
10746     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10747     ok(!lstrcmpA(patchcode, "apple"),
10748        "Expected patchcode to be unchanged, got %s\n", patchcode);
10749     ok(!lstrcmpA(targetprod, "banana"),
10750        "Expected targetprod to be unchanged, got %s\n", targetprod);
10751     ok(context == 0xdeadbeef,
10752        "Expected context to be unchanged, got %d\n", context);
10753     ok(!lstrcmpA(targetsid, "kiwi"),
10754        "Expected targetsid to be unchanged, got %s\n", targetsid);
10755     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10756 
10757     data = MSIPATCHSTATE_SUPERSEDED;
10758     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10759                          (const BYTE *)&data, sizeof(DWORD));
10760     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10761 
10762     /* State value is MSIPATCHSTATE_SUPERSEDED */
10763     lstrcpyA(patchcode, "apple");
10764     lstrcpyA(targetprod, "banana");
10765     context = 0xdeadbeef;
10766     lstrcpyA(targetsid, "kiwi");
10767     size = MAX_PATH;
10768     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10769                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10770                            &context, targetsid, &size);
10771     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10772     ok(!lstrcmpA(patchcode, patch),
10773        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10774     ok(!lstrcmpA(targetprod, prodcode),
10775        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10776     ok(context == MSIINSTALLCONTEXT_MACHINE,
10777        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10778     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
10779     ok(size == 0, "Expected 0, got %lu\n", size);
10780 
10781     /* MSIPATCHSTATE_OBSOLETED */
10782 
10783     lstrcpyA(patchcode, "apple");
10784     lstrcpyA(targetprod, "banana");
10785     context = 0xdeadbeef;
10786     lstrcpyA(targetsid, "kiwi");
10787     size = MAX_PATH;
10788     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10789                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
10790                            &context, targetsid, &size);
10791     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10792     ok(!lstrcmpA(patchcode, "apple"),
10793        "Expected patchcode to be unchanged, got %s\n", patchcode);
10794     ok(!lstrcmpA(targetprod, "banana"),
10795        "Expected targetprod to be unchanged, got %s\n", targetprod);
10796     ok(context == 0xdeadbeef,
10797        "Expected context to be unchanged, got %d\n", context);
10798     ok(!lstrcmpA(targetsid, "kiwi"),
10799        "Expected targetsid to be unchanged, got %s\n", targetsid);
10800     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10801 
10802     data = MSIPATCHSTATE_OBSOLETED;
10803     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10804                          (const BYTE *)&data, sizeof(DWORD));
10805     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10806 
10807     /* State value is obsoleted */
10808     lstrcpyA(patchcode, "apple");
10809     lstrcpyA(targetprod, "banana");
10810     context = 0xdeadbeef;
10811     lstrcpyA(targetsid, "kiwi");
10812     size = MAX_PATH;
10813     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10814                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
10815                            &context, targetsid, &size);
10816     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10817     ok(!lstrcmpA(patchcode, patch),
10818        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10819     ok(!lstrcmpA(targetprod, prodcode),
10820        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10821     ok(context == MSIINSTALLCONTEXT_MACHINE,
10822        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10823     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
10824     ok(size == 0, "Expected 0, got %lu\n", size);
10825 
10826     /* MSIPATCHSTATE_REGISTERED */
10827     /* FIXME */
10828 
10829     /* MSIPATCHSTATE_ALL */
10830 
10831     /* 1st */
10832     lstrcpyA(patchcode, "apple");
10833     lstrcpyA(targetprod, "banana");
10834     context = 0xdeadbeef;
10835     lstrcpyA(targetsid, "kiwi");
10836     size = MAX_PATH;
10837     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10838                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
10839                            &context, targetsid, &size);
10840     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10841     ok(!lstrcmpA(patchcode, patch),
10842        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10843     ok(!lstrcmpA(targetprod, prodcode),
10844        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10845     ok(context == MSIINSTALLCONTEXT_MACHINE,
10846        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10847     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
10848     ok(size == 0, "Expected 0, got %lu\n", size);
10849 
10850     /* same patch in multiple places, only one is enumerated */
10851     lstrcpyA(patchcode, "apple");
10852     lstrcpyA(targetprod, "banana");
10853     context = 0xdeadbeef;
10854     lstrcpyA(targetsid, "kiwi");
10855     size = MAX_PATH;
10856     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10857                            MSIPATCHSTATE_ALL, 1, patchcode, targetprod,
10858                            &context, targetsid, &size);
10859     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10860     ok(!lstrcmpA(patchcode, "apple"),
10861        "Expected patchcode to be unchanged, got %s\n", patchcode);
10862     ok(!lstrcmpA(targetprod, "banana"),
10863        "Expected targetprod to be unchanged, got %s\n", targetprod);
10864     ok(context == 0xdeadbeef,
10865        "Expected context to be unchanged, got %d\n", context);
10866     ok(!lstrcmpA(targetsid, "kiwi"),
10867        "Expected targetsid to be unchanged, got %s\n", targetsid);
10868     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10869 
10870     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
10871     RegDeleteValueA(hpatch, "State");
10872     RegCloseKey(hpatch);
10873     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
10874     RegCloseKey(udpatch);
10875     delete_key(udprod, "", access & KEY_WOW64_64KEY);
10876     RegCloseKey(udprod);
10877 
10878 done:
10879     RegDeleteValueA(patches, patch_squashed);
10880     RegDeleteValueA(patches, "Patches");
10881     delete_key(patches, "", access & KEY_WOW64_64KEY);
10882     RegCloseKey(patches);
10883     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
10884     RegCloseKey(prodkey);
10885 }
10886 
10887 static void test_MsiEnumPatchesEx(void)
10888 {
10889     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
10890     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
10891     CHAR patchcode[MAX_PATH];
10892     MSIINSTALLCONTEXT context;
10893     LPSTR usersid;
10894     DWORD size;
10895     UINT r;
10896 
10897     if (!pMsiEnumPatchesExA)
10898     {
10899         win_skip("MsiEnumPatchesExA not implemented\n");
10900         return;
10901     }
10902 
10903     create_test_guid(prodcode, prod_squashed);
10904     usersid = get_user_sid();
10905 
10906     /* empty szProductCode */
10907     lstrcpyA(patchcode, "apple");
10908     lstrcpyA(targetprod, "banana");
10909     context = 0xdeadbeef;
10910     lstrcpyA(targetsid, "kiwi");
10911     size = MAX_PATH;
10912     r = pMsiEnumPatchesExA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10913                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod, &context,
10914                            targetsid, &size);
10915     ok(r == ERROR_INVALID_PARAMETER,
10916        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10917     ok(!lstrcmpA(patchcode, "apple"),
10918        "Expected patchcode to be unchanged, got %s\n", patchcode);
10919     ok(!lstrcmpA(targetprod, "banana"),
10920        "Expected targetprod to be unchanged, got %s\n", targetprod);
10921     ok(context == 0xdeadbeef,
10922        "Expected context to be unchanged, got %d\n", context);
10923     ok(!lstrcmpA(targetsid, "kiwi"),
10924        "Expected targetsid to be unchanged, got %s\n", targetsid);
10925     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10926 
10927     /* garbage szProductCode */
10928     lstrcpyA(patchcode, "apple");
10929     lstrcpyA(targetprod, "banana");
10930     context = 0xdeadbeef;
10931     lstrcpyA(targetsid, "kiwi");
10932     size = MAX_PATH;
10933     r = pMsiEnumPatchesExA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10934                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod, &context,
10935                            targetsid, &size);
10936     ok(r == ERROR_INVALID_PARAMETER,
10937        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10938     ok(!lstrcmpA(patchcode, "apple"),
10939        "Expected patchcode to be unchanged, got %s\n", patchcode);
10940     ok(!lstrcmpA(targetprod, "banana"),
10941        "Expected targetprod to be unchanged, got %s\n", targetprod);
10942     ok(context == 0xdeadbeef,
10943        "Expected context to be unchanged, got %d\n", context);
10944     ok(!lstrcmpA(targetsid, "kiwi"),
10945        "Expected targetsid to be unchanged, got %s\n", targetsid);
10946     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10947 
10948     /* guid without brackets */
10949     lstrcpyA(patchcode, "apple");
10950     lstrcpyA(targetprod, "banana");
10951     context = 0xdeadbeef;
10952     lstrcpyA(targetsid, "kiwi");
10953     size = MAX_PATH;
10954     r = pMsiEnumPatchesExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", usersid,
10955                            MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
10956                            0, patchcode, targetprod, &context,
10957                            targetsid, &size);
10958     ok(r == ERROR_INVALID_PARAMETER,
10959        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10960     ok(!lstrcmpA(patchcode, "apple"),
10961        "Expected patchcode to be unchanged, got %s\n", patchcode);
10962     ok(!lstrcmpA(targetprod, "banana"),
10963        "Expected targetprod to be unchanged, got %s\n", targetprod);
10964     ok(context == 0xdeadbeef,
10965        "Expected context to be unchanged, got %d\n", context);
10966     ok(!lstrcmpA(targetsid, "kiwi"),
10967        "Expected targetsid to be unchanged, got %s\n", targetsid);
10968     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10969 
10970     /* guid with brackets */
10971     lstrcpyA(patchcode, "apple");
10972     lstrcpyA(targetprod, "banana");
10973     context = 0xdeadbeef;
10974     lstrcpyA(targetsid, "kiwi");
10975     size = MAX_PATH;
10976     r = pMsiEnumPatchesExA("{6700E8CF-95AB-4D9C-BC2C-15840DDA7A5D}", usersid,
10977                            MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
10978                            0, patchcode, targetprod, &context,
10979                            targetsid, &size);
10980     ok(r == ERROR_NO_MORE_ITEMS,
10981        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10982     ok(!lstrcmpA(patchcode, "apple"),
10983        "Expected patchcode to be unchanged, got %s\n", patchcode);
10984     ok(!lstrcmpA(targetprod, "banana"),
10985        "Expected targetprod to be unchanged, got %s\n", targetprod);
10986     ok(context == 0xdeadbeef,
10987        "Expected context to be unchanged, got %d\n", context);
10988     ok(!lstrcmpA(targetsid, "kiwi"),
10989        "Expected targetsid to be unchanged, got %s\n", targetsid);
10990     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10991 
10992     /* szUserSid is S-1-5-18 */
10993     lstrcpyA(patchcode, "apple");
10994     lstrcpyA(targetprod, "banana");
10995     context = 0xdeadbeef;
10996     lstrcpyA(targetsid, "kiwi");
10997     size = MAX_PATH;
10998     r = pMsiEnumPatchesExA(prodcode, "S-1-5-18",
10999                            MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
11000                            0, patchcode, targetprod, &context,
11001                            targetsid, &size);
11002     ok(r == ERROR_INVALID_PARAMETER,
11003        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11004     ok(!lstrcmpA(patchcode, "apple"),
11005        "Expected patchcode to be unchanged, got %s\n", patchcode);
11006     ok(!lstrcmpA(targetprod, "banana"),
11007        "Expected targetprod to be unchanged, got %s\n", targetprod);
11008     ok(context == 0xdeadbeef,
11009        "Expected context to be unchanged, got %d\n", context);
11010     ok(!lstrcmpA(targetsid, "kiwi"),
11011        "Expected targetsid to be unchanged, got %s\n", targetsid);
11012     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11013 
11014     /* dwContext is MSIINSTALLCONTEXT_MACHINE, but szUserSid is non-NULL */
11015     lstrcpyA(patchcode, "apple");
11016     lstrcpyA(targetprod, "banana");
11017     context = 0xdeadbeef;
11018     lstrcpyA(targetsid, "kiwi");
11019     size = MAX_PATH;
11020     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_MACHINE,
11021                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
11022                            &context, targetsid, &size);
11023     ok(r == ERROR_INVALID_PARAMETER,
11024        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11025     ok(!lstrcmpA(patchcode, "apple"),
11026        "Expected patchcode to be unchanged, got %s\n", patchcode);
11027     ok(!lstrcmpA(targetprod, "banana"),
11028        "Expected targetprod to be unchanged, got %s\n", targetprod);
11029     ok(context == 0xdeadbeef,
11030        "Expected context to be unchanged, got %d\n", context);
11031     ok(!lstrcmpA(targetsid, "kiwi"),
11032        "Expected targetsid to be unchanged, got %s\n", targetsid);
11033     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11034 
11035     /* dwContext is out of bounds */
11036     lstrcpyA(patchcode, "apple");
11037     lstrcpyA(targetprod, "banana");
11038     context = 0xdeadbeef;
11039     lstrcpyA(targetsid, "kiwi");
11040     size = MAX_PATH;
11041     r = pMsiEnumPatchesExA(prodcode, usersid, 0,
11042                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
11043                            &context, targetsid, &size);
11044     ok(r == ERROR_INVALID_PARAMETER,
11045        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11046     ok(!lstrcmpA(patchcode, "apple"),
11047        "Expected patchcode to be unchanged, got %s\n", patchcode);
11048     ok(!lstrcmpA(targetprod, "banana"),
11049        "Expected targetprod to be unchanged, got %s\n", targetprod);
11050     ok(context == 0xdeadbeef,
11051        "Expected context to be unchanged, got %d\n", context);
11052     ok(!lstrcmpA(targetsid, "kiwi"),
11053        "Expected targetsid to be unchanged, got %s\n", targetsid);
11054     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11055 
11056     /* dwContext is out of bounds */
11057     lstrcpyA(patchcode, "apple");
11058     lstrcpyA(targetprod, "banana");
11059     context = 0xdeadbeef;
11060     lstrcpyA(targetsid, "kiwi");
11061     size = MAX_PATH;
11062     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_ALL + 1,
11063                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
11064                            &context, targetsid, &size);
11065     ok(r == ERROR_INVALID_PARAMETER,
11066        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11067     ok(!lstrcmpA(patchcode, "apple"),
11068        "Expected patchcode to be unchanged, got %s\n", patchcode);
11069     ok(!lstrcmpA(targetprod, "banana"),
11070        "Expected targetprod to be unchanged, got %s\n", targetprod);
11071     ok(context == 0xdeadbeef,
11072        "Expected context to be unchanged, got %d\n", context);
11073     ok(!lstrcmpA(targetsid, "kiwi"),
11074        "Expected targetsid to be unchanged, got %s\n", targetsid);
11075     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11076 
11077     /* dwFilter is out of bounds */
11078     lstrcpyA(patchcode, "apple");
11079     lstrcpyA(targetprod, "banana");
11080     context = 0xdeadbeef;
11081     lstrcpyA(targetsid, "kiwi");
11082     size = MAX_PATH;
11083     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
11084                            MSIPATCHSTATE_INVALID, 0, patchcode, targetprod,
11085                            &context, targetsid, &size);
11086     ok(r == ERROR_INVALID_PARAMETER,
11087        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11088     ok(!lstrcmpA(patchcode, "apple"),
11089        "Expected patchcode to be unchanged, got %s\n", patchcode);
11090     ok(!lstrcmpA(targetprod, "banana"),
11091        "Expected targetprod to be unchanged, got %s\n", targetprod);
11092     ok(context == 0xdeadbeef,
11093        "Expected context to be unchanged, got %d\n", context);
11094     ok(!lstrcmpA(targetsid, "kiwi"),
11095        "Expected targetsid to be unchanged, got %s\n", targetsid);
11096     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11097 
11098     /* dwFilter is out of bounds */
11099     lstrcpyA(patchcode, "apple");
11100     lstrcpyA(targetprod, "banana");
11101     context = 0xdeadbeef;
11102     lstrcpyA(targetsid, "kiwi");
11103     size = MAX_PATH;
11104     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
11105                            MSIPATCHSTATE_ALL + 1, 0, patchcode, targetprod,
11106                            &context, targetsid, &size);
11107     ok(r == ERROR_INVALID_PARAMETER,
11108        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11109     ok(!lstrcmpA(patchcode, "apple"),
11110        "Expected patchcode to be unchanged, got %s\n", patchcode);
11111     ok(!lstrcmpA(targetprod, "banana"),
11112        "Expected targetprod to be unchanged, got %s\n", targetprod);
11113     ok(context == 0xdeadbeef,
11114        "Expected context to be unchanged, got %d\n", context);
11115     ok(!lstrcmpA(targetsid, "kiwi"),
11116        "Expected targetsid to be unchanged, got %s\n", targetsid);
11117     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11118 
11119     /* pcchTargetUserSid is NULL while szTargetUserSid is non-NULL */
11120     lstrcpyA(patchcode, "apple");
11121     lstrcpyA(targetprod, "banana");
11122     context = 0xdeadbeef;
11123     lstrcpyA(targetsid, "kiwi");
11124     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
11125                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
11126                            &context, targetsid, NULL);
11127     ok(r == ERROR_INVALID_PARAMETER,
11128        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11129     ok(!lstrcmpA(patchcode, "apple"),
11130        "Expected patchcode to be unchanged, got %s\n", patchcode);
11131     ok(!lstrcmpA(targetprod, "banana"),
11132        "Expected targetprod to be unchanged, got %s\n", targetprod);
11133     ok(context == 0xdeadbeef,
11134        "Expected context to be unchanged, got %d\n", context);
11135     ok(!lstrcmpA(targetsid, "kiwi"),
11136        "Expected targetsid to be unchanged, got %s\n", targetsid);
11137 
11138     test_MsiEnumPatchesEx_usermanaged(usersid, usersid);
11139     test_MsiEnumPatchesEx_usermanaged(NULL, usersid);
11140     test_MsiEnumPatchesEx_usermanaged("S-1-2-34", "S-1-2-34");
11141     test_MsiEnumPatchesEx_userunmanaged(usersid, usersid);
11142     test_MsiEnumPatchesEx_userunmanaged(NULL, usersid);
11143     /* FIXME: Successfully test userunmanaged with a different user */
11144     test_MsiEnumPatchesEx_machine();
11145     LocalFree(usersid);
11146 }
11147 
11148 static void test_MsiEnumPatches(void)
11149 {
11150     CHAR keypath[MAX_PATH], patch[MAX_PATH];
11151     CHAR patchcode[MAX_PATH], patch_squashed[MAX_PATH];
11152     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
11153     CHAR transforms[MAX_PATH];
11154     WCHAR patchW[MAX_PATH], prodcodeW[MAX_PATH], transformsW[MAX_PATH];
11155     HKEY prodkey, patches, udprod;
11156     HKEY userkey, hpatch, udpatch;
11157     DWORD size, data;
11158     LPSTR usersid;
11159     LONG res;
11160     UINT r;
11161     REGSAM access = KEY_ALL_ACCESS;
11162 
11163     create_test_guid(prodcode, prod_squashed);
11164     create_test_guid(patchcode, patch_squashed);
11165     usersid = get_user_sid();
11166 
11167     if (is_wow64)
11168         access |= KEY_WOW64_64KEY;
11169 
11170     /* NULL szProduct */
11171     size = MAX_PATH;
11172     lstrcpyA(patch, "apple");
11173     lstrcpyA(transforms, "banana");
11174     r = MsiEnumPatchesA(NULL, 0, patch, transforms, &size);
11175     ok(r == ERROR_INVALID_PARAMETER,
11176        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11177     ok(!lstrcmpA(patch, "apple"),
11178        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11179     ok(!lstrcmpA(transforms, "banana"),
11180        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11181     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11182 
11183     /* empty szProduct */
11184     size = MAX_PATH;
11185     lstrcpyA(patch, "apple");
11186     lstrcpyA(transforms, "banana");
11187     r = MsiEnumPatchesA("", 0, patch, transforms, &size);
11188     ok(r == ERROR_INVALID_PARAMETER,
11189        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11190     ok(!lstrcmpA(patch, "apple"),
11191        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11192     ok(!lstrcmpA(transforms, "banana"),
11193        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11194     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11195 
11196     /* garbage szProduct */
11197     size = MAX_PATH;
11198     lstrcpyA(patch, "apple");
11199     lstrcpyA(transforms, "banana");
11200     r = MsiEnumPatchesA("garbage", 0, patch, transforms, &size);
11201     ok(r == ERROR_INVALID_PARAMETER,
11202        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11203     ok(!lstrcmpA(patch, "apple"),
11204        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11205     ok(!lstrcmpA(transforms, "banana"),
11206        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11207     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11208 
11209     /* guid without brackets */
11210     size = MAX_PATH;
11211     lstrcpyA(patch, "apple");
11212     lstrcpyA(transforms, "banana");
11213     r = MsiEnumPatchesA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", 0, patch,
11214                         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 %lu\n", size);
11222 
11223     /* guid with brackets */
11224     size = MAX_PATH;
11225     lstrcpyA(patch, "apple");
11226     lstrcpyA(transforms, "banana");
11227     r = MsiEnumPatchesA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", 0, patch,
11228                         transforms, &size);
11229     ok(r == ERROR_UNKNOWN_PRODUCT,
11230        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11231     ok(!lstrcmpA(patch, "apple"),
11232        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11233     ok(!lstrcmpA(transforms, "banana"),
11234        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11235     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11236 
11237     /* same length as guid, but random */
11238     size = MAX_PATH;
11239     lstrcpyA(patch, "apple");
11240     lstrcpyA(transforms, "banana");
11241     r = MsiEnumPatchesA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", 0, patch,
11242                         transforms, &size);
11243     ok(r == ERROR_INVALID_PARAMETER,
11244        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11245     ok(!lstrcmpA(patch, "apple"),
11246        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11247     ok(!lstrcmpA(transforms, "banana"),
11248        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11249     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11250 
11251     /* MSIINSTALLCONTEXT_USERMANAGED */
11252 
11253     size = MAX_PATH;
11254     lstrcpyA(patch, "apple");
11255     lstrcpyA(transforms, "banana");
11256     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11257     ok(r == ERROR_UNKNOWN_PRODUCT,
11258        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11259     ok(!lstrcmpA(patch, "apple"),
11260        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11261     ok(!lstrcmpA(transforms, "banana"),
11262        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11263     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11264 
11265     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
11266     lstrcatA(keypath, usersid);
11267     lstrcatA(keypath, "\\Installer\\Products\\");
11268     lstrcatA(keypath, prod_squashed);
11269 
11270     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
11271     if (res == ERROR_ACCESS_DENIED)
11272     {
11273         skip("Not enough rights to perform tests\n");
11274         LocalFree(usersid);
11275         return;
11276     }
11277     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11278 
11279     /* managed product key exists */
11280     size = MAX_PATH;
11281     lstrcpyA(patch, "apple");
11282     lstrcpyA(transforms, "banana");
11283     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11284     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, 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 %lu\n", size);
11290 
11291     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
11292     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11293 
11294     /* patches key exists */
11295     size = MAX_PATH;
11296     lstrcpyA(patch, "apple");
11297     lstrcpyA(transforms, "banana");
11298     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11299     ok(r == ERROR_NO_MORE_ITEMS ||
11300        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11301        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11302     ok(!lstrcmpA(patch, "apple"),
11303        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11304     ok(!lstrcmpA(transforms, "banana"),
11305        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11306     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11307 
11308     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
11309                          (const BYTE *)patch_squashed,
11310                          lstrlenA(patch_squashed) + 1);
11311     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11312 
11313     /* Patches value exists, is not REG_MULTI_SZ */
11314     size = MAX_PATH;
11315     lstrcpyA(patch, "apple");
11316     lstrcpyA(transforms, "banana");
11317     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11318     ok(r == ERROR_BAD_CONFIGURATION ||
11319        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
11320        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11321     ok(!lstrcmpA(patch, "apple"),
11322        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11323     ok(!lstrcmpA(transforms, "banana"),
11324        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11325     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11326 
11327     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11328                          (const BYTE *)"a\0b\0c\0\0", 7);
11329     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11330 
11331     /* Patches value exists, is not a squashed guid */
11332     size = MAX_PATH;
11333     lstrcpyA(patch, "apple");
11334     lstrcpyA(transforms, "banana");
11335     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11336     ok(r == ERROR_BAD_CONFIGURATION,
11337        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11338     ok(!lstrcmpA(patch, "apple"),
11339        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11340     ok(!lstrcmpA(transforms, "banana"),
11341        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11342     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11343 
11344     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
11345     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11346                          (const BYTE *)patch_squashed,
11347                          lstrlenA(patch_squashed) + 2);
11348     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11349 
11350     /* Patches value exists */
11351     size = MAX_PATH;
11352     lstrcpyA(patch, "apple");
11353     lstrcpyA(transforms, "banana");
11354     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11355     ok(r == ERROR_NO_MORE_ITEMS ||
11356        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11357        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11358     ok(!lstrcmpA(patch, "apple") ||
11359        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
11360        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11361     ok(!lstrcmpA(transforms, "banana"),
11362        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11363     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11364 
11365     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
11366                          (const BYTE *)"whatever", 9);
11367     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11368 
11369     /* patch squashed value exists */
11370     size = MAX_PATH;
11371     lstrcpyA(patch, "apple");
11372     lstrcpyA(transforms, "banana");
11373     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11374     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11375     ok(!lstrcmpA(patch, patchcode),
11376        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11377     ok(!lstrcmpA(transforms, "whatever"),
11378        "Expected \"whatever\", got \"%s\"\n", transforms);
11379     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %lu\n", size);
11380 
11381     /* lpPatchBuf is NULL */
11382     size = MAX_PATH;
11383     lstrcpyA(transforms, "banana");
11384     r = MsiEnumPatchesA(prodcode, 0, NULL, transforms, &size);
11385     ok(r == ERROR_INVALID_PARAMETER,
11386        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11387     ok(!lstrcmpA(transforms, "banana"),
11388        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11389     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11390 
11391     /* lpTransformsBuf is NULL, pcchTransformsBuf is not */
11392     size = MAX_PATH;
11393     lstrcpyA(patch, "apple");
11394     r = MsiEnumPatchesA(prodcode, 0, patch, NULL, &size);
11395     ok(r == ERROR_INVALID_PARAMETER,
11396        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11397     ok(!lstrcmpA(patch, "apple"),
11398        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11399     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11400 
11401     /* pcchTransformsBuf is NULL, lpTransformsBuf is not */
11402     lstrcpyA(patch, "apple");
11403     lstrcpyA(transforms, "banana");
11404     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, NULL);
11405     ok(r == ERROR_INVALID_PARAMETER,
11406        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11407     ok(!lstrcmpA(patch, "apple"),
11408        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11409     ok(!lstrcmpA(transforms, "banana"),
11410        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11411 
11412     /* pcchTransformsBuf is too small */
11413     size = 6;
11414     lstrcpyA(patch, "apple");
11415     lstrcpyA(transforms, "banana");
11416     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11417     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
11418     ok(!lstrcmpA(patch, patchcode),
11419        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11420     ok(!lstrcmpA(transforms, "whate") ||
11421        broken(!lstrcmpA(transforms, "banana")), /* Windows Installer < 3.0 */
11422        "Expected \"whate\", got \"%s\"\n", transforms);
11423     ok(size == 8 || size == 16, "Expected 8 or 16, got %lu\n", size);
11424 
11425     /* increase the index */
11426     size = MAX_PATH;
11427     lstrcpyA(patch, "apple");
11428     lstrcpyA(transforms, "banana");
11429     r = MsiEnumPatchesA(prodcode, 1, patch, transforms, &size);
11430     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11431     ok(!lstrcmpA(patch, "apple"),
11432        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11433     ok(!lstrcmpA(transforms, "banana"),
11434        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11435     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11436 
11437     /* increase again */
11438     size = MAX_PATH;
11439     lstrcpyA(patch, "apple");
11440     lstrcpyA(transforms, "banana");
11441     r = MsiEnumPatchesA(prodcode, 2, patch, transforms, &size);
11442     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11443     ok(!lstrcmpA(patch, "apple"),
11444        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11445     ok(!lstrcmpA(transforms, "banana"),
11446        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11447     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11448 
11449     RegDeleteValueA(patches, "Patches");
11450     delete_key(patches, "", access & KEY_WOW64_64KEY);
11451     RegCloseKey(patches);
11452     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
11453     RegCloseKey(prodkey);
11454 
11455     /* MSIINSTALLCONTEXT_USERUNMANAGED */
11456 
11457     size = MAX_PATH;
11458     lstrcpyA(patch, "apple");
11459     lstrcpyA(transforms, "banana");
11460     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11461     ok(r == ERROR_UNKNOWN_PRODUCT,
11462        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11463     ok(!lstrcmpA(patch, "apple"),
11464        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11465     ok(!lstrcmpA(transforms, "banana"),
11466        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11467     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11468 
11469     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
11470     lstrcatA(keypath, prod_squashed);
11471 
11472     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
11473     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11474 
11475     /* current user product key exists */
11476     size = MAX_PATH;
11477     lstrcpyA(patch, "apple");
11478     lstrcpyA(transforms, "banana");
11479     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11480     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11481     ok(!lstrcmpA(patch, "apple"),
11482        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11483     ok(!lstrcmpA(transforms, "banana"),
11484        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11485     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11486 
11487     res = RegCreateKeyA(prodkey, "Patches", &patches);
11488     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11489 
11490     /* Patches key exists */
11491     size = MAX_PATH;
11492     lstrcpyA(patch, "apple");
11493     lstrcpyA(transforms, "banana");
11494     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11495     ok(r == ERROR_NO_MORE_ITEMS ||
11496        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11497        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11498     ok(!lstrcmpA(patch, "apple"),
11499        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11500     ok(!lstrcmpA(transforms, "banana"),
11501        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11502     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11503 
11504     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
11505                          (const BYTE *)patch_squashed,
11506                          lstrlenA(patch_squashed) + 1);
11507     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11508 
11509     /* Patches value exists, is not REG_MULTI_SZ */
11510     size = MAX_PATH;
11511     lstrcpyA(patch, "apple");
11512     lstrcpyA(transforms, "banana");
11513     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11514     ok(r == ERROR_BAD_CONFIGURATION ||
11515        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
11516        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11517     ok(!lstrcmpA(patch, "apple"),
11518        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11519     ok(!lstrcmpA(transforms, "banana"),
11520        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11521     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11522 
11523     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11524                          (const BYTE *)"a\0b\0c\0\0", 7);
11525     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11526 
11527     /* Patches value exists, is not a squashed guid */
11528     size = MAX_PATH;
11529     lstrcpyA(patch, "apple");
11530     lstrcpyA(transforms, "banana");
11531     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11532     ok(r == ERROR_BAD_CONFIGURATION,
11533        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11534     ok(!lstrcmpA(patch, "apple"),
11535        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11536     ok(!lstrcmpA(transforms, "banana"),
11537        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11538     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11539 
11540     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
11541     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11542                          (const BYTE *)patch_squashed,
11543                          lstrlenA(patch_squashed) + 2);
11544     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11545 
11546     /* Patches value exists */
11547     size = MAX_PATH;
11548     lstrcpyA(patch, "apple");
11549     lstrcpyA(transforms, "banana");
11550     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11551     ok(r == ERROR_NO_MORE_ITEMS ||
11552        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11553        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11554     ok(!lstrcmpA(patch, "apple") ||
11555        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
11556        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11557     ok(!lstrcmpA(transforms, "banana"),
11558        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11559     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11560 
11561     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
11562                          (const BYTE *)"whatever", 9);
11563     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11564 
11565     /* patch code value exists */
11566     size = MAX_PATH;
11567     lstrcpyA(patch, "apple");
11568     lstrcpyA(transforms, "banana");
11569     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11570     ok(r == ERROR_NO_MORE_ITEMS ||
11571        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
11572        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11573     ok(!lstrcmpA(patch, "apple") ||
11574        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
11575        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11576     ok(!lstrcmpA(transforms, "banana") ||
11577        broken(!lstrcmpA(transforms, "whatever")), /* Windows Installer < 3.0 */
11578        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11579     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11580 
11581     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
11582     lstrcatA(keypath, usersid);
11583     lstrcatA(keypath, "\\Patches\\");
11584     lstrcatA(keypath, patch_squashed);
11585 
11586     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
11587     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11588 
11589     /* userdata patch key exists */
11590     size = MAX_PATH;
11591     lstrcpyA(patch, "apple");
11592     lstrcpyA(transforms, "banana");
11593     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11594     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11595     ok(!lstrcmpA(patch, patchcode),
11596        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11597     ok(!lstrcmpA(transforms, "whatever"),
11598        "Expected \"whatever\", got \"%s\"\n", transforms);
11599     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %lu\n", size);
11600 
11601     delete_key(userkey, "", access & KEY_WOW64_64KEY);
11602     RegCloseKey(userkey);
11603     RegDeleteValueA(patches, patch_squashed);
11604     RegDeleteValueA(patches, "Patches");
11605     RegDeleteKeyA(patches, "");
11606     RegCloseKey(patches);
11607     RegDeleteKeyA(prodkey, "");
11608     RegCloseKey(prodkey);
11609 
11610     /* MSIINSTALLCONTEXT_MACHINE */
11611 
11612     size = MAX_PATH;
11613     lstrcpyA(patch, "apple");
11614     lstrcpyA(transforms, "banana");
11615     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11616     ok(r == ERROR_UNKNOWN_PRODUCT,
11617        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11618     ok(!lstrcmpA(patch, "apple"),
11619        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11620     ok(!lstrcmpA(transforms, "banana"),
11621        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11622     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11623 
11624     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
11625     lstrcatA(keypath, prod_squashed);
11626 
11627     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
11628     if (res == ERROR_ACCESS_DENIED)
11629     {
11630         skip("Not enough rights to perform tests\n");
11631         LocalFree(usersid);
11632         return;
11633     }
11634     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11635 
11636     /* local product key exists */
11637     size = MAX_PATH;
11638     lstrcpyA(patch, "apple");
11639     lstrcpyA(transforms, "banana");
11640     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11641     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11642     ok(!lstrcmpA(patch, "apple"),
11643        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11644     ok(!lstrcmpA(transforms, "banana"),
11645        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11646     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11647 
11648     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
11649     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11650 
11651     /* Patches key exists */
11652     size = MAX_PATH;
11653     lstrcpyA(patch, "apple");
11654     lstrcpyA(transforms, "banana");
11655     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11656     ok(r == ERROR_NO_MORE_ITEMS ||
11657        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11658        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11659     ok(!lstrcmpA(patch, "apple"),
11660        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11661     ok(!lstrcmpA(transforms, "banana"),
11662        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11663     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11664 
11665     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
11666                          (const BYTE *)patch_squashed,
11667                          lstrlenA(patch_squashed) + 1);
11668     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11669 
11670     /* Patches value exists, is not REG_MULTI_SZ */
11671     size = MAX_PATH;
11672     lstrcpyA(patch, "apple");
11673     lstrcpyA(transforms, "banana");
11674     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11675     ok(r == ERROR_BAD_CONFIGURATION ||
11676        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
11677        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11678     ok(!lstrcmpA(patch, "apple"),
11679        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11680     ok(!lstrcmpA(transforms, "banana"),
11681        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11682     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11683 
11684     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11685                          (const BYTE *)"a\0b\0c\0\0", 7);
11686     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11687 
11688     /* Patches value exists, is not a squashed guid */
11689     size = MAX_PATH;
11690     lstrcpyA(patch, "apple");
11691     lstrcpyA(transforms, "banana");
11692     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11693     ok(r == ERROR_BAD_CONFIGURATION,
11694        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11695     ok(!lstrcmpA(patch, "apple"),
11696        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11697     ok(!lstrcmpA(transforms, "banana"),
11698        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11699     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11700 
11701     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
11702     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11703                          (const BYTE *)patch_squashed,
11704                          lstrlenA(patch_squashed) + 2);
11705     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11706 
11707     /* Patches value exists */
11708     size = MAX_PATH;
11709     lstrcpyA(patch, "apple");
11710     lstrcpyA(transforms, "banana");
11711     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11712     ok(r == ERROR_NO_MORE_ITEMS ||
11713        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11714        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11715     ok(!lstrcmpA(patch, "apple") ||
11716        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
11717        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11718     ok(!lstrcmpA(transforms, "banana"),
11719        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11720     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11721 
11722     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
11723                          (const BYTE *)"whatever", 9);
11724     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11725 
11726     /* patch code value exists */
11727     size = MAX_PATH;
11728     lstrcpyA(patch, "apple");
11729     lstrcpyA(transforms, "banana");
11730     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11731     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11732     ok(!lstrcmpA(patch, patchcode),
11733        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11734     ok(!lstrcmpA(transforms, "whatever"),
11735        "Expected \"whatever\", got \"%s\"\n", transforms);
11736     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %lu\n", size);
11737 
11738     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
11739     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
11740     lstrcatA(keypath, prod_squashed);
11741 
11742     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
11743     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11744 
11745     /* local UserData product key exists */
11746     size = MAX_PATH;
11747     lstrcpyA(patch, "apple");
11748     lstrcpyA(transforms, "banana");
11749     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11750     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11751     ok(!lstrcmpA(patch, patchcode),
11752        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11753     ok(!lstrcmpA(transforms, "whatever"),
11754        "Expected \"whatever\", got \"%s\"\n", transforms);
11755     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %lu\n", size);
11756 
11757     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
11758     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11759 
11760     /* local UserData Patches key exists */
11761     size = MAX_PATH;
11762     lstrcpyA(patch, "apple");
11763     lstrcpyA(transforms, "banana");
11764     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11765     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11766     ok(!lstrcmpA(patch, patchcode),
11767        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11768     ok(!lstrcmpA(transforms, "whatever"),
11769        "Expected \"whatever\", got \"%s\"\n", transforms);
11770     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %lu\n", size);
11771 
11772     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
11773     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11774 
11775     /* local UserData Product patch key exists */
11776     size = MAX_PATH;
11777     lstrcpyA(patch, "apple");
11778     lstrcpyA(transforms, "banana");
11779     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11780     ok(r == ERROR_NO_MORE_ITEMS ||
11781        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
11782        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11783     ok(!lstrcmpA(patch, "apple") ||
11784        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
11785        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11786     ok(!lstrcmpA(transforms, "banana") ||
11787        broken(!lstrcmpA(transforms, "whatever")), /* Windows Installer < 3.0 */
11788        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11789     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11790 
11791     data = MSIPATCHSTATE_APPLIED;
11792     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
11793                          (const BYTE *)&data, sizeof(DWORD));
11794     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11795 
11796     /* State value exists */
11797     size = MAX_PATH;
11798     lstrcpyA(patch, "apple");
11799     lstrcpyA(transforms, "banana");
11800     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11801     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11802     ok(!lstrcmpA(patch, patchcode),
11803        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11804     ok(!lstrcmpA(transforms, "whatever"),
11805        "Expected \"whatever\", got \"%s\"\n", transforms);
11806     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %lu\n", size);
11807 
11808     /* now duplicate some of the tests for the W version */
11809 
11810     /* pcchTransformsBuf is too small */
11811     size = 6;
11812     MultiByteToWideChar( CP_ACP, 0, prodcode, -1, prodcodeW, MAX_PATH );
11813     MultiByteToWideChar( CP_ACP, 0, "apple", -1, patchW, MAX_PATH );
11814     MultiByteToWideChar( CP_ACP, 0, "banana", -1, transformsW, MAX_PATH );
11815     r = MsiEnumPatchesW(prodcodeW, 0, patchW, transformsW, &size);
11816     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
11817     WideCharToMultiByte( CP_ACP, 0, patchW, -1, patch, MAX_PATH, NULL, NULL );
11818     WideCharToMultiByte( CP_ACP, 0, transformsW, -1, transforms, MAX_PATH, NULL, NULL );
11819     ok(!lstrcmpA(patch, patchcode),
11820        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11821     ok(!lstrcmpA(transforms, "whate") ||
11822        broken(!lstrcmpA(transforms, "banana")), /* Windows Installer < 3.0 */
11823        "Expected \"whate\", got \"%s\"\n", transforms);
11824     ok(size == 8, "Expected 8, got %lu\n", size);
11825 
11826     /* patch code value exists */
11827     size = MAX_PATH;
11828     MultiByteToWideChar( CP_ACP, 0, "apple", -1, patchW, MAX_PATH );
11829     MultiByteToWideChar( CP_ACP, 0, "banana", -1, transformsW, MAX_PATH );
11830     r = MsiEnumPatchesW(prodcodeW, 0, patchW, transformsW, &size);
11831     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11832     WideCharToMultiByte( CP_ACP, 0, patchW, -1, patch, MAX_PATH, NULL, NULL );
11833     WideCharToMultiByte( CP_ACP, 0, transformsW, -1, transforms, MAX_PATH, NULL, NULL );
11834     ok(!lstrcmpA(patch, patchcode),
11835        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11836     ok(!lstrcmpA(transforms, "whatever"),
11837        "Expected \"whatever\", got \"%s\"\n", transforms);
11838     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %lu\n", size);
11839 
11840     RegDeleteValueA(patches, patch_squashed);
11841     RegDeleteValueA(patches, "Patches");
11842     delete_key(patches, "", access & KEY_WOW64_64KEY);
11843     RegCloseKey(patches);
11844     RegDeleteValueA(hpatch, "State");
11845     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
11846     RegCloseKey(hpatch);
11847     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
11848     RegCloseKey(udpatch);
11849     delete_key(udprod, "", access & KEY_WOW64_64KEY);
11850     RegCloseKey(udprod);
11851     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
11852     RegCloseKey(prodkey);
11853     LocalFree(usersid);
11854 }
11855 
11856 static void test_MsiGetPatchInfoEx(void)
11857 {
11858     CHAR keypath[MAX_PATH], val[MAX_PATH];
11859     CHAR patchcode[MAX_PATH], patch_squashed[MAX_PATH];
11860     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
11861     HKEY prodkey, patches, udprod, props;
11862     HKEY hpatch, udpatch, prodpatches;
11863     LPSTR usersid;
11864     DWORD size;
11865     LONG res;
11866     UINT r;
11867     REGSAM access = KEY_ALL_ACCESS;
11868 
11869     if (!pMsiGetPatchInfoExA)
11870     {
11871         win_skip("MsiGetPatchInfoEx not implemented\n");
11872         return;
11873     }
11874 
11875     create_test_guid(prodcode, prod_squashed);
11876     create_test_guid(patchcode, patch_squashed);
11877     usersid = get_user_sid();
11878 
11879     if (is_wow64)
11880         access |= KEY_WOW64_64KEY;
11881 
11882     /* NULL szPatchCode */
11883     lstrcpyA(val, "apple");
11884     size = MAX_PATH;
11885     r = pMsiGetPatchInfoExA(NULL, prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED,
11886                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11887     ok(r == ERROR_INVALID_PARAMETER,
11888        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11889     ok(!lstrcmpA(val, "apple"),
11890        "Expected val to be unchanged, got \"%s\"\n", val);
11891     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11892 
11893     /* empty szPatchCode */
11894     size = MAX_PATH;
11895     lstrcpyA(val, "apple");
11896     r = pMsiGetPatchInfoExA("", prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED,
11897                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11898     ok(r == ERROR_INVALID_PARAMETER,
11899        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11900     ok(!lstrcmpA(val, "apple"),
11901        "Expected val to be unchanged, got \"%s\"\n", val);
11902     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11903 
11904     /* garbage szPatchCode */
11905     size = MAX_PATH;
11906     lstrcpyA(val, "apple");
11907     r = pMsiGetPatchInfoExA("garbage", prodcode, NULL,
11908                             MSIINSTALLCONTEXT_USERMANAGED,
11909                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11910     ok(r == ERROR_INVALID_PARAMETER,
11911        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11912     ok(!lstrcmpA(val, "apple"),
11913        "Expected val to be unchanged, got \"%s\"\n", val);
11914     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11915 
11916     /* guid without brackets */
11917     size = MAX_PATH;
11918     lstrcpyA(val, "apple");
11919     r = pMsiGetPatchInfoExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", prodcode,
11920                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
11921                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11922     ok(r == ERROR_INVALID_PARAMETER,
11923        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11924     ok(!lstrcmpA(val, "apple"),
11925        "Expected val to be unchanged, got \"%s\"\n", val);
11926     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11927 
11928     /* guid with brackets */
11929     size = MAX_PATH;
11930     lstrcpyA(val, "apple");
11931     r = pMsiGetPatchInfoExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", prodcode,
11932                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
11933                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11934     ok(r == ERROR_UNKNOWN_PRODUCT,
11935        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11936     ok(!lstrcmpA(val, "apple"),
11937        "Expected val to be unchanged, got \"%s\"\n", val);
11938     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11939 
11940     /* same length as guid, but random */
11941     size = MAX_PATH;
11942     lstrcpyA(val, "apple");
11943     r = pMsiGetPatchInfoExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", prodcode,
11944                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
11945                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11946     ok(r == ERROR_INVALID_PARAMETER,
11947        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11948     ok(!lstrcmpA(val, "apple"),
11949        "Expected val to be unchanged, got \"%s\"\n", val);
11950     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11951 
11952     /* NULL szProductCode */
11953     lstrcpyA(val, "apple");
11954     size = MAX_PATH;
11955     r = pMsiGetPatchInfoExA(patchcode, NULL, NULL, MSIINSTALLCONTEXT_USERMANAGED,
11956                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11957     ok(r == ERROR_INVALID_PARAMETER,
11958        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11959     ok(!lstrcmpA(val, "apple"),
11960        "Expected val to be unchanged, got \"%s\"\n", val);
11961     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11962 
11963     /* empty szProductCode */
11964     size = MAX_PATH;
11965     lstrcpyA(val, "apple");
11966     r = pMsiGetPatchInfoExA(patchcode, "", NULL, MSIINSTALLCONTEXT_USERMANAGED,
11967                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11968     ok(r == ERROR_INVALID_PARAMETER,
11969        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11970     ok(!lstrcmpA(val, "apple"),
11971        "Expected val to be unchanged, got \"%s\"\n", val);
11972     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11973 
11974     /* garbage szProductCode */
11975     size = MAX_PATH;
11976     lstrcpyA(val, "apple");
11977     r = pMsiGetPatchInfoExA(patchcode, "garbage", NULL,
11978                             MSIINSTALLCONTEXT_USERMANAGED,
11979                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11980     ok(r == ERROR_INVALID_PARAMETER,
11981        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11982     ok(!lstrcmpA(val, "apple"),
11983        "Expected val to be unchanged, got \"%s\"\n", val);
11984     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11985 
11986     /* guid without brackets */
11987     size = MAX_PATH;
11988     lstrcpyA(val, "apple");
11989     r = pMsiGetPatchInfoExA(patchcode, "6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
11990                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
11991                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11992     ok(r == ERROR_INVALID_PARAMETER,
11993        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11994     ok(!lstrcmpA(val, "apple"),
11995        "Expected val to be unchanged, got \"%s\"\n", val);
11996     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11997 
11998     /* guid with brackets */
11999     size = MAX_PATH;
12000     lstrcpyA(val, "apple");
12001     r = pMsiGetPatchInfoExA(patchcode, "{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
12002                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
12003                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12004     ok(r == ERROR_UNKNOWN_PRODUCT,
12005        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12006     ok(!lstrcmpA(val, "apple"),
12007        "Expected val to be unchanged, got \"%s\"\n", val);
12008     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12009 
12010     /* same length as guid, but random */
12011     size = MAX_PATH;
12012     lstrcpyA(val, "apple");
12013     r = pMsiGetPatchInfoExA(patchcode, "A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
12014                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
12015                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12016     ok(r == ERROR_INVALID_PARAMETER,
12017        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12018     ok(!lstrcmpA(val, "apple"),
12019        "Expected val to be unchanged, got \"%s\"\n", val);
12020     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12021 
12022     /* szUserSid cannot be S-1-5-18 for MSIINSTALLCONTEXT_USERMANAGED */
12023     size = MAX_PATH;
12024     lstrcpyA(val, "apple");
12025     r = pMsiGetPatchInfoExA(patchcode, prodcode, "S-1-5-18",
12026                             MSIINSTALLCONTEXT_USERMANAGED,
12027                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12028     ok(r == ERROR_INVALID_PARAMETER,
12029        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12030     ok(!lstrcmpA(val, "apple"),
12031        "Expected val to be unchanged, got \"%s\"\n", val);
12032     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12033 
12034     /* szUserSid cannot be S-1-5-18 for MSIINSTALLCONTEXT_USERUNMANAGED */
12035     size = MAX_PATH;
12036     lstrcpyA(val, "apple");
12037     r = pMsiGetPatchInfoExA(patchcode, prodcode, "S-1-5-18",
12038                             MSIINSTALLCONTEXT_USERUNMANAGED,
12039                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12040     ok(r == ERROR_INVALID_PARAMETER,
12041        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12042     ok(!lstrcmpA(val, "apple"),
12043        "Expected val to be unchanged, got \"%s\"\n", val);
12044     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12045 
12046     /* szUserSid cannot be S-1-5-18 for MSIINSTALLCONTEXT_MACHINE */
12047     size = MAX_PATH;
12048     lstrcpyA(val, "apple");
12049     r = pMsiGetPatchInfoExA(patchcode, prodcode, "S-1-5-18",
12050                             MSIINSTALLCONTEXT_MACHINE,
12051                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12052     ok(r == ERROR_INVALID_PARAMETER,
12053        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12054     ok(!lstrcmpA(val, "apple"),
12055        "Expected val to be unchanged, got \"%s\"\n", val);
12056     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12057 
12058     /* szUserSid must be NULL for MSIINSTALLCONTEXT_MACHINE */
12059     size = MAX_PATH;
12060     lstrcpyA(val, "apple");
12061     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12062                             MSIINSTALLCONTEXT_MACHINE,
12063                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12064     ok(r == ERROR_INVALID_PARAMETER,
12065        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12066     ok(!lstrcmpA(val, "apple"),
12067        "Expected val to be unchanged, got \"%s\"\n", val);
12068     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12069 
12070     /* dwContext is out of range */
12071     size = MAX_PATH;
12072     lstrcpyA(val, "apple");
12073     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12074                             MSIINSTALLCONTEXT_NONE,
12075                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12076     ok(r == ERROR_INVALID_PARAMETER,
12077        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12078     ok(!lstrcmpA(val, "apple"),
12079        "Expected val to be unchanged, got \"%s\"\n", val);
12080     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12081 
12082     /* dwContext is out of range */
12083     size = MAX_PATH;
12084     lstrcpyA(val, "apple");
12085     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12086                             MSIINSTALLCONTEXT_ALL,
12087                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12088     ok(r == ERROR_INVALID_PARAMETER,
12089        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12090     ok(!lstrcmpA(val, "apple"),
12091        "Expected val to be unchanged, got \"%s\"\n", val);
12092     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12093 
12094     /* dwContext is invalid */
12095     size = MAX_PATH;
12096     lstrcpyA(val, "apple");
12097     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid, 3,
12098                            INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12099     ok(r == ERROR_INVALID_PARAMETER,
12100        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12101     ok(!lstrcmpA(val, "apple"),
12102        "Expected val to be unchanged, got \"%s\"\n", val);
12103     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12104 
12105     /* MSIINSTALLCONTEXT_USERMANAGED */
12106 
12107     size = MAX_PATH;
12108     lstrcpyA(val, "apple");
12109     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12110                             MSIINSTALLCONTEXT_USERMANAGED,
12111                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12112     ok(r == ERROR_UNKNOWN_PRODUCT,
12113        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12114     ok(!lstrcmpA(val, "apple"),
12115        "Expected val to be unchanged, got \"%s\"\n", val);
12116     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12117 
12118     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
12119     lstrcatA(keypath, usersid);
12120     lstrcatA(keypath, "\\Products\\");
12121     lstrcatA(keypath, prod_squashed);
12122 
12123     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
12124     if (res == ERROR_ACCESS_DENIED)
12125     {
12126         skip("Not enough rights to perform tests\n");
12127         LocalFree(usersid);
12128         return;
12129     }
12130     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12131 
12132     /* local UserData product key exists */
12133     size = MAX_PATH;
12134     lstrcpyA(val, "apple");
12135     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12136                             MSIINSTALLCONTEXT_USERMANAGED,
12137                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12138     ok(r == ERROR_UNKNOWN_PRODUCT,
12139        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12140     ok(!lstrcmpA(val, "apple"),
12141        "Expected val to be unchanged, got \"%s\"\n", val);
12142     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12143 
12144     res = RegCreateKeyExA(udprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
12145     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12146 
12147     /* InstallProperties key exists */
12148     size = MAX_PATH;
12149     lstrcpyA(val, "apple");
12150     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12151                             MSIINSTALLCONTEXT_USERMANAGED,
12152                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12153     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, 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 %lu\n", size);
12157 
12158     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
12159     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12160 
12161     /* Patches key exists */
12162     size = MAX_PATH;
12163     lstrcpyA(val, "apple");
12164     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12165                             MSIINSTALLCONTEXT_USERMANAGED,
12166                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12167     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCHA, got %d\n", r);
12168     ok(!lstrcmpA(val, "apple"),
12169        "Expected val to be unchanged, got \"%s\"\n", val);
12170     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12171 
12172     res = RegCreateKeyExA(patches, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
12173     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12174 
12175     /* Patches key exists */
12176     size = MAX_PATH;
12177     lstrcpyA(val, "apple");
12178     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12179                             MSIINSTALLCONTEXT_USERMANAGED,
12180                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12181     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12182     ok(!lstrcmpA(val, "apple"),
12183        "Expected val to be unchanged, got \"%s\"\n", val);
12184     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12185 
12186     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
12187     lstrcatA(keypath, usersid);
12188     lstrcatA(keypath, "\\Installer\\Products\\");
12189     lstrcatA(keypath, prod_squashed);
12190 
12191     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
12192     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12193 
12194     /* managed product key exists */
12195     size = MAX_PATH;
12196     lstrcpyA(val, "apple");
12197     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12198                             MSIINSTALLCONTEXT_USERMANAGED,
12199                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12200     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12201     ok(!lstrcmpA(val, "apple"),
12202        "Expected val to be unchanged, got \"%s\"\n", val);
12203     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12204 
12205     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &prodpatches, NULL);
12206     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12207 
12208     /* Patches key exists */
12209     size = MAX_PATH;
12210     lstrcpyA(val, "apple");
12211     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12212                             MSIINSTALLCONTEXT_USERMANAGED,
12213                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12214     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12215     ok(!lstrcmpA(val, "apple"),
12216        "Expected val to be unchanged, got \"%s\"\n", val);
12217     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12218 
12219     res = RegSetValueExA(prodpatches, patch_squashed, 0, REG_SZ,
12220                          (const BYTE *)"transforms", 11);
12221     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12222 
12223     /* specific patch value exists */
12224     size = MAX_PATH;
12225     lstrcpyA(val, "apple");
12226     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12227                             MSIINSTALLCONTEXT_USERMANAGED,
12228                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12229     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12230     ok(!lstrcmpA(val, "apple"),
12231        "Expected val to be unchanged, got \"%s\"\n", val);
12232     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12233 
12234     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
12235     lstrcatA(keypath, usersid);
12236     lstrcatA(keypath, "\\Patches\\");
12237     lstrcatA(keypath, patch_squashed);
12238 
12239     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udpatch, NULL);
12240     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12241 
12242     /* UserData Patches key exists */
12243     size = MAX_PATH;
12244     lstrcpyA(val, "apple");
12245     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12246                             MSIINSTALLCONTEXT_USERMANAGED,
12247                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12248     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12249     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
12250     ok(size == 0, "Expected 0, got %lu\n", size);
12251 
12252     res = RegSetValueExA(udpatch, "ManagedLocalPackage", 0, REG_SZ,
12253                          (const BYTE *)"pack", 5);
12254     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12255 
12256     /* ManagedLocalPatch value exists */
12257     size = MAX_PATH;
12258     lstrcpyA(val, "apple");
12259     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12260                             MSIINSTALLCONTEXT_USERMANAGED,
12261                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12262     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12263     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12264     ok(size == 4, "Expected 4, got %lu\n", size);
12265 
12266     size = MAX_PATH;
12267     lstrcpyA(val, "apple");
12268     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12269                             MSIINSTALLCONTEXT_USERMANAGED,
12270                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12271     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12272     ok(!lstrcmpA(val, "transforms"), "Expected \"transforms\", got \"%s\"\n", val);
12273     ok(size == 10, "Expected 10, got %lu\n", size);
12274 
12275     res = RegSetValueExA(hpatch, "Installed", 0, REG_SZ,
12276                          (const BYTE *)"mydate", 7);
12277     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12278 
12279     /* Installed value exists */
12280     size = MAX_PATH;
12281     lstrcpyA(val, "apple");
12282     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12283                             MSIINSTALLCONTEXT_USERMANAGED,
12284                             INSTALLPROPERTY_INSTALLDATEA, val, &size);
12285     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12286     ok(!lstrcmpA(val, "mydate"), "Expected \"mydate\", got \"%s\"\n", val);
12287     ok(size == 6, "Expected 6, got %lu\n", size);
12288 
12289     res = RegSetValueExA(hpatch, "Uninstallable", 0, REG_SZ,
12290                          (const BYTE *)"yes", 4);
12291     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12292 
12293     /* Uninstallable value exists */
12294     size = MAX_PATH;
12295     lstrcpyA(val, "apple");
12296     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12297                             MSIINSTALLCONTEXT_USERMANAGED,
12298                             INSTALLPROPERTY_UNINSTALLABLEA, val, &size);
12299     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12300     ok(!lstrcmpA(val, "yes"), "Expected \"yes\", got \"%s\"\n", val);
12301     ok(size == 3, "Expected 3, got %lu\n", size);
12302 
12303     res = RegSetValueExA(hpatch, "State", 0, REG_SZ,
12304                          (const BYTE *)"good", 5);
12305     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12306 
12307     /* State value exists */
12308     size = MAX_PATH;
12309     lstrcpyA(val, "apple");
12310     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12311                             MSIINSTALLCONTEXT_USERMANAGED,
12312                             INSTALLPROPERTY_PATCHSTATEA, val, &size);
12313     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12314     ok(!lstrcmpA(val, "good"), "Expected \"good\", got \"%s\"\n", val);
12315     ok(size == 4, "Expected 4, got %lu\n", size);
12316 
12317     size = 1;
12318     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
12319                          (const BYTE *)&size, sizeof(DWORD));
12320     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12321 
12322     /* State value exists */
12323     size = MAX_PATH;
12324     lstrcpyA(val, "apple");
12325     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12326                             MSIINSTALLCONTEXT_USERMANAGED,
12327                             INSTALLPROPERTY_PATCHSTATEA, val, &size);
12328     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12329     ok(!lstrcmpA(val, "1"), "Expected \"1\", got \"%s\"\n", val);
12330     ok(size == 1, "Expected 1, got %lu\n", size);
12331 
12332     size = 1;
12333     res = RegSetValueExA(hpatch, "Uninstallable", 0, REG_DWORD,
12334                          (const BYTE *)&size, sizeof(DWORD));
12335     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12336 
12337     /* Uninstallable value exists */
12338     size = MAX_PATH;
12339     lstrcpyA(val, "apple");
12340     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12341                             MSIINSTALLCONTEXT_USERMANAGED,
12342                             INSTALLPROPERTY_UNINSTALLABLEA, val, &size);
12343     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12344     ok(!lstrcmpA(val, "1"), "Expected \"1\", got \"%s\"\n", val);
12345     ok(size == 1, "Expected 1, got %lu\n", size);
12346 
12347     res = RegSetValueExA(hpatch, "DisplayName", 0, REG_SZ,
12348                          (const BYTE *)"display", 8);
12349     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12350 
12351     /* DisplayName value exists */
12352     size = MAX_PATH;
12353     lstrcpyA(val, "apple");
12354     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12355                             MSIINSTALLCONTEXT_USERMANAGED,
12356                             INSTALLPROPERTY_DISPLAYNAMEA, val, &size);
12357     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12358     ok(!lstrcmpA(val, "display"), "Expected \"display\", got \"%s\"\n", val);
12359     ok(size == 7, "Expected 7, got %lu\n", size);
12360 
12361     res = RegSetValueExA(hpatch, "MoreInfoURL", 0, REG_SZ,
12362                          (const BYTE *)"moreinfo", 9);
12363     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12364 
12365     /* MoreInfoURL value exists */
12366     size = MAX_PATH;
12367     lstrcpyA(val, "apple");
12368     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12369                             MSIINSTALLCONTEXT_USERMANAGED,
12370                             INSTALLPROPERTY_MOREINFOURLA, val, &size);
12371     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12372     ok(!lstrcmpA(val, "moreinfo"), "Expected \"moreinfo\", got \"%s\"\n", val);
12373     ok(size == 8, "Expected 8, got %lu\n", size);
12374 
12375     /* szProperty is invalid */
12376     size = MAX_PATH;
12377     lstrcpyA(val, "apple");
12378     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12379                             MSIINSTALLCONTEXT_USERMANAGED,
12380                             "IDontExist", val, &size);
12381     ok(r == ERROR_UNKNOWN_PROPERTY,
12382        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
12383     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
12384     ok(size == MAX_PATH, "Expected MAX_PATH, got %lu\n", size);
12385 
12386     /* lpValue is NULL, while pcchValue is non-NULL */
12387     size = MAX_PATH;
12388     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12389                             MSIINSTALLCONTEXT_USERMANAGED,
12390                             INSTALLPROPERTY_MOREINFOURLA, NULL, &size);
12391     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12392     ok(size == 16, "Expected 16, got %lu\n", size);
12393 
12394     /* pcchValue is NULL, while lpValue is non-NULL */
12395     lstrcpyA(val, "apple");
12396     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12397                             MSIINSTALLCONTEXT_USERMANAGED,
12398                             INSTALLPROPERTY_MOREINFOURLA, val, NULL);
12399     ok(r == ERROR_INVALID_PARAMETER,
12400        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12401     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
12402 
12403     /* both lpValue and pcchValue are NULL */
12404     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12405                             MSIINSTALLCONTEXT_USERMANAGED,
12406                             INSTALLPROPERTY_MOREINFOURLA, NULL, NULL);
12407     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12408 
12409     /* pcchValue doesn't have enough room for NULL terminator */
12410     size = 8;
12411     lstrcpyA(val, "apple");
12412     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12413                             MSIINSTALLCONTEXT_USERMANAGED,
12414                             INSTALLPROPERTY_MOREINFOURLA, val, &size);
12415     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
12416     ok(!lstrcmpA(val, "moreinf"),
12417        "Expected \"moreinf\", got \"%s\"\n", val);
12418     ok(size == 16, "Expected 16, got %lu\n", size);
12419 
12420     /* pcchValue has exactly enough room for NULL terminator */
12421     size = 9;
12422     lstrcpyA(val, "apple");
12423     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12424                             MSIINSTALLCONTEXT_USERMANAGED,
12425                             INSTALLPROPERTY_MOREINFOURLA, val, &size);
12426     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12427     ok(!lstrcmpA(val, "moreinfo"),
12428        "Expected \"moreinfo\", got \"%s\"\n", val);
12429     ok(size == 8, "Expected 8, got %lu\n", size);
12430 
12431     /* pcchValue is too small, lpValue is NULL */
12432     size = 0;
12433     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12434                             MSIINSTALLCONTEXT_USERMANAGED,
12435                             INSTALLPROPERTY_MOREINFOURLA, NULL, &size);
12436     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12437     ok(size == 16, "Expected 16, got %lu\n", size);
12438 
12439     RegDeleteValueA(prodpatches, patch_squashed);
12440     delete_key(prodpatches, "", access & KEY_WOW64_64KEY);
12441     RegCloseKey(prodpatches);
12442     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
12443     RegCloseKey(prodkey);
12444 
12445     /* UserData is sufficient for all properties
12446      * except INSTALLPROPERTY_TRANSFORMS
12447      */
12448     size = MAX_PATH;
12449     lstrcpyA(val, "apple");
12450     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12451                             MSIINSTALLCONTEXT_USERMANAGED,
12452                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12453     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12454     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12455     ok(size == 4, "Expected 4, got %lu\n", size);
12456 
12457     /* UserData is sufficient for all properties
12458      * except INSTALLPROPERTY_TRANSFORMS
12459      */
12460     size = MAX_PATH;
12461     lstrcpyA(val, "apple");
12462     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12463                             MSIINSTALLCONTEXT_USERMANAGED,
12464                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12465     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12466     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
12467     ok(size == MAX_PATH, "Expected MAX_PATH, got %lu\n", size);
12468 
12469     RegDeleteValueA(hpatch, "MoreInfoURL");
12470     RegDeleteValueA(hpatch, "Display");
12471     RegDeleteValueA(hpatch, "State");
12472     RegDeleteValueA(hpatch, "Uninstallable");
12473     RegDeleteValueA(hpatch, "Installed");
12474     RegDeleteValueA(udpatch, "ManagedLocalPackage");
12475     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
12476     RegCloseKey(udpatch);
12477     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
12478     RegCloseKey(hpatch);
12479     delete_key(patches, "", access & KEY_WOW64_64KEY);
12480     RegCloseKey(patches);
12481     delete_key(props, "", access & KEY_WOW64_64KEY);
12482     RegCloseKey(props);
12483     delete_key(udprod, "", access & KEY_WOW64_64KEY);
12484     RegCloseKey(udprod);
12485 
12486     /* MSIINSTALLCONTEXT_USERUNMANAGED */
12487 
12488     size = MAX_PATH;
12489     lstrcpyA(val, "apple");
12490     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12491                             MSIINSTALLCONTEXT_USERUNMANAGED,
12492                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12493     ok(r == ERROR_UNKNOWN_PRODUCT,
12494        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12495     ok(!lstrcmpA(val, "apple"),
12496        "Expected val to be unchanged, got \"%s\"\n", val);
12497     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12498 
12499     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
12500     lstrcatA(keypath, usersid);
12501     lstrcatA(keypath, "\\Products\\");
12502     lstrcatA(keypath, prod_squashed);
12503 
12504     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
12505     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12506 
12507     /* local UserData product key exists */
12508     size = MAX_PATH;
12509     lstrcpyA(val, "apple");
12510     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12511                             MSIINSTALLCONTEXT_USERUNMANAGED,
12512                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12513     ok(r == ERROR_UNKNOWN_PRODUCT,
12514        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12515     ok(!lstrcmpA(val, "apple"),
12516        "Expected val to be unchanged, got \"%s\"\n", val);
12517     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12518 
12519     res = RegCreateKeyExA(udprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
12520     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12521 
12522     /* InstallProperties key exists */
12523     size = MAX_PATH;
12524     lstrcpyA(val, "apple");
12525     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12526                             MSIINSTALLCONTEXT_USERUNMANAGED,
12527                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12528     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12529     ok(!lstrcmpA(val, "apple"),
12530        "Expected val to be unchanged, got \"%s\"\n", val);
12531     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12532 
12533     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
12534     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12535 
12536     /* Patches key exists */
12537     size = MAX_PATH;
12538     lstrcpyA(val, "apple");
12539     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12540                             MSIINSTALLCONTEXT_USERUNMANAGED,
12541                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12542     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12543     ok(!lstrcmpA(val, "apple"),
12544        "Expected val to be unchanged, got \"%s\"\n", val);
12545     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12546 
12547     res = RegCreateKeyExA(patches, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
12548     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12549 
12550     /* Patches key exists */
12551     size = MAX_PATH;
12552     lstrcpyA(val, "apple");
12553     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12554                             MSIINSTALLCONTEXT_USERUNMANAGED,
12555                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12556     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12557     ok(!lstrcmpA(val, "apple"),
12558        "Expected val to be unchanged, got \"%s\"\n", val);
12559     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12560 
12561     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
12562     lstrcatA(keypath, prod_squashed);
12563 
12564     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
12565     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12566 
12567     /* current user product key exists */
12568     size = MAX_PATH;
12569     lstrcpyA(val, "apple");
12570     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12571                             MSIINSTALLCONTEXT_USERUNMANAGED,
12572                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12573     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12574     ok(!lstrcmpA(val, "apple"),
12575        "Expected val to be unchanged, got \"%s\"\n", val);
12576     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12577 
12578     res = RegCreateKeyA(prodkey, "Patches", &prodpatches);
12579     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12580 
12581     /* Patches key exists */
12582     size = MAX_PATH;
12583     lstrcpyA(val, "apple");
12584     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12585                             MSIINSTALLCONTEXT_USERUNMANAGED,
12586                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12587     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12588     ok(!lstrcmpA(val, "apple"),
12589        "Expected val to be unchanged, got \"%s\"\n", val);
12590     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12591 
12592     res = RegSetValueExA(prodpatches, patch_squashed, 0, REG_SZ,
12593                          (const BYTE *)"transforms", 11);
12594     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12595 
12596     /* specific patch value exists */
12597     size = MAX_PATH;
12598     lstrcpyA(val, "apple");
12599     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12600                             MSIINSTALLCONTEXT_USERUNMANAGED,
12601                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12602     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12603     ok(!lstrcmpA(val, "apple"),
12604        "Expected val to be unchanged, got \"%s\"\n", val);
12605     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12606 
12607     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
12608     lstrcatA(keypath, usersid);
12609     lstrcatA(keypath, "\\Patches\\");
12610     lstrcatA(keypath, patch_squashed);
12611 
12612     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udpatch, NULL);
12613     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12614 
12615     /* UserData Patches key exists */
12616     size = MAX_PATH;
12617     lstrcpyA(val, "apple");
12618     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12619                             MSIINSTALLCONTEXT_USERUNMANAGED,
12620                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12621     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12622     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
12623     ok(size == 0, "Expected 0, got %lu\n", size);
12624 
12625     res = RegSetValueExA(udpatch, "LocalPackage", 0, REG_SZ,
12626                          (const BYTE *)"pack", 5);
12627     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12628 
12629     /* LocalPatch value exists */
12630     size = MAX_PATH;
12631     lstrcpyA(val, "apple");
12632     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12633                             MSIINSTALLCONTEXT_USERUNMANAGED,
12634                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12635     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12636     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12637     ok(size == 4, "Expected 4, got %lu\n", size);
12638 
12639     size = MAX_PATH;
12640     lstrcpyA(val, "apple");
12641     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12642                             MSIINSTALLCONTEXT_USERUNMANAGED,
12643                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12644     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12645     ok(!lstrcmpA(val, "transforms"), "Expected \"transforms\", got \"%s\"\n", val);
12646     ok(size == 10, "Expected 10, got %lu\n", size);
12647 
12648     RegDeleteValueA(prodpatches, patch_squashed);
12649     delete_key(prodpatches, "", access & KEY_WOW64_64KEY);
12650     RegCloseKey(prodpatches);
12651     RegDeleteKeyA(prodkey, "");
12652     RegCloseKey(prodkey);
12653 
12654     /* UserData is sufficient for all properties
12655      * except INSTALLPROPERTY_TRANSFORMS
12656      */
12657     size = MAX_PATH;
12658     lstrcpyA(val, "apple");
12659     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12660                             MSIINSTALLCONTEXT_USERUNMANAGED,
12661                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12662     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12663     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12664     ok(size == 4, "Expected 4, got %lu\n", size);
12665 
12666     /* UserData is sufficient for all properties
12667      * except INSTALLPROPERTY_TRANSFORMS
12668      */
12669     size = MAX_PATH;
12670     lstrcpyA(val, "apple");
12671     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12672                             MSIINSTALLCONTEXT_USERUNMANAGED,
12673                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12674     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12675     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
12676     ok(size == MAX_PATH, "Expected MAX_PATH, got %lu\n", size);
12677 
12678     RegDeleteValueA(udpatch, "LocalPackage");
12679     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
12680     RegCloseKey(udpatch);
12681     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
12682     RegCloseKey(hpatch);
12683     delete_key(patches, "", access & KEY_WOW64_64KEY);
12684     RegCloseKey(patches);
12685     delete_key(props, "", access & KEY_WOW64_64KEY);
12686     RegCloseKey(props);
12687     delete_key(udprod, "", access & KEY_WOW64_64KEY);
12688     RegCloseKey(udprod);
12689 
12690     /* MSIINSTALLCONTEXT_MACHINE */
12691 
12692     size = MAX_PATH;
12693     lstrcpyA(val, "apple");
12694     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12695                             MSIINSTALLCONTEXT_MACHINE,
12696                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12697     ok(r == ERROR_UNKNOWN_PRODUCT,
12698        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12699     ok(!lstrcmpA(val, "apple"),
12700        "Expected val to be unchanged, got \"%s\"\n", val);
12701     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12702 
12703     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
12704     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Products\\");
12705     lstrcatA(keypath, prod_squashed);
12706 
12707     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
12708     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12709 
12710     /* local UserData product key exists */
12711     size = MAX_PATH;
12712     lstrcpyA(val, "apple");
12713     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12714                             MSIINSTALLCONTEXT_MACHINE,
12715                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12716     ok(r == ERROR_UNKNOWN_PRODUCT,
12717        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12718     ok(!lstrcmpA(val, "apple"),
12719        "Expected val to be unchanged, got \"%s\"\n", val);
12720     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12721 
12722     res = RegCreateKeyExA(udprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
12723     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12724 
12725     /* InstallProperties key exists */
12726     size = MAX_PATH;
12727     lstrcpyA(val, "apple");
12728     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12729                             MSIINSTALLCONTEXT_MACHINE,
12730                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12731     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12732     ok(!lstrcmpA(val, "apple"),
12733        "Expected val to be unchanged, got \"%s\"\n", val);
12734     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12735 
12736     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
12737     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12738 
12739     /* Patches key exists */
12740     size = MAX_PATH;
12741     lstrcpyA(val, "apple");
12742     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12743                             MSIINSTALLCONTEXT_MACHINE,
12744                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12745     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12746     ok(!lstrcmpA(val, "apple"),
12747        "Expected val to be unchanged, got \"%s\"\n", val);
12748     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12749 
12750     res = RegCreateKeyExA(patches, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
12751     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12752 
12753     /* Patches key exists */
12754     size = MAX_PATH;
12755     lstrcpyA(val, "apple");
12756     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12757                             MSIINSTALLCONTEXT_MACHINE,
12758                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12759     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12760     ok(!lstrcmpA(val, "apple"),
12761        "Expected val to be unchanged, got \"%s\"\n", val);
12762     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12763 
12764     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
12765     lstrcatA(keypath, prod_squashed);
12766 
12767     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
12768     if (res == ERROR_ACCESS_DENIED)
12769     {
12770         skip( "insufficient rights\n" );
12771         LocalFree( usersid );
12772         return;
12773     }
12774     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12775 
12776     /* local product key exists */
12777     size = MAX_PATH;
12778     lstrcpyA(val, "apple");
12779     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12780                             MSIINSTALLCONTEXT_MACHINE,
12781                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12782     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12783     ok(!lstrcmpA(val, "apple"),
12784        "Expected val to be unchanged, got \"%s\"\n", val);
12785     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12786 
12787     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &prodpatches, NULL);
12788     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12789 
12790     /* Patches key exists */
12791     size = MAX_PATH;
12792     lstrcpyA(val, "apple");
12793     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12794                             MSIINSTALLCONTEXT_MACHINE,
12795                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12796     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12797     ok(!lstrcmpA(val, "apple"),
12798        "Expected val to be unchanged, got \"%s\"\n", val);
12799     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12800 
12801     res = RegSetValueExA(prodpatches, patch_squashed, 0, REG_SZ,
12802                          (const BYTE *)"transforms", 11);
12803     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12804 
12805     /* specific patch value exists */
12806     size = MAX_PATH;
12807     lstrcpyA(val, "apple");
12808     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12809                             MSIINSTALLCONTEXT_MACHINE,
12810                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12811     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12812     ok(!lstrcmpA(val, "apple"),
12813        "Expected val to be unchanged, got \"%s\"\n", val);
12814     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
12815 
12816     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
12817     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Patches\\");
12818     lstrcatA(keypath, patch_squashed);
12819 
12820     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udpatch, NULL);
12821     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12822 
12823     /* UserData Patches key exists */
12824     size = MAX_PATH;
12825     lstrcpyA(val, "apple");
12826     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12827                             MSIINSTALLCONTEXT_MACHINE,
12828                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12829     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12830     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
12831     ok(size == 0, "Expected 0, got %lu\n", size);
12832 
12833     res = RegSetValueExA(udpatch, "LocalPackage", 0, REG_SZ,
12834                          (const BYTE *)"pack", 5);
12835     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12836 
12837     /* LocalPatch value exists */
12838     size = MAX_PATH;
12839     lstrcpyA(val, "apple");
12840     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12841                             MSIINSTALLCONTEXT_MACHINE,
12842                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12843     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12844     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12845     ok(size == 4, "Expected 4, got %lu\n", size);
12846 
12847     size = MAX_PATH;
12848     lstrcpyA(val, "apple");
12849     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12850                             MSIINSTALLCONTEXT_MACHINE,
12851                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12852     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12853     ok(!lstrcmpA(val, "transforms"), "Expected \"transforms\", got \"%s\"\n", val);
12854     ok(size == 10, "Expected 10, got %lu\n", size);
12855 
12856     RegDeleteValueA(prodpatches, patch_squashed);
12857     delete_key(prodpatches, "", access & KEY_WOW64_64KEY);
12858     RegCloseKey(prodpatches);
12859     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
12860     RegCloseKey(prodkey);
12861 
12862     /* UserData is sufficient for all properties
12863      * except INSTALLPROPERTY_TRANSFORMS
12864      */
12865     size = MAX_PATH;
12866     lstrcpyA(val, "apple");
12867     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12868                             MSIINSTALLCONTEXT_MACHINE,
12869                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12870     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12871     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12872     ok(size == 4, "Expected 4, got %lu\n", size);
12873 
12874     /* UserData is sufficient for all properties
12875      * except INSTALLPROPERTY_TRANSFORMS
12876      */
12877     size = MAX_PATH;
12878     lstrcpyA(val, "apple");
12879     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12880                             MSIINSTALLCONTEXT_MACHINE,
12881                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12882     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12883     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
12884     ok(size == MAX_PATH, "Expected MAX_PATH, got %lu\n", size);
12885 
12886     RegDeleteValueA(udpatch, "LocalPackage");
12887     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
12888     RegCloseKey(udpatch);
12889     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
12890     RegCloseKey(hpatch);
12891     delete_key(patches, "", access & KEY_WOW64_64KEY);
12892     RegCloseKey(patches);
12893     delete_key(props, "", access & KEY_WOW64_64KEY);
12894     RegCloseKey(props);
12895     delete_key(udprod, "", access & KEY_WOW64_64KEY);
12896     RegCloseKey(udprod);
12897     LocalFree(usersid);
12898 }
12899 
12900 static void test_MsiGetPatchInfo(void)
12901 {
12902     UINT r;
12903     char prod_code[MAX_PATH], prod_squashed[MAX_PATH], val[MAX_PATH];
12904     char patch_code[MAX_PATH], patch_squashed[MAX_PATH], keypath[MAX_PATH];
12905     WCHAR valW[MAX_PATH], patch_codeW[MAX_PATH];
12906     HKEY hkey_product, hkey_patch, hkey_patches, hkey_udprops, hkey_udproduct;
12907     HKEY hkey_udpatch, hkey_udpatches, hkey_udproductpatches, hkey_udproductpatch;
12908     DWORD size;
12909     LONG res;
12910     REGSAM access = KEY_ALL_ACCESS;
12911 
12912     create_test_guid(patch_code, patch_squashed);
12913     create_test_guid(prod_code, prod_squashed);
12914     MultiByteToWideChar(CP_ACP, 0, patch_code, -1, patch_codeW, MAX_PATH);
12915 
12916     if (is_wow64)
12917         access |= KEY_WOW64_64KEY;
12918 
12919     r = MsiGetPatchInfoA(NULL, NULL, NULL, NULL);
12920     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
12921 
12922     r = MsiGetPatchInfoA(patch_code, NULL, NULL, NULL);
12923     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
12924 
12925     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, NULL, NULL);
12926     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
12927 
12928     size = 0;
12929     r = MsiGetPatchInfoA(patch_code, NULL, NULL, &size);
12930     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
12931 
12932     r = MsiGetPatchInfoA(patch_code, "", NULL, &size);
12933     ok(r == ERROR_UNKNOWN_PROPERTY, "expected ERROR_UNKNOWN_PROPERTY, got %u\n", r);
12934 
12935     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
12936     lstrcatA(keypath, prod_squashed);
12937 
12938     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey_product, NULL);
12939     if (res == ERROR_ACCESS_DENIED)
12940     {
12941         skip("Not enough rights to perform tests\n");
12942         return;
12943     }
12944     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %ld\n", res);
12945 
12946     /* product key exists */
12947     size = MAX_PATH;
12948     lstrcpyA(val, "apple");
12949     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12950     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
12951     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged, got \"%s\"\n", val);
12952     ok(size == MAX_PATH, "expected size to be unchanged got %lu\n", size);
12953 
12954     res = RegCreateKeyExA(hkey_product, "Patches", 0, NULL, 0, access, NULL, &hkey_patches, NULL);
12955     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %ld\n", res);
12956 
12957     /* patches key exists */
12958     size = MAX_PATH;
12959     lstrcpyA(val, "apple");
12960     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12961     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
12962     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
12963     ok(size == MAX_PATH, "expected size to be unchanged got %lu\n", size);
12964 
12965     res = RegCreateKeyExA(hkey_patches, patch_squashed, 0, NULL, 0, access, NULL, &hkey_patch, NULL);
12966     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %ld\n", res);
12967 
12968     /* patch key exists */
12969     size = MAX_PATH;
12970     lstrcpyA(val, "apple");
12971     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12972     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
12973     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
12974     ok(size == MAX_PATH, "expected size to be unchanged got %lu\n", size);
12975 
12976     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
12977     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Products\\");
12978     lstrcatA(keypath, prod_squashed);
12979 
12980     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey_udproduct, NULL);
12981     if (res == ERROR_ACCESS_DENIED)
12982     {
12983         skip("Not enough rights to perform tests\n");
12984         goto done;
12985     }
12986     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %ld\n", res);
12987 
12988     /* UserData product key exists */
12989     size = MAX_PATH;
12990     lstrcpyA(val, "apple");
12991     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12992     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
12993     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
12994     ok(size == MAX_PATH, "expected size to be unchanged got %lu\n", size);
12995 
12996     res = RegCreateKeyExA(hkey_udproduct, "InstallProperties", 0, NULL, 0, access, NULL, &hkey_udprops, NULL);
12997     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %ld\n", res);
12998 
12999     /* InstallProperties key exists */
13000     size = MAX_PATH;
13001     lstrcpyA(val, "apple");
13002     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13003     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13004     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged, got \"%s\"\n", val);
13005     ok(size == MAX_PATH, "expected size to be unchanged got %lu\n", size);
13006 
13007     res = RegCreateKeyExA(hkey_udproduct, "Patches", 0, NULL, 0, access, NULL, &hkey_udpatches, NULL);
13008     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %ld\n", res);
13009 
13010     /* UserData Patches key exists */
13011     size = MAX_PATH;
13012     lstrcpyA(val, "apple");
13013     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13014     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13015     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
13016     ok(size == MAX_PATH, "expected size to be unchanged got %lu\n", size);
13017 
13018     res = RegCreateKeyExA(hkey_udproduct, "Patches", 0, NULL, 0, access, NULL, &hkey_udproductpatches, NULL);
13019     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
13020 
13021     res = RegCreateKeyExA(hkey_udproductpatches, patch_squashed, 0, NULL, 0, access, NULL, &hkey_udproductpatch, NULL);
13022     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
13023 
13024     /* UserData product patch key exists */
13025     size = MAX_PATH;
13026     lstrcpyA(val, "apple");
13027     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13028     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13029     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
13030     ok(size == MAX_PATH, "expected size to be unchanged got %lu\n", size);
13031 
13032     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
13033     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Patches\\");
13034     lstrcatA(keypath, patch_squashed);
13035 
13036     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey_udpatch, NULL);
13037     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %ld\n", res);
13038 
13039     res = RegSetValueExA(hkey_udpatch, "LocalPackage", 0, REG_SZ, (const BYTE *)"c:\\test.msp", 12);
13040     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %ld\n", res);
13041 
13042     /* UserData Patch key exists */
13043     size = 0;
13044     lstrcpyA(val, "apple");
13045     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13046     ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", r);
13047     ok(!lstrcmpA(val, "apple"), "expected \"apple\", got \"%s\"\n", val);
13048     ok(size == 11, "expected 11 got %lu\n", size);
13049 
13050     size = MAX_PATH;
13051     lstrcpyA(val, "apple");
13052     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13053     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS got %u\n", r);
13054     ok(!lstrcmpA(val, "c:\\test.msp"), "expected \"c:\\test.msp\", got \"%s\"\n", val);
13055     ok(size == 11, "expected 11 got %lu\n", size);
13056 
13057     size = 0;
13058     valW[0] = 0;
13059     r = MsiGetPatchInfoW(patch_codeW, INSTALLPROPERTY_LOCALPACKAGEW, valW, &size);
13060     ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", r);
13061     ok(!valW[0], "expected 0 got %u\n", valW[0]);
13062     ok(size == 11, "expected 11 got %lu\n", size);
13063 
13064     size = MAX_PATH;
13065     valW[0] = 0;
13066     r = MsiGetPatchInfoW(patch_codeW, INSTALLPROPERTY_LOCALPACKAGEW, valW, &size);
13067     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS got %u\n", r);
13068     ok(valW[0], "expected > 0 got %u\n", valW[0]);
13069     ok(size == 11, "expected 11 got %lu\n", size);
13070 
13071     delete_key(hkey_udproductpatch, "", access & KEY_WOW64_64KEY);
13072     RegCloseKey(hkey_udproductpatch);
13073     delete_key(hkey_udproductpatches, "", access & KEY_WOW64_64KEY);
13074     RegCloseKey(hkey_udproductpatches);
13075     delete_key(hkey_udpatch, "", access & KEY_WOW64_64KEY);
13076     RegCloseKey(hkey_udpatch);
13077     delete_key(hkey_udpatches, "", access & KEY_WOW64_64KEY);
13078     RegCloseKey(hkey_udpatches);
13079     delete_key(hkey_udprops, "", access & KEY_WOW64_64KEY);
13080     RegCloseKey(hkey_udprops);
13081     delete_key(hkey_udproduct, "", access & KEY_WOW64_64KEY);
13082     RegCloseKey(hkey_udproduct);
13083 
13084 done:
13085     delete_key(hkey_patches, "", access & KEY_WOW64_64KEY);
13086     RegCloseKey(hkey_patches);
13087     delete_key(hkey_product, "", access & KEY_WOW64_64KEY);
13088     RegCloseKey(hkey_product);
13089     delete_key(hkey_patch, "", access & KEY_WOW64_64KEY);
13090     RegCloseKey(hkey_patch);
13091 }
13092 
13093 static void test_MsiEnumProducts(void)
13094 {
13095     UINT r;
13096     BOOL found1, found2, found3;
13097     DWORD index;
13098     char product1[39], product2[39], product3[39], guid[39];
13099     char product_squashed1[33], product_squashed2[33], product_squashed3[33];
13100     char keypath1[MAX_PATH], keypath2[MAX_PATH], keypath3[MAX_PATH];
13101     char *usersid;
13102     HKEY key1, key2, key3;
13103     REGSAM access = KEY_ALL_ACCESS;
13104 
13105     if (is_process_limited())
13106     {
13107         skip( "process is limited\n" );
13108         return;
13109     }
13110 
13111     create_test_guid(product1, product_squashed1);
13112     create_test_guid(product2, product_squashed2);
13113     create_test_guid(product3, product_squashed3);
13114     usersid = get_user_sid();
13115 
13116     if (is_wow64)
13117         access |= KEY_WOW64_64KEY;
13118 
13119     strcpy(keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
13120     strcat(keypath2, usersid);
13121     strcat(keypath2, "\\Installer\\Products\\");
13122     strcat(keypath2, product_squashed2);
13123 
13124     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL);
13125     if (r == ERROR_ACCESS_DENIED)
13126     {
13127         skip("Not enough rights to perform tests\n");
13128         LocalFree(usersid);
13129         return;
13130     }
13131     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13132 
13133     strcpy(keypath1, "Software\\Classes\\Installer\\Products\\");
13134     strcat(keypath1, product_squashed1);
13135 
13136     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL);
13137     if (r == ERROR_ACCESS_DENIED)
13138     {
13139         skip( "insufficient rights\n" );
13140         LocalFree( usersid );
13141         return;
13142     }
13143     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13144 
13145     strcpy(keypath3, "Software\\Microsoft\\Installer\\Products\\");
13146     strcat(keypath3, product_squashed3);
13147 
13148     r = RegCreateKeyA(HKEY_CURRENT_USER, keypath3, &key3);
13149     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13150 
13151     index = 0;
13152     r = MsiEnumProductsA(index, guid);
13153     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13154 
13155     r = MsiEnumProductsA(index, NULL);
13156     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
13157 
13158     index = 2;
13159     r = MsiEnumProductsA(index, guid);
13160     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
13161 
13162     index = 0;
13163     r = MsiEnumProductsA(index, guid);
13164     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13165 
13166     found1 = found2 = found3 = FALSE;
13167     while ((r = MsiEnumProductsA(index, guid)) == ERROR_SUCCESS)
13168     {
13169         if (!strcmp(product1, guid)) found1 = TRUE;
13170         if (!strcmp(product2, guid)) found2 = TRUE;
13171         if (!strcmp(product3, guid)) found3 = TRUE;
13172         if (found1 && found2 && found3) break;
13173         index++;
13174     }
13175     ok(found1, "product1 not found\n");
13176     ok(found2, "product2 not found\n");
13177     ros_skip_flaky
13178     ok(found3, "product3 not found\n");
13179 
13180     delete_key(key1, "", access & KEY_WOW64_64KEY);
13181     delete_key(key2, "", access & KEY_WOW64_64KEY);
13182     RegDeleteKeyA(key3, "");
13183     RegCloseKey(key1);
13184     RegCloseKey(key2);
13185     RegCloseKey(key3);
13186     LocalFree(usersid);
13187 }
13188 
13189 static void test_MsiGetFileSignatureInformation(void)
13190 {
13191     HRESULT hr;
13192     const CERT_CONTEXT *cert;
13193     DWORD len;
13194 
13195     hr = MsiGetFileSignatureInformationA( NULL, 0, NULL, NULL, NULL );
13196     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %#lx\n", hr);
13197 
13198     hr = MsiGetFileSignatureInformationA( NULL, 0, NULL, NULL, &len );
13199     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %#lx\n", hr);
13200 
13201     hr = MsiGetFileSignatureInformationA( NULL, 0, &cert, NULL, &len );
13202     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %#lx\n", hr);
13203 
13204     hr = MsiGetFileSignatureInformationA( "", 0, NULL, NULL, NULL );
13205     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %#lx\n", hr);
13206 
13207     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, NULL );
13208     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %#lx\n", hr);
13209 
13210     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, &len );
13211     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %#lx\n", hr);
13212 
13213     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, &cert, NULL, &len );
13214     todo_wine ok(hr == CRYPT_E_FILE_ERROR, "expected CRYPT_E_FILE_ERROR got %#lx\n", hr);
13215 
13216     create_file_data( "signature.bin", "signature", sizeof("signature") );
13217 
13218     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, NULL );
13219     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %#lx\n", hr);
13220 
13221     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, &len );
13222     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %#lx\n", hr);
13223 
13224     cert = (const CERT_CONTEXT *)0xdeadbeef;
13225     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, &cert, NULL, &len );
13226     todo_wine ok(hr == HRESULT_FROM_WIN32(ERROR_FUNCTION_FAILED), "got %#lx\n", hr);
13227     ok(cert == NULL, "got %p\n", cert);
13228 
13229     DeleteFileA( "signature.bin" );
13230 }
13231 
13232 static void test_MsiEnumProductsEx(void)
13233 {
13234     UINT r;
13235     DWORD len, index;
13236     MSIINSTALLCONTEXT context;
13237     char product0[39], product1[39], product2[39], product3[39], guid[39], sid[128];
13238     char product_squashed1[33], product_squashed2[33], product_squashed3[33];
13239     char keypath1[MAX_PATH], keypath2[MAX_PATH], keypath3[MAX_PATH];
13240     HKEY key1 = NULL, key2 = NULL, key3 = NULL;
13241     REGSAM access = KEY_ALL_ACCESS;
13242     char *usersid = get_user_sid();
13243     BOOL found1, found2, found3;
13244 
13245     if (!pMsiEnumProductsExA)
13246     {
13247         win_skip("MsiEnumProductsExA not implemented\n");
13248         return;
13249     }
13250 
13251     create_test_guid( product0, NULL );
13252     create_test_guid( product1, product_squashed1 );
13253     create_test_guid( product2, product_squashed2 );
13254     create_test_guid( product3, product_squashed3 );
13255 
13256     if (is_wow64) access |= KEY_WOW64_64KEY;
13257 
13258     strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\" );
13259     strcat( keypath2, usersid );
13260     strcat( keypath2, "\\Installer\\Products\\" );
13261     strcat( keypath2, product_squashed2 );
13262 
13263     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
13264     if (r == ERROR_ACCESS_DENIED)
13265     {
13266         skip( "insufficient rights\n" );
13267         goto done;
13268     }
13269     ok( r == ERROR_SUCCESS, "got %u\n", r );
13270 
13271     strcpy( keypath1, "Software\\Classes\\Installer\\Products\\" );
13272     strcat( keypath1, product_squashed1 );
13273 
13274     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
13275     if (r == ERROR_ACCESS_DENIED)
13276     {
13277         skip( "insufficient rights\n" );
13278         goto done;
13279     }
13280     ok( r == ERROR_SUCCESS, "got %u\n", r );
13281 
13282     strcpy( keypath3, usersid );
13283     strcat( keypath3, "\\Software\\Microsoft\\Installer\\Products\\" );
13284     strcat( keypath3, product_squashed3 );
13285 
13286     r = RegCreateKeyExA( HKEY_USERS, keypath3, 0, NULL, 0, access, NULL, &key3, NULL );
13287     ok( r == ERROR_SUCCESS, "got %u\n", r );
13288 
13289     r = pMsiEnumProductsExA( NULL, NULL, 0, 0, NULL, NULL, NULL, NULL );
13290     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13291 
13292     len = sizeof(sid);
13293     r = pMsiEnumProductsExA( NULL, NULL, 0, 0, NULL, NULL, NULL, &len );
13294     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13295     ok( len == sizeof(sid), "got %lu\n", len );
13296 
13297     r = pMsiEnumProductsExA( NULL, NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, NULL, NULL );
13298     ok( r == ERROR_SUCCESS, "got %u\n", r );
13299 
13300     sid[0] = 0;
13301     len = sizeof(sid);
13302     r = pMsiEnumProductsExA( product0, NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, &len );
13303     ok( r == ERROR_NO_MORE_ITEMS, "got %u\n", r );
13304     ok( len == sizeof(sid), "got %lu\n", len );
13305     ok( !sid[0], "got %s\n", sid );
13306 
13307     sid[0] = 0;
13308     len = sizeof(sid);
13309     r = pMsiEnumProductsExA( product0, usersid, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, &len );
13310     ok( r == ERROR_NO_MORE_ITEMS, "got %u\n", r );
13311     ok( len == sizeof(sid), "got %lu\n", len );
13312     ok( !sid[0], "got %s\n", sid );
13313 
13314     sid[0] = 0;
13315     len = 0;
13316     r = pMsiEnumProductsExA( NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, 0, NULL, NULL, sid, &len );
13317     ok( r == ERROR_MORE_DATA, "got %u\n", r );
13318     ok( len, "length unchanged\n" );
13319     ok( !sid[0], "got %s\n", sid );
13320 
13321     guid[0] = 0;
13322     context = 0xdeadbeef;
13323     sid[0] = 0;
13324     len = sizeof(sid);
13325     r = pMsiEnumProductsExA( NULL, NULL, MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
13326     ok( r == ERROR_SUCCESS, "got %u\n", r );
13327     ok( guid[0], "empty guid\n" );
13328     ok( context != 0xdeadbeef, "context unchanged\n" );
13329     ok( !len, "got %lu\n", len );
13330     ok( !sid[0], "got %s\n", sid );
13331 
13332     guid[0] = 0;
13333     context = 0xdeadbeef;
13334     sid[0] = 0;
13335     len = sizeof(sid);
13336     r = pMsiEnumProductsExA( NULL, usersid, MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
13337     ok( r == ERROR_SUCCESS, "got %u\n", r );
13338     ok( guid[0], "empty guid\n" );
13339     ok( context != 0xdeadbeef, "context unchanged\n" );
13340     ok( !len, "got %lu\n", len );
13341     ok( !sid[0], "got %s\n", sid );
13342 
13343     guid[0] = 0;
13344     context = 0xdeadbeef;
13345     sid[0] = 0;
13346     len = sizeof(sid);
13347     r = pMsiEnumProductsExA( NULL, "S-1-1-0", MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
13348     if (r == ERROR_ACCESS_DENIED)
13349     {
13350         skip( "insufficient rights\n" );
13351         goto done;
13352     }
13353     ok( r == ERROR_SUCCESS, "got %u\n", r );
13354     ok( guid[0], "empty guid\n" );
13355     ok( context != 0xdeadbeef, "context unchanged\n" );
13356     ok( !len, "got %lu\n", len );
13357     ok( !sid[0], "got %s\n", sid );
13358 
13359     index = 0;
13360     guid[0] = 0;
13361     context = 0xdeadbeef;
13362     sid[0] = 0;
13363     len = sizeof(sid);
13364     found1 = found2 = found3 = FALSE;
13365     while (!pMsiEnumProductsExA( NULL, "S-1-1-0", MSIINSTALLCONTEXT_ALL, index, guid, &context, sid, &len ))
13366     {
13367         if (!strcmp( product1, guid ))
13368         {
13369             ok( context == MSIINSTALLCONTEXT_MACHINE, "got %u\n", context );
13370             ok( !sid[0], "got \"%s\"\n", sid );
13371             ok( !len, "unexpected length %lu\n", len );
13372             found1 = TRUE;
13373         }
13374         if (!strcmp( product2, guid ))
13375         {
13376             ok( context == MSIINSTALLCONTEXT_USERMANAGED, "got %u\n", context );
13377             ok( sid[0], "empty sid\n" );
13378             ok( len == strlen(sid), "unexpected length %lu\n", len );
13379             found2 = TRUE;
13380         }
13381         if (!strcmp( product3, guid ))
13382         {
13383             ok( context == MSIINSTALLCONTEXT_USERUNMANAGED, "got %u\n", context );
13384             ok( sid[0], "empty sid\n" );
13385             ok( len == strlen(sid), "unexpected length %lu\n", len );
13386             found3 = TRUE;
13387         }
13388         if (found1 && found2 && found3) break;
13389         index++;
13390         guid[0] = 0;
13391         context = 0xdeadbeef;
13392         sid[0] = 0;
13393         len = sizeof(sid);
13394     }
13395     ok(found1, "product1 not found\n");
13396     ok(found2, "product2 not found\n");
13397     ok(found3, "product3 not found\n");
13398 
13399 done:
13400     delete_key( key1, "", access );
13401     delete_key( key2, "", access );
13402     delete_key( key3, "", access );
13403     RegCloseKey( key1 );
13404     RegCloseKey( key2 );
13405     RegCloseKey( key3 );
13406     LocalFree( usersid );
13407 }
13408 
13409 static void test_MsiEnumComponents(void)
13410 {
13411     UINT r;
13412     BOOL found1, found2;
13413     DWORD index;
13414     char comp1[39], comp2[39], guid[39];
13415     char comp_squashed1[33], comp_squashed2[33];
13416     char keypath1[MAX_PATH], keypath2[MAX_PATH];
13417     REGSAM access = KEY_ALL_ACCESS;
13418     char *usersid = get_user_sid();
13419     HKEY key1 = NULL, key2 = NULL;
13420 
13421     if (is_process_limited())
13422     {
13423         skip("process is limited\n");
13424         return;
13425     }
13426 
13427     create_test_guid( comp1, comp_squashed1 );
13428     create_test_guid( comp2, comp_squashed2 );
13429 
13430     if (is_wow64) access |= KEY_WOW64_64KEY;
13431 
13432     strcpy( keypath1, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
13433     strcat( keypath1, "S-1-5-18\\Components\\" );
13434     strcat( keypath1, comp_squashed1 );
13435 
13436     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
13437     if (r == ERROR_ACCESS_DENIED)
13438     {
13439         skip( "insufficient rights\n" );
13440         goto done;
13441     }
13442     ok( r == ERROR_SUCCESS, "got %u\n", r );
13443 
13444     strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
13445     strcat( keypath2, usersid );
13446     strcat( keypath2, "\\Components\\" );
13447     strcat( keypath2, comp_squashed2 );
13448 
13449     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
13450     if (r == ERROR_ACCESS_DENIED)
13451     {
13452         skip( "insufficient rights\n" );
13453         goto done;
13454     }
13455 
13456     r = MsiEnumComponentsA( 0, NULL );
13457     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13458 
13459     index = 0;
13460     guid[0] = 0;
13461     found1 = found2 = FALSE;
13462     while (!MsiEnumComponentsA( index, guid ))
13463     {
13464         if (!strcmp( guid, comp1 )) found1 = TRUE;
13465         if (!strcmp( guid, comp2 )) found2 = TRUE;
13466         ok( guid[0], "empty guid\n" );
13467         if (found1 && found2) break;
13468         guid[0] = 0;
13469         index++;
13470     }
13471     ok( found1, "comp1 not found\n" );
13472     ok( found2, "comp2 not found\n" );
13473 
13474 done:
13475     delete_key( key1, "", access );
13476     delete_key( key2, "", access );
13477     RegCloseKey( key1 );
13478     RegCloseKey( key2 );
13479     LocalFree( usersid );
13480 }
13481 
13482 static void test_MsiEnumComponentsEx(void)
13483 {
13484     UINT r;
13485     BOOL found1, found2;
13486     DWORD len, index;
13487     MSIINSTALLCONTEXT context;
13488     char comp1[39], comp2[39], guid[39], sid[128];
13489     char comp_squashed1[33], comp_squashed2[33];
13490     char keypath1[MAX_PATH], keypath2[MAX_PATH];
13491     HKEY key1 = NULL, key2 = NULL;
13492     REGSAM access = KEY_ALL_ACCESS;
13493     char *usersid = get_user_sid();
13494 
13495     if (!pMsiEnumComponentsExA)
13496     {
13497         win_skip( "MsiEnumComponentsExA not implemented\n" );
13498         return;
13499     }
13500     if (is_process_limited())
13501     {
13502         skip("process is limited\n");
13503         return;
13504     }
13505 
13506     create_test_guid( comp1, comp_squashed1 );
13507     create_test_guid( comp2, comp_squashed2 );
13508 
13509     if (is_wow64) access |= KEY_WOW64_64KEY;
13510 
13511     strcpy( keypath1, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
13512     strcat( keypath1, "S-1-5-18\\Components\\" );
13513     strcat( keypath1, comp_squashed1 );
13514 
13515     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
13516     if (r == ERROR_ACCESS_DENIED)
13517     {
13518         skip( "insufficient rights\n" );
13519         goto done;
13520     }
13521     ok( r == ERROR_SUCCESS, "got %u\n", r );
13522 
13523     strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
13524     strcat( keypath2, usersid );
13525     strcat( keypath2, "\\Components\\" );
13526     strcat( keypath2, comp_squashed2 );
13527 
13528     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
13529     if (r == ERROR_ACCESS_DENIED)
13530     {
13531         skip( "insufficient rights\n" );
13532         goto done;
13533     }
13534     ok( r == ERROR_SUCCESS, "got %u\n", r );
13535     r = RegSetValueExA( key2, comp_squashed2, 0, REG_SZ, (const BYTE *)"c:\\doesnotexist",
13536                         sizeof("c:\\doesnotexist"));
13537     ok( r == ERROR_SUCCESS, "got %u\n", r );
13538 
13539     index = 0;
13540     guid[0] = 0;
13541     context = 0xdeadbeef;
13542     sid[0] = 0;
13543     len = sizeof(sid);
13544     found1 = found2 = FALSE;
13545     while (!pMsiEnumComponentsExA( "S-1-1-0", MSIINSTALLCONTEXT_ALL, index, guid, &context, sid, &len ))
13546     {
13547         if (!strcmp( comp1, guid ))
13548         {
13549             ok( context == MSIINSTALLCONTEXT_MACHINE, "got %u\n", context );
13550             ok( !sid[0], "got \"%s\"\n", sid );
13551             ok( !len, "unexpected length %lu\n", len );
13552             found1 = TRUE;
13553             if (found2) break;
13554         }
13555         if (!strcmp( comp2, guid ))
13556         {
13557             ok( context == MSIINSTALLCONTEXT_USERUNMANAGED, "got %u\n", context );
13558             ok( sid[0], "empty sid\n" );
13559             ok( len == strlen(sid), "unexpected length %lu\n", len );
13560             found2 = TRUE;
13561             if (found1) break;
13562         }
13563         index++;
13564         guid[0] = 0;
13565         context = 0xdeadbeef;
13566         sid[0] = 0;
13567         len = sizeof(sid);
13568     }
13569     ok( found1, "comp1 not found\n" );
13570     ok( found2, "comp2 not found\n" );
13571 
13572     r = pMsiEnumComponentsExA( NULL, 0, 0, NULL, NULL, NULL, NULL );
13573     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13574 
13575     r = pMsiEnumComponentsExA( NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, NULL );
13576     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13577 
13578 done:
13579     RegDeleteValueA( key2, comp_squashed2 );
13580     delete_key( key1, "", access );
13581     delete_key( key2, "", access );
13582     RegCloseKey( key1 );
13583     RegCloseKey( key2 );
13584     LocalFree( usersid );
13585 }
13586 
13587 static void test_MsiConfigureProductEx(void)
13588 {
13589     UINT r;
13590     LONG res;
13591     DWORD type, size;
13592     HKEY props, source;
13593     CHAR keypath[MAX_PATH * 2], localpackage[MAX_PATH], packagename[MAX_PATH];
13594     REGSAM access = KEY_ALL_ACCESS;
13595 
13596     if (is_process_limited())
13597     {
13598         skip("process is limited\n");
13599         return;
13600     }
13601 
13602     CreateDirectoryA("msitest", NULL);
13603     create_file_data("msitest\\hydrogen", "hydrogen", 500);
13604     create_file_data("msitest\\helium", "helium", 500);
13605     create_file_data("msitest\\lithium", "lithium", 500);
13606 
13607     create_database(msifile, mcp_tables, ARRAY_SIZE(mcp_tables));
13608 
13609     if (is_wow64)
13610         access |= KEY_WOW64_64KEY;
13611 
13612     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
13613 
13614     /* NULL szProduct */
13615     r = MsiConfigureProductExA(NULL, INSTALLLEVEL_DEFAULT,
13616                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
13617     ok(r == ERROR_INVALID_PARAMETER,
13618        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
13619 
13620     /* empty szProduct */
13621     r = MsiConfigureProductExA("", INSTALLLEVEL_DEFAULT,
13622                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
13623     ok(r == ERROR_INVALID_PARAMETER,
13624        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
13625 
13626     /* garbage szProduct */
13627     r = MsiConfigureProductExA("garbage", INSTALLLEVEL_DEFAULT,
13628                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
13629     ok(r == ERROR_INVALID_PARAMETER,
13630        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
13631 
13632     /* guid without brackets */
13633     r = MsiConfigureProductExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
13634                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13635                                "PROPVAR=42");
13636     ok(r == ERROR_INVALID_PARAMETER,
13637        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
13638 
13639     /* guid with brackets */
13640     r = MsiConfigureProductExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
13641                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13642                                "PROPVAR=42");
13643     ok(r == ERROR_UNKNOWN_PRODUCT,
13644        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
13645 
13646     /* same length as guid, but random */
13647     r = MsiConfigureProductExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
13648                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13649                                "PROPVAR=42");
13650     ok(r == ERROR_UNKNOWN_PRODUCT,
13651        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
13652 
13653     /* product not installed yet */
13654     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
13655                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13656                                "PROPVAR=42");
13657     ok(r == ERROR_UNKNOWN_PRODUCT,
13658        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
13659 
13660     /* install the product, per-user unmanaged */
13661     r = MsiInstallProductA(msifile, "INSTALLLEVEL=10 PROPVAR=42");
13662     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
13663     {
13664         skip("Not enough rights to perform tests\n");
13665         goto error;
13666     }
13667     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13668     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13669     ok(pf_exists("msitest\\helium"), "File not installed\n");
13670     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13671     ok(pf_exists("msitest"), "File not installed\n");
13672 
13673     /* product is installed per-user managed, remove it */
13674     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13675                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13676                                "PROPVAR=42");
13677     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13678     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
13679     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
13680     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
13681     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
13682 
13683     /* product has been removed */
13684     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13685                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13686                                "PROPVAR=42");
13687     ok(r == ERROR_UNKNOWN_PRODUCT,
13688        "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
13689 
13690     /* install the product, machine */
13691     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
13692     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13693     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13694     ok(pf_exists("msitest\\helium"), "File not installed\n");
13695     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13696     ok(pf_exists("msitest"), "File not installed\n");
13697 
13698     /* product is installed machine, remove it */
13699     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13700                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13701                                "PROPVAR=42");
13702     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13703     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
13704     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
13705     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
13706     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
13707 
13708     /* product has been removed */
13709     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13710                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13711                                "PROPVAR=42");
13712     ok(r == ERROR_UNKNOWN_PRODUCT,
13713        "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
13714 
13715     /* install the product, machine */
13716     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
13717     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13718     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13719     ok(pf_exists("msitest\\helium"), "File not installed\n");
13720     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13721     ok(pf_exists("msitest"), "File not installed\n");
13722 
13723     DeleteFileA(msifile);
13724 
13725     /* msifile is removed */
13726     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13727                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13728                                "PROPVAR=42");
13729     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13730     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
13731     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
13732     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
13733     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
13734 
13735     create_database(msifile, mcp_tables, ARRAY_SIZE(mcp_tables));
13736 
13737     /* install the product, machine */
13738     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
13739     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13740     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13741     ok(pf_exists("msitest\\helium"), "File not installed\n");
13742     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13743     ok(pf_exists("msitest"), "File not installed\n");
13744 
13745     DeleteFileA(msifile);
13746 
13747     lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
13748     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
13749     lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\InstallProperties");
13750 
13751     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &props);
13752     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
13753 
13754     type = REG_SZ;
13755     size = MAX_PATH;
13756     res = RegQueryValueExA(props, "LocalPackage", NULL, &type,
13757                            (LPBYTE)localpackage, &size);
13758     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
13759 
13760     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
13761                          (const BYTE *)"C:\\idontexist.msi", 18);
13762     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
13763 
13764     /* LocalPackage is used to find the cached msi package */
13765     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13766                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13767                                "PROPVAR=42");
13768     ok(r == ERROR_INSTALL_SOURCE_ABSENT,
13769        "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
13770     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13771     ok(pf_exists("msitest\\helium"), "File not installed\n");
13772     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13773     ok(pf_exists("msitest"), "File not installed\n");
13774 
13775     RegCloseKey(props);
13776     create_database(msifile, mcp_tables, ARRAY_SIZE(mcp_tables));
13777 
13778     /* LastUsedSource can be used as a last resort */
13779     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13780                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13781                                "PROPVAR=42");
13782     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13783     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
13784     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
13785     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
13786     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
13787     DeleteFileA( localpackage );
13788 
13789     /* install the product, machine */
13790     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
13791     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13792     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13793     ok(pf_exists("msitest\\helium"), "File not installed\n");
13794     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13795     ok(pf_exists("msitest"), "File not installed\n");
13796 
13797     lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
13798     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
13799     lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\InstallProperties");
13800 
13801     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &props);
13802     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
13803 
13804     type = REG_SZ;
13805     size = MAX_PATH;
13806     res = RegQueryValueExA(props, "LocalPackage", NULL, &type,
13807                            (LPBYTE)localpackage, &size);
13808     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
13809 
13810     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
13811                          (const BYTE *)"C:\\idontexist.msi", 18);
13812     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
13813 
13814     lstrcpyA(keypath, "SOFTWARE\\Classes\\Installer\\Products\\");
13815     lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\SourceList");
13816 
13817     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &source);
13818     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
13819 
13820     type = REG_SZ;
13821     size = MAX_PATH;
13822     res = RegQueryValueExA(source, "PackageName", NULL, &type,
13823                            (LPBYTE)packagename, &size);
13824     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
13825 
13826     res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
13827                          (const BYTE *)"idontexist.msi", 15);
13828     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
13829 
13830     /* SourceList is altered */
13831     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13832                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13833                                "PROPVAR=42");
13834     ok(r == ERROR_INSTALL_SOURCE_ABSENT,
13835        "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
13836     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13837     ok(pf_exists("msitest\\helium"), "File not installed\n");
13838     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13839     ok(pf_exists("msitest"), "File not installed\n");
13840 
13841     /* restore PackageName */
13842     res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
13843                          (const BYTE *)packagename, lstrlenA(packagename) + 1);
13844     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
13845 
13846     /* restore LocalPackage */
13847     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
13848                          (const BYTE *)localpackage, lstrlenA(localpackage) + 1);
13849     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
13850 
13851     /* finally remove the product */
13852     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13853                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13854                                "PROPVAR=42");
13855     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13856     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
13857     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
13858     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
13859     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
13860 
13861     RegCloseKey(source);
13862     RegCloseKey(props);
13863 
13864 error:
13865     DeleteFileA("msitest\\hydrogen");
13866     DeleteFileA("msitest\\helium");
13867     DeleteFileA("msitest\\lithium");
13868     RemoveDirectoryA("msitest");
13869     DeleteFileA(msifile);
13870 }
13871 
13872 static void test_MsiSetFeatureAttributes(void)
13873 {
13874     UINT r;
13875     DWORD attrs;
13876     char path[MAX_PATH];
13877     MSIHANDLE package;
13878 
13879     if (is_process_limited())
13880     {
13881         skip("process is limited\n");
13882         return;
13883     }
13884     create_database( msifile, tables, ARRAY_SIZE( tables ));
13885 
13886     strcpy( path, CURR_DIR );
13887     strcat( path, "\\" );
13888     strcat( path, msifile );
13889 
13890     r = MsiOpenPackageA( path, &package );
13891     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
13892     {
13893         skip("Not enough rights to perform tests\n");
13894         DeleteFileA( msifile );
13895         return;
13896     }
13897     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13898 
13899     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
13900     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %u\n", r);
13901 
13902     r = MsiDoActionA( package, "CostInitialize" );
13903     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13904 
13905     r = MsiSetFeatureAttributesA( 0, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
13906     ok(r == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", r);
13907 
13908     r = MsiSetFeatureAttributesA( package, "", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
13909     ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
13910 
13911     r = MsiSetFeatureAttributesA( package, NULL, INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
13912     ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
13913 
13914     r = MsiSetFeatureAttributesA( package, "One", 0 );
13915     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13916 
13917     attrs = 0xdeadbeef;
13918     r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL );
13919     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13920     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL,
13921        "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %#lx\n", attrs);
13922 
13923     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
13924     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13925 
13926     attrs = 0;
13927     r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL );
13928     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13929     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL,
13930        "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %#lx\n", attrs);
13931 
13932     r = MsiDoActionA( package, "FileCost" );
13933     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13934 
13935     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORSOURCE );
13936     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13937 
13938     attrs = 0;
13939     r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL );
13940     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13941     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORSOURCE,
13942        "expected INSTALLFEATUREATTRIBUTE_FAVORSOURCE, got %#lx\n", attrs);
13943 
13944     r = MsiDoActionA( package, "CostFinalize" );
13945     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13946 
13947     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
13948     ok(r == ERROR_FUNCTION_FAILED, "expected ERROR_FUNCTION_FAILED, got %u\n", r);
13949 
13950     MsiCloseHandle( package );
13951     DeleteFileA( msifile );
13952 }
13953 
13954 static void test_MsiGetFeatureInfo(void)
13955 {
13956     UINT r;
13957     MSIHANDLE package;
13958     char title[32], help[32], path[MAX_PATH];
13959     DWORD attrs, title_len, help_len;
13960 
13961     if (is_process_limited())
13962     {
13963         skip("process is limited\n");
13964         return;
13965     }
13966     create_database( msifile, tables, ARRAY_SIZE( tables ));
13967 
13968     strcpy( path, CURR_DIR );
13969     strcat( path, "\\" );
13970     strcat( path, msifile );
13971 
13972     r = MsiOpenPackageA( path, &package );
13973     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
13974     {
13975         skip("Not enough rights to perform tests\n");
13976         DeleteFileA( msifile );
13977         return;
13978     }
13979     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13980 
13981     r = MsiGetFeatureInfoA( 0, NULL, NULL, NULL, NULL, NULL, NULL );
13982     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
13983 
13984     r = MsiGetFeatureInfoA( package, NULL, NULL, NULL, NULL, NULL, NULL );
13985     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
13986 
13987     r = MsiGetFeatureInfoA( package, "", NULL, NULL, NULL, NULL, NULL );
13988     ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
13989 
13990     r = MsiGetFeatureInfoA( package, "One", NULL, NULL, NULL, NULL, NULL );
13991     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13992 
13993     r = MsiGetFeatureInfoA( 0, "One", NULL, NULL, NULL, NULL, NULL );
13994     ok(r == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", r);
13995 
13996     title_len = help_len = 0;
13997     r = MsiGetFeatureInfoA( package, "One", NULL, NULL, &title_len, NULL, &help_len );
13998     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13999     ok(title_len == 3, "expected 3, got %lu\n", title_len);
14000     ok(help_len == 3, "expected 3, got %lu\n", help_len);
14001 
14002     title[0] = help[0] = 0;
14003     title_len = help_len = 0;
14004     r = MsiGetFeatureInfoA( package, "One", NULL, title, &title_len, help, &help_len );
14005     ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %u\n", r);
14006     ok(title_len == 3, "expected 3, got %lu\n", title_len);
14007     ok(help_len == 3, "expected 3, got %lu\n", help_len);
14008 
14009     attrs = 0;
14010     title[0] = help[0] = 0;
14011     title_len = sizeof(title);
14012     help_len = sizeof(help);
14013     r = MsiGetFeatureInfoA( package, "One", &attrs, title, &title_len, help, &help_len );
14014     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14015     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %lu\n", attrs);
14016     ok(title_len == 3, "expected 3, got %lu\n", title_len);
14017     ok(help_len == 3, "expected 3, got %lu\n", help_len);
14018     ok(!strcmp(title, "One"), "expected \"One\", got \"%s\"\n", title);
14019     ok(!strcmp(help, "One"), "expected \"One\", got \"%s\"\n", help);
14020 
14021     attrs = 0;
14022     title[0] = help[0] = 0;
14023     title_len = sizeof(title);
14024     help_len = sizeof(help);
14025     r = MsiGetFeatureInfoA( package, "Two", &attrs, title, &title_len, help, &help_len );
14026     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14027     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %lu\n", attrs);
14028     ok(!title_len, "expected 0, got %lu\n", title_len);
14029     ok(!help_len, "expected 0, got %lu\n", help_len);
14030     ok(!title[0], "expected \"\", got \"%s\"\n", title);
14031     ok(!help[0], "expected \"\", got \"%s\"\n", help);
14032 
14033     MsiCloseHandle( package );
14034     DeleteFileA( msifile );
14035 }
14036 
14037 static INT CALLBACK handler_a(LPVOID context, UINT type, LPCSTR msg)
14038 {
14039     return IDOK;
14040 }
14041 
14042 static INT CALLBACK handler_w(LPVOID context, UINT type, LPCWSTR msg)
14043 {
14044     return IDOK;
14045 }
14046 
14047 static INT CALLBACK handler_record(LPVOID context, UINT type, MSIHANDLE record)
14048 {
14049     return IDOK;
14050 }
14051 
14052 static void test_MsiSetInternalUI(void)
14053 {
14054     INSTALLUILEVEL level;
14055 
14056     level = MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
14057     ok(level == INSTALLUILEVEL_DEFAULT, "expected INSTALLUILEVEL_DEFAULT, got %d\n", level);
14058 
14059     level = MsiSetInternalUI(INSTALLUILEVEL_DEFAULT, NULL);
14060     ok(level == INSTALLUILEVEL_FULL, "expected INSTALLUILEVEL_FULL, got %d\n", level);
14061 
14062     level = MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE, NULL);
14063     ok(level == INSTALLUILEVEL_DEFAULT, "expected INSTALLUILEVEL_DEFAULT, got %d\n", level);
14064 
14065     level = MsiSetInternalUI(0xdeadbeef, NULL);
14066     ok(level == INSTALLUILEVEL_NOCHANGE, "expected INSTALLUILEVEL_NOCHANGE, got %d\n", level);
14067 }
14068 
14069 static void test_MsiSetExternalUI(void)
14070 {
14071     INSTALLUI_HANDLERA ret_a;
14072     INSTALLUI_HANDLERW ret_w;
14073     INSTALLUI_HANDLER_RECORD prev;
14074     UINT error;
14075 
14076     ret_a = MsiSetExternalUIA(handler_a, INSTALLLOGMODE_ERROR, NULL);
14077     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
14078 
14079     ret_a = MsiSetExternalUIA(NULL, 0, NULL);
14080     ok(ret_a == handler_a, "expected %p, got %p\n", handler_a, ret_a);
14081 
14082     /* Not present before Installer 3.1 */
14083     if (!pMsiSetExternalUIRecord) {
14084         win_skip("MsiSetExternalUIRecord is not available\n");
14085         return;
14086     }
14087 
14088     error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, &prev);
14089     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14090     ok(prev == NULL, "expected NULL, got %p\n", prev);
14091 
14092     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
14093     error = pMsiSetExternalUIRecord(NULL, INSTALLLOGMODE_ERROR, NULL, &prev);
14094     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14095     ok(prev == handler_record, "expected %p, got %p\n", handler_record, prev);
14096 
14097     ret_w = MsiSetExternalUIW(handler_w, INSTALLLOGMODE_ERROR, NULL);
14098     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
14099 
14100     ret_w = MsiSetExternalUIW(NULL, 0, NULL);
14101     ok(ret_w == handler_w, "expected %p, got %p\n", handler_w, ret_w);
14102 
14103     ret_a = MsiSetExternalUIA(handler_a, INSTALLLOGMODE_ERROR, NULL);
14104     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
14105 
14106     ret_w = MsiSetExternalUIW(handler_w, INSTALLLOGMODE_ERROR, NULL);
14107     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
14108 
14109     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
14110     error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, &prev);
14111     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14112     ok(prev == NULL, "expected NULL, got %p\n", prev);
14113 
14114     ret_a = MsiSetExternalUIA(NULL, 0, NULL);
14115     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
14116 
14117     ret_w = MsiSetExternalUIW(NULL, 0, NULL);
14118     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
14119 
14120     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
14121     error = pMsiSetExternalUIRecord(NULL, 0, NULL, &prev);
14122     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14123     ok(prev == handler_record, "expected %p, got %p\n", handler_record, prev);
14124 
14125     error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, NULL);
14126     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14127 
14128     error = pMsiSetExternalUIRecord(NULL, 0, NULL, NULL);
14129     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14130 }
14131 
14132 static void test_lastusedsource(void)
14133 {
14134     static const char prodcode[] = "{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}";
14135     char value[MAX_PATH], path[MAX_PATH];
14136     DWORD size;
14137     UINT r;
14138 
14139     if (!pMsiSourceListGetInfoA)
14140     {
14141         win_skip("MsiSourceListGetInfoA is not available\n");
14142         return;
14143     }
14144 
14145     CreateDirectoryA("msitest", NULL);
14146     create_file("maximus", 500);
14147     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
14148     DeleteFileA("maximus");
14149 
14150     create_database("msifile0.msi", lus0_tables, ARRAY_SIZE(lus0_tables));
14151     create_database("msifile1.msi", lus1_tables, ARRAY_SIZE(lus1_tables));
14152     create_database("msifile2.msi", lus2_tables, ARRAY_SIZE(lus2_tables));
14153 
14154     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
14155 
14156     /* no cabinet file */
14157 
14158     size = MAX_PATH;
14159     lstrcpyA(value, "aaa");
14160     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14161                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14162     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14163     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
14164 
14165     r = MsiInstallProductA("msifile0.msi", "PUBLISH_PRODUCT=1");
14166     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14167     {
14168         skip("Not enough rights to perform tests\n");
14169         goto error;
14170     }
14171     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14172 
14173     lstrcpyA(path, CURR_DIR);
14174     lstrcatA(path, "\\");
14175 
14176     size = MAX_PATH;
14177     lstrcpyA(value, "aaa");
14178     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14179                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14180     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14181     ok(!lstrcmpA(value, path), "expected \"%s\", got \"%s\"\n", path, value);
14182     ok(size == lstrlenA(path), "expected %d, got %lu\n", lstrlenA(path), size);
14183 
14184     r = MsiInstallProductA("msifile0.msi", "REMOVE=ALL FULL=1");
14185     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14186 
14187     /* separate cabinet file */
14188 
14189     size = MAX_PATH;
14190     lstrcpyA(value, "aaa");
14191     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14192                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14193     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14194     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
14195 
14196     r = MsiInstallProductA("msifile1.msi", "PUBLISH_PRODUCT=1");
14197     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14198 
14199     lstrcpyA(path, CURR_DIR);
14200     lstrcatA(path, "\\");
14201 
14202     size = MAX_PATH;
14203     lstrcpyA(value, "aaa");
14204     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14205                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14206     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14207     ok(!lstrcmpA(value, path), "expected \"%s\", got \"%s\"\n", path, value);
14208     ok(size == lstrlenA(path), "expected %d, got %lu\n", lstrlenA(path), size);
14209 
14210     r = MsiInstallProductA("msifile1.msi", "REMOVE=ALL FULL=1");
14211     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14212 
14213     size = MAX_PATH;
14214     lstrcpyA(value, "aaa");
14215     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14216                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14217     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14218     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
14219 
14220     /* embedded cabinet stream */
14221 
14222     add_cabinet_storage("msifile2.msi", "test1.cab");
14223 
14224     r = MsiInstallProductA("msifile2.msi", "PUBLISH_PRODUCT=1");
14225     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14226 
14227     size = MAX_PATH;
14228     lstrcpyA(value, "aaa");
14229     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14230                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14231     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14232     ok(!lstrcmpA(value, path), "expected \"%s\", got \"%s\"\n", path, value);
14233     ok(size == lstrlenA(path), "expected %d, got %lu\n", lstrlenA(path), size);
14234 
14235     r = MsiInstallProductA("msifile2.msi", "REMOVE=ALL FULL=1");
14236     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14237 
14238     size = MAX_PATH;
14239     lstrcpyA(value, "aaa");
14240     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14241                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14242     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14243     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
14244 
14245 error:
14246     delete_cab_files();
14247     DeleteFileA("msitest\\maximus");
14248     RemoveDirectoryA("msitest");
14249     DeleteFileA("msifile0.msi");
14250     DeleteFileA("msifile1.msi");
14251     DeleteFileA("msifile2.msi");
14252 }
14253 
14254 static void test_setpropertyfolder(void)
14255 {
14256     UINT r;
14257 
14258     if (is_process_limited())
14259     {
14260         skip("process is limited\n");
14261         return;
14262     }
14263 
14264     CreateDirectoryA("msitest", NULL);
14265     create_file("msitest\\maximus", 500);
14266 
14267     create_database(msifile, spf_tables, ARRAY_SIZE(spf_tables));
14268 
14269     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
14270 
14271     r = MsiInstallProductA(msifile, NULL);
14272     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14273     {
14274         skip("Not enough rights to perform tests\n");
14275         goto error;
14276     }
14277     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14278     ok(delete_pf("msitest\\added\\added2\\maximus", TRUE), "File not installed\n");
14279     ok(delete_pf("msitest\\added\\added2", FALSE), "Directory not created\n");
14280     ok(delete_pf("msitest\\added", FALSE), "Directory not created\n");
14281     ok(delete_pf("msitest", FALSE), "Directory not created\n");
14282 
14283     CreateDirectoryA("parent", NULL);
14284     CreateDirectoryA("parent\\child", NULL);
14285     create_file("parent\\child\\maximus", 500);
14286 
14287     create_database(msifile, spf2_tables, ARRAY_SIZE(spf2_tables));
14288 
14289     r = MsiInstallProductA(msifile, "TARGETDIR=c:\\");
14290     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14291 
14292     ok(delete_pf("msitest\\maximus", TRUE), "file not installed\n");
14293     ok(delete_pf("msitest", FALSE), "directory not created\n");
14294 
14295     ok(DeleteFileA("c:\\parent\\child\\Shortcut.lnk"), "file not installed\n");
14296     ok(RemoveDirectoryA("c:\\parent\\child"), "directory not created\n");
14297     ok(RemoveDirectoryA("c:\\parent"), "directory not created\n");
14298 
14299     DeleteFileA("parent\\child\\maximus");
14300     RemoveDirectoryA("parent\\child");
14301     RemoveDirectoryA("parent");
14302 
14303 error:
14304     DeleteFileA(msifile);
14305     DeleteFileA("msitest\\maximus");
14306     RemoveDirectoryA("msitest");
14307 }
14308 
14309 static void test_sourcedir_props(void)
14310 {
14311     UINT r;
14312 
14313     if (is_process_limited())
14314     {
14315         skip("process is limited\n");
14316         return;
14317     }
14318 
14319     create_test_files();
14320     create_file("msitest\\sourcedir.txt", 1000);
14321     create_database(msifile, sd_tables, ARRAY_SIZE(sd_tables));
14322 
14323     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
14324 
14325     /* full UI, no ResolveSource action */
14326     r = MsiInstallProductA(msifile, NULL);
14327     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14328 
14329     r = MsiInstallProductA(msifile, "REMOVE=ALL");
14330     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14331 
14332     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
14333     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
14334 
14335     /* full UI, ResolveSource action */
14336     r = MsiInstallProductA(msifile, "ResolveSource=1");
14337     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14338 
14339     r = MsiInstallProductA(msifile, "REMOVE=ALL");
14340     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14341 
14342     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
14343     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
14344 
14345     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
14346 
14347     /* no UI, no ResolveSource action */
14348     r = MsiInstallProductA(msifile, NULL);
14349     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14350 
14351     r = MsiInstallProductA(msifile, "REMOVE=ALL");
14352     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14353 
14354     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
14355     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
14356 
14357     /* no UI, ResolveSource action */
14358     r = MsiInstallProductA(msifile, "ResolveSource=1");
14359     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14360 
14361     r = MsiInstallProductA(msifile, "REMOVE=ALL");
14362     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14363 
14364     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
14365     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
14366 
14367     DeleteFileA("msitest\\sourcedir.txt");
14368     delete_test_files();
14369     DeleteFileA(msifile);
14370 }
14371 
14372 static void test_concurrentinstall(void)
14373 {
14374     UINT r;
14375     CHAR path[MAX_PATH];
14376 
14377     if (is_process_limited())
14378     {
14379         skip("process is limited\n");
14380         return;
14381     }
14382 
14383     CreateDirectoryA("msitest", NULL);
14384     CreateDirectoryA("msitest\\msitest", NULL);
14385     create_file("msitest\\maximus", 500);
14386     create_file("msitest\\msitest\\augustus", 500);
14387 
14388     create_database(msifile, ci_tables, ARRAY_SIZE(ci_tables));
14389 
14390     lstrcpyA(path, CURR_DIR);
14391     lstrcatA(path, "\\msitest\\concurrent.msi");
14392     create_database(path, ci2_tables, ARRAY_SIZE(ci2_tables));
14393 
14394     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
14395 
14396     r = MsiInstallProductA(msifile, NULL);
14397     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14398     {
14399         skip("Not enough rights to perform tests\n");
14400         goto error;
14401     }
14402     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14403     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
14404     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
14405     ok(delete_pf("msitest", FALSE), "Directory not created\n");
14406 
14407     r = MsiConfigureProductA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", INSTALLLEVEL_DEFAULT,
14408                              INSTALLSTATE_ABSENT);
14409     ok(r == ERROR_SUCCESS, "got %u\n", r);
14410 
14411     r = MsiConfigureProductA("{FF4AFE9C-6AC2-44F9-A060-9EA6BD16C75E}", INSTALLLEVEL_DEFAULT,
14412                              INSTALLSTATE_ABSENT);
14413     ok(r == ERROR_SUCCESS, "got %u\n", r);
14414 
14415 error:
14416     DeleteFileA(path);
14417     DeleteFileA(msifile);
14418     DeleteFileA("msitest\\msitest\\augustus");
14419     DeleteFileA("msitest\\maximus");
14420     RemoveDirectoryA("msitest\\msitest");
14421     RemoveDirectoryA("msitest");
14422 }
14423 
14424 static void test_command_line_parsing(void)
14425 {
14426     UINT r;
14427     const char *cmd;
14428 
14429     if (is_process_limited())
14430     {
14431         skip("process is limited\n");
14432         return;
14433     }
14434 
14435     create_test_files();
14436     create_database(msifile, cl_tables, ARRAY_SIZE(cl_tables));
14437 
14438     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
14439 
14440     cmd = " ";
14441     r = MsiInstallProductA(msifile, cmd);
14442     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14443 
14444     cmd = "=";
14445     r = MsiInstallProductA(msifile, cmd);
14446     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14447 
14448     cmd = "==";
14449     r = MsiInstallProductA(msifile, cmd);
14450     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14451 
14452     cmd = "one";
14453     r = MsiInstallProductA(msifile, cmd);
14454     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14455 
14456     cmd = "=one";
14457     r = MsiInstallProductA(msifile, cmd);
14458     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14459 
14460     cmd = "P=";
14461     r = MsiInstallProductA(msifile, cmd);
14462     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14463 
14464     cmd = "  P=";
14465     r = MsiInstallProductA(msifile, cmd);
14466     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14467 
14468     cmd = "P=  ";
14469     r = MsiInstallProductA(msifile, cmd);
14470     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14471 
14472     cmd = "P=\"";
14473     r = MsiInstallProductA(msifile, cmd);
14474     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14475 
14476     cmd = "P=\"\"";
14477     r = MsiInstallProductA(msifile, cmd);
14478     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14479 
14480     cmd = "P=\"\"\"";
14481     r = MsiInstallProductA(msifile, cmd);
14482     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14483 
14484     cmd = "P=\"\"\"\"";
14485     r = MsiInstallProductA(msifile, cmd);
14486     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14487 
14488     cmd = "P=\" ";
14489     r = MsiInstallProductA(msifile, cmd);
14490     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14491 
14492     cmd = "P= \"";
14493     r = MsiInstallProductA(msifile, cmd);
14494     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14495 
14496     cmd = "P= \"\" ";
14497     r = MsiInstallProductA(msifile, cmd);
14498     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, 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=one";
14505     r = MsiInstallProductA(msifile, cmd);
14506     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14507 
14508     cmd = "P= one";
14509     r = MsiInstallProductA(msifile, cmd);
14510     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14511 
14512     cmd = "P=\"one";
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=one\"";
14517     r = MsiInstallProductA(msifile, cmd);
14518     todo_wine ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14519 
14520     cmd = "P=\"one\"";
14521     r = MsiInstallProductA(msifile, cmd);
14522     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14523 
14524     cmd = "P= \"one\" ";
14525     r = MsiInstallProductA(msifile, cmd);
14526     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14527 
14528     cmd = "P=\"one\"\"";
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=\"\"one\"";
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=\"\"one\"\"";
14537     r = MsiInstallProductA(msifile, cmd);
14538     todo_wine ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14539 
14540     cmd = "P=\"one two\"";
14541     r = MsiInstallProductA(msifile, cmd);
14542     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14543 
14544     cmd = "P=\"\"\"one\"\" two\"";
14545     r = MsiInstallProductA(msifile, cmd);
14546     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14547 
14548     cmd = "P=\"\"\"one\"\" two\" Q=three";
14549     r = MsiInstallProductA(msifile, cmd);
14550     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14551 
14552     cmd = "P=\"\" Q=\"two\"";
14553     r = MsiInstallProductA(msifile, cmd);
14554     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14555 
14556     cmd = "P=\"one\" Q=\"two\"";
14557     r = MsiInstallProductA(msifile, cmd);
14558     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14559 
14560     cmd = "P=\"one=two\"";
14561     r = MsiInstallProductA(msifile, cmd);
14562     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14563 
14564     cmd = "Q=\"\" 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\"\"\" Q=\"two\"";
14569     r = MsiInstallProductA(msifile, cmd);
14570     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14571 
14572     cmd = "P=\"one \"\"two\"\"\" Q=\"three\"";
14573     r = MsiInstallProductA(msifile, cmd);
14574     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14575 
14576     cmd = "P=\"\"\"one\"\" two\" Q=\"three\"";
14577     r = MsiInstallProductA(msifile, cmd);
14578     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14579 
14580     DeleteFileA(msifile);
14581     delete_test_files();
14582 }
14583 
14584 START_TEST(msi)
14585 {
14586     DWORD len;
14587     char temp_path[MAX_PATH], prev_path[MAX_PATH];
14588 
14589 #ifdef __REACTOS__
14590     if (!winetest_interactive &&
14591         !strcmp(winetest_platform, "windows"))
14592     {
14593         skip("ROSTESTS-180: Skipping msi_winetest:msi because it hangs on WHS-Testbot. Set winetest_interactive to run it anyway.\n");
14594         return;
14595     }
14596 #endif
14597 
14598     init_functionpointers();
14599 
14600     if (pIsWow64Process)
14601         pIsWow64Process(GetCurrentProcess(), &is_wow64);
14602 
14603     GetCurrentDirectoryA(MAX_PATH, prev_path);
14604     GetTempPathA(MAX_PATH, temp_path);
14605     SetCurrentDirectoryA(temp_path);
14606 
14607     lstrcpyA(CURR_DIR, temp_path);
14608     len = lstrlenA(CURR_DIR);
14609 
14610     if(len && (CURR_DIR[len - 1] == '\\'))
14611         CURR_DIR[len - 1] = 0;
14612 
14613     ok(get_system_dirs(), "failed to retrieve system dirs\n");
14614 
14615     test_usefeature();
14616     test_null();
14617     test_getcomponentpath();
14618     test_MsiGetFileHash();
14619     test_MsiSetInternalUI();
14620     test_MsiSetExternalUI();
14621     test_MsiQueryProductState();
14622     test_MsiQueryFeatureState();
14623     test_MsiQueryComponentState();
14624     test_MsiGetComponentPath();
14625     test_MsiGetComponentPathEx();
14626     test_MsiProvideComponent();
14627     test_MsiGetProductCode();
14628     test_MsiEnumClients();
14629     test_MsiGetProductInfo();
14630     test_MsiGetProductInfoEx();
14631     test_MsiGetUserInfo();
14632     test_MsiOpenProduct();
14633     test_MsiEnumPatchesEx();
14634     test_MsiEnumPatches();
14635     test_MsiGetPatchInfoEx();
14636     test_MsiGetPatchInfo();
14637     test_MsiEnumProducts();
14638     test_MsiEnumProductsEx();
14639     test_MsiEnumComponents();
14640     test_MsiEnumComponentsEx();
14641     test_MsiGetFileVersion();
14642     test_MsiGetFileSignatureInformation();
14643     test_MsiConfigureProductEx();
14644     test_MsiSetFeatureAttributes();
14645     test_MsiGetFeatureInfo();
14646     test_lastusedsource();
14647     test_setpropertyfolder();
14648     test_sourcedir_props();
14649     if (pMsiGetComponentPathExA)
14650         test_concurrentinstall();
14651     test_command_line_parsing();
14652     test_MsiProvideQualifiedComponentEx();
14653 
14654     SetCurrentDirectoryA(prev_path);
14655 }
14656