xref: /reactos/modules/rostests/winetests/msi/msi.c (revision b016bb6b)
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 static BOOL is_wow64;
38 static const char msifile[] = "winetest.msi";
39 static const WCHAR msifileW[] = {'w','i','n','e','t','e','s','t','.','m','s','i',0};
40 
41 static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
42 static LONG (WINAPI *pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD);
43 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
44 
45 static INSTALLSTATE (WINAPI *pMsiGetComponentPathA)
46     (LPCSTR, LPCSTR, LPSTR, DWORD*);
47 static INSTALLSTATE (WINAPI *pMsiGetComponentPathExA)
48     (LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPSTR, LPDWORD);
49 static INSTALLSTATE (WINAPI *pMsiProvideComponentA)
50     (LPCSTR, LPCSTR, LPCSTR, DWORD, LPSTR, LPDWORD);
51 static INSTALLSTATE (WINAPI *pMsiProvideComponentW)
52     (LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPWSTR, LPDWORD);
53 static UINT (WINAPI *pMsiGetFileHashA)
54     (LPCSTR, DWORD, PMSIFILEHASHINFO);
55 static UINT (WINAPI *pMsiGetProductInfoExA)
56     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, LPSTR, LPDWORD);
57 static UINT (WINAPI *pMsiOpenPackageExA)
58     (LPCSTR, DWORD, MSIHANDLE*);
59 static UINT (WINAPI *pMsiOpenPackageExW)
60     (LPCWSTR, DWORD, MSIHANDLE*);
61 static UINT (WINAPI *pMsiEnumPatchesExA)
62     (LPCSTR, LPCSTR, DWORD, DWORD, DWORD, LPSTR, LPSTR,
63     MSIINSTALLCONTEXT*, LPSTR, LPDWORD);
64 static UINT (WINAPI *pMsiQueryComponentStateA)
65     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, INSTALLSTATE*);
66 static INSTALLSTATE (WINAPI *pMsiUseFeatureExA)
67     (LPCSTR, LPCSTR ,DWORD, DWORD);
68 static UINT (WINAPI *pMsiGetPatchInfoExA)
69     (LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, LPSTR, DWORD *);
70 static UINT (WINAPI *pMsiEnumProductsExA)
71     (LPCSTR, LPCSTR, DWORD, DWORD, CHAR[39], MSIINSTALLCONTEXT *, LPSTR, LPDWORD);
72 static UINT (WINAPI *pMsiEnumComponentsExA)
73     (LPCSTR, DWORD, DWORD, CHAR[39], MSIINSTALLCONTEXT *, LPSTR, LPDWORD);
74 static UINT (WINAPI *pMsiSetExternalUIRecord)
75     (INSTALLUI_HANDLER_RECORD, DWORD, LPVOID, PINSTALLUI_HANDLER_RECORD);
76 static UINT (WINAPI *pMsiSourceListGetInfoA)
77     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, LPSTR, LPDWORD);
78 
79 static void init_functionpointers(void)
80 {
81     HMODULE hmsi = GetModuleHandleA("msi.dll");
82     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
83     HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
84 
85 #define GET_PROC(dll, func) \
86     p ## func = (void *)GetProcAddress(dll, #func); \
87     if(!p ## func) \
88       trace("GetProcAddress(%s) failed\n", #func);
89 
90     GET_PROC(hmsi, MsiGetComponentPathA)
91     GET_PROC(hmsi, MsiGetComponentPathExA);
92     GET_PROC(hmsi, MsiProvideComponentA)
93     GET_PROC(hmsi, MsiProvideComponentW)
94     GET_PROC(hmsi, MsiGetFileHashA)
95     GET_PROC(hmsi, MsiGetProductInfoExA)
96     GET_PROC(hmsi, MsiOpenPackageExA)
97     GET_PROC(hmsi, MsiOpenPackageExW)
98     GET_PROC(hmsi, MsiEnumPatchesExA)
99     GET_PROC(hmsi, MsiQueryComponentStateA)
100     GET_PROC(hmsi, MsiSetExternalUIRecord)
101     GET_PROC(hmsi, MsiUseFeatureExA)
102     GET_PROC(hmsi, MsiGetPatchInfoExA)
103     GET_PROC(hmsi, MsiEnumProductsExA)
104     GET_PROC(hmsi, MsiEnumComponentsExA)
105     GET_PROC(hmsi, MsiSourceListGetInfoA)
106 
107     GET_PROC(hadvapi32, ConvertSidToStringSidA)
108     GET_PROC(hadvapi32, RegDeleteKeyExA)
109     GET_PROC(hkernel32, IsWow64Process)
110 
111 #undef GET_PROC
112 }
113 
114 /* cabinet definitions */
115 
116 /* make the max size large so there is only one cab file */
117 #define MEDIA_SIZE          0x7FFFFFFF
118 #define FOLDER_THRESHOLD    900000
119 
120 static BOOL add_cabinet_storage(LPCSTR db, LPCSTR cabinet)
121 {
122     WCHAR dbW[MAX_PATH], cabinetW[MAX_PATH];
123     IStorage *stg;
124     IStream *stm;
125     HRESULT hr;
126     HANDLE handle;
127 
128     MultiByteToWideChar(CP_ACP, 0, db, -1, dbW, MAX_PATH);
129     hr = StgOpenStorage(dbW, NULL, STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
130     if (FAILED(hr))
131         return FALSE;
132 
133     MultiByteToWideChar(CP_ACP, 0, cabinet, -1, cabinetW, MAX_PATH);
134     hr = IStorage_CreateStream(stg, cabinetW, STGM_WRITE|STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
135     if (FAILED(hr))
136     {
137         IStorage_Release(stg);
138         return FALSE;
139     }
140 
141     handle = CreateFileW(cabinetW, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
142     if (handle != INVALID_HANDLE_VALUE)
143     {
144         DWORD count;
145         char buffer[1024];
146         if (ReadFile(handle, buffer, sizeof(buffer), &count, NULL))
147             IStream_Write(stm, buffer, count, &count);
148         CloseHandle(handle);
149     }
150 
151     IStream_Release(stm);
152     IStorage_Release(stg);
153 
154     return TRUE;
155 }
156 
157 /* msi database data */
158 
159 static const char directory_dat[] =
160     "Directory\tDirectory_Parent\tDefaultDir\n"
161     "s72\tS72\tl255\n"
162     "Directory\tDirectory\n"
163     "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
164     "ProgramFilesFolder\tTARGETDIR\t.\n"
165     "TARGETDIR\t\tSourceDir";
166 
167 static const char component_dat[] =
168     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
169     "s72\tS38\ts72\ti2\tS255\tS72\n"
170     "Component\tComponent\n"
171     "One\t{8F5BAEEF-DD92-40AC-9397-BE3CF9F97C81}\tMSITESTDIR\t2\tNOT REINSTALL\tone.txt\n";
172 
173 static const char feature_dat[] =
174     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
175     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
176     "Feature\tFeature\n"
177     "One\t\tOne\tOne\t1\t3\tMSITESTDIR\t0\n"
178     "Two\t\t\t\t2\t1\tTARGETDIR\t0\n";
179 
180 static const char feature_comp_dat[] =
181     "Feature_\tComponent_\n"
182     "s38\ts72\n"
183     "FeatureComponents\tFeature_\tComponent_\n"
184     "One\tOne\n";
185 
186 static const char file_dat[] =
187     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
188     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
189     "File\tFile\n"
190     "one.txt\tOne\tone.txt\t1000\t\t\t0\t1\n";
191 
192 static const char install_exec_seq_dat[] =
193     "Action\tCondition\tSequence\n"
194     "s72\tS255\tI2\n"
195     "InstallExecuteSequence\tAction\n"
196     "ValidateProductID\t\t700\n"
197     "CostInitialize\t\t800\n"
198     "FileCost\t\t900\n"
199     "CostFinalize\t\t1000\n"
200     "InstallValidate\t\t1400\n"
201     "InstallInitialize\t\t1500\n"
202     "ProcessComponents\t\t1600\n"
203     "UnpublishFeatures\t\t1800\n"
204     "RemoveFiles\t\t3500\n"
205     "InstallFiles\t\t4000\n"
206     "RegisterProduct\t\t6100\n"
207     "PublishFeatures\t\t6300\n"
208     "PublishProduct\t\t6400\n"
209     "InstallFinalize\t\t6600";
210 
211 static const char media_dat[] =
212     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
213     "i2\ti4\tL64\tS255\tS32\tS72\n"
214     "Media\tDiskId\n"
215     "1\t1\t\t\tDISK1\t\n";
216 
217 static const char property_dat[] =
218     "Property\tValue\n"
219     "s72\tl0\n"
220     "Property\tProperty\n"
221     "INSTALLLEVEL\t3\n"
222     "Manufacturer\tWine\n"
223     "ProductCode\t{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}\n"
224     "ProductName\tMSITEST\n"
225     "ProductVersion\t1.1.1\n"
226     "UpgradeCode\t{9574448F-9B86-4E07-B6F6-8D199DA12127}\n"
227     "MSIFASTINSTALL\t1\n";
228 
229 static const char ci2_property_dat[] =
230     "Property\tValue\n"
231     "s72\tl0\n"
232     "Property\tProperty\n"
233     "INSTALLLEVEL\t3\n"
234     "Manufacturer\tWine\n"
235     "ProductCode\t{FF4AFE9C-6AC2-44F9-A060-9EA6BD16C75E}\n"
236     "ProductName\tMSITEST2\n"
237     "ProductVersion\t1.1.1\n"
238     "UpgradeCode\t{6B60C3CA-B8CA-4FB7-A395-092D98FF5D2A}\n"
239     "MSIFASTINSTALL\t1\n";
240 
241 static const char mcp_component_dat[] =
242     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
243     "s72\tS38\ts72\ti2\tS255\tS72\n"
244     "Component\tComponent\n"
245     "hydrogen\t{C844BD1E-1907-4C00-8BC9-150BD70DF0A1}\tMSITESTDIR\t2\t\thydrogen\n"
246     "helium\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t2\t\thelium\n"
247     "lithium\t{4AF28FFC-71C7-4307-BDE4-B77C5338F56F}\tMSITESTDIR\t2\tPROPVAR=42\tlithium\n";
248 
249 static const char mcp_feature_dat[] =
250     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
251     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
252     "Feature\tFeature\n"
253     "hydroxyl\t\thydroxyl\thydroxyl\t2\t1\tTARGETDIR\t0\n"
254     "heliox\t\theliox\theliox\t2\t5\tTARGETDIR\t0\n"
255     "lithia\t\tlithia\tlithia\t2\t10\tTARGETDIR\t0";
256 
257 static const char mcp_feature_comp_dat[] =
258     "Feature_\tComponent_\n"
259     "s38\ts72\n"
260     "FeatureComponents\tFeature_\tComponent_\n"
261     "hydroxyl\thydrogen\n"
262     "heliox\thelium\n"
263     "lithia\tlithium";
264 
265 static const char mcp_file_dat[] =
266     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
267     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
268     "File\tFile\n"
269     "hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n"
270     "helium\thelium\thelium\t0\t\t\t8192\t1\n"
271     "lithium\tlithium\tlithium\t0\t\t\t8192\t1";
272 
273 static const char lus_component_dat[] =
274     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
275     "s72\tS38\ts72\ti2\tS255\tS72\n"
276     "Component\tComponent\n"
277     "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
278 
279 static const char lus_feature_dat[] =
280     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
281     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
282     "Feature\tFeature\n"
283     "feature\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0\n"
284     "montecristo\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0";
285 
286 static const char lus_file_dat[] =
287     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
288     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
289     "File\tFile\n"
290     "maximus\tmaximus\tmaximus\t500\t\t\t8192\t1";
291 
292 static const char lus_feature_comp_dat[] =
293     "Feature_\tComponent_\n"
294     "s38\ts72\n"
295     "FeatureComponents\tFeature_\tComponent_\n"
296     "feature\tmaximus\n"
297     "montecristo\tmaximus";
298 
299 static const char lus_install_exec_seq_dat[] =
300     "Action\tCondition\tSequence\n"
301     "s72\tS255\tI2\n"
302     "InstallExecuteSequence\tAction\n"
303     "ValidateProductID\t\t700\n"
304     "CostInitialize\t\t800\n"
305     "FileCost\t\t900\n"
306     "CostFinalize\t\t1000\n"
307     "InstallValidate\t\t1400\n"
308     "InstallInitialize\t\t1500\n"
309     "ProcessComponents\tPROCESS_COMPONENTS=1 Or FULL=1\t1600\n"
310     "UnpublishFeatures\tUNPUBLISH_FEATURES=1 Or FULL=1\t1800\n"
311     "RemoveFiles\t\t3500\n"
312     "InstallFiles\t\t4000\n"
313     "RegisterUser\tREGISTER_USER=1 Or FULL=1\t6000\n"
314     "RegisterProduct\tREGISTER_PRODUCT=1 Or FULL=1\t6100\n"
315     "PublishFeatures\tPUBLISH_FEATURES=1 Or FULL=1\t6300\n"
316     "PublishProduct\tPUBLISH_PRODUCT=1 Or FULL=1\t6400\n"
317     "InstallFinalize\t\t6600";
318 
319 static const char lus0_media_dat[] =
320     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
321     "i2\ti4\tL64\tS255\tS32\tS72\n"
322     "Media\tDiskId\n"
323     "1\t1\t\t\tDISK1\t\n";
324 
325 static const char lus1_media_dat[] =
326     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
327     "i2\ti4\tL64\tS255\tS32\tS72\n"
328     "Media\tDiskId\n"
329     "1\t1\t\ttest1.cab\tDISK1\t\n";
330 
331 static const char lus2_media_dat[] =
332     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
333     "i2\ti4\tL64\tS255\tS32\tS72\n"
334     "Media\tDiskId\n"
335     "1\t1\t\t#test1.cab\tDISK1\t\n";
336 
337 static const char spf_custom_action_dat[] =
338     "Action\tType\tSource\tTarget\tISComments\n"
339     "s72\ti2\tS64\tS0\tS255\n"
340     "CustomAction\tAction\n"
341     "SetFolderProp\t51\tMSITESTDIR\t[ProgramFilesFolder]\\msitest\\added\t\n";
342 
343 static const char spf_install_exec_seq_dat[] =
344     "Action\tCondition\tSequence\n"
345     "s72\tS255\tI2\n"
346     "InstallExecuteSequence\tAction\n"
347     "CostFinalize\t\t1000\n"
348     "CostInitialize\t\t800\n"
349     "FileCost\t\t900\n"
350     "SetFolderProp\t\t950\n"
351     "InstallFiles\t\t4000\n"
352     "InstallServices\t\t5000\n"
353     "InstallFinalize\t\t6600\n"
354     "InstallInitialize\t\t1500\n"
355     "InstallValidate\t\t1400\n"
356     "LaunchConditions\t\t100";
357 
358 static const char spf_install_ui_seq_dat[] =
359     "Action\tCondition\tSequence\n"
360     "s72\tS255\tI2\n"
361     "InstallUISequence\tAction\n"
362     "CostInitialize\t\t800\n"
363     "FileCost\t\t900\n"
364     "CostFinalize\t\t1000\n"
365     "ExecuteAction\t\t1100\n";
366 
367 static const char sd_file_dat[] =
368     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
369     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
370     "File\tFile\n"
371     "sourcedir.txt\tsourcedir\tsourcedir.txt\t1000\t\t\t8192\t1\n";
372 
373 static const char sd_feature_dat[] =
374     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
375     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
376     "Feature\tFeature\n"
377     "sourcedir\t\t\tsourcedir feature\t1\t2\tMSITESTDIR\t0\n";
378 
379 static const char sd_feature_comp_dat[] =
380     "Feature_\tComponent_\n"
381     "s38\ts72\n"
382     "FeatureComponents\tFeature_\tComponent_\n"
383     "sourcedir\tsourcedir\n";
384 
385 static const char sd_component_dat[] =
386     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
387     "s72\tS38\ts72\ti2\tS255\tS72\n"
388     "Component\tComponent\n"
389     "sourcedir\t{DD422F92-3ED8-49B5-A0B7-F266F98357DF}\tMSITESTDIR\t0\t\tsourcedir.txt\n";
390 
391 static const char sd_install_ui_seq_dat[] =
392     "Action\tCondition\tSequence\n"
393     "s72\tS255\tI2\n"
394     "InstallUISequence\tAction\n"
395     "TestSourceDirProp1\tnot SourceDir and not SOURCEDIR and not Installed\t99\n"
396     "AppSearch\t\t100\n"
397     "TestSourceDirProp2\tnot SourceDir and not SOURCEDIR and not Installed\t101\n"
398     "LaunchConditions\tnot Installed \t110\n"
399     "TestSourceDirProp3\tnot SourceDir and not SOURCEDIR and not Installed\t111\n"
400     "FindRelatedProducts\t\t120\n"
401     "TestSourceDirProp4\tnot SourceDir and not SOURCEDIR and not Installed\t121\n"
402     "CCPSearch\t\t130\n"
403     "TestSourceDirProp5\tnot SourceDir and not SOURCEDIR and not Installed\t131\n"
404     "RMCCPSearch\t\t140\n"
405     "TestSourceDirProp6\tnot SourceDir and not SOURCEDIR and not Installed\t141\n"
406     "ValidateProductID\t\t150\n"
407     "TestSourceDirProp7\tnot SourceDir and not SOURCEDIR and not Installed\t151\n"
408     "CostInitialize\t\t800\n"
409     "TestSourceDirProp8\tnot SourceDir and not SOURCEDIR and not Installed\t801\n"
410     "FileCost\t\t900\n"
411     "TestSourceDirProp9\tnot SourceDir and not SOURCEDIR and not Installed\t901\n"
412     "IsolateComponents\t\t1000\n"
413     "TestSourceDirProp10\tnot SourceDir and not SOURCEDIR and not Installed\t1001\n"
414     "CostFinalize\t\t1100\n"
415     "TestSourceDirProp11\tnot SourceDir and not SOURCEDIR and not Installed\t1101\n"
416     "MigrateFeatureStates\t\t1200\n"
417     "TestSourceDirProp12\tnot SourceDir and not SOURCEDIR and not Installed\t1201\n"
418     "ExecuteAction\t\t1300\n"
419     "TestSourceDirProp13\tnot SourceDir and not SOURCEDIR and not Installed\t1301\n";
420 
421 static const char sd_install_exec_seq_dat[] =
422     "Action\tCondition\tSequence\n"
423     "s72\tS255\tI2\n"
424     "InstallExecuteSequence\tAction\n"
425     "TestSourceDirProp14\tSourceDir and SOURCEDIR and not Installed\t99\n"
426     "LaunchConditions\t\t100\n"
427     "TestSourceDirProp15\tSourceDir and SOURCEDIR and not Installed\t101\n"
428     "ValidateProductID\t\t700\n"
429     "TestSourceDirProp16\tSourceDir and SOURCEDIR and not Installed\t701\n"
430     "CostInitialize\t\t800\n"
431     "TestSourceDirProp17\tSourceDir and SOURCEDIR and not Installed\t801\n"
432     "ResolveSource\tResolveSource and not Installed\t850\n"
433     "TestSourceDirProp18\tResolveSource and not SourceDir and not SOURCEDIR and not Installed\t851\n"
434     "TestSourceDirProp19\tnot ResolveSource and SourceDir and SOURCEDIR and not Installed\t852\n"
435     "FileCost\t\t900\n"
436     "TestSourceDirProp20\tSourceDir and SOURCEDIR and not Installed\t901\n"
437     "IsolateComponents\t\t1000\n"
438     "TestSourceDirProp21\tSourceDir and SOURCEDIR and not Installed\t1001\n"
439     "CostFinalize\t\t1100\n"
440     "TestSourceDirProp22\tSourceDir and SOURCEDIR and not Installed\t1101\n"
441     "MigrateFeatureStates\t\t1200\n"
442     "TestSourceDirProp23\tSourceDir and SOURCEDIR and not Installed\t1201\n"
443     "InstallValidate\t\t1400\n"
444     "TestSourceDirProp24\tSourceDir and SOURCEDIR and not Installed\t1401\n"
445     "InstallInitialize\t\t1500\n"
446     "TestSourceDirProp25\tSourceDir and SOURCEDIR and not Installed\t1501\n"
447     "ProcessComponents\t\t1600\n"
448     "TestSourceDirProp26\tnot SourceDir and not SOURCEDIR and not Installed\t1601\n"
449     "UnpublishFeatures\t\t1800\n"
450     "TestSourceDirProp27\tnot SourceDir and not SOURCEDIR and not Installed\t1801\n"
451     "RemoveFiles\t\t3500\n"
452     "TestSourceDirProp28\tnot SourceDir and not SOURCEDIR and not Installed\t3501\n"
453     "InstallFiles\t\t4000\n"
454     "TestSourceDirProp29\tnot SourceDir and not SOURCEDIR and not Installed\t4001\n"
455     "RegisterUser\t\t6000\n"
456     "TestSourceDirProp30\tnot SourceDir and not SOURCEDIR and not Installed\t6001\n"
457     "RegisterProduct\t\t6100\n"
458     "TestSourceDirProp31\tnot SourceDir and not SOURCEDIR and not Installed\t6101\n"
459     "PublishFeatures\t\t6300\n"
460     "TestSourceDirProp32\tnot SourceDir and not SOURCEDIR and not Installed\t6301\n"
461     "PublishProduct\t\t6400\n"
462     "TestSourceDirProp33\tnot SourceDir and not SOURCEDIR and not Installed\t6401\n"
463     "InstallExecute\t\t6500\n"
464     "TestSourceDirProp34\tnot SourceDir and not SOURCEDIR and not Installed\t6501\n"
465     "InstallFinalize\t\t6600\n"
466     "TestSourceDirProp35\tnot SourceDir and not SOURCEDIR and not Installed\t6601\n";
467 
468 static const char sd_custom_action_dat[] =
469     "Action\tType\tSource\tTarget\tISComments\n"
470     "s72\ti2\tS64\tS0\tS255\n"
471     "CustomAction\tAction\n"
472     "TestSourceDirProp1\t19\t\tTest 1 failed\t\n"
473     "TestSourceDirProp2\t19\t\tTest 2 failed\t\n"
474     "TestSourceDirProp3\t19\t\tTest 3 failed\t\n"
475     "TestSourceDirProp4\t19\t\tTest 4 failed\t\n"
476     "TestSourceDirProp5\t19\t\tTest 5 failed\t\n"
477     "TestSourceDirProp6\t19\t\tTest 6 failed\t\n"
478     "TestSourceDirProp7\t19\t\tTest 7 failed\t\n"
479     "TestSourceDirProp8\t19\t\tTest 8 failed\t\n"
480     "TestSourceDirProp9\t19\t\tTest 9 failed\t\n"
481     "TestSourceDirProp10\t19\t\tTest 10 failed\t\n"
482     "TestSourceDirProp11\t19\t\tTest 11 failed\t\n"
483     "TestSourceDirProp12\t19\t\tTest 12 failed\t\n"
484     "TestSourceDirProp13\t19\t\tTest 13 failed\t\n"
485     "TestSourceDirProp14\t19\t\tTest 14 failed\t\n"
486     "TestSourceDirProp15\t19\t\tTest 15 failed\t\n"
487     "TestSourceDirProp16\t19\t\tTest 16 failed\t\n"
488     "TestSourceDirProp17\t19\t\tTest 17 failed\t\n"
489     "TestSourceDirProp18\t19\t\tTest 18 failed\t\n"
490     "TestSourceDirProp19\t19\t\tTest 19 failed\t\n"
491     "TestSourceDirProp20\t19\t\tTest 20 failed\t\n"
492     "TestSourceDirProp21\t19\t\tTest 21 failed\t\n"
493     "TestSourceDirProp22\t19\t\tTest 22 failed\t\n"
494     "TestSourceDirProp23\t19\t\tTest 23 failed\t\n"
495     "TestSourceDirProp24\t19\t\tTest 24 failed\t\n"
496     "TestSourceDirProp25\t19\t\tTest 25 failed\t\n"
497     "TestSourceDirProp26\t19\t\tTest 26 failed\t\n"
498     "TestSourceDirProp27\t19\t\tTest 27 failed\t\n"
499     "TestSourceDirProp28\t19\t\tTest 28 failed\t\n"
500     "TestSourceDirProp29\t19\t\tTest 29 failed\t\n"
501     "TestSourceDirProp30\t19\t\tTest 30 failed\t\n"
502     "TestSourceDirProp31\t19\t\tTest 31 failed\t\n"
503     "TestSourceDirProp32\t19\t\tTest 32 failed\t\n"
504     "TestSourceDirProp33\t19\t\tTest 33 failed\t\n"
505     "TestSourceDirProp34\t19\t\tTest 34 failed\t\n"
506     "TestSourceDirProp35\t19\t\tTest 35 failed\t\n";
507 
508 static const char ci_install_exec_seq_dat[] =
509     "Action\tCondition\tSequence\n"
510     "s72\tS255\tI2\n"
511     "InstallExecuteSequence\tAction\n"
512     "CostInitialize\t\t800\n"
513     "FileCost\t\t900\n"
514     "CostFinalize\t\t1000\n"
515     "InstallValidate\t\t1400\n"
516     "InstallInitialize\t\t1500\n"
517     "RunInstall\tnot Installed\t1550\n"
518     "ProcessComponents\t\t1600\n"
519     "UnpublishFeatures\t\t1800\n"
520     "RemoveFiles\t\t3500\n"
521     "InstallFiles\t\t4000\n"
522     "RegisterProduct\t\t6100\n"
523     "PublishFeatures\t\t6300\n"
524     "PublishProduct\t\t6400\n"
525     "InstallFinalize\t\t6600\n";
526 
527 static const char ci_custom_action_dat[] =
528     "Action\tType\tSource\tTarget\tISComments\n"
529     "s72\ti2\tS64\tS0\tS255\n"
530     "CustomAction\tAction\n"
531     "RunInstall\t23\tmsitest\\concurrent.msi\tMYPROP=[UILevel]\t\n";
532 
533 static const char ci_component_dat[] =
534     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
535     "s72\tS38\ts72\ti2\tS255\tS72\n"
536     "Component\tComponent\n"
537     "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
538 
539 static const char ci2_component_dat[] =
540     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
541     "s72\tS38\ts72\ti2\tS255\tS72\n"
542     "Component\tComponent\n"
543     "augustus\t\tMSITESTDIR\t0\tUILevel=3 AND MYPROP=5\taugustus\n";
544 
545 static const char ci2_feature_comp_dat[] =
546     "Feature_\tComponent_\n"
547     "s38\ts72\n"
548     "FeatureComponents\tFeature_\tComponent_\n"
549     "feature\taugustus";
550 
551 static const char ci2_file_dat[] =
552     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
553     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
554     "File\tFile\n"
555     "augustus\taugustus\taugustus\t500\t\t\t8192\t1";
556 
557 static const char cl_custom_action_dat[] =
558     "Action\tType\tSource\tTarget\tISComments\n"
559     "s72\ti2\tS64\tS0\tS255\n"
560     "CustomAction\tAction\n"
561     "TestCommandlineProp\t19\t\tTest1\t\n";
562 
563 static const char cl_install_exec_seq_dat[] =
564     "Action\tCondition\tSequence\n"
565     "s72\tS255\tI2\n"
566     "InstallExecuteSequence\tAction\n"
567     "LaunchConditions\t\t100\n"
568     "ValidateProductID\t\t700\n"
569     "CostInitialize\t\t800\n"
570     "FileCost\t\t900\n"
571     "CostFinalize\t\t1000\n"
572     "TestCommandlineProp\tP=\"one\"\t1100\n"
573     "InstallInitialize\t\t1500\n"
574     "ProcessComponents\t\t1600\n"
575     "InstallValidate\t\t1400\n"
576     "InstallFinalize\t\t5000\n";
577 
578 static const msi_table tables[] =
579 {
580     ADD_TABLE(directory),
581     ADD_TABLE(component),
582     ADD_TABLE(feature),
583     ADD_TABLE(feature_comp),
584     ADD_TABLE(file),
585     ADD_TABLE(install_exec_seq),
586     ADD_TABLE(media),
587     ADD_TABLE(property),
588 };
589 
590 static const msi_table mcp_tables[] =
591 {
592     ADD_TABLE(directory),
593     ADD_TABLE(mcp_component),
594     ADD_TABLE(mcp_feature),
595     ADD_TABLE(mcp_feature_comp),
596     ADD_TABLE(mcp_file),
597     ADD_TABLE(install_exec_seq),
598     ADD_TABLE(media),
599     ADD_TABLE(property)
600 };
601 
602 static const msi_table lus0_tables[] =
603 {
604     ADD_TABLE(lus_component),
605     ADD_TABLE(directory),
606     ADD_TABLE(lus_feature),
607     ADD_TABLE(lus_feature_comp),
608     ADD_TABLE(lus_file),
609     ADD_TABLE(lus_install_exec_seq),
610     ADD_TABLE(lus0_media),
611     ADD_TABLE(property)
612 };
613 
614 static const msi_table lus1_tables[] =
615 {
616     ADD_TABLE(lus_component),
617     ADD_TABLE(directory),
618     ADD_TABLE(lus_feature),
619     ADD_TABLE(lus_feature_comp),
620     ADD_TABLE(lus_file),
621     ADD_TABLE(lus_install_exec_seq),
622     ADD_TABLE(lus1_media),
623     ADD_TABLE(property)
624 };
625 
626 static const msi_table lus2_tables[] =
627 {
628     ADD_TABLE(lus_component),
629     ADD_TABLE(directory),
630     ADD_TABLE(lus_feature),
631     ADD_TABLE(lus_feature_comp),
632     ADD_TABLE(lus_file),
633     ADD_TABLE(lus_install_exec_seq),
634     ADD_TABLE(lus2_media),
635     ADD_TABLE(property)
636 };
637 
638 static const msi_table spf_tables[] =
639 {
640     ADD_TABLE(lus_component),
641     ADD_TABLE(directory),
642     ADD_TABLE(lus_feature),
643     ADD_TABLE(lus_feature_comp),
644     ADD_TABLE(lus_file),
645     ADD_TABLE(lus0_media),
646     ADD_TABLE(property),
647     ADD_TABLE(spf_custom_action),
648     ADD_TABLE(spf_install_exec_seq),
649     ADD_TABLE(spf_install_ui_seq)
650 };
651 
652 static const msi_table sd_tables[] =
653 {
654     ADD_TABLE(directory),
655     ADD_TABLE(sd_component),
656     ADD_TABLE(sd_feature),
657     ADD_TABLE(sd_feature_comp),
658     ADD_TABLE(sd_file),
659     ADD_TABLE(sd_install_exec_seq),
660     ADD_TABLE(sd_install_ui_seq),
661     ADD_TABLE(sd_custom_action),
662     ADD_TABLE(media),
663     ADD_TABLE(property)
664 };
665 
666 static const msi_table ci_tables[] =
667 {
668     ADD_TABLE(ci_component),
669     ADD_TABLE(directory),
670     ADD_TABLE(lus_feature),
671     ADD_TABLE(lus_feature_comp),
672     ADD_TABLE(lus_file),
673     ADD_TABLE(ci_install_exec_seq),
674     ADD_TABLE(lus0_media),
675     ADD_TABLE(property),
676     ADD_TABLE(ci_custom_action),
677 };
678 
679 static const msi_table ci2_tables[] =
680 {
681     ADD_TABLE(ci2_component),
682     ADD_TABLE(directory),
683     ADD_TABLE(lus_feature),
684     ADD_TABLE(ci2_feature_comp),
685     ADD_TABLE(ci2_file),
686     ADD_TABLE(install_exec_seq),
687     ADD_TABLE(lus0_media),
688     ADD_TABLE(ci2_property),
689 };
690 
691 static const msi_table cl_tables[] =
692 {
693     ADD_TABLE(component),
694     ADD_TABLE(directory),
695     ADD_TABLE(feature),
696     ADD_TABLE(feature_comp),
697     ADD_TABLE(file),
698     ADD_TABLE(cl_custom_action),
699     ADD_TABLE(cl_install_exec_seq),
700     ADD_TABLE(media),
701     ADD_TABLE(property)
702 };
703 
704 static UINT set_summary_info(MSIHANDLE hdb, LPSTR prodcode)
705 {
706     UINT res;
707     MSIHANDLE suminfo;
708 
709     /* build summary info */
710     res = MsiGetSummaryInformationA(hdb, NULL, 7, &suminfo);
711     ok(res == ERROR_SUCCESS, "Failed to open summaryinfo\n");
712 
713     res = MsiSummaryInfoSetPropertyA(suminfo, 2, VT_LPSTR, 0, NULL,
714                                     "Installation Database");
715     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
716 
717     res = MsiSummaryInfoSetPropertyA(suminfo, 3, VT_LPSTR, 0, NULL,
718                                     "Installation Database");
719     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
720 
721     res = MsiSummaryInfoSetPropertyA(suminfo, 4, VT_LPSTR, 0, NULL,
722                                     "Wine Hackers");
723     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
724 
725     res = MsiSummaryInfoSetPropertyA(suminfo, 7, VT_LPSTR, 0, NULL,
726                                     ";1033");
727     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
728 
729     res = MsiSummaryInfoSetPropertyA(suminfo, PID_REVNUMBER, VT_LPSTR, 0, NULL,
730                                     "{A2078D65-94D6-4205-8DEE-F68D6FD622AA}");
731     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
732 
733     res = MsiSummaryInfoSetPropertyA(suminfo, 14, VT_I4, 100, NULL, NULL);
734     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
735 
736     res = MsiSummaryInfoSetPropertyA(suminfo, 15, VT_I4, 0, NULL, NULL);
737     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
738 
739     res = MsiSummaryInfoPersist(suminfo);
740     ok(res == ERROR_SUCCESS, "Failed to make summary info persist\n");
741 
742     res = MsiCloseHandle(suminfo);
743     ok(res == ERROR_SUCCESS, "Failed to close suminfo\n");
744 
745     return res;
746 }
747 
748 static MSIHANDLE create_package_db(LPSTR prodcode)
749 {
750     MSIHANDLE hdb = 0;
751     CHAR query[MAX_PATH];
752     UINT res;
753 
754     DeleteFileA(msifile);
755 
756     /* create an empty database */
757     res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
758     ok( res == ERROR_SUCCESS , "Failed to create database\n" );
759     if (res != ERROR_SUCCESS)
760         return hdb;
761 
762     res = MsiDatabaseCommit(hdb);
763     ok(res == ERROR_SUCCESS, "Failed to commit database\n");
764 
765     set_summary_info(hdb, prodcode);
766 
767     res = run_query(hdb, 0,
768             "CREATE TABLE `Directory` ( "
769             "`Directory` CHAR(255) NOT NULL, "
770             "`Directory_Parent` CHAR(255), "
771             "`DefaultDir` CHAR(255) NOT NULL "
772             "PRIMARY KEY `Directory`)");
773     ok(res == ERROR_SUCCESS , "Failed to create directory table\n");
774 
775     res = run_query(hdb, 0,
776             "CREATE TABLE `Property` ( "
777             "`Property` CHAR(72) NOT NULL, "
778             "`Value` CHAR(255) "
779             "PRIMARY KEY `Property`)");
780     ok(res == ERROR_SUCCESS , "Failed to create directory table\n");
781 
782     sprintf(query, "INSERT INTO `Property` "
783             "(`Property`, `Value`) "
784             "VALUES( 'ProductCode', '%s' )", prodcode);
785     res = run_query(hdb, 0, query);
786     ok(res == ERROR_SUCCESS , "Failed\n");
787 
788     res = MsiDatabaseCommit(hdb);
789     ok(res == ERROR_SUCCESS, "Failed to commit database\n");
790 
791     return hdb;
792 }
793 
794 static void test_usefeature(void)
795 {
796     INSTALLSTATE r;
797 
798     if (!pMsiUseFeatureExA)
799     {
800         win_skip("MsiUseFeatureExA not implemented\n");
801         return;
802     }
803 
804     r = MsiQueryFeatureStateA(NULL, NULL);
805     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
806 
807     r = MsiQueryFeatureStateA("{9085040-6000-11d3-8cfe-0150048383c9}" ,NULL);
808     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
809 
810     r = pMsiUseFeatureExA(NULL,NULL,0,0);
811     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
812 
813     r = pMsiUseFeatureExA(NULL, "WORDVIEWFiles", -2, 1 );
814     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
815 
816     r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}",
817                          NULL, -2, 0 );
818     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
819 
820     r = pMsiUseFeatureExA("{9085040-6000-11d3-8cfe-0150048383c9}",
821                          "WORDVIEWFiles", -2, 0 );
822     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
823 
824     r = pMsiUseFeatureExA("{0085040-6000-11d3-8cfe-0150048383c9}",
825                          "WORDVIEWFiles", -2, 0 );
826     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
827 
828     r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}",
829                          "WORDVIEWFiles", -2, 1 );
830     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
831 }
832 
833 static LONG delete_key( HKEY key, LPCSTR subkey, REGSAM access )
834 {
835     if (pRegDeleteKeyExA)
836         return pRegDeleteKeyExA( key, subkey, access, 0 );
837     return RegDeleteKeyA( key, subkey );
838 }
839 
840 static void test_null(void)
841 {
842     MSIHANDLE hpkg;
843     UINT r;
844     HKEY hkey;
845     DWORD dwType, cbData;
846     LPBYTE lpData = NULL;
847     INSTALLSTATE state;
848     REGSAM access = KEY_ALL_ACCESS;
849 
850     if (is_wow64)
851         access |= KEY_WOW64_64KEY;
852 
853     r = pMsiOpenPackageExW(NULL, 0, &hpkg);
854     ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
855 
856     state = MsiQueryProductStateW(NULL);
857     ok( state == INSTALLSTATE_INVALIDARG, "wrong return\n");
858 
859     r = MsiEnumFeaturesW(NULL,0,NULL,NULL);
860     ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
861 
862     r = MsiConfigureFeatureW(NULL, NULL, 0);
863     ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
864 
865     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", NULL, 0);
866     ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
867 
868     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000001}", "foo", 0);
869     ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
870 
871     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000002}", "foo", INSTALLSTATE_DEFAULT);
872     ok( r == ERROR_UNKNOWN_PRODUCT, "wrong error %d\n", r);
873 
874     /* make sure empty string to MsiGetProductInfo is not a handle to default registry value, saving and restoring the
875      * necessary registry values */
876 
877     /* empty product string */
878     r = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", 0, access, &hkey);
879     if (r == ERROR_ACCESS_DENIED)
880     {
881         skip("Not enough rights to perform tests\n");
882         return;
883     }
884     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
885 
886     r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
887     ok ( r == ERROR_SUCCESS || r == ERROR_FILE_NOT_FOUND, "wrong error %d\n", r);
888     if ( r == ERROR_SUCCESS )
889     {
890         lpData = HeapAlloc(GetProcessHeap(), 0, cbData);
891         if (!lpData)
892             skip("Out of memory\n");
893         else
894         {
895             r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
896             ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
897         }
898     }
899 
900     r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
901     if (r == ERROR_ACCESS_DENIED)
902     {
903         skip("Not enough rights to perform tests\n");
904         HeapFree(GetProcessHeap(), 0, lpData);
905         RegCloseKey(hkey);
906         return;
907     }
908     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
909 
910     r = MsiGetProductInfoA("", "", NULL, NULL);
911     ok ( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
912 
913     if (lpData)
914     {
915         r = RegSetValueExA(hkey, NULL, 0, dwType, lpData, cbData);
916         ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
917 
918         HeapFree(GetProcessHeap(), 0, lpData);
919     }
920     else
921     {
922         r = RegDeleteValueA(hkey, NULL);
923         ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
924     }
925 
926     r = RegCloseKey(hkey);
927     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
928 
929     /* empty attribute */
930     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}",
931                         0, NULL, 0, access, NULL, &hkey, NULL);
932     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
933 
934     r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
935     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
936 
937     r = MsiGetProductInfoA("{F1C3AF50-8B56-4A69-A00C-00773FE42F30}", "", NULL, NULL);
938     ok ( r == ERROR_UNKNOWN_PROPERTY, "wrong error %d\n", r);
939 
940     r = RegCloseKey(hkey);
941     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
942 
943     r = delete_key(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}",
944                    access & KEY_WOW64_64KEY);
945     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
946 }
947 
948 static void test_getcomponentpath(void)
949 {
950     INSTALLSTATE r;
951     char buffer[0x100];
952     DWORD sz;
953 
954     if(!pMsiGetComponentPathA)
955         return;
956 
957     r = pMsiGetComponentPathA( NULL, NULL, NULL, NULL );
958     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
959 
960     r = pMsiGetComponentPathA( "bogus", "bogus", NULL, NULL );
961     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
962 
963     r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", NULL, NULL );
964     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
965 
966     sz = sizeof buffer;
967     buffer[0]=0;
968     r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", buffer, &sz );
969     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
970 
971     r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C998E7}",
972         "{00000000-0000-0000-0000-000000000000}", buffer, &sz );
973     ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
974 
975     r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
976         "{00000000-0000-0000-0000-00000000}", buffer, &sz );
977     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
978 
979     r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
980         "{029E403D-A86A-1D11-5B5B0006799C897E}", buffer, &sz );
981     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
982 
983     r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C9987e}",
984                             "{00000000-A68A-11d1-5B5B-0006799C897E}", buffer, &sz );
985     ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
986 }
987 
988 static void create_test_files(void)
989 {
990     CreateDirectoryA("msitest", NULL);
991     create_file("msitest\\one.txt", 100);
992     CreateDirectoryA("msitest\\first", NULL);
993     create_file("msitest\\first\\two.txt", 100);
994     CreateDirectoryA("msitest\\second", NULL);
995     create_file("msitest\\second\\three.txt", 100);
996 
997     create_file("four.txt", 100);
998     create_file("five.txt", 100);
999     create_cab_file("msitest.cab", MEDIA_SIZE, "four.txt\0five.txt\0");
1000 
1001     create_file("msitest\\filename", 100);
1002     create_file("msitest\\service.exe", 100);
1003 
1004     DeleteFileA("four.txt");
1005     DeleteFileA("five.txt");
1006 }
1007 
1008 static void delete_test_files(void)
1009 {
1010     DeleteFileA("msitest.msi");
1011     DeleteFileA("msitest.cab");
1012     DeleteFileA("msitest\\second\\three.txt");
1013     DeleteFileA("msitest\\first\\two.txt");
1014     DeleteFileA("msitest\\one.txt");
1015     DeleteFileA("msitest\\service.exe");
1016     DeleteFileA("msitest\\filename");
1017     RemoveDirectoryA("msitest\\second");
1018     RemoveDirectoryA("msitest\\first");
1019     RemoveDirectoryA("msitest");
1020 }
1021 
1022 #define HASHSIZE sizeof(MSIFILEHASHINFO)
1023 
1024 static const struct
1025 {
1026     LPCSTR data;
1027     DWORD size;
1028     MSIFILEHASHINFO hash;
1029 } hash_data[] =
1030 {
1031     { "", 0,
1032       { HASHSIZE,
1033         { 0, 0, 0, 0 },
1034       },
1035     },
1036 
1037     { "abc", 0,
1038       { HASHSIZE,
1039         { 0x98500190, 0xb04fd23c, 0x7d3f96d6, 0x727fe128 },
1040       },
1041     },
1042 
1043     { "C:\\Program Files\\msitest\\caesar\n", 0,
1044       { HASHSIZE,
1045         { 0x2b566794, 0xfd42181b, 0x2514d6e4, 0x5768b4e2 },
1046       },
1047     },
1048 
1049     { "C:\\Program Files\\msitest\\caesar\n", 500,
1050       { HASHSIZE,
1051         { 0x58095058, 0x805efeff, 0x10f3483e, 0x0147d653 },
1052       },
1053     },
1054 };
1055 
1056 static void test_MsiGetFileHash(void)
1057 {
1058     const char name[] = "msitest.bin";
1059     UINT r;
1060     MSIFILEHASHINFO hash;
1061     DWORD i;
1062 
1063     if (!pMsiGetFileHashA)
1064     {
1065         win_skip("MsiGetFileHash not implemented\n");
1066         return;
1067     }
1068 
1069     hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
1070 
1071     /* szFilePath is NULL */
1072     r = pMsiGetFileHashA(NULL, 0, &hash);
1073     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1074 
1075     /* szFilePath is empty */
1076     r = pMsiGetFileHashA("", 0, &hash);
1077     ok(r == ERROR_PATH_NOT_FOUND || r == ERROR_BAD_PATHNAME,
1078        "Expected ERROR_PATH_NOT_FOUND or ERROR_BAD_PATHNAME, got %d\n", r);
1079 
1080     /* szFilePath is nonexistent */
1081     r = pMsiGetFileHashA(name, 0, &hash);
1082     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
1083 
1084     /* dwOptions is non-zero */
1085     r = pMsiGetFileHashA(name, 1, &hash);
1086     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1087 
1088     /* pHash.dwFileHashInfoSize is not correct */
1089     hash.dwFileHashInfoSize = 0;
1090     r = pMsiGetFileHashA(name, 0, &hash);
1091     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1092 
1093     /* pHash is NULL */
1094     r = pMsiGetFileHashA(name, 0, NULL);
1095     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1096 
1097     for (i = 0; i < sizeof(hash_data) / sizeof(hash_data[0]); i++)
1098     {
1099         int ret;
1100 
1101         create_file_data(name, hash_data[i].data, hash_data[i].size);
1102 
1103         memset(&hash, 0, sizeof(MSIFILEHASHINFO));
1104         hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
1105 
1106         r = pMsiGetFileHashA(name, 0, &hash);
1107         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1108 
1109         ret = memcmp(&hash, &hash_data[i].hash, HASHSIZE);
1110         ok(!ret, "Hash incorrect\n");
1111 
1112         DeleteFileA(name);
1113     }
1114 }
1115 
1116 /* copied from dlls/msi/registry.c */
1117 static BOOL squash_guid(LPCWSTR in, LPWSTR out)
1118 {
1119     DWORD i,n=1;
1120     GUID guid;
1121 
1122     if (FAILED(CLSIDFromString((LPCOLESTR)in, &guid)))
1123         return FALSE;
1124 
1125     for(i=0; i<8; i++)
1126         out[7-i] = in[n++];
1127     n++;
1128     for(i=0; i<4; i++)
1129         out[11-i] = in[n++];
1130     n++;
1131     for(i=0; i<4; i++)
1132         out[15-i] = in[n++];
1133     n++;
1134     for(i=0; i<2; i++)
1135     {
1136         out[17+i*2] = in[n++];
1137         out[16+i*2] = in[n++];
1138     }
1139     n++;
1140     for( ; i<8; i++)
1141     {
1142         out[17+i*2] = in[n++];
1143         out[16+i*2] = in[n++];
1144     }
1145     out[32]=0;
1146     return TRUE;
1147 }
1148 
1149 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
1150 {
1151     WCHAR guidW[MAX_PATH];
1152     WCHAR squashedW[MAX_PATH];
1153     GUID guid;
1154     HRESULT hr;
1155     int size;
1156 
1157     hr = CoCreateGuid(&guid);
1158     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
1159 
1160     size = StringFromGUID2(&guid, guidW, MAX_PATH);
1161     ok(size == 39, "Expected 39, got %d\n", hr);
1162 
1163     WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
1164     if (squashed)
1165     {
1166         squash_guid(guidW, squashedW);
1167         WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
1168     }
1169 }
1170 
1171 static char *get_user_sid(void)
1172 {
1173     HANDLE token;
1174     DWORD size = 0;
1175     TOKEN_USER *user;
1176     char *usersid = NULL;
1177 
1178     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
1179     GetTokenInformation(token, TokenUser, NULL, size, &size);
1180 
1181     user = HeapAlloc(GetProcessHeap(), 0, size);
1182     GetTokenInformation(token, TokenUser, user, size, &size);
1183     pConvertSidToStringSidA(user->User.Sid, &usersid);
1184     HeapFree(GetProcessHeap(), 0, user);
1185 
1186     CloseHandle(token);
1187     return usersid;
1188 }
1189 
1190 static void test_MsiQueryProductState(void)
1191 {
1192     CHAR prodcode[MAX_PATH];
1193     CHAR prod_squashed[MAX_PATH];
1194     CHAR keypath[MAX_PATH*2];
1195     LPSTR usersid;
1196     INSTALLSTATE state;
1197     LONG res;
1198     HKEY userkey, localkey, props;
1199     HKEY prodkey;
1200     DWORD data, error;
1201     REGSAM access = KEY_ALL_ACCESS;
1202 
1203     create_test_guid(prodcode, prod_squashed);
1204     usersid = get_user_sid();
1205 
1206     if (is_wow64)
1207         access |= KEY_WOW64_64KEY;
1208 
1209     /* NULL prodcode */
1210     SetLastError(0xdeadbeef);
1211     state = MsiQueryProductStateA(NULL);
1212     error = GetLastError();
1213     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1214     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1215 
1216     /* empty prodcode */
1217     SetLastError(0xdeadbeef);
1218     state = MsiQueryProductStateA("");
1219     error = GetLastError();
1220     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1221     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1222 
1223     /* garbage prodcode */
1224     SetLastError(0xdeadbeef);
1225     state = MsiQueryProductStateA("garbage");
1226     error = GetLastError();
1227     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1228     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1229 
1230     /* guid without brackets */
1231     SetLastError(0xdeadbeef);
1232     state = MsiQueryProductStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D");
1233     error = GetLastError();
1234     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1235     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1236 
1237     /* guid with brackets */
1238     SetLastError(0xdeadbeef);
1239     state = MsiQueryProductStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}");
1240     error = GetLastError();
1241     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1242     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1243        "expected ERROR_SUCCESS, got %u\n", error);
1244 
1245     /* same length as guid, but random */
1246     SetLastError(0xdeadbeef);
1247     state = MsiQueryProductStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93");
1248     error = GetLastError();
1249     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1250     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1251 
1252     /* MSIINSTALLCONTEXT_USERUNMANAGED */
1253 
1254     SetLastError(0xdeadbeef);
1255     state = MsiQueryProductStateA(prodcode);
1256     error = GetLastError();
1257     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1258     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1259        "expected ERROR_SUCCESS, got %u\n", error);
1260 
1261     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
1262     lstrcatA(keypath, prod_squashed);
1263 
1264     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
1265     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1266 
1267     /* user product key exists */
1268     SetLastError(0xdeadbeef);
1269     state = MsiQueryProductStateA(prodcode);
1270     error = GetLastError();
1271     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1272     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1273        "expected ERROR_SUCCESS, got %u\n", error);
1274 
1275     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
1276     lstrcatA(keypath, prodcode);
1277 
1278     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1279     if (res == ERROR_ACCESS_DENIED)
1280     {
1281         skip("Not enough rights to perform tests\n");
1282         RegDeleteKeyA(userkey, "");
1283         RegCloseKey(userkey);
1284         LocalFree(usersid);
1285         return;
1286     }
1287     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1288 
1289     /* local uninstall key exists */
1290     SetLastError(0xdeadbeef);
1291     state = MsiQueryProductStateA(prodcode);
1292     error = GetLastError();
1293     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1294     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1295        "expected ERROR_SUCCESS, got %u\n", error);
1296 
1297     data = 1;
1298     res = RegSetValueExA(localkey, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1299     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1300 
1301     /* WindowsInstaller value exists */
1302     SetLastError(0xdeadbeef);
1303     state = MsiQueryProductStateA(prodcode);
1304     error = GetLastError();
1305     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1306     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1307        "expected ERROR_SUCCESS, got %u\n", error);
1308 
1309     RegDeleteValueA(localkey, "WindowsInstaller");
1310     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1311 
1312     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1313     lstrcatA(keypath, usersid);
1314     lstrcatA(keypath, "\\Products\\");
1315     lstrcatA(keypath, prod_squashed);
1316 
1317     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1318     if (res == ERROR_ACCESS_DENIED)
1319     {
1320         skip("Not enough rights to perform tests\n");
1321         RegDeleteKeyA(userkey, "");
1322         RegCloseKey(userkey);
1323         LocalFree(usersid);
1324         return;
1325     }
1326     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1327 
1328     /* local product key exists */
1329     SetLastError(0xdeadbeef);
1330     state = MsiQueryProductStateA(prodcode);
1331     error = GetLastError();
1332     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1333     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1334        "expected ERROR_SUCCESS, got %u\n", error);
1335 
1336     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1337     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1338 
1339     /* install properties key exists */
1340     SetLastError(0xdeadbeef);
1341     state = MsiQueryProductStateA(prodcode);
1342     error = GetLastError();
1343     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1344     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1345        "expected ERROR_SUCCESS, got %u\n", error);
1346 
1347     data = 1;
1348     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1349     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1350 
1351     /* WindowsInstaller value exists */
1352     SetLastError(0xdeadbeef);
1353     state = MsiQueryProductStateA(prodcode);
1354     error = GetLastError();
1355     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1356     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1357        "expected ERROR_SUCCESS, got %u\n", error);
1358 
1359     data = 2;
1360     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1361     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1362 
1363     /* WindowsInstaller value is not 1 */
1364     SetLastError(0xdeadbeef);
1365     state = MsiQueryProductStateA(prodcode);
1366     error = GetLastError();
1367     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1368     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1369        "expected ERROR_SUCCESS, got %u\n", error);
1370 
1371     RegDeleteKeyA(userkey, "");
1372 
1373     /* user product key does not exist */
1374     SetLastError(0xdeadbeef);
1375     state = MsiQueryProductStateA(prodcode);
1376     error = GetLastError();
1377     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1378     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1379        "expected ERROR_SUCCESS, got %u\n", error);
1380 
1381     RegDeleteValueA(props, "WindowsInstaller");
1382     delete_key(props, "", access & KEY_WOW64_64KEY);
1383     RegCloseKey(props);
1384     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1385     RegCloseKey(localkey);
1386     RegDeleteKeyA(userkey, "");
1387     RegCloseKey(userkey);
1388 
1389     /* MSIINSTALLCONTEXT_USERMANAGED */
1390 
1391     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
1392     lstrcatA(keypath, usersid);
1393     lstrcatA(keypath, "\\Installer\\Products\\");
1394     lstrcatA(keypath, prod_squashed);
1395 
1396     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
1397     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1398 
1399     state = MsiQueryProductStateA(prodcode);
1400     ok(state == INSTALLSTATE_ADVERTISED,
1401        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1402 
1403     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1404     lstrcatA(keypath, usersid);
1405     lstrcatA(keypath, "\\Products\\");
1406     lstrcatA(keypath, prod_squashed);
1407 
1408     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1409     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1410 
1411     state = MsiQueryProductStateA(prodcode);
1412     ok(state == INSTALLSTATE_ADVERTISED,
1413        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1414 
1415     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1416     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1417 
1418     state = MsiQueryProductStateA(prodcode);
1419     ok(state == INSTALLSTATE_ADVERTISED,
1420        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1421 
1422     data = 1;
1423     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1424     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1425 
1426     /* WindowsInstaller value exists */
1427     state = MsiQueryProductStateA(prodcode);
1428     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1429 
1430     RegDeleteValueA(props, "WindowsInstaller");
1431     delete_key(props, "", access & KEY_WOW64_64KEY);
1432     RegCloseKey(props);
1433     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1434     RegCloseKey(localkey);
1435     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
1436     RegCloseKey(prodkey);
1437 
1438     /* MSIINSTALLCONTEXT_MACHINE */
1439 
1440     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
1441     lstrcatA(keypath, prod_squashed);
1442 
1443     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
1444     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1445 
1446     state = MsiQueryProductStateA(prodcode);
1447     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1448 
1449     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1450     lstrcatA(keypath, "S-1-5-18\\Products\\");
1451     lstrcatA(keypath, prod_squashed);
1452 
1453     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1454     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1455 
1456     state = MsiQueryProductStateA(prodcode);
1457     ok(state == INSTALLSTATE_ADVERTISED,
1458        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1459 
1460     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1461     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1462 
1463     state = MsiQueryProductStateA(prodcode);
1464     ok(state == INSTALLSTATE_ADVERTISED,
1465        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1466 
1467     data = 1;
1468     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1469     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1470 
1471     /* WindowsInstaller value exists */
1472     state = MsiQueryProductStateA(prodcode);
1473     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1474 
1475     RegDeleteValueA(props, "WindowsInstaller");
1476     delete_key(props, "", access & KEY_WOW64_64KEY);
1477     RegCloseKey(props);
1478     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1479     RegCloseKey(localkey);
1480     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
1481     RegCloseKey(prodkey);
1482 
1483     LocalFree(usersid);
1484 }
1485 
1486 static const char table_enc85[] =
1487 "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
1488 "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
1489 "yz{}~";
1490 
1491 /*
1492  *  Encodes a base85 guid given a GUID pointer
1493  *  Caller should provide a 21 character buffer for the encoded string.
1494  */
1495 static void encode_base85_guid( GUID *guid, LPWSTR str )
1496 {
1497     unsigned int x, *p, i;
1498 
1499     p = (unsigned int*) guid;
1500     for( i=0; i<4; i++ )
1501     {
1502         x = p[i];
1503         *str++ = table_enc85[x%85];
1504         x = x/85;
1505         *str++ = table_enc85[x%85];
1506         x = x/85;
1507         *str++ = table_enc85[x%85];
1508         x = x/85;
1509         *str++ = table_enc85[x%85];
1510         x = x/85;
1511         *str++ = table_enc85[x%85];
1512     }
1513     *str = 0;
1514 }
1515 
1516 static void compose_base85_guid(LPSTR component, LPSTR comp_base85, LPSTR squashed)
1517 {
1518     WCHAR guidW[MAX_PATH];
1519     WCHAR base85W[MAX_PATH];
1520     WCHAR squashedW[MAX_PATH];
1521     GUID guid;
1522     HRESULT hr;
1523     int size;
1524 
1525     hr = CoCreateGuid(&guid);
1526     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
1527 
1528     size = StringFromGUID2(&guid, guidW, MAX_PATH);
1529     ok(size == 39, "Expected 39, got %d\n", hr);
1530 
1531     WideCharToMultiByte(CP_ACP, 0, guidW, size, component, MAX_PATH, NULL, NULL);
1532     encode_base85_guid(&guid, base85W);
1533     WideCharToMultiByte(CP_ACP, 0, base85W, -1, comp_base85, MAX_PATH, NULL, NULL);
1534     squash_guid(guidW, squashedW);
1535     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
1536 }
1537 
1538 static void test_MsiQueryFeatureState(void)
1539 {
1540     HKEY userkey, localkey, compkey, compkey2;
1541     CHAR prodcode[MAX_PATH];
1542     CHAR prod_squashed[MAX_PATH];
1543     CHAR component[MAX_PATH];
1544     CHAR comp_base85[MAX_PATH];
1545     CHAR comp_squashed[MAX_PATH], comp_squashed2[MAX_PATH];
1546     CHAR keypath[MAX_PATH*2];
1547     INSTALLSTATE state;
1548     LPSTR usersid;
1549     LONG res;
1550     REGSAM access = KEY_ALL_ACCESS;
1551     DWORD error;
1552 
1553     create_test_guid(prodcode, prod_squashed);
1554     compose_base85_guid(component, comp_base85, comp_squashed);
1555     compose_base85_guid(component, comp_base85 + 20, comp_squashed2);
1556     usersid = get_user_sid();
1557 
1558     if (is_wow64)
1559         access |= KEY_WOW64_64KEY;
1560 
1561     /* NULL prodcode */
1562     SetLastError(0xdeadbeef);
1563     state = MsiQueryFeatureStateA(NULL, "feature");
1564     error = GetLastError();
1565     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1566     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1567 
1568     /* empty prodcode */
1569     SetLastError(0xdeadbeef);
1570     state = MsiQueryFeatureStateA("", "feature");
1571     error = GetLastError();
1572     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1573     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1574 
1575     /* garbage prodcode */
1576     SetLastError(0xdeadbeef);
1577     state = MsiQueryFeatureStateA("garbage", "feature");
1578     error = GetLastError();
1579     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1580     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1581 
1582     /* guid without brackets */
1583     SetLastError(0xdeadbeef);
1584     state = MsiQueryFeatureStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", "feature");
1585     error = GetLastError();
1586     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1587     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1588 
1589     /* guid with brackets */
1590     SetLastError(0xdeadbeef);
1591     state = MsiQueryFeatureStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", "feature");
1592     error = GetLastError();
1593     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1594     ok(error == ERROR_SUCCESS || broken(error == ERROR_ALREADY_EXISTS) /* win2k */,
1595        "expected ERROR_SUCCESS, got %u\n", error);
1596 
1597     /* same length as guid, but random */
1598     SetLastError(0xdeadbeef);
1599     state = MsiQueryFeatureStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", "feature");
1600     error = GetLastError();
1601     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1602     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1603 
1604     /* NULL szFeature */
1605     SetLastError(0xdeadbeef);
1606     state = MsiQueryFeatureStateA(prodcode, NULL);
1607     error = GetLastError();
1608     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1609     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1610 
1611     /* empty szFeature */
1612     SetLastError(0xdeadbeef);
1613     state = MsiQueryFeatureStateA(prodcode, "");
1614     error = GetLastError();
1615     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1616     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1617        "expected ERROR_SUCCESS, got %u\n", error);
1618 
1619     /* feature key does not exist yet */
1620     SetLastError(0xdeadbeef);
1621     state = MsiQueryFeatureStateA(prodcode, "feature");
1622     error = GetLastError();
1623     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1624     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1625        "expected ERROR_SUCCESS, got %u\n", error);
1626 
1627     /* MSIINSTALLCONTEXT_USERUNMANAGED */
1628 
1629     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Features\\");
1630     lstrcatA(keypath, prod_squashed);
1631 
1632     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
1633     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1634 
1635     /* feature key exists */
1636     SetLastError(0xdeadbeef);
1637     state = MsiQueryFeatureStateA(prodcode, "feature");
1638     error = GetLastError();
1639     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1640     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1641        "expected ERROR_SUCCESS, got %u\n", error);
1642 
1643     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 2);
1644     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1645 
1646     /* feature value exists */
1647     SetLastError(0xdeadbeef);
1648     state = MsiQueryFeatureStateA(prodcode, "feature");
1649     error = GetLastError();
1650     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1651     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1652        "expected ERROR_SUCCESS, got %u\n", error);
1653 
1654     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1655     lstrcatA(keypath, usersid);
1656     lstrcatA(keypath, "\\Products\\");
1657     lstrcatA(keypath, prod_squashed);
1658     lstrcatA(keypath, "\\Features");
1659 
1660     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1661     if (res == ERROR_ACCESS_DENIED)
1662     {
1663         skip("Not enough rights to perform tests\n");
1664         RegDeleteKeyA(userkey, "");
1665         RegCloseKey(userkey);
1666         LocalFree(usersid);
1667         return;
1668     }
1669     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1670 
1671     /* userdata features key exists */
1672     SetLastError(0xdeadbeef);
1673     state = MsiQueryFeatureStateA(prodcode, "feature");
1674     error = GetLastError();
1675     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1676     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1677        "expected ERROR_SUCCESS, got %u\n", error);
1678 
1679     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
1680     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1681 
1682     SetLastError(0xdeadbeef);
1683     state = MsiQueryFeatureStateA(prodcode, "feature");
1684     error = GetLastError();
1685     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
1686     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1687        "expected ERROR_SUCCESS, got %u\n", error);
1688 
1689     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
1690     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1691 
1692     SetLastError(0xdeadbeef);
1693     state = MsiQueryFeatureStateA(prodcode, "feature");
1694     error = GetLastError();
1695     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1696     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1697        "expected ERROR_SUCCESS, got %u\n", error);
1698 
1699     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
1700     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1701 
1702     SetLastError(0xdeadbeef);
1703     state = MsiQueryFeatureStateA(prodcode, "feature");
1704     error = GetLastError();
1705     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1706     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1707        "expected ERROR_SUCCESS, got %u\n", error);
1708 
1709     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
1710     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1711 
1712     SetLastError(0xdeadbeef);
1713     state = MsiQueryFeatureStateA(prodcode, "feature");
1714     error = GetLastError();
1715     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1716     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1717        "expected ERROR_SUCCESS, got %u\n", error);
1718 
1719     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1720     lstrcatA(keypath, usersid);
1721     lstrcatA(keypath, "\\Components\\");
1722     lstrcatA(keypath, comp_squashed);
1723 
1724     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
1725     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1726 
1727     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1728     lstrcatA(keypath, usersid);
1729     lstrcatA(keypath, "\\Components\\");
1730     lstrcatA(keypath, comp_squashed2);
1731 
1732     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
1733     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1734 
1735     SetLastError(0xdeadbeef);
1736     state = MsiQueryFeatureStateA(prodcode, "feature");
1737     error = GetLastError();
1738     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1739     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1740        "expected ERROR_SUCCESS, got %u\n", error);
1741 
1742     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
1743     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1744 
1745     SetLastError(0xdeadbeef);
1746     state = MsiQueryFeatureStateA(prodcode, "feature");
1747     error = GetLastError();
1748     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1749     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1750        "expected ERROR_SUCCESS, got %u\n", error);
1751 
1752     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
1753     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1754 
1755     SetLastError(0xdeadbeef);
1756     state = MsiQueryFeatureStateA(prodcode, "feature");
1757     error = GetLastError();
1758     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1759     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1760        "expected ERROR_SUCCESS, got %u\n", error);
1761 
1762     res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
1763     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1764 
1765     /* INSTALLSTATE_LOCAL */
1766     SetLastError(0xdeadbeef);
1767     state = MsiQueryFeatureStateA(prodcode, "feature");
1768     error = GetLastError();
1769     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1770     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1771        "expected ERROR_SUCCESS, got %u\n", error);
1772 
1773     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01\\", 4);
1774     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1775 
1776     /* INSTALLSTATE_SOURCE */
1777     SetLastError(0xdeadbeef);
1778     state = MsiQueryFeatureStateA(prodcode, "feature");
1779     error = GetLastError();
1780     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
1781     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1782        "expected ERROR_SUCCESS, got %u\n", error);
1783 
1784     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
1785     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1786 
1787     /* bad INSTALLSTATE_SOURCE */
1788     SetLastError(0xdeadbeef);
1789     state = MsiQueryFeatureStateA(prodcode, "feature");
1790     error = GetLastError();
1791     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1792     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1793        "expected ERROR_SUCCESS, got %u\n", error);
1794 
1795     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01a", 4);
1796     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1797 
1798     /* INSTALLSTATE_SOURCE */
1799     SetLastError(0xdeadbeef);
1800     state = MsiQueryFeatureStateA(prodcode, "feature");
1801     error = GetLastError();
1802     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
1803     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1804        "expected ERROR_SUCCESS, got %u\n", error);
1805 
1806     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
1807     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1808 
1809     /* bad INSTALLSTATE_SOURCE */
1810     SetLastError(0xdeadbeef);
1811     state = MsiQueryFeatureStateA(prodcode, "feature");
1812     error = GetLastError();
1813     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1814     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1815        "expected ERROR_SUCCESS, got %u\n", error);
1816 
1817     RegDeleteValueA(compkey, prod_squashed);
1818     RegDeleteValueA(compkey2, prod_squashed);
1819     delete_key(compkey, "", access & KEY_WOW64_64KEY);
1820     delete_key(compkey2, "", access & KEY_WOW64_64KEY);
1821     RegDeleteValueA(localkey, "feature");
1822     RegDeleteValueA(userkey, "feature");
1823     RegDeleteKeyA(userkey, "");
1824     RegCloseKey(compkey);
1825     RegCloseKey(compkey2);
1826     RegCloseKey(localkey);
1827     RegCloseKey(userkey);
1828 
1829     /* MSIINSTALLCONTEXT_USERMANAGED */
1830 
1831     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
1832     lstrcatA(keypath, usersid);
1833     lstrcatA(keypath, "\\Installer\\Features\\");
1834     lstrcatA(keypath, prod_squashed);
1835 
1836     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
1837     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1838 
1839     /* feature key exists */
1840     state = MsiQueryFeatureStateA(prodcode, "feature");
1841     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1842 
1843     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 1);
1844     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1845 
1846     /* feature value exists */
1847     state = MsiQueryFeatureStateA(prodcode, "feature");
1848     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1849 
1850     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1851     lstrcatA(keypath, usersid);
1852     lstrcatA(keypath, "\\Products\\");
1853     lstrcatA(keypath, prod_squashed);
1854     lstrcatA(keypath, "\\Features");
1855 
1856     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1857     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1858 
1859     /* userdata features key exists */
1860     state = MsiQueryFeatureStateA(prodcode, "feature");
1861     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1862 
1863     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
1864     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1865 
1866     state = MsiQueryFeatureStateA(prodcode, "feature");
1867     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
1868 
1869     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
1870     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1871 
1872     state = MsiQueryFeatureStateA(prodcode, "feature");
1873     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1874 
1875     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
1876     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1877 
1878     state = MsiQueryFeatureStateA(prodcode, "feature");
1879     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1880 
1881     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
1882     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1883 
1884     state = MsiQueryFeatureStateA(prodcode, "feature");
1885     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1886 
1887     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1888     lstrcatA(keypath, usersid);
1889     lstrcatA(keypath, "\\Components\\");
1890     lstrcatA(keypath, comp_squashed);
1891 
1892     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
1893     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1894 
1895     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1896     lstrcatA(keypath, usersid);
1897     lstrcatA(keypath, "\\Components\\");
1898     lstrcatA(keypath, comp_squashed2);
1899 
1900     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
1901     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1902 
1903     state = MsiQueryFeatureStateA(prodcode, "feature");
1904     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1905 
1906     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
1907     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1908 
1909     state = MsiQueryFeatureStateA(prodcode, "feature");
1910     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1911 
1912     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
1913     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1914 
1915     state = MsiQueryFeatureStateA(prodcode, "feature");
1916     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1917 
1918     res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
1919     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1920 
1921     state = MsiQueryFeatureStateA(prodcode, "feature");
1922     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1923 
1924     RegDeleteValueA(compkey, prod_squashed);
1925     RegDeleteValueA(compkey2, prod_squashed);
1926     delete_key(compkey, "", access & KEY_WOW64_64KEY);
1927     delete_key(compkey2, "", access & KEY_WOW64_64KEY);
1928     RegDeleteValueA(localkey, "feature");
1929     RegDeleteValueA(userkey, "feature");
1930     delete_key(userkey, "", access & KEY_WOW64_64KEY);
1931     RegCloseKey(compkey);
1932     RegCloseKey(compkey2);
1933     RegCloseKey(localkey);
1934     RegCloseKey(userkey);
1935 
1936     /* MSIINSTALLCONTEXT_MACHINE */
1937 
1938     lstrcpyA(keypath, "Software\\Classes\\Installer\\Features\\");
1939     lstrcatA(keypath, prod_squashed);
1940 
1941     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
1942     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1943 
1944     /* feature key exists */
1945     state = MsiQueryFeatureStateA(prodcode, "feature");
1946     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1947 
1948     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 1);
1949     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1950 
1951     /* feature value exists */
1952     state = MsiQueryFeatureStateA(prodcode, "feature");
1953     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1954 
1955     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1956     lstrcatA(keypath, "S-1-5-18\\Products\\");
1957     lstrcatA(keypath, prod_squashed);
1958     lstrcatA(keypath, "\\Features");
1959 
1960     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1961     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1962 
1963     /* userdata features key exists */
1964     state = MsiQueryFeatureStateA(prodcode, "feature");
1965     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1966 
1967     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
1968     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1969 
1970     state = MsiQueryFeatureStateA(prodcode, "feature");
1971     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
1972 
1973     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
1974     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1975 
1976     state = MsiQueryFeatureStateA(prodcode, "feature");
1977     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1978 
1979     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
1980     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1981 
1982     state = MsiQueryFeatureStateA(prodcode, "feature");
1983     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1984 
1985     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
1986     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1987 
1988     state = MsiQueryFeatureStateA(prodcode, "feature");
1989     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1990 
1991     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1992     lstrcatA(keypath, "S-1-5-18\\Components\\");
1993     lstrcatA(keypath, comp_squashed);
1994 
1995     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
1996     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1997 
1998     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1999     lstrcatA(keypath, "S-1-5-18\\Components\\");
2000     lstrcatA(keypath, comp_squashed2);
2001 
2002     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
2003     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2004 
2005     state = MsiQueryFeatureStateA(prodcode, "feature");
2006     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2007 
2008     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
2009     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2010 
2011     state = MsiQueryFeatureStateA(prodcode, "feature");
2012     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2013 
2014     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
2015     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2016 
2017     state = MsiQueryFeatureStateA(prodcode, "feature");
2018     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2019 
2020     res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
2021     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2022 
2023     state = MsiQueryFeatureStateA(prodcode, "feature");
2024     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2025 
2026     RegDeleteValueA(compkey, prod_squashed);
2027     RegDeleteValueA(compkey2, prod_squashed);
2028     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2029     delete_key(compkey2, "", access & KEY_WOW64_64KEY);
2030     RegDeleteValueA(localkey, "feature");
2031     RegDeleteValueA(userkey, "feature");
2032     delete_key(userkey, "", access & KEY_WOW64_64KEY);
2033     RegCloseKey(compkey);
2034     RegCloseKey(compkey2);
2035     RegCloseKey(localkey);
2036     RegCloseKey(userkey);
2037     LocalFree(usersid);
2038 }
2039 
2040 static void test_MsiQueryComponentState(void)
2041 {
2042     HKEY compkey, prodkey;
2043     CHAR prodcode[MAX_PATH];
2044     CHAR prod_squashed[MAX_PATH];
2045     CHAR component[MAX_PATH];
2046     CHAR comp_base85[MAX_PATH];
2047     CHAR comp_squashed[MAX_PATH];
2048     CHAR keypath[MAX_PATH];
2049     INSTALLSTATE state;
2050     LPSTR usersid;
2051     LONG res;
2052     UINT r;
2053     REGSAM access = KEY_ALL_ACCESS;
2054     DWORD error;
2055 
2056     static const INSTALLSTATE MAGIC_ERROR = 0xdeadbeef;
2057 
2058     if (!pMsiQueryComponentStateA)
2059     {
2060         win_skip("MsiQueryComponentStateA not implemented\n");
2061         return;
2062     }
2063 
2064     create_test_guid(prodcode, prod_squashed);
2065     compose_base85_guid(component, comp_base85, comp_squashed);
2066     usersid = get_user_sid();
2067 
2068     if (is_wow64)
2069         access |= KEY_WOW64_64KEY;
2070 
2071     /* NULL szProductCode */
2072     state = MAGIC_ERROR;
2073     SetLastError(0xdeadbeef);
2074     r = pMsiQueryComponentStateA(NULL, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2075     error = GetLastError();
2076     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2077     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2078     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2079 
2080     /* empty szProductCode */
2081     state = MAGIC_ERROR;
2082     SetLastError(0xdeadbeef);
2083     r = pMsiQueryComponentStateA("", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2084     error = GetLastError();
2085     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2086     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2087     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2088 
2089     /* random szProductCode */
2090     state = MAGIC_ERROR;
2091     SetLastError(0xdeadbeef);
2092     r = pMsiQueryComponentStateA("random", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2093     error = GetLastError();
2094     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2095     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2096     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2097 
2098     /* GUID-length szProductCode */
2099     state = MAGIC_ERROR;
2100     SetLastError(0xdeadbeef);
2101     r = pMsiQueryComponentStateA("DJANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KDE", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2102     error = GetLastError();
2103     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2104     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2105     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2106 
2107     /* GUID-length with brackets */
2108     state = MAGIC_ERROR;
2109     SetLastError(0xdeadbeef);
2110     r = pMsiQueryComponentStateA("{JANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KD}", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2111     error = GetLastError();
2112     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2113     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2114     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2115 
2116     /* actual GUID */
2117     state = MAGIC_ERROR;
2118     SetLastError(0xdeadbeef);
2119     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2120     error = GetLastError();
2121     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2122     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2123     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2124 
2125     state = MAGIC_ERROR;
2126     SetLastError(0xdeadbeef);
2127     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2128     error = GetLastError();
2129     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2130     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2131     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2132 
2133     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
2134     lstrcatA(keypath, prod_squashed);
2135 
2136     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2137     if (res == ERROR_ACCESS_DENIED)
2138     {
2139         skip("Not enough rights to perform tests\n");
2140         LocalFree(usersid);
2141         return;
2142     }
2143     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2144 
2145     state = MAGIC_ERROR;
2146     SetLastError(0xdeadbeef);
2147     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2148     error = GetLastError();
2149     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2150     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2151     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2152 
2153     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2154     RegCloseKey(prodkey);
2155 
2156     /* create local system product key */
2157     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\");
2158     lstrcatA(keypath, prod_squashed);
2159     lstrcatA(keypath, "\\InstallProperties");
2160 
2161     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2162     if (res == ERROR_ACCESS_DENIED)
2163     {
2164         skip("Not enough rights to perform tests\n");
2165         LocalFree(usersid);
2166         return;
2167     }
2168     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2169 
2170     /* local system product key exists */
2171     state = MAGIC_ERROR;
2172     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2173     error = GetLastError();
2174     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2175     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2176     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2177 
2178     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2179     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2180 
2181     /* LocalPackage value exists */
2182     state = MAGIC_ERROR;
2183     SetLastError(0xdeadbeef);
2184     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2185     error = GetLastError();
2186     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2187     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2188     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2189 
2190     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\");
2191     lstrcatA(keypath, comp_squashed);
2192 
2193     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2194     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2195 
2196     /* component key exists */
2197     state = MAGIC_ERROR;
2198     SetLastError(0xdeadbeef);
2199     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2200     error = GetLastError();
2201     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2202     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2203     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2204 
2205     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
2206     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2207 
2208     /* component\product exists */
2209     state = MAGIC_ERROR;
2210     SetLastError(0xdeadbeef);
2211     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2212     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2213     error = GetLastError();
2214     ok(state == INSTALLSTATE_NOTUSED || state == INSTALLSTATE_LOCAL,
2215        "Expected INSTALLSTATE_NOTUSED or INSTALLSTATE_LOCAL, got %d\n", state);
2216     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2217 
2218     /* NULL component, product exists */
2219     state = MAGIC_ERROR;
2220     SetLastError(0xdeadbeef);
2221     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, NULL, &state);
2222     error = GetLastError();
2223     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2224     ok(state == MAGIC_ERROR, "Expected state not changed, got %d\n", state);
2225     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2226 
2227     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
2228     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2229 
2230     /* INSTALLSTATE_LOCAL */
2231     state = MAGIC_ERROR;
2232     SetLastError(0xdeadbeef);
2233     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2234     error = GetLastError();
2235     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2236     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2237     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2238 
2239     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01\\", 4);
2240     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2241 
2242     /* INSTALLSTATE_SOURCE */
2243     state = MAGIC_ERROR;
2244     SetLastError(0xdeadbeef);
2245     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2246     error = GetLastError();
2247     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2248     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2249     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2250 
2251     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
2252     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2253 
2254     /* bad INSTALLSTATE_SOURCE */
2255     state = MAGIC_ERROR;
2256     SetLastError(0xdeadbeef);
2257     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2258     error = GetLastError();
2259     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2260     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2261     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2262 
2263     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01a", 4);
2264     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2265 
2266     /* INSTALLSTATE_SOURCE */
2267     state = MAGIC_ERROR;
2268     SetLastError(0xdeadbeef);
2269     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2270     error = GetLastError();
2271     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2272     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2273     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2274 
2275     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01:", 4);
2276     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2277 
2278     /* registry component */
2279     state = MAGIC_ERROR;
2280     SetLastError(0xdeadbeef);
2281     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2282     error = GetLastError();
2283     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2284     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2285     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2286 
2287     RegDeleteValueA(prodkey, "LocalPackage");
2288     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2289     RegDeleteValueA(compkey, prod_squashed);
2290     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2291     RegCloseKey(prodkey);
2292     RegCloseKey(compkey);
2293 
2294     /* MSIINSTALLCONTEXT_USERUNMANAGED */
2295 
2296     state = MAGIC_ERROR;
2297     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2298     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2299     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2300 
2301     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2302     lstrcatA(keypath, prod_squashed);
2303 
2304     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
2305     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2306 
2307     state = MAGIC_ERROR;
2308     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2309     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2310     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2311 
2312     RegDeleteKeyA(prodkey, "");
2313     RegCloseKey(prodkey);
2314 
2315     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2316     lstrcatA(keypath, usersid);
2317     lstrcatA(keypath, "\\Products\\");
2318     lstrcatA(keypath, prod_squashed);
2319     lstrcatA(keypath, "\\InstallProperties");
2320 
2321     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2322     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2323 
2324     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2325     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2326 
2327     RegCloseKey(prodkey);
2328 
2329     state = MAGIC_ERROR;
2330     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2331     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2332     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2333 
2334     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2335     lstrcatA(keypath, usersid);
2336     lstrcatA(keypath, "\\Components\\");
2337     lstrcatA(keypath, comp_squashed);
2338 
2339     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2340     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2341 
2342     /* component key exists */
2343     state = MAGIC_ERROR;
2344     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2345     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2346     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2347 
2348     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
2349     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2350 
2351     /* component\product exists */
2352     state = MAGIC_ERROR;
2353     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2354     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2355     ok(state == INSTALLSTATE_NOTUSED || state == INSTALLSTATE_LOCAL,
2356        "Expected INSTALLSTATE_NOTUSED or INSTALLSTATE_LOCAL, got %d\n", state);
2357 
2358     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
2359     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2360 
2361     state = MAGIC_ERROR;
2362     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2363     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2364     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2365 
2366     /* MSIINSTALLCONTEXT_USERMANAGED */
2367 
2368     state = MAGIC_ERROR;
2369     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2370     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2371     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2372 
2373     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2374     lstrcatA(keypath, prod_squashed);
2375 
2376     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
2377     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2378 
2379     state = MAGIC_ERROR;
2380     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2381     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2382     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2383 
2384     RegDeleteKeyA(prodkey, "");
2385     RegCloseKey(prodkey);
2386 
2387     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
2388     lstrcatA(keypath, usersid);
2389     lstrcatA(keypath, "\\Installer\\Products\\");
2390     lstrcatA(keypath, prod_squashed);
2391 
2392     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2393     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2394 
2395     state = MAGIC_ERROR;
2396     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2397     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2398     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2399 
2400     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2401     RegCloseKey(prodkey);
2402 
2403     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2404     lstrcatA(keypath, usersid);
2405     lstrcatA(keypath, "\\Products\\");
2406     lstrcatA(keypath, prod_squashed);
2407     lstrcatA(keypath, "\\InstallProperties");
2408 
2409     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2410     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2411 
2412     res = RegSetValueExA(prodkey, "ManagedLocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2413     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2414 
2415     state = MAGIC_ERROR;
2416     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2417     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2418     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2419 
2420     RegDeleteValueA(prodkey, "LocalPackage");
2421     RegDeleteValueA(prodkey, "ManagedLocalPackage");
2422     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2423     RegDeleteValueA(compkey, prod_squashed);
2424     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2425     RegCloseKey(prodkey);
2426     RegCloseKey(compkey);
2427     LocalFree(usersid);
2428 }
2429 
2430 static void test_MsiGetComponentPath(void)
2431 {
2432     HKEY compkey, prodkey, installprop;
2433     CHAR prodcode[MAX_PATH];
2434     CHAR prod_squashed[MAX_PATH];
2435     CHAR component[MAX_PATH];
2436     CHAR comp_base85[MAX_PATH];
2437     CHAR comp_squashed[MAX_PATH];
2438     CHAR keypath[MAX_PATH];
2439     CHAR path[MAX_PATH];
2440     INSTALLSTATE state;
2441     LPSTR usersid;
2442     DWORD size, val;
2443     REGSAM access = KEY_ALL_ACCESS;
2444     LONG res;
2445 
2446     create_test_guid(prodcode, prod_squashed);
2447     compose_base85_guid(component, comp_base85, comp_squashed);
2448     usersid = get_user_sid();
2449 
2450     if (is_wow64)
2451         access |= KEY_WOW64_64KEY;
2452 
2453     /* NULL szProduct */
2454     size = MAX_PATH;
2455     state = MsiGetComponentPathA(NULL, component, path, &size);
2456     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2457     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2458 
2459     /* NULL szComponent */
2460     size = MAX_PATH;
2461     state = MsiGetComponentPathA(prodcode, NULL, path, &size);
2462     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2463     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2464 
2465     size = MAX_PATH;
2466     state = MsiLocateComponentA(NULL, path, &size);
2467     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2468     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2469 
2470     /* NULL lpPathBuf */
2471     size = MAX_PATH;
2472     state = MsiGetComponentPathA(prodcode, component, NULL, &size);
2473     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2474     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2475 
2476     size = MAX_PATH;
2477     state = MsiLocateComponentA(component, NULL, &size);
2478     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2479     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2480 
2481     /* NULL pcchBuf */
2482     size = MAX_PATH;
2483     state = MsiGetComponentPathA(prodcode, component, path, NULL);
2484     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2485     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2486 
2487     size = MAX_PATH;
2488     state = MsiLocateComponentA(component, path, NULL);
2489     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2490     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2491 
2492     /* all params valid */
2493     size = MAX_PATH;
2494     state = MsiGetComponentPathA(prodcode, component, path, &size);
2495     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2496     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2497 
2498     size = MAX_PATH;
2499     state = MsiLocateComponentA(component, path, &size);
2500     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2501     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2502 
2503     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2504     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
2505     lstrcatA(keypath, comp_squashed);
2506 
2507     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2508     if (res == ERROR_ACCESS_DENIED)
2509     {
2510         skip("Not enough rights to perform tests\n");
2511         LocalFree(usersid);
2512         return;
2513     }
2514     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2515 
2516     /* local system component key exists */
2517     size = MAX_PATH;
2518     state = MsiGetComponentPathA(prodcode, component, path, &size);
2519     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2520     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2521 
2522     size = MAX_PATH;
2523     state = MsiLocateComponentA(component, path, &size);
2524     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2525     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2526 
2527     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2528     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2529 
2530     /* product value exists */
2531     path[0] = 0;
2532     size = MAX_PATH;
2533     state = MsiGetComponentPathA(prodcode, component, path, &size);
2534     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2535     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2536     ok(size == 10, "Expected 10, got %d\n", size);
2537 
2538     path[0] = 0;
2539     size = MAX_PATH;
2540     state = MsiLocateComponentA(component, path, &size);
2541     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2542     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2543     ok(size == 10, "Expected 10, got %d\n", size);
2544 
2545     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2546     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
2547     lstrcatA(keypath, prod_squashed);
2548     lstrcatA(keypath, "\\InstallProperties");
2549 
2550     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &installprop, NULL);
2551     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2552 
2553     val = 1;
2554     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
2555     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2556 
2557     /* install properties key exists */
2558     path[0] = 0;
2559     size = MAX_PATH;
2560     state = MsiGetComponentPathA(prodcode, component, path, &size);
2561     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2562     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2563     ok(size == 10, "Expected 10, got %d\n", size);
2564 
2565     path[0] = 0;
2566     size = MAX_PATH;
2567     state = MsiLocateComponentA(component, path, &size);
2568     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2569     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2570     ok(size == 10, "Expected 10, got %d\n", size);
2571 
2572     create_file("C:\\imapath", 11);
2573 
2574     /* file exists */
2575     path[0] = 'a';
2576     size = 0;
2577     state = MsiGetComponentPathA(prodcode, component, path, &size);
2578     ok(state == INSTALLSTATE_MOREDATA, "Expected INSTALLSTATE_MOREDATA, got %d\n", state);
2579     ok(path[0] == 'a', "got %s\n", path);
2580     ok(size == 10, "Expected 10, got %d\n", size);
2581 
2582     path[0] = 0;
2583     size = MAX_PATH;
2584     state = MsiGetComponentPathA(prodcode, component, path, &size);
2585     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2586     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2587     ok(size == 10, "Expected 10, got %d\n", size);
2588 
2589     size = 0;
2590     path[0] = 'a';
2591     state = MsiLocateComponentA(component, path, &size);
2592     ok(state == INSTALLSTATE_MOREDATA, "Expected INSTALLSTATE_MOREDATA, got %d\n", state);
2593     ok(path[0] == 'a', "got %s\n", path);
2594     ok(size == 10, "Expected 10, got %d\n", size);
2595 
2596     path[0] = 0;
2597     size = MAX_PATH;
2598     state = MsiLocateComponentA(component, path, &size);
2599     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2600     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2601     ok(size == 10, "Expected 10, got %d\n", size);
2602 
2603     RegDeleteValueA(compkey, prod_squashed);
2604     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2605     RegDeleteValueA(installprop, "WindowsInstaller");
2606     delete_key(installprop, "", access & KEY_WOW64_64KEY);
2607     RegCloseKey(compkey);
2608     RegCloseKey(installprop);
2609     DeleteFileA("C:\\imapath");
2610 
2611     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2612     lstrcatA(keypath, "Installer\\UserData\\");
2613     lstrcatA(keypath, usersid);
2614     lstrcatA(keypath, "\\Components\\");
2615     lstrcatA(keypath, comp_squashed);
2616 
2617     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2618     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2619 
2620     /* user managed component key exists */
2621     size = MAX_PATH;
2622     state = MsiGetComponentPathA(prodcode, component, path, &size);
2623     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2624     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2625 
2626     size = MAX_PATH;
2627     state = MsiLocateComponentA(component, path, &size);
2628     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2629     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2630 
2631     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2632     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2633 
2634     /* product value exists */
2635     path[0] = 0;
2636     size = MAX_PATH;
2637     state = MsiGetComponentPathA(prodcode, component, path, &size);
2638     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2639     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2640     ok(size == 10, "Expected 10, got %d\n", size);
2641 
2642     path[0] = 0;
2643     size = MAX_PATH;
2644     state = MsiLocateComponentA(component, path, &size);
2645     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2646     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2647     ok(size == 10, "Expected 10, got %d\n", size);
2648 
2649     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2650     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
2651     lstrcatA(keypath, prod_squashed);
2652     lstrcatA(keypath, "\\InstallProperties");
2653 
2654     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &installprop, NULL);
2655     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2656 
2657     val = 1;
2658     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
2659     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2660 
2661     /* install properties key exists */
2662     path[0] = 0;
2663     size = MAX_PATH;
2664     state = MsiGetComponentPathA(prodcode, component, path, &size);
2665     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2666     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2667     ok(size == 10, "Expected 10, got %d\n", size);
2668 
2669     path[0] = 0;
2670     size = MAX_PATH;
2671     state = MsiLocateComponentA(component, path, &size);
2672     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2673     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2674     ok(size == 10, "Expected 10, got %d\n", size);
2675 
2676     create_file("C:\\imapath", 11);
2677 
2678     /* file exists */
2679     path[0] = 0;
2680     size = MAX_PATH;
2681     state = MsiGetComponentPathA(prodcode, component, path, &size);
2682     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2683     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2684     ok(size == 10, "Expected 10, got %d\n", size);
2685 
2686     path[0] = 0;
2687     size = MAX_PATH;
2688     state = MsiLocateComponentA(component, path, &size);
2689     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2690     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2691     ok(size == 10, "Expected 10, got %d\n", size);
2692 
2693     RegDeleteValueA(compkey, prod_squashed);
2694     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2695     RegDeleteValueA(installprop, "WindowsInstaller");
2696     delete_key(installprop, "", access & KEY_WOW64_64KEY);
2697     RegCloseKey(compkey);
2698     RegCloseKey(installprop);
2699     DeleteFileA("C:\\imapath");
2700 
2701     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2702     lstrcatA(keypath, "Installer\\Managed\\");
2703     lstrcatA(keypath, usersid);
2704     lstrcatA(keypath, "\\Installer\\Products\\");
2705     lstrcatA(keypath, prod_squashed);
2706 
2707     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2708     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2709 
2710     /* user managed product key exists */
2711     size = MAX_PATH;
2712     state = MsiGetComponentPathA(prodcode, component, path, &size);
2713     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2714     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2715 
2716     size = MAX_PATH;
2717     state = MsiLocateComponentA(component, path, &size);
2718     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2719     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2720 
2721     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2722     lstrcatA(keypath, "Installer\\UserData\\");
2723     lstrcatA(keypath, usersid);
2724     lstrcatA(keypath, "\\Components\\");
2725     lstrcatA(keypath, comp_squashed);
2726 
2727     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2728     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2729 
2730     /* user managed component key exists */
2731     size = MAX_PATH;
2732     state = MsiGetComponentPathA(prodcode, component, path, &size);
2733     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2734     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2735 
2736     size = MAX_PATH;
2737     state = MsiLocateComponentA(component, path, &size);
2738     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2739     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2740 
2741     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2742     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2743 
2744     /* product value exists */
2745     path[0] = 0;
2746     size = MAX_PATH;
2747     state = MsiGetComponentPathA(prodcode, component, path, &size);
2748     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2749     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2750     ok(size == 10, "Expected 10, got %d\n", size);
2751 
2752     path[0] = 0;
2753     size = MAX_PATH;
2754     state = MsiLocateComponentA(component, path, &size);
2755     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2756     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2757     ok(size == 10, "Expected 10, got %d\n", size);
2758 
2759     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2760     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
2761     lstrcatA(keypath, prod_squashed);
2762     lstrcatA(keypath, "\\InstallProperties");
2763 
2764     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &installprop, NULL);
2765     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2766 
2767     val = 1;
2768     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
2769     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2770 
2771     /* install properties key exists */
2772     path[0] = 0;
2773     size = MAX_PATH;
2774     state = MsiGetComponentPathA(prodcode, component, path, &size);
2775     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2776     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2777     ok(size == 10, "Expected 10, got %d\n", size);
2778 
2779     path[0] = 0;
2780     size = MAX_PATH;
2781     state = MsiLocateComponentA(component, path, &size);
2782     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2783     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2784     ok(size == 10, "Expected 10, got %d\n", size);
2785 
2786     create_file("C:\\imapath", 11);
2787 
2788     /* file exists */
2789     path[0] = 0;
2790     size = MAX_PATH;
2791     state = MsiGetComponentPathA(prodcode, component, path, &size);
2792     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2793     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2794     ok(size == 10, "Expected 10, got %d\n", size);
2795 
2796     path[0] = 0;
2797     size = MAX_PATH;
2798     state = MsiLocateComponentA(component, path, &size);
2799     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2800     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2801     ok(size == 10, "Expected 10, got %d\n", size);
2802 
2803     RegDeleteValueA(compkey, prod_squashed);
2804     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2805     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2806     RegDeleteValueA(installprop, "WindowsInstaller");
2807     delete_key(installprop, "", access & KEY_WOW64_64KEY);
2808     RegCloseKey(prodkey);
2809     RegCloseKey(compkey);
2810     RegCloseKey(installprop);
2811     DeleteFileA("C:\\imapath");
2812 
2813     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2814     lstrcatA(keypath, prod_squashed);
2815 
2816     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
2817     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2818 
2819     /* user unmanaged product key exists */
2820     size = MAX_PATH;
2821     state = MsiGetComponentPathA(prodcode, component, path, &size);
2822     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2823     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2824 
2825     size = MAX_PATH;
2826     state = MsiLocateComponentA(component, path, &size);
2827     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2828     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2829 
2830     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2831     lstrcatA(keypath, "Installer\\UserData\\");
2832     lstrcatA(keypath, usersid);
2833     lstrcatA(keypath, "\\Components\\");
2834     lstrcatA(keypath, comp_squashed);
2835 
2836     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2837     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2838 
2839     /* user unmanaged component key exists */
2840     size = MAX_PATH;
2841     state = MsiGetComponentPathA(prodcode, component, path, &size);
2842     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2843     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2844 
2845     size = MAX_PATH;
2846     state = MsiLocateComponentA(component, path, &size);
2847     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2848     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2849 
2850     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2851     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2852 
2853     /* product value exists */
2854     path[0] = 0;
2855     size = MAX_PATH;
2856     state = MsiGetComponentPathA(prodcode, component, path, &size);
2857     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2858     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2859     ok(size == 10, "Expected 10, got %d\n", size);
2860 
2861     path[0] = 0;
2862     size = MAX_PATH;
2863     state = MsiLocateComponentA(component, path, &size);
2864     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2865     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2866     ok(size == 10, "Expected 10, got %d\n", size);
2867 
2868     create_file("C:\\imapath", 11);
2869 
2870     /* file exists */
2871     path[0] = 0;
2872     size = MAX_PATH;
2873     state = MsiGetComponentPathA(prodcode, component, path, &size);
2874     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2875     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2876     ok(size == 10, "Expected 10, got %d\n", size);
2877 
2878     path[0] = 0;
2879     size = MAX_PATH;
2880     state = MsiLocateComponentA(component, path, &size);
2881     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2882     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2883     ok(size == 10, "Expected 10, got %d\n", size);
2884 
2885     RegDeleteValueA(compkey, prod_squashed);
2886     RegDeleteKeyA(prodkey, "");
2887     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2888     RegCloseKey(prodkey);
2889     RegCloseKey(compkey);
2890     DeleteFileA("C:\\imapath");
2891 
2892     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
2893     lstrcatA(keypath, prod_squashed);
2894 
2895     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2896     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2897 
2898     /* local classes product key exists */
2899     size = MAX_PATH;
2900     state = MsiGetComponentPathA(prodcode, component, path, &size);
2901     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2902     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2903 
2904     size = MAX_PATH;
2905     state = MsiLocateComponentA(component, path, &size);
2906     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2907     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2908 
2909     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2910     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
2911     lstrcatA(keypath, comp_squashed);
2912 
2913     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2914     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2915 
2916     /* local user component key exists */
2917     size = MAX_PATH;
2918     state = MsiGetComponentPathA(prodcode, component, path, &size);
2919     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2920     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2921 
2922     size = MAX_PATH;
2923     state = MsiLocateComponentA(component, path, &size);
2924     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2925     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2926 
2927     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2928     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2929 
2930     /* product value exists */
2931     path[0] = 0;
2932     size = MAX_PATH;
2933     state = MsiGetComponentPathA(prodcode, component, path, &size);
2934     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2935     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2936     ok(size == 10, "Expected 10, got %d\n", size);
2937 
2938     path[0] = 0;
2939     size = MAX_PATH;
2940     state = MsiLocateComponentA(component, path, &size);
2941     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2942     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2943     ok(size == 10, "Expected 10, got %d\n", size);
2944 
2945     create_file("C:\\imapath", 11);
2946 
2947     /* file exists */
2948     path[0] = 0;
2949     size = MAX_PATH;
2950     state = MsiGetComponentPathA(prodcode, component, path, &size);
2951     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2952     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2953     ok(size == 10, "Expected 10, got %d\n", size);
2954 
2955     path[0] = 0;
2956     size = MAX_PATH;
2957     state = MsiLocateComponentA(component, path, &size);
2958     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2959     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2960     ok(size == 10, "Expected 10, got %d\n", size);
2961 
2962     RegDeleteValueA(compkey, prod_squashed);
2963     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2964     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2965     RegCloseKey(prodkey);
2966     RegCloseKey(compkey);
2967     DeleteFileA("C:\\imapath");
2968     LocalFree(usersid);
2969 }
2970 
2971 static void test_MsiGetComponentPathEx(void)
2972 {
2973     HKEY key_comp, key_installprop, key_prod;
2974     char prod[MAX_PATH], prod_squashed[MAX_PATH];
2975     char comp[MAX_PATH], comp_base85[MAX_PATH], comp_squashed[MAX_PATH];
2976     char path[MAX_PATH], path_key[MAX_PATH], *usersid;
2977     INSTALLSTATE state;
2978     DWORD size, val;
2979     REGSAM access = KEY_ALL_ACCESS;
2980     LONG res;
2981 
2982     if (!pMsiGetComponentPathExA)
2983     {
2984         win_skip( "MsiGetComponentPathExA not present\n" );
2985         return;
2986     }
2987 
2988     if (is_wow64) access |= KEY_WOW64_64KEY;
2989 
2990     create_test_guid( prod, prod_squashed );
2991     compose_base85_guid( comp, comp_base85, comp_squashed );
2992     usersid = get_user_sid();
2993 
2994     /* NULL product */
2995     size = MAX_PATH;
2996     state = pMsiGetComponentPathExA( NULL, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
2997     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
2998     todo_wine ok( !size, "got %u\n", size );
2999 
3000     /* NULL component */
3001     size = MAX_PATH;
3002     state = pMsiGetComponentPathExA( prod, NULL, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3003     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
3004     todo_wine ok( !size, "got %u\n", size );
3005 
3006     /* non-NULL usersid, MSIINSTALLCONTEXT_MACHINE */
3007     size = MAX_PATH;
3008     state = pMsiGetComponentPathExA( prod, comp, usersid, MSIINSTALLCONTEXT_MACHINE, path, &size);
3009     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
3010     todo_wine ok( !size, "got %u\n", size );
3011 
3012     /* NULL buf */
3013     size = MAX_PATH;
3014     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, NULL, &size );
3015     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3016     todo_wine ok( size == MAX_PATH * 2, "got %u\n", size );
3017 
3018     /* NULL buflen */
3019     size = MAX_PATH;
3020     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, NULL );
3021     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
3022     ok( size == MAX_PATH, "got %u\n", size );
3023 
3024     /* all params valid */
3025     size = MAX_PATH;
3026     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3027     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3028     todo_wine ok( !size, "got %u\n", size );
3029 
3030     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3031     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Components\\" );
3032     lstrcatA( path_key, comp_squashed );
3033 
3034     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3035     if (res == ERROR_ACCESS_DENIED)
3036     {
3037         skip( "insufficient rights\n" );
3038         LocalFree( usersid );
3039         return;
3040     }
3041     ok( res == ERROR_SUCCESS, "got %d\n", res );
3042 
3043     /* local system component key exists */
3044     size = MAX_PATH;
3045     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3046     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3047 
3048     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3049     ok( res == ERROR_SUCCESS, "got %d\n", res );
3050 
3051     /* product value exists */
3052     path[0] = 0;
3053     size = MAX_PATH;
3054     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3055     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3056     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3057     ok( size == 20, "got %u\n", size );
3058 
3059     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3060     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Products\\" );
3061     lstrcatA( path_key, prod_squashed );
3062     lstrcatA( path_key, "\\InstallProperties" );
3063 
3064     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_installprop, NULL );
3065     ok( res == ERROR_SUCCESS, "got %d\n", res );
3066 
3067     val = 1;
3068     res = RegSetValueExA( key_installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(val) );
3069     ok( res == ERROR_SUCCESS, "got %d\n", res );
3070 
3071     /* install properties key exists */
3072     path[0] = 0;
3073     size = MAX_PATH;
3074     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3075     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3076     ok( !lstrcmpA( path, "c:\\testcomponentpath"), "got %s\n", path );
3077     ok( size == 20, "got %u\n", size );
3078 
3079     create_file( "c:\\testcomponentpath", 21 );
3080 
3081     /* file exists */
3082     path[0] = 0;
3083     size = 0;
3084     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3085     ok( state == INSTALLSTATE_MOREDATA, "got %d\n", state );
3086     ok( !path[0], "got %s\n", path );
3087     todo_wine ok( size == 40, "got %u\n", size );
3088 
3089     path[0] = 0;
3090     size = MAX_PATH;
3091     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3092     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3093     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3094     ok( size == 20, "got %d\n", size );
3095 
3096     RegDeleteValueA( key_comp, prod_squashed );
3097     delete_key( key_comp, "", access & KEY_WOW64_64KEY );
3098     RegDeleteValueA( key_installprop, "WindowsInstaller" );
3099     delete_key( key_installprop, "", access & KEY_WOW64_64KEY );
3100     RegCloseKey( key_comp );
3101     RegCloseKey( key_installprop );
3102     DeleteFileA( "c:\\testcomponentpath" );
3103 
3104     lstrcpyA( path_key, "Software\\Microsoft\\Installer\\Products\\" );
3105     lstrcatA( path_key, prod_squashed );
3106 
3107     res = RegCreateKeyA( HKEY_CURRENT_USER, path_key, &key_prod );
3108     ok( res == ERROR_SUCCESS, "got %d\n", res );
3109 
3110     /* user unmanaged product key exists */
3111     size = MAX_PATH;
3112     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3113     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3114     todo_wine ok(!size, "got %u\n", size);
3115 
3116     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3117     lstrcatA( path_key, "Installer\\UserData\\" );
3118     lstrcatA( path_key, usersid );
3119     lstrcatA( path_key, "\\Components\\" );
3120     lstrcatA( path_key, comp_squashed );
3121 
3122     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3123     ok( res == ERROR_SUCCESS, "got %d\n", res );
3124 
3125     /* user unmanaged component key exists */
3126     size = MAX_PATH;
3127     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3128     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3129     todo_wine ok(!size, "got %u\n", size);
3130 
3131     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3132     ok( res == ERROR_SUCCESS, "got %d\n", res );
3133 
3134     /* product value exists */
3135     path[0] = 0;
3136     size = MAX_PATH;
3137     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3138     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3139     ok( !lstrcmpA( path, "c:\\testcomponentpath"), "got %s\n", path );
3140     ok( size == 20, "got %u\n", size );
3141 
3142     create_file( "c:\\testcomponentpath", 21 );
3143 
3144     /* file exists */
3145     path[0] = 0;
3146     size = MAX_PATH;
3147     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3148     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3149     ok( !lstrcmpA( path, "c:\\testcomponentpath"), "got %s\n", path );
3150     ok( size == 20, "got %u\n", size );
3151 
3152     RegDeleteValueA( key_comp, prod_squashed );
3153     RegDeleteKeyA( key_prod, "" );
3154     delete_key( key_comp, "", access & KEY_WOW64_64KEY );
3155     RegCloseKey( key_prod );
3156     RegCloseKey( key_comp );
3157     DeleteFileA( "c:\\testcomponentpath" );
3158 
3159     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3160     lstrcatA( path_key, "Installer\\Managed\\" );
3161     lstrcatA( path_key, usersid );
3162     lstrcatA( path_key, "\\Installer\\Products\\" );
3163     lstrcatA( path_key, prod_squashed );
3164 
3165     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_prod, NULL );
3166     ok( res == ERROR_SUCCESS, "got %d\n", res );
3167 
3168     /* user managed product key exists */
3169     size = MAX_PATH;
3170     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3171     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3172 
3173     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3174     lstrcatA( path_key, "Installer\\UserData\\" );
3175     lstrcatA( path_key, usersid );
3176     lstrcatA( path_key, "\\Components\\" );
3177     lstrcatA( path_key, comp_squashed );
3178 
3179     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3180     ok( res == ERROR_SUCCESS, "got %d\n", res );
3181 
3182     /* user managed component key exists */
3183     size = MAX_PATH;
3184     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3185     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3186 
3187     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3188     ok( res == ERROR_SUCCESS, "got %d\n", res );
3189 
3190     /* product value exists */
3191     path[0] = 0;
3192     size = MAX_PATH;
3193     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3194     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3195     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3196     ok( size == 20, "got %u\n", size );
3197 
3198     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3199     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Products\\" );
3200     lstrcatA( path_key, prod_squashed );
3201     lstrcatA( path_key, "\\InstallProperties" );
3202 
3203     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_installprop, NULL );
3204     ok( res == ERROR_SUCCESS, "got %d\n", res );
3205 
3206     val = 1;
3207     res = RegSetValueExA( key_installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(val) );
3208     ok( res == ERROR_SUCCESS, "got %d\n", res );
3209 
3210     /* install properties key exists */
3211     path[0] = 0;
3212     size = MAX_PATH;
3213     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3214     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3215     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3216     ok( size == 20, "got %u\n", size );
3217 
3218     create_file( "c:\\testcomponentpath", 21 );
3219 
3220     /* file exists */
3221     path[0] = 0;
3222     size = MAX_PATH;
3223     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3224     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3225     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3226     ok( size == 20, "got %u\n", size );
3227 
3228     RegDeleteValueA( key_comp, prod_squashed );
3229     delete_key( key_prod, "", access & KEY_WOW64_64KEY );
3230     delete_key( key_comp, "", access & KEY_WOW64_64KEY );
3231     RegDeleteValueA( key_installprop, "WindowsInstaller" );
3232     delete_key( key_installprop, "", access & KEY_WOW64_64KEY );
3233     RegCloseKey( key_prod );
3234     RegCloseKey( key_comp );
3235     RegCloseKey( key_installprop );
3236     DeleteFileA( "c:\\testcomponentpath" );
3237     lstrcpyA( path_key, "Software\\Classes\\Installer\\Products\\" );
3238     lstrcatA( path_key, prod_squashed );
3239 
3240     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_prod, NULL );
3241     ok( res == ERROR_SUCCESS, "got %d\n", res );
3242 
3243     /* local classes product key exists */
3244     size = MAX_PATH;
3245     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3246     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3247     todo_wine ok(!size, "got %u\n", size);
3248 
3249     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3250     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Components\\" );
3251     lstrcatA( path_key, comp_squashed );
3252 
3253     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE,  path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3254     ok( res == ERROR_SUCCESS, "got %d\n", res );
3255 
3256     /* local user component key exists */
3257     size = MAX_PATH;
3258     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3259     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3260     todo_wine ok(!size, "got %u\n", size);
3261 
3262     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3263     ok( res == ERROR_SUCCESS, "got %d\n", res );
3264 
3265     /* product value exists */
3266     path[0] = 0;
3267     size = MAX_PATH;
3268     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3269     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3270     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3271     ok( size == 20, "got %u\n", size );
3272 
3273     create_file( "c:\\testcomponentpath", 21 );
3274 
3275     /* file exists */
3276     path[0] = 0;
3277     size = MAX_PATH;
3278     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3279     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3280     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3281     ok( size == 20, "got %u\n", size );
3282 
3283     RegDeleteValueA( key_comp, prod_squashed );
3284     delete_key( key_prod, "", access & KEY_WOW64_64KEY );
3285     delete_key( key_comp, "", access & KEY_WOW64_64KEY );
3286     RegCloseKey( key_prod );
3287     RegCloseKey( key_comp );
3288     DeleteFileA( "c:\\testcomponentpath" );
3289     LocalFree( usersid );
3290 }
3291 
3292 static void test_MsiProvideComponent(void)
3293 {
3294     static const WCHAR sourcedirW[] =
3295         {'s','o','u','r','c','e','d','i','r',0};
3296     static const WCHAR productW[] =
3297         {'{','3','8','8','4','7','3','3','8','-','1','B','B','C','-','4','1','0','4','-',
3298          '8','1','A','C','-','2','F','A','A','C','7','E','C','D','D','C','D','}',0};
3299     static const WCHAR componentW[] =
3300         {'{','D','D','4','2','2','F','9','2','-','3','E','D','8','-','4','9','B','5','-',
3301          'A','0','B','7','-','F','2','6','6','F','9','8','3','5','7','D','F','}',0};
3302     INSTALLSTATE state;
3303     char buf[0x100];
3304     WCHAR bufW[0x100];
3305     DWORD len, len2;
3306     UINT r;
3307 
3308     if (is_process_limited())
3309     {
3310         skip("process is limited\n");
3311         return;
3312     }
3313 
3314     create_test_files();
3315     create_file("msitest\\sourcedir.txt", 1000);
3316     create_database(msifile, sd_tables, sizeof(sd_tables) / sizeof(msi_table));
3317 
3318     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3319 
3320     buf[0] = 0;
3321     len = sizeof(buf);
3322     r = pMsiProvideComponentA("{90120000-0070-0000-0000-4000000FF1CE}",
3323                               "{17961602-C4E2-482E-800A-DF6E627549CF}",
3324                               "ProductFiles", INSTALLMODE_NODETECTION, buf, &len);
3325     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
3326 
3327     r = MsiInstallProductA(msifile, NULL);
3328     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3329 
3330     state = MsiQueryFeatureStateA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir");
3331     ok(state == INSTALLSTATE_LOCAL, "got %d\n", state);
3332 
3333     buf[0] = 0;
3334     len = sizeof(buf);
3335     r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir",
3336                               "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
3337                               INSTALLMODE_NODETECTION, buf, &len);
3338     ok(r == ERROR_SUCCESS, "got %u\n", r);
3339     ok(buf[0], "empty path\n");
3340     ok(len == lstrlenA(buf), "got %u\n", len);
3341 
3342     len2 = 0;
3343     r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir",
3344                               "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
3345                               INSTALLMODE_NODETECTION, NULL, &len2);
3346     ok(r == ERROR_SUCCESS, "got %u\n", r);
3347     ok(len2 == len, "got %u\n", len2);
3348 
3349     len2 = 0;
3350     r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir",
3351                               "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
3352                               INSTALLMODE_NODETECTION, buf, &len2);
3353     ok(r == ERROR_MORE_DATA, "got %u\n", r);
3354     ok(len2 == len, "got %u\n", len2);
3355 
3356     /* wide version */
3357 
3358     bufW[0] = 0;
3359     len = sizeof(buf);
3360     r = pMsiProvideComponentW(productW, sourcedirW, componentW,
3361                               INSTALLMODE_NODETECTION, bufW, &len);
3362     ok(r == ERROR_SUCCESS, "got %u\n", r);
3363     ok(bufW[0], "empty path\n");
3364     ok(len == lstrlenW(bufW), "got %u\n", len);
3365 
3366     len2 = 0;
3367     r = pMsiProvideComponentW(productW, sourcedirW, componentW,
3368                               INSTALLMODE_NODETECTION, NULL, &len2);
3369     ok(r == ERROR_SUCCESS, "got %u\n", r);
3370     ok(len2 == len, "got %u\n", len2);
3371 
3372     len2 = 0;
3373     r = pMsiProvideComponentW(productW, sourcedirW, componentW,
3374                               INSTALLMODE_NODETECTION, bufW, &len2);
3375     ok(r == ERROR_MORE_DATA, "got %u\n", r);
3376     ok(len2 == len, "got %u\n", len2);
3377 
3378     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3379     ok(r == ERROR_SUCCESS, "got %u\n", r);
3380 
3381     DeleteFileA("msitest\\sourcedir.txt");
3382     delete_test_files();
3383     DeleteFileA(msifile);
3384 }
3385 
3386 static void test_MsiProvideQualifiedComponentEx(void)
3387 {
3388     UINT r;
3389     INSTALLSTATE state;
3390     char comp[39], comp_squashed[33], comp2[39], comp2_base85[21], comp2_squashed[33];
3391     char prod[39], prod_base85[21], prod_squashed[33];
3392     char desc[MAX_PATH], buf[MAX_PATH], keypath[MAX_PATH], path[MAX_PATH];
3393     DWORD len = sizeof(buf);
3394     REGSAM access = KEY_ALL_ACCESS;
3395     HKEY hkey, hkey2, hkey3, hkey4, hkey5;
3396     LONG res;
3397 
3398     if (is_process_limited())
3399     {
3400         skip( "process is limited\n" );
3401         return;
3402     }
3403 
3404     create_test_guid( comp, comp_squashed );
3405     compose_base85_guid( comp2, comp2_base85, comp2_squashed );
3406     compose_base85_guid( prod, prod_base85, prod_squashed );
3407 
3408     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3409     ok( r == ERROR_UNKNOWN_COMPONENT, "got %u\n", r );
3410 
3411     lstrcpyA( keypath, "Software\\Classes\\Installer\\Components\\" );
3412     lstrcatA( keypath, comp_squashed );
3413 
3414     if (is_wow64) access |= KEY_WOW64_64KEY;
3415     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey, NULL );
3416     ok( res == ERROR_SUCCESS, "got %d\n", res );
3417 
3418     lstrcpyA( desc, prod_base85 );
3419     memcpy( desc + lstrlenA(desc), "feature<\0", sizeof("feature<\0") );
3420     res = RegSetValueExA( hkey, "qualifier", 0, REG_MULTI_SZ, (const BYTE *)desc,
3421                           lstrlenA(prod_base85) + sizeof("feature<\0") );
3422     ok( res == ERROR_SUCCESS, "got %d\n", res );
3423 
3424     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3425     ok( r == ERROR_UNKNOWN_PRODUCT, "got %u\n", r );
3426 
3427     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, NULL, 0, 0, buf, &len );
3428     ok( r == ERROR_UNKNOWN_PRODUCT, "got %u\n", r );
3429 
3430     state = MsiQueryProductStateA( prod );
3431     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3432 
3433     lstrcpyA( keypath, "Software\\Classes\\Installer\\Products\\" );
3434     lstrcatA( keypath, prod_squashed );
3435 
3436     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey2, NULL );
3437     ok( res == ERROR_SUCCESS, "got %d\n", res );
3438 
3439     state = MsiQueryProductStateA( prod );
3440     ok( state == INSTALLSTATE_ADVERTISED, "got %d\n", state );
3441 
3442     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3443     todo_wine ok( r == ERROR_UNKNOWN_FEATURE, "got %u\n", r );
3444 
3445     lstrcpyA( keypath, "Software\\Classes\\Installer\\Features\\" );
3446     lstrcatA( keypath, prod_squashed );
3447 
3448     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey3, NULL );
3449     ok( res == ERROR_SUCCESS, "got %d\n", res );
3450 
3451     state = MsiQueryFeatureStateA( prod, "feature" );
3452     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3453 
3454     res = RegSetValueExA( hkey3, "feature", 0, REG_SZ, (const BYTE *)"", 1 );
3455     ok( res == ERROR_SUCCESS, "got %d\n", res );
3456 
3457     state = MsiQueryFeatureStateA( prod, "feature" );
3458     ok( state == INSTALLSTATE_ADVERTISED, "got %d\n", state );
3459 
3460     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3461     ok( r == ERROR_FILE_NOT_FOUND, "got %u\n", r );
3462 
3463     len = sizeof(buf);
3464     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, NULL, 0, 0, buf, &len );
3465     ok( r == ERROR_FILE_NOT_FOUND, "got %u\n", r );
3466 
3467     lstrcpyA( keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\" );
3468     lstrcatA( keypath, prod_squashed );
3469     lstrcatA( keypath, "\\Features" );
3470 
3471     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey4, NULL );
3472     ok( res == ERROR_SUCCESS, "got %d\n", res );
3473 
3474     res = RegSetValueExA( hkey4, "feature", 0, REG_SZ, (const BYTE *)comp2_base85, sizeof(comp2_base85) );
3475     ok( res == ERROR_SUCCESS, "got %d\n", res );
3476 
3477     state = MsiQueryFeatureStateA( prod, "feature" );
3478     ok( state == INSTALLSTATE_ADVERTISED, "got %d\n", state );
3479 
3480     lstrcpyA( keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\" );
3481     lstrcatA( keypath, comp2_squashed );
3482 
3483     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey5, NULL );
3484     ok( res == ERROR_SUCCESS, "got %d\n", res );
3485 
3486     res = RegSetValueExA( hkey5, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\nosuchfile", sizeof("c:\\nosuchfile") );
3487     ok( res == ERROR_SUCCESS, "got %d\n", res );
3488 
3489     state = MsiQueryFeatureStateA( prod, "feature" );
3490     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3491 
3492     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3493     ok( r == ERROR_FILE_NOT_FOUND, "got %u\n", r );
3494 
3495     GetCurrentDirectoryA( MAX_PATH, path );
3496     lstrcatA( path, "\\msitest" );
3497     CreateDirectoryA( path, NULL );
3498     lstrcatA( path, "\\test.txt" );
3499     create_file_data( path, "test", 100 );
3500 
3501     res = RegSetValueExA( hkey5, prod_squashed, 0, REG_SZ, (const BYTE *)path, lstrlenA(path) + 1 );
3502     ok( res == ERROR_SUCCESS, "got %d\n", res );
3503 
3504     buf[0] = 0;
3505     len = sizeof(buf);
3506     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3507     ok( r == ERROR_SUCCESS, "got %u\n", r );
3508     ok( len == lstrlenA(path), "got %u\n", len );
3509     ok( !lstrcmpA( path, buf ), "got '%s'\n", buf );
3510 
3511     DeleteFileA( "msitest\\text.txt" );
3512     RemoveDirectoryA( "msitest" );
3513 
3514     delete_key( hkey5, "", access & KEY_WOW64_64KEY );
3515     RegCloseKey( hkey5 );
3516     delete_key( hkey4, "", access & KEY_WOW64_64KEY );
3517     RegCloseKey( hkey4 );
3518     delete_key( hkey3, "", access & KEY_WOW64_64KEY );
3519     RegCloseKey( hkey3 );
3520     delete_key( hkey2, "", access & KEY_WOW64_64KEY );
3521     RegCloseKey( hkey2 );
3522     delete_key( hkey, "", access & KEY_WOW64_64KEY );
3523     RegCloseKey( hkey );
3524 }
3525 
3526 static void test_MsiGetProductCode(void)
3527 {
3528     HKEY compkey, prodkey;
3529     CHAR prodcode[MAX_PATH];
3530     CHAR prod_squashed[MAX_PATH];
3531     CHAR prodcode2[MAX_PATH];
3532     CHAR prod2_squashed[MAX_PATH];
3533     CHAR component[MAX_PATH];
3534     CHAR comp_base85[MAX_PATH];
3535     CHAR comp_squashed[MAX_PATH];
3536     CHAR keypath[MAX_PATH];
3537     CHAR product[MAX_PATH];
3538     LPSTR usersid;
3539     LONG res;
3540     UINT r;
3541     REGSAM access = KEY_ALL_ACCESS;
3542 
3543     create_test_guid(prodcode, prod_squashed);
3544     create_test_guid(prodcode2, prod2_squashed);
3545     compose_base85_guid(component, comp_base85, comp_squashed);
3546     usersid = get_user_sid();
3547 
3548     if (is_wow64)
3549         access |= KEY_WOW64_64KEY;
3550 
3551     /* szComponent is NULL */
3552     lstrcpyA(product, "prod");
3553     r = MsiGetProductCodeA(NULL, product);
3554     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3555     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3556 
3557     /* szComponent is empty */
3558     lstrcpyA(product, "prod");
3559     r = MsiGetProductCodeA("", product);
3560     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3561     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3562 
3563     /* garbage szComponent */
3564     lstrcpyA(product, "prod");
3565     r = MsiGetProductCodeA("garbage", product);
3566     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3567     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3568 
3569     /* guid without brackets */
3570     lstrcpyA(product, "prod");
3571     r = MsiGetProductCodeA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", product);
3572     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3573     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3574 
3575     /* guid with brackets */
3576     lstrcpyA(product, "prod");
3577     r = MsiGetProductCodeA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", product);
3578     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3579     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3580 
3581     /* same length as guid, but random */
3582     lstrcpyA(product, "prod");
3583     r = MsiGetProductCodeA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", product);
3584     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3585     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3586 
3587     /* all params correct, szComponent not published */
3588     lstrcpyA(product, "prod");
3589     r = MsiGetProductCodeA(component, product);
3590     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3591     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3592 
3593     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3594     lstrcatA(keypath, "Installer\\UserData\\");
3595     lstrcatA(keypath, usersid);
3596     lstrcatA(keypath, "\\Components\\");
3597     lstrcatA(keypath, comp_squashed);
3598 
3599     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3600     if (res == ERROR_ACCESS_DENIED)
3601     {
3602         skip("Not enough rights to perform tests\n");
3603         LocalFree(usersid);
3604         return;
3605     }
3606     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3607 
3608     /* user unmanaged component key exists */
3609     lstrcpyA(product, "prod");
3610     r = MsiGetProductCodeA(component, product);
3611     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3612     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3613 
3614     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3615     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3616 
3617     /* product value exists */
3618     lstrcpyA(product, "prod");
3619     r = MsiGetProductCodeA(component, product);
3620     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3621     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3622 
3623     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
3624     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3625 
3626     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3627     lstrcatA(keypath, "Installer\\Managed\\");
3628     lstrcatA(keypath, usersid);
3629     lstrcatA(keypath, "\\Installer\\Products\\");
3630     lstrcatA(keypath, prod_squashed);
3631 
3632     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3633     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3634 
3635     /* user managed product key of first product exists */
3636     lstrcpyA(product, "prod");
3637     r = MsiGetProductCodeA(component, product);
3638     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3639     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3640 
3641     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3642     RegCloseKey(prodkey);
3643 
3644     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
3645     lstrcatA(keypath, prod_squashed);
3646 
3647     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
3648     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3649 
3650     /* user unmanaged product key exists */
3651     lstrcpyA(product, "prod");
3652     r = MsiGetProductCodeA(component, product);
3653     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3654     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3655 
3656     RegDeleteKeyA(prodkey, "");
3657     RegCloseKey(prodkey);
3658 
3659     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
3660     lstrcatA(keypath, prod_squashed);
3661 
3662     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3663     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3664 
3665     /* local classes product key exists */
3666     lstrcpyA(product, "prod");
3667     r = MsiGetProductCodeA(component, product);
3668     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3669     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3670 
3671     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3672     RegCloseKey(prodkey);
3673 
3674     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3675     lstrcatA(keypath, "Installer\\Managed\\");
3676     lstrcatA(keypath, usersid);
3677     lstrcatA(keypath, "\\Installer\\Products\\");
3678     lstrcatA(keypath, prod2_squashed);
3679 
3680     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3681     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3682 
3683     /* user managed product key of second product exists */
3684     lstrcpyA(product, "prod");
3685     r = MsiGetProductCodeA(component, product);
3686     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3687     ok(!lstrcmpA(product, prodcode2), "Expected %s, got %s\n", prodcode2, product);
3688 
3689     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3690     RegCloseKey(prodkey);
3691     RegDeleteValueA(compkey, prod_squashed);
3692     RegDeleteValueA(compkey, prod2_squashed);
3693     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3694     RegCloseKey(compkey);
3695 
3696     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3697     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
3698     lstrcatA(keypath, comp_squashed);
3699 
3700     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3701     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3702 
3703     /* local user component key exists */
3704     lstrcpyA(product, "prod");
3705     r = MsiGetProductCodeA(component, product);
3706     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3707     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3708 
3709     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3710     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3711 
3712     /* product value 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     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
3719     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3720 
3721     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3722     lstrcatA(keypath, "Installer\\Managed\\");
3723     lstrcatA(keypath, usersid);
3724     lstrcatA(keypath, "\\Installer\\Products\\");
3725     lstrcatA(keypath, prod_squashed);
3726 
3727     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3728     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3729 
3730     /* user managed product key of first product exists */
3731     lstrcpyA(product, "prod");
3732     r = MsiGetProductCodeA(component, product);
3733     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3734     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3735 
3736     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3737     RegCloseKey(prodkey);
3738 
3739     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
3740     lstrcatA(keypath, prod_squashed);
3741 
3742     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
3743     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3744 
3745     /* user unmanaged product key exists */
3746     lstrcpyA(product, "prod");
3747     r = MsiGetProductCodeA(component, product);
3748     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3749     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3750 
3751     RegDeleteKeyA(prodkey, "");
3752     RegCloseKey(prodkey);
3753 
3754     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
3755     lstrcatA(keypath, prod_squashed);
3756 
3757     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3758     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3759 
3760     /* local classes product key exists */
3761     lstrcpyA(product, "prod");
3762     r = MsiGetProductCodeA(component, product);
3763     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3764     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3765 
3766     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3767     RegCloseKey(prodkey);
3768 
3769     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3770     lstrcatA(keypath, "Installer\\Managed\\");
3771     lstrcatA(keypath, usersid);
3772     lstrcatA(keypath, "\\Installer\\Products\\");
3773     lstrcatA(keypath, prod2_squashed);
3774 
3775     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3776     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3777 
3778     /* user managed product key of second product exists */
3779     lstrcpyA(product, "prod");
3780     r = MsiGetProductCodeA(component, product);
3781     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3782     ok(!lstrcmpA(product, prodcode2), "Expected %s, got %s\n", prodcode2, product);
3783 
3784     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3785     RegCloseKey(prodkey);
3786     RegDeleteValueA(compkey, prod_squashed);
3787     RegDeleteValueA(compkey, prod2_squashed);
3788     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3789     RegCloseKey(compkey);
3790     LocalFree(usersid);
3791 }
3792 
3793 static void test_MsiEnumClients(void)
3794 {
3795     HKEY compkey;
3796     CHAR prodcode[MAX_PATH];
3797     CHAR prod_squashed[MAX_PATH];
3798     CHAR prodcode2[MAX_PATH];
3799     CHAR prod2_squashed[MAX_PATH];
3800     CHAR component[MAX_PATH];
3801     CHAR comp_base85[MAX_PATH];
3802     CHAR comp_squashed[MAX_PATH];
3803     CHAR product[MAX_PATH];
3804     CHAR keypath[MAX_PATH];
3805     LPSTR usersid;
3806     LONG res;
3807     UINT r;
3808     REGSAM access = KEY_ALL_ACCESS;
3809 
3810     create_test_guid(prodcode, prod_squashed);
3811     create_test_guid(prodcode2, prod2_squashed);
3812     compose_base85_guid(component, comp_base85, comp_squashed);
3813     usersid = get_user_sid();
3814 
3815     if (is_wow64)
3816         access |= KEY_WOW64_64KEY;
3817 
3818     /* NULL szComponent */
3819     product[0] = '\0';
3820     r = MsiEnumClientsA(NULL, 0, product);
3821     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3822     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3823 
3824     /* empty szComponent */
3825     product[0] = '\0';
3826     r = MsiEnumClientsA("", 0, product);
3827     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3828     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3829 
3830     /* NULL lpProductBuf */
3831     r = MsiEnumClientsA(component, 0, NULL);
3832     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3833 
3834     /* all params correct, component missing */
3835     product[0] = '\0';
3836     r = MsiEnumClientsA(component, 0, product);
3837     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3838     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3839 
3840     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3841     lstrcatA(keypath, "Installer\\UserData\\");
3842     lstrcatA(keypath, usersid);
3843     lstrcatA(keypath, "\\Components\\");
3844     lstrcatA(keypath, comp_squashed);
3845 
3846     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3847     if (res == ERROR_ACCESS_DENIED)
3848     {
3849         skip("Not enough rights to perform tests\n");
3850         LocalFree(usersid);
3851         return;
3852     }
3853     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3854 
3855     /* user unmanaged component key exists */
3856     product[0] = '\0';
3857     r = MsiEnumClientsA(component, 0, product);
3858     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3859     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3860 
3861     /* index > 0, no products exist */
3862     product[0] = '\0';
3863     r = MsiEnumClientsA(component, 1, product);
3864     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3865     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3866 
3867     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3868     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3869 
3870     /* product value exists */
3871     r = MsiEnumClientsA(component, 0, product);
3872     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3873     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3874 
3875     /* try index 0 again */
3876     product[0] = '\0';
3877     r = MsiEnumClientsA(component, 0, product);
3878     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3879     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3880 
3881     /* try index 1, second product value does not exist */
3882     product[0] = '\0';
3883     r = MsiEnumClientsA(component, 1, product);
3884     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3885     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3886 
3887     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
3888     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3889 
3890     /* try index 1, second product value does exist */
3891     product[0] = '\0';
3892     r = MsiEnumClientsA(component, 1, product);
3893     todo_wine
3894     {
3895         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3896         ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3897     }
3898 
3899     /* start the enumeration over */
3900     product[0] = '\0';
3901     r = MsiEnumClientsA(component, 0, product);
3902     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3903     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
3904        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
3905 
3906     /* correctly query second product */
3907     product[0] = '\0';
3908     r = MsiEnumClientsA(component, 1, product);
3909     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3910     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
3911        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
3912 
3913     RegDeleteValueA(compkey, prod_squashed);
3914     RegDeleteValueA(compkey, prod2_squashed);
3915     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3916     RegCloseKey(compkey);
3917 
3918     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3919     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
3920     lstrcatA(keypath, comp_squashed);
3921 
3922     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3923     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3924 
3925     /* user local component key exists */
3926     product[0] = '\0';
3927     r = MsiEnumClientsA(component, 0, product);
3928     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3929     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3930 
3931     /* index > 0, no products exist */
3932     product[0] = '\0';
3933     r = MsiEnumClientsA(component, 1, product);
3934     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3935     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3936 
3937     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3938     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3939 
3940     /* product value exists */
3941     product[0] = '\0';
3942     r = MsiEnumClientsA(component, 0, product);
3943     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3944     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3945 
3946     /* try index 0 again */
3947     product[0] = '\0';
3948     r = MsiEnumClientsA(component, 0, product);
3949     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3950 
3951     /* try index 1, second product value does not exist */
3952     product[0] = '\0';
3953     r = MsiEnumClientsA(component, 1, product);
3954     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3955     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3956 
3957     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
3958     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3959 
3960     /* try index 1, second product value does exist */
3961     product[0] = '\0';
3962     r = MsiEnumClientsA(component, 1, product);
3963     todo_wine
3964     {
3965         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3966         ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3967     }
3968 
3969     /* start the enumeration over */
3970     product[0] = '\0';
3971     r = MsiEnumClientsA(component, 0, product);
3972     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3973     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
3974        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
3975 
3976     /* correctly query second product */
3977     product[0] = '\0';
3978     r = MsiEnumClientsA(component, 1, product);
3979     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3980     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
3981        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
3982 
3983     RegDeleteValueA(compkey, prod_squashed);
3984     RegDeleteValueA(compkey, prod2_squashed);
3985     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3986     RegCloseKey(compkey);
3987     LocalFree(usersid);
3988 }
3989 
3990 static void get_version_info(LPSTR path, LPSTR *vercheck, LPDWORD verchecksz,
3991                              LPSTR *langcheck, LPDWORD langchecksz)
3992 {
3993     LPSTR version;
3994     VS_FIXEDFILEINFO *ffi;
3995     DWORD size = GetFileVersionInfoSizeA(path, NULL);
3996     USHORT *lang;
3997 
3998     version = HeapAlloc(GetProcessHeap(), 0, size);
3999     GetFileVersionInfoA(path, 0, size, version);
4000 
4001     VerQueryValueA(version, "\\", (LPVOID *)&ffi, &size);
4002     *vercheck = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
4003     sprintf(*vercheck, "%d.%d.%d.%d", HIWORD(ffi->dwFileVersionMS),
4004             LOWORD(ffi->dwFileVersionMS), HIWORD(ffi->dwFileVersionLS),
4005             LOWORD(ffi->dwFileVersionLS));
4006     *verchecksz = lstrlenA(*vercheck);
4007 
4008     VerQueryValueA(version, "\\VarFileInfo\\Translation", (void **)&lang, &size);
4009     *langcheck = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
4010     sprintf(*langcheck, "%d", *lang);
4011     *langchecksz = lstrlenA(*langcheck);
4012 
4013     HeapFree(GetProcessHeap(), 0, version);
4014 }
4015 
4016 static void test_MsiGetFileVersion(void)
4017 {
4018     UINT r;
4019     DWORD versz, langsz;
4020     char version[MAX_PATH];
4021     char lang[MAX_PATH];
4022     char path[MAX_PATH];
4023     LPSTR vercheck, langcheck;
4024     DWORD verchecksz, langchecksz;
4025 
4026     /* NULL szFilePath */
4027     r = MsiGetFileVersionA(NULL, NULL, NULL, NULL, NULL);
4028     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4029 
4030     versz = MAX_PATH;
4031     langsz = MAX_PATH;
4032     lstrcpyA(version, "version");
4033     lstrcpyA(lang, "lang");
4034     r = MsiGetFileVersionA(NULL, version, &versz, lang, &langsz);
4035     ok(r == ERROR_INVALID_PARAMETER,
4036        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4037     ok(!lstrcmpA(version, "version"),
4038        "Expected version to be unchanged, got %s\n", version);
4039     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4040     ok(!lstrcmpA(lang, "lang"),
4041        "Expected lang to be unchanged, got %s\n", lang);
4042     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4043 
4044     /* empty szFilePath */
4045     r = MsiGetFileVersionA("", NULL, NULL, NULL, NULL);
4046     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4047 
4048     versz = MAX_PATH;
4049     langsz = MAX_PATH;
4050     lstrcpyA(version, "version");
4051     lstrcpyA(lang, "lang");
4052     r = MsiGetFileVersionA("", version, &versz, lang, &langsz);
4053     ok(r == ERROR_FILE_NOT_FOUND,
4054        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4055     ok(!lstrcmpA(version, "version"),
4056        "Expected version to be unchanged, got %s\n", version);
4057     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4058     ok(!lstrcmpA(lang, "lang"),
4059        "Expected lang to be unchanged, got %s\n", lang);
4060     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4061 
4062     /* nonexistent szFilePath */
4063     versz = MAX_PATH;
4064     langsz = MAX_PATH;
4065     lstrcpyA(version, "version");
4066     lstrcpyA(lang, "lang");
4067     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
4068     ok(r == ERROR_FILE_NOT_FOUND,
4069        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4070     ok(!lstrcmpA(version, "version"),
4071        "Expected version to be unchanged, got %s\n", version);
4072     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4073     ok(!lstrcmpA(lang, "lang"),
4074        "Expected lang to be unchanged, got %s\n", lang);
4075     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4076 
4077     /* nonexistent szFilePath, valid lpVersionBuf, NULL pcchVersionBuf */
4078     versz = MAX_PATH;
4079     langsz = MAX_PATH;
4080     lstrcpyA(version, "version");
4081     lstrcpyA(lang, "lang");
4082     r = MsiGetFileVersionA("nonexistent", version, NULL, lang, &langsz);
4083     ok(r == ERROR_INVALID_PARAMETER,
4084        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4085     ok(!lstrcmpA(version, "version"),
4086        "Expected version to be unchanged, got %s\n", version);
4087     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4088     ok(!lstrcmpA(lang, "lang"),
4089        "Expected lang to be unchanged, got %s\n", lang);
4090     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4091 
4092     /* nonexistent szFilePath, valid lpLangBuf, NULL pcchLangBuf */
4093     versz = MAX_PATH;
4094     langsz = MAX_PATH;
4095     lstrcpyA(version, "version");
4096     lstrcpyA(lang, "lang");
4097     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, NULL);
4098     ok(r == ERROR_INVALID_PARAMETER,
4099        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4100     ok(!lstrcmpA(version, "version"),
4101        "Expected version to be unchanged, got %s\n", version);
4102     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4103     ok(!lstrcmpA(lang, "lang"),
4104        "Expected lang to be unchanged, got %s\n", lang);
4105     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4106 
4107     /* nonexistent szFilePath, valid lpVersionBuf, pcchVersionBuf is zero */
4108     versz = 0;
4109     langsz = MAX_PATH;
4110     lstrcpyA(version, "version");
4111     lstrcpyA(lang, "lang");
4112     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
4113     ok(r == ERROR_FILE_NOT_FOUND,
4114        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4115     ok(!lstrcmpA(version, "version"),
4116        "Expected version to be unchanged, got %s\n", version);
4117     ok(versz == 0, "Expected 0, got %d\n", versz);
4118     ok(!lstrcmpA(lang, "lang"),
4119        "Expected lang to be unchanged, got %s\n", lang);
4120     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4121 
4122     /* nonexistent szFilePath, valid lpLangBuf, pcchLangBuf is zero */
4123     versz = MAX_PATH;
4124     langsz = 0;
4125     lstrcpyA(version, "version");
4126     lstrcpyA(lang, "lang");
4127     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
4128     ok(r == ERROR_FILE_NOT_FOUND,
4129        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4130     ok(!lstrcmpA(version, "version"),
4131        "Expected version to be unchanged, got %s\n", version);
4132     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4133     ok(!lstrcmpA(lang, "lang"),
4134        "Expected lang to be unchanged, got %s\n", lang);
4135     ok(langsz == 0, "Expected 0, got %d\n", langsz);
4136 
4137     /* nonexistent szFilePath, rest NULL */
4138     r = MsiGetFileVersionA("nonexistent", NULL, NULL, NULL, NULL);
4139     ok(r == ERROR_FILE_NOT_FOUND,
4140        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4141 
4142     create_file("ver.txt", 20);
4143 
4144     /* file exists, no version information */
4145     r = MsiGetFileVersionA("ver.txt", NULL, NULL, NULL, NULL);
4146     ok(r == ERROR_FILE_INVALID, "Expected ERROR_FILE_INVALID, got %d\n", r);
4147 
4148     versz = MAX_PATH;
4149     langsz = MAX_PATH;
4150     lstrcpyA(version, "version");
4151     lstrcpyA(lang, "lang");
4152     r = MsiGetFileVersionA("ver.txt", version, &versz, lang, &langsz);
4153     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4154     ok(!lstrcmpA(version, "version"),
4155        "Expected version to be unchanged, got %s\n", version);
4156     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4157     ok(!lstrcmpA(lang, "lang"),
4158        "Expected lang to be unchanged, got %s\n", lang);
4159     ok(r == ERROR_FILE_INVALID,
4160        "Expected ERROR_FILE_INVALID, got %d\n", r);
4161 
4162     DeleteFileA("ver.txt");
4163 
4164     /* relative path, has version information */
4165     versz = MAX_PATH;
4166     langsz = MAX_PATH;
4167     lstrcpyA(version, "version");
4168     lstrcpyA(lang, "lang");
4169     r = MsiGetFileVersionA("kernel32.dll", version, &versz, lang, &langsz);
4170     todo_wine
4171     {
4172         ok(r == ERROR_FILE_NOT_FOUND,
4173            "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4174         ok(!lstrcmpA(version, "version"),
4175            "Expected version to be unchanged, got %s\n", version);
4176         ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4177         ok(!lstrcmpA(lang, "lang"),
4178            "Expected lang to be unchanged, got %s\n", lang);
4179         ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4180     }
4181 
4182     GetSystemDirectoryA(path, MAX_PATH);
4183     lstrcatA(path, "\\kernel32.dll");
4184 
4185     get_version_info(path, &vercheck, &verchecksz, &langcheck, &langchecksz);
4186 
4187     /* absolute path, has version information */
4188     versz = MAX_PATH;
4189     langsz = MAX_PATH;
4190     lstrcpyA(version, "version");
4191     lstrcpyA(lang, "lang");
4192     r = MsiGetFileVersionA(path, version, &versz, lang, &langsz);
4193     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4194     if (langchecksz && !langsz)
4195     {
4196         win_skip("broken MsiGetFileVersionA detected\n");
4197         HeapFree(GetProcessHeap(), 0, vercheck);
4198         HeapFree(GetProcessHeap(), 0, langcheck);
4199         return;
4200     }
4201     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4202     ok(strstr(lang, langcheck) != NULL, "Expected \"%s\" in \"%s\"\n", langcheck, lang);
4203     ok(!lstrcmpA(version, vercheck),
4204         "Expected %s, got %s\n", vercheck, version);
4205 
4206     /* only check version */
4207     versz = MAX_PATH;
4208     lstrcpyA(version, "version");
4209     r = MsiGetFileVersionA(path, version, &versz, NULL, NULL);
4210     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4211     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4212     ok(!lstrcmpA(version, vercheck),
4213        "Expected %s, got %s\n", vercheck, version);
4214 
4215     /* only check language */
4216     langsz = MAX_PATH;
4217     lstrcpyA(lang, "lang");
4218     r = MsiGetFileVersionA(path, NULL, NULL, lang, &langsz);
4219     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4220     ok(strstr(lang, langcheck) != NULL, "Expected \"%s\" in \"%s\"\n", langcheck, lang);
4221 
4222     /* check neither version nor language */
4223     r = MsiGetFileVersionA(path, NULL, NULL, NULL, NULL);
4224     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4225 
4226     /* get pcchVersionBuf */
4227     versz = MAX_PATH;
4228     r = MsiGetFileVersionA(path, NULL, &versz, NULL, NULL);
4229     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4230     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4231 
4232     /* get pcchLangBuf */
4233     langsz = MAX_PATH;
4234     r = MsiGetFileVersionA(path, NULL, NULL, NULL, &langsz);
4235     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4236     ok(langsz >= langchecksz, "Expected %d >= %d\n", langsz, langchecksz);
4237 
4238     /* pcchVersionBuf not big enough */
4239     versz = 5;
4240     lstrcpyA(version, "version");
4241     r = MsiGetFileVersionA(path, version, &versz, NULL, NULL);
4242     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4243     ok(!strncmp(version, vercheck, 4),
4244        "Expected first 4 characters of \"%s\", got \"%s\"\n", vercheck, version);
4245     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4246 
4247     /* pcchLangBuf not big enough */
4248     langsz = 4;
4249     lstrcpyA(lang, "lang");
4250     r = MsiGetFileVersionA(path, NULL, NULL, lang, &langsz);
4251     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4252     ok(lstrcmpA(lang, "lang"), "lang not set\n");
4253     ok(langsz >= langchecksz, "Expected %d >= %d\n", langsz, langchecksz);
4254 
4255     /* pcchVersionBuf big enough, pcchLangBuf not big enough */
4256     versz = MAX_PATH;
4257     langsz = 0;
4258     lstrcpyA(version, "version");
4259     r = MsiGetFileVersionA(path, version, &versz, NULL, &langsz);
4260     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4261     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4262     ok(!lstrcmpA(version, vercheck), "Expected \"%s\", got \"%s\"\n", vercheck, version);
4263     ok(langsz >= langchecksz && langsz < MAX_PATH, "Expected %d >= %d\n", langsz, langchecksz);
4264 
4265     /* pcchVersionBuf not big enough, pcchLangBuf big enough */
4266     versz = 5;
4267     langsz = MAX_PATH;
4268     lstrcpyA(lang, "lang");
4269     r = MsiGetFileVersionA(path, NULL, &versz, lang, &langsz);
4270     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4271     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4272     ok(langsz >= langchecksz && langsz < MAX_PATH, "Expected %d >= %d\n", langsz, langchecksz);
4273     ok(strstr(lang, langcheck) != NULL, "expected %s in %s\n", langcheck, lang);
4274 
4275     /* NULL pcchVersionBuf and pcchLangBuf */
4276     r = MsiGetFileVersionA(path, version, NULL, lang, NULL);
4277     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4278 
4279     /* All NULL except szFilePath */
4280     r = MsiGetFileVersionA(path, NULL, NULL, NULL, NULL);
4281     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4282 
4283     HeapFree(GetProcessHeap(), 0, vercheck);
4284     HeapFree(GetProcessHeap(), 0, langcheck);
4285 }
4286 
4287 static void test_MsiGetProductInfo(void)
4288 {
4289     UINT r;
4290     LONG res;
4291     HKEY propkey, source;
4292     HKEY prodkey, localkey;
4293     CHAR prodcode[MAX_PATH];
4294     CHAR prod_squashed[MAX_PATH];
4295     CHAR packcode[MAX_PATH];
4296     CHAR pack_squashed[MAX_PATH];
4297     CHAR buf[MAX_PATH];
4298     CHAR keypath[MAX_PATH];
4299     LPSTR usersid;
4300     DWORD sz, val = 42;
4301     REGSAM access = KEY_ALL_ACCESS;
4302 
4303     create_test_guid(prodcode, prod_squashed);
4304     create_test_guid(packcode, pack_squashed);
4305     usersid = get_user_sid();
4306 
4307     if (is_wow64)
4308         access |= KEY_WOW64_64KEY;
4309 
4310     /* NULL szProduct */
4311     sz = MAX_PATH;
4312     lstrcpyA(buf, "apple");
4313     r = MsiGetProductInfoA(NULL, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4314     ok(r == ERROR_INVALID_PARAMETER,
4315        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4316     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4317     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4318 
4319     /* empty szProduct */
4320     sz = MAX_PATH;
4321     lstrcpyA(buf, "apple");
4322     r = MsiGetProductInfoA("", INSTALLPROPERTY_HELPLINKA, buf, &sz);
4323     ok(r == ERROR_INVALID_PARAMETER,
4324        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4325     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4326     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4327 
4328     /* garbage szProduct */
4329     sz = MAX_PATH;
4330     lstrcpyA(buf, "apple");
4331     r = MsiGetProductInfoA("garbage", INSTALLPROPERTY_HELPLINKA, buf, &sz);
4332     ok(r == ERROR_INVALID_PARAMETER,
4333        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4334     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4335     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4336 
4337     /* guid without brackets */
4338     sz = MAX_PATH;
4339     lstrcpyA(buf, "apple");
4340     r = MsiGetProductInfoA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
4341                            INSTALLPROPERTY_HELPLINKA, buf, &sz);
4342     ok(r == ERROR_INVALID_PARAMETER,
4343        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4344     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4345     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4346 
4347     /* guid with brackets */
4348     sz = MAX_PATH;
4349     lstrcpyA(buf, "apple");
4350     r = MsiGetProductInfoA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
4351                            INSTALLPROPERTY_HELPLINKA, buf, &sz);
4352     ok(r == ERROR_UNKNOWN_PRODUCT,
4353        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4354     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4355     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4356 
4357     /* same length as guid, but random */
4358     sz = MAX_PATH;
4359     lstrcpyA(buf, "apple");
4360     r = MsiGetProductInfoA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
4361                            INSTALLPROPERTY_HELPLINKA, buf, &sz);
4362     ok(r == ERROR_INVALID_PARAMETER,
4363        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4364     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4365     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4366 
4367     /* not installed, NULL szAttribute */
4368     sz = MAX_PATH;
4369     lstrcpyA(buf, "apple");
4370     r = MsiGetProductInfoA(prodcode, NULL, buf, &sz);
4371     ok(r == ERROR_INVALID_PARAMETER,
4372        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4373     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4374     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4375 
4376     /* not installed, NULL lpValueBuf */
4377     sz = MAX_PATH;
4378     lstrcpyA(buf, "apple");
4379     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, &sz);
4380     ok(r == ERROR_UNKNOWN_PRODUCT,
4381        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4382     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4383     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4384 
4385     /* not installed, NULL pcchValueBuf */
4386     sz = MAX_PATH;
4387     lstrcpyA(buf, "apple");
4388     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, NULL);
4389     ok(r == ERROR_INVALID_PARAMETER,
4390        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4391     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4392     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4393 
4394     /* created guid cannot possibly be an installed product code */
4395     sz = MAX_PATH;
4396     lstrcpyA(buf, "apple");
4397     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4398     ok(r == ERROR_UNKNOWN_PRODUCT,
4399        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4400     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4401     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4402 
4403     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
4404     lstrcatA(keypath, usersid);
4405     lstrcatA(keypath, "\\Installer\\Products\\");
4406     lstrcatA(keypath, prod_squashed);
4407 
4408     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4409     if (res == ERROR_ACCESS_DENIED)
4410     {
4411         skip("Not enough rights to perform tests\n");
4412         LocalFree(usersid);
4413         return;
4414     }
4415     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4416 
4417     /* managed product code exists */
4418     sz = MAX_PATH;
4419     lstrcpyA(buf, "apple");
4420     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4421     ok(r == ERROR_UNKNOWN_PROPERTY,
4422        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4423     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4424     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4425 
4426     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4427     RegCloseKey(prodkey);
4428 
4429     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
4430     lstrcatA(keypath, usersid);
4431     lstrcatA(keypath, "\\Products\\");
4432     lstrcatA(keypath, prod_squashed);
4433 
4434     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
4435     if (res == ERROR_ACCESS_DENIED)
4436     {
4437         skip("Not enough rights to perform tests\n");
4438         LocalFree(usersid);
4439         return;
4440     }
4441     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4442 
4443     /* local user product code exists */
4444     sz = MAX_PATH;
4445     lstrcpyA(buf, "apple");
4446     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4447     ok(r == ERROR_UNKNOWN_PRODUCT,
4448        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4449     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4450     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4451 
4452     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
4453     lstrcatA(keypath, usersid);
4454     lstrcatA(keypath, "\\Installer\\Products\\");
4455     lstrcatA(keypath, prod_squashed);
4456 
4457     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4458     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4459 
4460     /* both local and managed product code exist */
4461     sz = MAX_PATH;
4462     lstrcpyA(buf, "apple");
4463     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4464     ok(r == ERROR_UNKNOWN_PROPERTY,
4465        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4466     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4467     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4468 
4469     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
4470     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4471 
4472     /* InstallProperties key exists */
4473     sz = MAX_PATH;
4474     lstrcpyA(buf, "apple");
4475     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4476     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4477     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4478     ok(sz == 0, "Expected 0, got %d\n", sz);
4479 
4480     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
4481     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4482 
4483     /* HelpLink value exists */
4484     sz = MAX_PATH;
4485     lstrcpyA(buf, "apple");
4486     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4487     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4488     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
4489     ok(sz == 4, "Expected 4, got %d\n", sz);
4490 
4491     /* pcchBuf is NULL */
4492     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, NULL);
4493     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4494 
4495     /* lpValueBuf is NULL */
4496     sz = MAX_PATH;
4497     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, &sz);
4498     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4499     ok(sz == 4, "Expected 4, got %d\n", sz);
4500 
4501     /* lpValueBuf is NULL, pcchValueBuf is too small */
4502     sz = 2;
4503     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, &sz);
4504     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4505     ok(sz == 4, "Expected 4, got %d\n", sz);
4506 
4507     /* lpValueBuf is non-NULL, pcchValueBuf is too small */
4508     sz = 2;
4509     lstrcpyA(buf, "apple");
4510     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4511     ok(!lstrcmpA(buf, "apple"), "Expected buf to remain unchanged, got \"%s\"\n", buf);
4512     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4513     ok(sz == 4, "Expected 4, got %d\n", sz);
4514 
4515     /* lpValueBuf is non-NULL, pcchValueBuf is exactly 4 */
4516     sz = 4;
4517     lstrcpyA(buf, "apple");
4518     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4519     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4520     ok(!lstrcmpA(buf, "apple"),
4521        "Expected buf to remain unchanged, got \"%s\"\n", buf);
4522     ok(sz == 4, "Expected 4, got %d\n", sz);
4523 
4524     res = RegSetValueExA(propkey, "IMadeThis", 0, REG_SZ, (LPBYTE)"random", 7);
4525     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4526 
4527     /* random property not supported by MSI, value exists */
4528     sz = MAX_PATH;
4529     lstrcpyA(buf, "apple");
4530     r = MsiGetProductInfoA(prodcode, "IMadeThis", buf, &sz);
4531     ok(r == ERROR_UNKNOWN_PROPERTY,
4532        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4533     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4534     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4535 
4536     RegDeleteValueA(propkey, "IMadeThis");
4537     RegDeleteValueA(propkey, "HelpLink");
4538     delete_key(propkey, "", access & KEY_WOW64_64KEY);
4539     delete_key(localkey, "", access & KEY_WOW64_64KEY);
4540     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4541     RegCloseKey(propkey);
4542     RegCloseKey(localkey);
4543     RegCloseKey(prodkey);
4544 
4545     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
4546     lstrcatA(keypath, prod_squashed);
4547 
4548     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
4549     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4550 
4551     /* user product key exists */
4552     sz = MAX_PATH;
4553     lstrcpyA(buf, "apple");
4554     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4555     ok(r == ERROR_UNKNOWN_PROPERTY,
4556        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4557     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4558     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4559 
4560     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
4561     lstrcatA(keypath, usersid);
4562     lstrcatA(keypath, "\\Products\\");
4563     lstrcatA(keypath, prod_squashed);
4564 
4565     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
4566     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4567 
4568     /* local user product key exists */
4569     sz = MAX_PATH;
4570     lstrcpyA(buf, "apple");
4571     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4572     ok(r == ERROR_UNKNOWN_PROPERTY,
4573        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4574     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4575     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4576 
4577     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
4578     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4579 
4580     /* InstallProperties key exists */
4581     sz = MAX_PATH;
4582     lstrcpyA(buf, "apple");
4583     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4584     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4585     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4586     ok(sz == 0, "Expected 0, got %d\n", sz);
4587 
4588     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
4589     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4590 
4591     /* HelpLink value exists */
4592     sz = MAX_PATH;
4593     lstrcpyA(buf, "apple");
4594     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4595     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4596     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
4597     ok(sz == 4, "Expected 4, got %d\n", sz);
4598 
4599     RegDeleteValueA(propkey, "HelpLink");
4600     delete_key(propkey, "", access & KEY_WOW64_64KEY);
4601     delete_key(localkey, "", access & KEY_WOW64_64KEY);
4602     RegDeleteKeyA(prodkey, "");
4603     RegCloseKey(propkey);
4604     RegCloseKey(localkey);
4605     RegCloseKey(prodkey);
4606 
4607     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
4608     lstrcatA(keypath, prod_squashed);
4609 
4610     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4611     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4612 
4613     /* classes product key exists */
4614     sz = MAX_PATH;
4615     lstrcpyA(buf, "apple");
4616     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4617     ok(r == ERROR_UNKNOWN_PROPERTY,
4618        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4619     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4620     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4621 
4622     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
4623     lstrcatA(keypath, usersid);
4624     lstrcatA(keypath, "\\Products\\");
4625     lstrcatA(keypath, prod_squashed);
4626 
4627     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
4628     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4629 
4630     /* local user product key exists */
4631     sz = MAX_PATH;
4632     lstrcpyA(buf, "apple");
4633     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4634     ok(r == ERROR_UNKNOWN_PROPERTY,
4635        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4636     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4637     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4638 
4639     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
4640     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4641 
4642     /* InstallProperties key exists */
4643     sz = MAX_PATH;
4644     lstrcpyA(buf, "apple");
4645     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4646     ok(r == ERROR_UNKNOWN_PROPERTY,
4647        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4648     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4649     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4650 
4651     delete_key(propkey, "", access & KEY_WOW64_64KEY);
4652     delete_key(localkey, "", access & KEY_WOW64_64KEY);
4653     RegCloseKey(propkey);
4654     RegCloseKey(localkey);
4655 
4656     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
4657     lstrcatA(keypath, "S-1-5-18\\\\Products\\");
4658     lstrcatA(keypath, prod_squashed);
4659 
4660     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
4661     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4662 
4663     /* Local System product key exists */
4664     sz = MAX_PATH;
4665     lstrcpyA(buf, "apple");
4666     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4667     ok(r == ERROR_UNKNOWN_PROPERTY,
4668         "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4669     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4670     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4671 
4672     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
4673     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4674 
4675     /* InstallProperties key exists */
4676     sz = MAX_PATH;
4677     lstrcpyA(buf, "apple");
4678     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4679     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4680     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4681     ok(sz == 0, "Expected 0, got %d\n", sz);
4682 
4683     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
4684     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4685 
4686     /* HelpLink value exists */
4687     sz = MAX_PATH;
4688     lstrcpyA(buf, "apple");
4689     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4690     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4691     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
4692     ok(sz == 4, "Expected 4, got %d\n", sz);
4693 
4694     res = RegSetValueExA(propkey, "HelpLink", 0, REG_DWORD,
4695                          (const BYTE *)&val, sizeof(DWORD));
4696     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4697 
4698     /* HelpLink type is REG_DWORD */
4699     sz = MAX_PATH;
4700     lstrcpyA(buf, "apple");
4701     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4702     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4703     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4704     ok(sz == 2, "Expected 2, got %d\n", sz);
4705 
4706     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
4707     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4708 
4709     /* DisplayName value exists */
4710     sz = MAX_PATH;
4711     lstrcpyA(buf, "apple");
4712     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
4713     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4714     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
4715     ok(sz == 4, "Expected 4, got %d\n", sz);
4716 
4717     res = RegSetValueExA(propkey, "DisplayName", 0, REG_DWORD,
4718                          (const BYTE *)&val, sizeof(DWORD));
4719     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4720 
4721     /* DisplayName type is REG_DWORD */
4722     sz = MAX_PATH;
4723     lstrcpyA(buf, "apple");
4724     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
4725     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4726     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4727     ok(sz == 2, "Expected 2, got %d\n", sz);
4728 
4729     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"1.1.1", 6);
4730     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4731 
4732     /* DisplayVersion value exists */
4733     sz = MAX_PATH;
4734     lstrcpyA(buf, "apple");
4735     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
4736     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4737     ok(!lstrcmpA(buf, "1.1.1"), "Expected \"1.1.1\", got \"%s\"\n", buf);
4738     ok(sz == 5, "Expected 5, got %d\n", sz);
4739 
4740     res = RegSetValueExA(propkey, "DisplayVersion", 0,
4741                          REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
4742     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4743 
4744     /* DisplayVersion type is REG_DWORD */
4745     sz = MAX_PATH;
4746     lstrcpyA(buf, "apple");
4747     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
4748     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4749     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4750     ok(sz == 2, "Expected 2, got %d\n", sz);
4751 
4752     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"tele", 5);
4753     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4754 
4755     /* HelpTelephone value exists */
4756     sz = MAX_PATH;
4757     lstrcpyA(buf, "apple");
4758     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
4759     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4760     ok(!lstrcmpA(buf, "tele"), "Expected \"tele\", got \"%s\"\n", buf);
4761     ok(sz == 4, "Expected 4, got %d\n", sz);
4762 
4763     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_DWORD,
4764                          (const BYTE *)&val, sizeof(DWORD));
4765     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4766 
4767     /* HelpTelephone type is REG_DWORD */
4768     sz = MAX_PATH;
4769     lstrcpyA(buf, "apple");
4770     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
4771     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4772     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4773     ok(sz == 2, "Expected 2, got %d\n", sz);
4774 
4775     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
4776     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4777 
4778     /* InstallLocation value exists */
4779     sz = MAX_PATH;
4780     lstrcpyA(buf, "apple");
4781     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
4782     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4783     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
4784     ok(sz == 3, "Expected 3, got %d\n", sz);
4785 
4786     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_DWORD,
4787                          (const BYTE *)&val, sizeof(DWORD));
4788     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4789 
4790     /* InstallLocation type is REG_DWORD */
4791     sz = MAX_PATH;
4792     lstrcpyA(buf, "apple");
4793     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
4794     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4795     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4796     ok(sz == 2, "Expected 2, got %d\n", sz);
4797 
4798     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
4799     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4800 
4801     /* InstallSource value exists */
4802     sz = MAX_PATH;
4803     lstrcpyA(buf, "apple");
4804     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
4805     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4806     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
4807     ok(sz == 6, "Expected 6, got %d\n", sz);
4808 
4809     res = RegSetValueExA(propkey, "InstallSource", 0, REG_DWORD,
4810                          (const BYTE *)&val, sizeof(DWORD));
4811     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4812 
4813     /* InstallSource type is REG_DWORD */
4814     sz = MAX_PATH;
4815     lstrcpyA(buf, "apple");
4816     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
4817     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4818     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4819     ok(sz == 2, "Expected 2, got %d\n", sz);
4820 
4821     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
4822     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4823 
4824     /* InstallDate value exists */
4825     sz = MAX_PATH;
4826     lstrcpyA(buf, "apple");
4827     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
4828     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4829     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
4830     ok(sz == 4, "Expected 4, got %d\n", sz);
4831 
4832     res = RegSetValueExA(propkey, "InstallDate", 0, REG_DWORD,
4833                          (const BYTE *)&val, sizeof(DWORD));
4834     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4835 
4836     /* InstallDate type is REG_DWORD */
4837     sz = MAX_PATH;
4838     lstrcpyA(buf, "apple");
4839     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
4840     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4841     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4842     ok(sz == 2, "Expected 2, got %d\n", sz);
4843 
4844     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
4845     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4846 
4847     /* Publisher value exists */
4848     sz = MAX_PATH;
4849     lstrcpyA(buf, "apple");
4850     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PUBLISHERA, buf, &sz);
4851     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4852     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
4853     ok(sz == 3, "Expected 3, got %d\n", sz);
4854 
4855     res = RegSetValueExA(propkey, "Publisher", 0, REG_DWORD,
4856                          (const BYTE *)&val, sizeof(DWORD));
4857     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4858 
4859     /* Publisher type is REG_DWORD */
4860     sz = MAX_PATH;
4861     lstrcpyA(buf, "apple");
4862     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PUBLISHERA, buf, &sz);
4863     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4864     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4865     ok(sz == 2, "Expected 2, got %d\n", sz);
4866 
4867     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"pack", 5);
4868     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4869 
4870     /* LocalPackage value exists */
4871     sz = MAX_PATH;
4872     lstrcpyA(buf, "apple");
4873     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
4874     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4875     ok(!lstrcmpA(buf, "pack"), "Expected \"pack\", got \"%s\"\n", buf);
4876     ok(sz == 4, "Expected 4, got %d\n", sz);
4877 
4878     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_DWORD,
4879                          (const BYTE *)&val, sizeof(DWORD));
4880     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4881 
4882     /* LocalPackage type is REG_DWORD */
4883     sz = MAX_PATH;
4884     lstrcpyA(buf, "apple");
4885     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
4886     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4887     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4888     ok(sz == 2, "Expected 2, got %d\n", sz);
4889 
4890     res = RegSetValueExA(propkey, "UrlInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
4891     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4892 
4893     /* UrlInfoAbout value exists */
4894     sz = MAX_PATH;
4895     lstrcpyA(buf, "apple");
4896     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
4897     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4898     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
4899     ok(sz == 5, "Expected 5, got %d\n", sz);
4900 
4901     res = RegSetValueExA(propkey, "UrlInfoAbout", 0, REG_DWORD,
4902                          (const BYTE *)&val, sizeof(DWORD));
4903     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4904 
4905     /* UrlInfoAbout type is REG_DWORD */
4906     sz = MAX_PATH;
4907     lstrcpyA(buf, "apple");
4908     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
4909     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4910     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4911     ok(sz == 2, "Expected 2, got %d\n", sz);
4912 
4913     res = RegSetValueExA(propkey, "UrlUpdateInfo", 0, REG_SZ, (LPBYTE)"info", 5);
4914     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4915 
4916     /* UrlUpdateInfo value exists */
4917     sz = MAX_PATH;
4918     lstrcpyA(buf, "apple");
4919     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
4920     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4921     ok(!lstrcmpA(buf, "info"), "Expected \"info\", got \"%s\"\n", buf);
4922     ok(sz == 4, "Expected 4, got %d\n", sz);
4923 
4924     res = RegSetValueExA(propkey, "UrlUpdateInfo", 0, REG_DWORD,
4925                          (const BYTE *)&val, sizeof(DWORD));
4926     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4927 
4928     /* UrlUpdateInfo type is REG_DWORD */
4929     sz = MAX_PATH;
4930     lstrcpyA(buf, "apple");
4931     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
4932     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4933     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4934     ok(sz == 2, "Expected 2, got %d\n", sz);
4935 
4936     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"1", 2);
4937     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4938 
4939     /* VersionMinor value exists */
4940     sz = MAX_PATH;
4941     lstrcpyA(buf, "apple");
4942     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
4943     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4944     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
4945     ok(sz == 1, "Expected 1, got %d\n", sz);
4946 
4947     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_DWORD,
4948                          (const BYTE *)&val, sizeof(DWORD));
4949     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4950 
4951     /* VersionMinor type is REG_DWORD */
4952     sz = MAX_PATH;
4953     lstrcpyA(buf, "apple");
4954     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
4955     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4956     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4957     ok(sz == 2, "Expected 2, got %d\n", sz);
4958 
4959     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"1", 2);
4960     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4961 
4962     /* VersionMajor value exists */
4963     sz = MAX_PATH;
4964     lstrcpyA(buf, "apple");
4965     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
4966     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4967     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
4968     ok(sz == 1, "Expected 1, got %d\n", sz);
4969 
4970     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_DWORD,
4971                          (const BYTE *)&val, sizeof(DWORD));
4972     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4973 
4974     /* VersionMajor type is REG_DWORD */
4975     sz = MAX_PATH;
4976     lstrcpyA(buf, "apple");
4977     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
4978     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4979     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4980     ok(sz == 2, "Expected 2, got %d\n", sz);
4981 
4982     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
4983     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4984 
4985     /* ProductID value exists */
4986     sz = MAX_PATH;
4987     lstrcpyA(buf, "apple");
4988     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
4989     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4990     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
4991     ok(sz == 2, "Expected 2, got %d\n", sz);
4992 
4993     res = RegSetValueExA(propkey, "ProductID", 0, REG_DWORD,
4994                          (const BYTE *)&val, sizeof(DWORD));
4995     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4996 
4997     /* ProductID type is REG_DWORD */
4998     sz = MAX_PATH;
4999     lstrcpyA(buf, "apple");
5000     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
5001     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5002     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5003     ok(sz == 2, "Expected 2, got %d\n", sz);
5004 
5005     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
5006     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5007 
5008     /* RegCompany value exists */
5009     sz = MAX_PATH;
5010     lstrcpyA(buf, "apple");
5011     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
5012     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5013     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
5014     ok(sz == 4, "Expected 4, got %d\n", sz);
5015 
5016     res = RegSetValueExA(propkey, "RegCompany", 0, REG_DWORD,
5017                          (const BYTE *)&val, sizeof(DWORD));
5018     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5019 
5020     /* RegCompany type is REG_DWORD */
5021     sz = MAX_PATH;
5022     lstrcpyA(buf, "apple");
5023     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
5024     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5025     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5026     ok(sz == 2, "Expected 2, got %d\n", sz);
5027 
5028     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"own", 4);
5029     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5030 
5031     /* RegOwner value exists */
5032     sz = MAX_PATH;
5033     lstrcpyA(buf, "apple");
5034     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGOWNERA, buf, &sz);
5035     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5036     ok(!lstrcmpA(buf, "own"), "Expected \"own\", got \"%s\"\n", buf);
5037     ok(sz == 3, "Expected 3, got %d\n", sz);
5038 
5039     res = RegSetValueExA(propkey, "RegOwner", 0, REG_DWORD,
5040                          (const BYTE *)&val, sizeof(DWORD));
5041     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5042 
5043     /* RegOwner type is REG_DWORD */
5044     sz = MAX_PATH;
5045     lstrcpyA(buf, "apple");
5046     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGOWNERA, buf, &sz);
5047     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5048     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5049     ok(sz == 2, "Expected 2, got %d\n", sz);
5050 
5051     res = RegSetValueExA(propkey, "InstanceType", 0, REG_SZ, (LPBYTE)"type", 5);
5052     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5053 
5054     /* InstanceType value exists */
5055     sz = MAX_PATH;
5056     lstrcpyA(buf, "apple");
5057     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5058     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5059     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5060     ok(sz == 0, "Expected 0, got %d\n", sz);
5061 
5062     res = RegSetValueExA(propkey, "InstanceType", 0, REG_DWORD,
5063                          (const BYTE *)&val, sizeof(DWORD));
5064     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5065 
5066     /* InstanceType type is REG_DWORD */
5067     sz = MAX_PATH;
5068     lstrcpyA(buf, "apple");
5069     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5070     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5071     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5072     ok(sz == 0, "Expected 0, got %d\n", sz);
5073 
5074     res = RegSetValueExA(prodkey, "InstanceType", 0, REG_SZ, (LPBYTE)"type", 5);
5075     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5076 
5077     /* InstanceType value exists */
5078     sz = MAX_PATH;
5079     lstrcpyA(buf, "apple");
5080     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5081     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5082     ok(!lstrcmpA(buf, "type"), "Expected \"type\", got \"%s\"\n", buf);
5083     ok(sz == 4, "Expected 4, got %d\n", sz);
5084 
5085     res = RegSetValueExA(prodkey, "InstanceType", 0, REG_DWORD,
5086                          (const BYTE *)&val, sizeof(DWORD));
5087     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5088 
5089     /* InstanceType type is REG_DWORD */
5090     sz = MAX_PATH;
5091     lstrcpyA(buf, "apple");
5092     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5093     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5094     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5095     ok(sz == 2, "Expected 2, got %d\n", sz);
5096 
5097     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"tforms", 7);
5098     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5099 
5100     /* Transforms value exists */
5101     sz = MAX_PATH;
5102     lstrcpyA(buf, "apple");
5103     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5104     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5105     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5106     ok(sz == 0, "Expected 0, got %d\n", sz);
5107 
5108     res = RegSetValueExA(propkey, "Transforms", 0, REG_DWORD,
5109                          (const BYTE *)&val, sizeof(DWORD));
5110     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5111 
5112     /* Transforms type is REG_DWORD */
5113     sz = MAX_PATH;
5114     lstrcpyA(buf, "apple");
5115     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5116     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5117     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5118     ok(sz == 0, "Expected 0, got %d\n", sz);
5119 
5120     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"tforms", 7);
5121     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5122 
5123     /* Transforms value exists */
5124     sz = MAX_PATH;
5125     lstrcpyA(buf, "apple");
5126     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5127     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5128     ok(!lstrcmpA(buf, "tforms"), "Expected \"tforms\", got \"%s\"\n", buf);
5129     ok(sz == 6, "Expected 6, got %d\n", sz);
5130 
5131     res = RegSetValueExA(prodkey, "Transforms", 0, REG_DWORD,
5132                          (const BYTE *)&val, sizeof(DWORD));
5133     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5134 
5135     /* Transforms type is REG_DWORD */
5136     sz = MAX_PATH;
5137     lstrcpyA(buf, "apple");
5138     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5139     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5140     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5141     ok(sz == 2, "Expected 2, got %d\n", sz);
5142 
5143     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
5144     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5145 
5146     /* Language value exists */
5147     sz = MAX_PATH;
5148     lstrcpyA(buf, "apple");
5149     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5150     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5151     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5152     ok(sz == 0, "Expected 0, got %d\n", sz);
5153 
5154     res = RegSetValueExA(propkey, "Language", 0, REG_DWORD,
5155                          (const BYTE *)&val, sizeof(DWORD));
5156     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5157 
5158     /* Language type is REG_DWORD */
5159     sz = MAX_PATH;
5160     lstrcpyA(buf, "apple");
5161     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5162     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5163     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5164     ok(sz == 0, "Expected 0, got %d\n", sz);
5165 
5166     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
5167     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5168 
5169     /* Language value exists */
5170     sz = MAX_PATH;
5171     lstrcpyA(buf, "apple");
5172     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5173     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5174     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
5175     ok(sz == 4, "Expected 4, got %d\n", sz);
5176 
5177     res = RegSetValueExA(prodkey, "Language", 0, REG_DWORD,
5178                          (const BYTE *)&val, sizeof(DWORD));
5179     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5180 
5181     /* Language type is REG_DWORD */
5182     sz = MAX_PATH;
5183     lstrcpyA(buf, "apple");
5184     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5185     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5186     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5187     ok(sz == 2, "Expected 2, got %d\n", sz);
5188 
5189     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
5190     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5191 
5192     /* ProductName value exists */
5193     sz = MAX_PATH;
5194     lstrcpyA(buf, "apple");
5195     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5196     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5197     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5198     ok(sz == 0, "Expected 0, got %d\n", sz);
5199 
5200     res = RegSetValueExA(propkey, "ProductName", 0, REG_DWORD,
5201                          (const BYTE *)&val, sizeof(DWORD));
5202     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5203 
5204     /* ProductName type is REG_DWORD */
5205     sz = MAX_PATH;
5206     lstrcpyA(buf, "apple");
5207     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5208     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5209     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5210     ok(sz == 0, "Expected 0, got %d\n", sz);
5211 
5212     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
5213     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5214 
5215     /* ProductName value exists */
5216     sz = MAX_PATH;
5217     lstrcpyA(buf, "apple");
5218     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5219     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5220     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
5221     ok(sz == 4, "Expected 4, got %d\n", sz);
5222 
5223     res = RegSetValueExA(prodkey, "ProductName", 0, REG_DWORD,
5224                          (const BYTE *)&val, sizeof(DWORD));
5225     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5226 
5227     /* ProductName type is REG_DWORD */
5228     sz = MAX_PATH;
5229     lstrcpyA(buf, "apple");
5230     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5231     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5232     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5233     ok(sz == 2, "Expected 2, got %d\n", sz);
5234 
5235     res = RegSetValueExA(propkey, "Assignment", 0, REG_SZ, (LPBYTE)"at", 3);
5236     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5237 
5238     /* Assignment value exists */
5239     sz = MAX_PATH;
5240     lstrcpyA(buf, "apple");
5241     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5242     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5243     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5244     ok(sz == 0, "Expected 0, got %d\n", sz);
5245 
5246     res = RegSetValueExA(propkey, "Assignment", 0, REG_DWORD,
5247                          (const BYTE *)&val, sizeof(DWORD));
5248     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5249 
5250     /* Assignment type is REG_DWORD */
5251     sz = MAX_PATH;
5252     lstrcpyA(buf, "apple");
5253     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5254     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5255     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5256     ok(sz == 0, "Expected 0, got %d\n", sz);
5257 
5258     res = RegSetValueExA(prodkey, "Assignment", 0, REG_SZ, (LPBYTE)"at", 3);
5259     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5260 
5261     /* Assignment value exists */
5262     sz = MAX_PATH;
5263     lstrcpyA(buf, "apple");
5264     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5265     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5266     ok(!lstrcmpA(buf, "at"), "Expected \"at\", got \"%s\"\n", buf);
5267     ok(sz == 2, "Expected 2, got %d\n", sz);
5268 
5269     res = RegSetValueExA(prodkey, "Assignment", 0, REG_DWORD,
5270                          (const BYTE *)&val, sizeof(DWORD));
5271     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5272 
5273     /* Assignment type is REG_DWORD */
5274     sz = MAX_PATH;
5275     lstrcpyA(buf, "apple");
5276     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5277     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5278     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5279     ok(sz == 2, "Expected 2, got %d\n", sz);
5280 
5281     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
5282     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5283 
5284     /* PackageCode value exists */
5285     sz = MAX_PATH;
5286     lstrcpyA(buf, "apple");
5287     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5288     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5289     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5290     ok(sz == 0, "Expected 0, got %d\n", sz);
5291 
5292     res = RegSetValueExA(propkey, "PackageCode", 0, REG_DWORD,
5293                          (const BYTE *)&val, sizeof(DWORD));
5294     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5295 
5296     /* PackageCode type is REG_DWORD */
5297     sz = MAX_PATH;
5298     lstrcpyA(buf, "apple");
5299     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5300     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5301     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5302     ok(sz == 0, "Expected 0, got %d\n", sz);
5303 
5304     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
5305     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5306 
5307     /* PackageCode value exists */
5308     sz = MAX_PATH;
5309     lstrcpyA(buf, "apple");
5310     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5311     ok(r == ERROR_BAD_CONFIGURATION,
5312        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
5313     ok(!lstrcmpA(buf, "code"), "Expected \"code\", got \"%s\"\n", buf);
5314     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5315 
5316     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_DWORD,
5317                          (const BYTE *)&val, sizeof(DWORD));
5318     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5319 
5320     /* PackageCode type is REG_DWORD */
5321     sz = MAX_PATH;
5322     lstrcpyA(buf, "apple");
5323     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5324     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5325     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5326     ok(sz == 2, "Expected 2, got %d\n", sz);
5327 
5328     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)pack_squashed, 33);
5329     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5330 
5331     /* PackageCode value exists */
5332     sz = MAX_PATH;
5333     lstrcpyA(buf, "apple");
5334     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5335     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5336     ok(!lstrcmpA(buf, packcode), "Expected \"%s\", got \"%s\"\n", packcode, buf);
5337     ok(sz == 38, "Expected 38, got %d\n", sz);
5338 
5339     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
5340     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5341 
5342     /* Version value exists */
5343     sz = MAX_PATH;
5344     lstrcpyA(buf, "apple");
5345     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5346     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5347     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5348     ok(sz == 0, "Expected 0, got %d\n", sz);
5349 
5350     res = RegSetValueExA(propkey, "Version", 0, REG_DWORD,
5351                          (const BYTE *)&val, sizeof(DWORD));
5352     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5353 
5354     /* Version type is REG_DWORD */
5355     sz = MAX_PATH;
5356     lstrcpyA(buf, "apple");
5357     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5358     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5359     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5360     ok(sz == 0, "Expected 0, got %d\n", sz);
5361 
5362     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
5363     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5364 
5365     /* Version value exists */
5366     sz = MAX_PATH;
5367     lstrcpyA(buf, "apple");
5368     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5369     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5370     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
5371     ok(sz == 3, "Expected 3, got %d\n", sz);
5372 
5373     res = RegSetValueExA(prodkey, "Version", 0, REG_DWORD,
5374                          (const BYTE *)&val, sizeof(DWORD));
5375     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5376 
5377     /* Version type is REG_DWORD */
5378     sz = MAX_PATH;
5379     lstrcpyA(buf, "apple");
5380     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5381     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5382     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5383     ok(sz == 2, "Expected 2, got %d\n", sz);
5384 
5385     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"ico", 4);
5386     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5387 
5388     /* ProductIcon value exists */
5389     sz = MAX_PATH;
5390     lstrcpyA(buf, "apple");
5391     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5392     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5393     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5394     ok(sz == 0, "Expected 0, got %d\n", sz);
5395 
5396     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_DWORD,
5397                          (const BYTE *)&val, sizeof(DWORD));
5398     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5399 
5400     /* ProductIcon type is REG_DWORD */
5401     sz = MAX_PATH;
5402     lstrcpyA(buf, "apple");
5403     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5404     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5405     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5406     ok(sz == 0, "Expected 0, got %d\n", sz);
5407 
5408     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"ico", 4);
5409     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5410 
5411     /* ProductIcon value exists */
5412     sz = MAX_PATH;
5413     lstrcpyA(buf, "apple");
5414     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5415     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5416     ok(!lstrcmpA(buf, "ico"), "Expected \"ico\", got \"%s\"\n", buf);
5417     ok(sz == 3, "Expected 3, got %d\n", sz);
5418 
5419     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_DWORD,
5420                          (const BYTE *)&val, sizeof(DWORD));
5421     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5422 
5423     /* ProductIcon type is REG_DWORD */
5424     sz = MAX_PATH;
5425     lstrcpyA(buf, "apple");
5426     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5427     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5428     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5429     ok(sz == 2, "Expected 2, got %d\n", sz);
5430 
5431     /* SourceList key does not exist */
5432     sz = MAX_PATH;
5433     lstrcpyA(buf, "apple");
5434     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5435     ok(r == ERROR_UNKNOWN_PRODUCT,
5436        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5437     ok(!lstrcmpA(buf, "apple"),
5438        "Expected buf to be unchanged, got \"%s\"\n", buf);
5439     ok(sz == MAX_PATH, "Expected sz to be unchanged, got %d\n", sz);
5440 
5441     res = RegCreateKeyExA(prodkey, "SourceList", 0, NULL, 0, access, NULL, &source, NULL);
5442     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5443 
5444     /* SourceList key exists, but PackageName val does not exist */
5445     sz = MAX_PATH;
5446     lstrcpyA(buf, "apple");
5447     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5448     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5449     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5450     ok(sz == 0, "Expected 0, got %d\n", sz);
5451 
5452     res = RegSetValueExA(source, "PackageName", 0, REG_SZ, (LPBYTE)"packname", 9);
5453     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5454 
5455     /* PackageName val exists */
5456     sz = MAX_PATH;
5457     lstrcpyA(buf, "apple");
5458     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5459     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5460     ok(!lstrcmpA(buf, "packname"), "Expected \"packname\", got \"%s\"\n", buf);
5461     ok(sz == 8, "Expected 8, got %d\n", sz);
5462 
5463     res = RegSetValueExA(source, "PackageName", 0, REG_DWORD,
5464                          (const BYTE *)&val, sizeof(DWORD));
5465     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5466 
5467     /* PackageName type is REG_DWORD */
5468     sz = MAX_PATH;
5469     lstrcpyA(buf, "apple");
5470     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5471     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5472     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5473     ok(sz == 2, "Expected 2, got %d\n", sz);
5474 
5475     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
5476     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5477 
5478     /* Authorized value exists */
5479     sz = MAX_PATH;
5480     lstrcpyA(buf, "apple");
5481     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5482     if (r != ERROR_UNKNOWN_PROPERTY)
5483     {
5484         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5485         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5486         ok(sz == 0, "Expected 0, got %d\n", sz);
5487     }
5488 
5489     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_DWORD,
5490                          (const BYTE *)&val, sizeof(DWORD));
5491     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5492 
5493     /* AuthorizedLUAApp type is REG_DWORD */
5494     sz = MAX_PATH;
5495     lstrcpyA(buf, "apple");
5496     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5497     if (r != ERROR_UNKNOWN_PROPERTY)
5498     {
5499         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5500         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5501         ok(sz == 0, "Expected 0, got %d\n", sz);
5502     }
5503 
5504     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
5505     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5506 
5507     /* Authorized value exists */
5508     sz = MAX_PATH;
5509     lstrcpyA(buf, "apple");
5510     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5511     if (r != ERROR_UNKNOWN_PROPERTY)
5512     {
5513         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5514         ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
5515         ok(sz == 4, "Expected 4, got %d\n", sz);
5516     }
5517 
5518     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_DWORD,
5519                          (const BYTE *)&val, sizeof(DWORD));
5520     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5521 
5522     /* AuthorizedLUAApp type is REG_DWORD */
5523     sz = MAX_PATH;
5524     lstrcpyA(buf, "apple");
5525     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5526     if (r != ERROR_UNKNOWN_PROPERTY)
5527     {
5528         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5529         ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5530         ok(sz == 2, "Expected 2, got %d\n", sz);
5531     }
5532 
5533     RegDeleteValueA(propkey, "HelpLink");
5534     RegDeleteValueA(propkey, "DisplayName");
5535     RegDeleteValueA(propkey, "DisplayVersion");
5536     RegDeleteValueA(propkey, "HelpTelephone");
5537     RegDeleteValueA(propkey, "InstallLocation");
5538     RegDeleteValueA(propkey, "InstallSource");
5539     RegDeleteValueA(propkey, "InstallDate");
5540     RegDeleteValueA(propkey, "Publisher");
5541     RegDeleteValueA(propkey, "LocalPackage");
5542     RegDeleteValueA(propkey, "UrlInfoAbout");
5543     RegDeleteValueA(propkey, "UrlUpdateInfo");
5544     RegDeleteValueA(propkey, "VersionMinor");
5545     RegDeleteValueA(propkey, "VersionMajor");
5546     RegDeleteValueA(propkey, "ProductID");
5547     RegDeleteValueA(propkey, "RegCompany");
5548     RegDeleteValueA(propkey, "RegOwner");
5549     RegDeleteValueA(propkey, "InstanceType");
5550     RegDeleteValueA(propkey, "Transforms");
5551     RegDeleteValueA(propkey, "Language");
5552     RegDeleteValueA(propkey, "ProductName");
5553     RegDeleteValueA(propkey, "Assignment");
5554     RegDeleteValueA(propkey, "PackageCode");
5555     RegDeleteValueA(propkey, "Version");
5556     RegDeleteValueA(propkey, "ProductIcon");
5557     RegDeleteValueA(propkey, "AuthorizedLUAApp");
5558     delete_key(propkey, "", access & KEY_WOW64_64KEY);
5559     delete_key(localkey, "", access & KEY_WOW64_64KEY);
5560     RegDeleteValueA(prodkey, "InstanceType");
5561     RegDeleteValueA(prodkey, "Transforms");
5562     RegDeleteValueA(prodkey, "Language");
5563     RegDeleteValueA(prodkey, "ProductName");
5564     RegDeleteValueA(prodkey, "Assignment");
5565     RegDeleteValueA(prodkey, "PackageCode");
5566     RegDeleteValueA(prodkey, "Version");
5567     RegDeleteValueA(prodkey, "ProductIcon");
5568     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
5569     RegDeleteValueA(source, "PackageName");
5570     delete_key(source, "", access & KEY_WOW64_64KEY);
5571     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
5572     RegCloseKey(propkey);
5573     RegCloseKey(localkey);
5574     RegCloseKey(source);
5575     RegCloseKey(prodkey);
5576     LocalFree(usersid);
5577 }
5578 
5579 static void test_MsiGetProductInfoEx(void)
5580 {
5581     UINT r;
5582     LONG res;
5583     HKEY propkey, userkey;
5584     HKEY prodkey, localkey;
5585     CHAR prodcode[MAX_PATH];
5586     CHAR prod_squashed[MAX_PATH];
5587     CHAR packcode[MAX_PATH];
5588     CHAR pack_squashed[MAX_PATH];
5589     CHAR buf[MAX_PATH];
5590     CHAR keypath[MAX_PATH];
5591     LPSTR usersid;
5592     DWORD sz;
5593     REGSAM access = KEY_ALL_ACCESS;
5594 
5595     if (!pMsiGetProductInfoExA)
5596     {
5597         win_skip("MsiGetProductInfoExA is not available\n");
5598         return;
5599     }
5600 
5601     create_test_guid(prodcode, prod_squashed);
5602     create_test_guid(packcode, pack_squashed);
5603     usersid = get_user_sid();
5604 
5605     if (is_wow64)
5606         access |= KEY_WOW64_64KEY;
5607 
5608     /* NULL szProductCode */
5609     sz = MAX_PATH;
5610     lstrcpyA(buf, "apple");
5611     r = pMsiGetProductInfoExA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
5612                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5613     ok(r == ERROR_INVALID_PARAMETER,
5614        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5615     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5616     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5617 
5618     /* empty szProductCode */
5619     sz = MAX_PATH;
5620     lstrcpyA(buf, "apple");
5621     r = pMsiGetProductInfoExA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
5622                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5623     ok(r == ERROR_INVALID_PARAMETER,
5624        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5625     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5626     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5627 
5628     /* garbage szProductCode */
5629     sz = MAX_PATH;
5630     lstrcpyA(buf, "apple");
5631     r = pMsiGetProductInfoExA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
5632                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5633     ok(r == ERROR_INVALID_PARAMETER,
5634        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5635     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5636     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5637 
5638     /* guid without brackets */
5639     sz = MAX_PATH;
5640     lstrcpyA(buf, "apple");
5641     r = pMsiGetProductInfoExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", usersid,
5642                               MSIINSTALLCONTEXT_USERUNMANAGED,
5643                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5644     ok(r == ERROR_INVALID_PARAMETER,
5645        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5646     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5647     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5648 
5649     /* guid with brackets */
5650     sz = MAX_PATH;
5651     lstrcpyA(buf, "apple");
5652     r = pMsiGetProductInfoExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", usersid,
5653                               MSIINSTALLCONTEXT_USERUNMANAGED,
5654                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5655     ok(r == ERROR_UNKNOWN_PRODUCT,
5656        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5657     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5658     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5659 
5660     /* szValue is non-NULL while pcchValue is NULL */
5661     lstrcpyA(buf, "apple");
5662     r = pMsiGetProductInfoExA(prodcode, usersid,
5663                               MSIINSTALLCONTEXT_USERUNMANAGED,
5664                               INSTALLPROPERTY_PRODUCTSTATEA, buf, NULL);
5665     ok(r == ERROR_INVALID_PARAMETER,
5666        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5667     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5668 
5669     /* dwContext is out of range */
5670     sz = MAX_PATH;
5671     lstrcpyA(buf, "apple");
5672     r = pMsiGetProductInfoExA(prodcode, usersid, 42,
5673                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5674     ok(r == ERROR_INVALID_PARAMETER,
5675        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5676     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5677     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5678 
5679     /* szProperty is NULL */
5680     sz = MAX_PATH;
5681     lstrcpyA(buf, "apple");
5682     r = pMsiGetProductInfoExA(prodcode, usersid,
5683                               MSIINSTALLCONTEXT_USERUNMANAGED,
5684                               NULL, buf, &sz);
5685     ok(r == ERROR_INVALID_PARAMETER,
5686        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5687     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5688     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5689 
5690     /* szProperty is empty */
5691     sz = MAX_PATH;
5692     lstrcpyA(buf, "apple");
5693     r = pMsiGetProductInfoExA(prodcode, usersid,
5694                               MSIINSTALLCONTEXT_USERUNMANAGED,
5695                               "", buf, &sz);
5696     ok(r == ERROR_INVALID_PARAMETER,
5697        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5698     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5699     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5700 
5701     /* szProperty is not a valid property */
5702     sz = MAX_PATH;
5703     lstrcpyA(buf, "apple");
5704     r = pMsiGetProductInfoExA(prodcode, usersid,
5705                               MSIINSTALLCONTEXT_USERUNMANAGED,
5706                               "notvalid", buf, &sz);
5707     ok(r == ERROR_UNKNOWN_PRODUCT,
5708        "Expected ERROR_UNKNOWN_PRODUCT, 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 %d\n", sz);
5711 
5712     /* same length as guid, but random */
5713     sz = MAX_PATH;
5714     lstrcpyA(buf, "apple");
5715     r = pMsiGetProductInfoExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", usersid,
5716                               MSIINSTALLCONTEXT_USERUNMANAGED,
5717                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5718     ok(r == ERROR_INVALID_PARAMETER,
5719        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5720     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5721     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5722 
5723     /* MSIINSTALLCONTEXT_USERUNMANAGED */
5724 
5725     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
5726     lstrcatA(keypath, usersid);
5727     lstrcatA(keypath, "\\Products\\");
5728     lstrcatA(keypath, prod_squashed);
5729 
5730     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
5731     if (res == ERROR_ACCESS_DENIED)
5732     {
5733         skip("Not enough rights to perform tests\n");
5734         LocalFree(usersid);
5735         return;
5736     }
5737     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5738 
5739     /* local user product key exists */
5740     sz = MAX_PATH;
5741     lstrcpyA(buf, "apple");
5742     r = pMsiGetProductInfoExA(prodcode, usersid,
5743                               MSIINSTALLCONTEXT_USERUNMANAGED,
5744                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5745     ok(r == ERROR_UNKNOWN_PRODUCT,
5746        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5747     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5748     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5749 
5750     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
5751     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5752 
5753     /* InstallProperties key exists */
5754     sz = MAX_PATH;
5755     lstrcpyA(buf, "apple");
5756     r = pMsiGetProductInfoExA(prodcode, usersid,
5757                               MSIINSTALLCONTEXT_USERUNMANAGED,
5758                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5759     ok(r == ERROR_UNKNOWN_PRODUCT,
5760        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5761     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5762     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5763 
5764     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
5765     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5766 
5767     /* LocalPackage value exists */
5768     sz = MAX_PATH;
5769     lstrcpyA(buf, "apple");
5770     r = pMsiGetProductInfoExA(prodcode, usersid,
5771                               MSIINSTALLCONTEXT_USERUNMANAGED,
5772                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5773     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5774     ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
5775     ok(sz == 1, "Expected 1, got %d\n", sz);
5776 
5777     RegDeleteValueA(propkey, "LocalPackage");
5778 
5779     /* LocalPackage value must exist */
5780     sz = MAX_PATH;
5781     lstrcpyA(buf, "apple");
5782     r = pMsiGetProductInfoExA(prodcode, usersid,
5783                               MSIINSTALLCONTEXT_USERUNMANAGED,
5784                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
5785     ok(r == ERROR_UNKNOWN_PRODUCT,
5786        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5787     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5788     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5789 
5790     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
5791     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5792 
5793     /* LocalPackage exists, but HelpLink does not exist */
5794     sz = MAX_PATH;
5795     lstrcpyA(buf, "apple");
5796     r = pMsiGetProductInfoExA(prodcode, usersid,
5797                               MSIINSTALLCONTEXT_USERUNMANAGED,
5798                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
5799     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5800     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5801     ok(sz == 0, "Expected 0, got %d\n", sz);
5802 
5803     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
5804     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5805 
5806     /* HelpLink value exists */
5807     sz = MAX_PATH;
5808     lstrcpyA(buf, "apple");
5809     r = pMsiGetProductInfoExA(prodcode, usersid,
5810                               MSIINSTALLCONTEXT_USERUNMANAGED,
5811                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
5812     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5813     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
5814     ok(sz == 4, "Expected 4, got %d\n", sz);
5815 
5816     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
5817     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5818 
5819     /* HelpTelephone value exists */
5820     sz = MAX_PATH;
5821     lstrcpyA(buf, "apple");
5822     r = pMsiGetProductInfoExA(prodcode, usersid,
5823                               MSIINSTALLCONTEXT_USERUNMANAGED,
5824                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
5825     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5826     ok(!lstrcmpA(buf, "phone"), "Expected \"phone\", got \"%s\"\n", buf);
5827     ok(sz == 5, "Expected 5, got %d\n", sz);
5828 
5829     /* szValue and pcchValue are NULL */
5830     r = pMsiGetProductInfoExA(prodcode, usersid,
5831                               MSIINSTALLCONTEXT_USERUNMANAGED,
5832                               INSTALLPROPERTY_HELPTELEPHONEA, NULL, NULL);
5833     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5834 
5835     /* pcchValue is exactly 5 */
5836     sz = 5;
5837     lstrcpyA(buf, "apple");
5838     r = pMsiGetProductInfoExA(prodcode, usersid,
5839                               MSIINSTALLCONTEXT_USERUNMANAGED,
5840                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
5841     ok(r == ERROR_MORE_DATA,
5842        "Expected ERROR_MORE_DATA, got %d\n", r);
5843     ok(sz == 10, "Expected 10, got %d\n", sz);
5844 
5845     /* szValue is NULL, pcchValue is exactly 5 */
5846     sz = 5;
5847     r = pMsiGetProductInfoExA(prodcode, usersid,
5848                               MSIINSTALLCONTEXT_USERUNMANAGED,
5849                               INSTALLPROPERTY_HELPTELEPHONEA, NULL, &sz);
5850     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5851     ok(sz == 10, "Expected 10, got %d\n", sz);
5852 
5853     /* szValue is NULL, pcchValue is MAX_PATH */
5854     sz = MAX_PATH;
5855     r = pMsiGetProductInfoExA(prodcode, usersid,
5856                               MSIINSTALLCONTEXT_USERUNMANAGED,
5857                               INSTALLPROPERTY_HELPTELEPHONEA, NULL, &sz);
5858     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5859     ok(sz == 10, "Expected 10, got %d\n", sz);
5860 
5861     /* pcchValue is exactly 0 */
5862     sz = 0;
5863     lstrcpyA(buf, "apple");
5864     r = pMsiGetProductInfoExA(prodcode, usersid,
5865                               MSIINSTALLCONTEXT_USERUNMANAGED,
5866                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
5867     ok(r == ERROR_MORE_DATA,
5868        "Expected ERROR_MORE_DATA, got %d\n", r);
5869     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
5870     ok(sz == 10, "Expected 10, got %d\n", sz);
5871 
5872     res = RegSetValueExA(propkey, "notvalid", 0, REG_SZ, (LPBYTE)"invalid", 8);
5873     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5874 
5875     /* szProperty is not a valid property */
5876     sz = MAX_PATH;
5877     lstrcpyA(buf, "apple");
5878     r = pMsiGetProductInfoExA(prodcode, usersid,
5879                               MSIINSTALLCONTEXT_USERUNMANAGED,
5880                               "notvalid", buf, &sz);
5881     ok(r == ERROR_UNKNOWN_PROPERTY,
5882        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5883     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5884     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5885 
5886     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
5887     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5888 
5889     /* InstallDate value exists */
5890     sz = MAX_PATH;
5891     lstrcpyA(buf, "apple");
5892     r = pMsiGetProductInfoExA(prodcode, usersid,
5893                               MSIINSTALLCONTEXT_USERUNMANAGED,
5894                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
5895     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5896     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
5897     ok(sz == 4, "Expected 4, got %d\n", sz);
5898 
5899     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
5900     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5901 
5902     /* DisplayName value exists */
5903     sz = MAX_PATH;
5904     lstrcpyA(buf, "apple");
5905     r = pMsiGetProductInfoExA(prodcode, usersid,
5906                               MSIINSTALLCONTEXT_USERUNMANAGED,
5907                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
5908     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5909     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
5910     ok(sz == 4, "Expected 4, got %d\n", sz);
5911 
5912     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
5913     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5914 
5915     /* InstallLocation value exists */
5916     sz = MAX_PATH;
5917     lstrcpyA(buf, "apple");
5918     r = pMsiGetProductInfoExA(prodcode, usersid,
5919                               MSIINSTALLCONTEXT_USERUNMANAGED,
5920                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
5921     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5922     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
5923     ok(sz == 3, "Expected 3, got %d\n", sz);
5924 
5925     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
5926     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5927 
5928     /* InstallSource value exists */
5929     sz = MAX_PATH;
5930     lstrcpyA(buf, "apple");
5931     r = pMsiGetProductInfoExA(prodcode, usersid,
5932                               MSIINSTALLCONTEXT_USERUNMANAGED,
5933                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
5934     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5935     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
5936     ok(sz == 6, "Expected 6, got %d\n", sz);
5937 
5938     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
5939     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5940 
5941     /* LocalPackage value exists */
5942     sz = MAX_PATH;
5943     lstrcpyA(buf, "apple");
5944     r = pMsiGetProductInfoExA(prodcode, usersid,
5945                               MSIINSTALLCONTEXT_USERUNMANAGED,
5946                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
5947     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5948     ok(!lstrcmpA(buf, "local"), "Expected \"local\", got \"%s\"\n", buf);
5949     ok(sz == 5, "Expected 5, got %d\n", sz);
5950 
5951     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
5952     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5953 
5954     /* Publisher value exists */
5955     sz = MAX_PATH;
5956     lstrcpyA(buf, "apple");
5957     r = pMsiGetProductInfoExA(prodcode, usersid,
5958                               MSIINSTALLCONTEXT_USERUNMANAGED,
5959                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
5960     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5961     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
5962     ok(sz == 3, "Expected 3, got %d\n", sz);
5963 
5964     res = RegSetValueExA(propkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
5965     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5966 
5967     /* URLInfoAbout value exists */
5968     sz = MAX_PATH;
5969     lstrcpyA(buf, "apple");
5970     r = pMsiGetProductInfoExA(prodcode, usersid,
5971                               MSIINSTALLCONTEXT_USERUNMANAGED,
5972                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
5973     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5974     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
5975     ok(sz == 5, "Expected 5, got %d\n", sz);
5976 
5977     res = RegSetValueExA(propkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
5978     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5979 
5980     /* URLUpdateInfo value exists */
5981     sz = MAX_PATH;
5982     lstrcpyA(buf, "apple");
5983     r = pMsiGetProductInfoExA(prodcode, usersid,
5984                               MSIINSTALLCONTEXT_USERUNMANAGED,
5985                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
5986     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5987     ok(!lstrcmpA(buf, "update"), "Expected \"update\", got \"%s\"\n", buf);
5988     ok(sz == 6, "Expected 6, got %d\n", sz);
5989 
5990     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
5991     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5992 
5993     /* VersionMinor value exists */
5994     sz = MAX_PATH;
5995     lstrcpyA(buf, "apple");
5996     r = pMsiGetProductInfoExA(prodcode, usersid,
5997                               MSIINSTALLCONTEXT_USERUNMANAGED,
5998                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
5999     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6000     ok(!lstrcmpA(buf, "2"), "Expected \"2\", got \"%s\"\n", buf);
6001     ok(sz == 1, "Expected 1, got %d\n", sz);
6002 
6003     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
6004     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6005 
6006     /* VersionMajor value exists */
6007     sz = MAX_PATH;
6008     lstrcpyA(buf, "apple");
6009     r = pMsiGetProductInfoExA(prodcode, usersid,
6010                               MSIINSTALLCONTEXT_USERUNMANAGED,
6011                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
6012     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6013     ok(!lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
6014     ok(sz == 1, "Expected 1, got %d\n", sz);
6015 
6016     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
6017     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6018 
6019     /* DisplayVersion value exists */
6020     sz = MAX_PATH;
6021     lstrcpyA(buf, "apple");
6022     r = pMsiGetProductInfoExA(prodcode, usersid,
6023                               MSIINSTALLCONTEXT_USERUNMANAGED,
6024                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
6025     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6026     ok(!lstrcmpA(buf, "3.2.1"), "Expected \"3.2.1\", got \"%s\"\n", buf);
6027     ok(sz == 5, "Expected 5, got %d\n", sz);
6028 
6029     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
6030     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6031 
6032     /* ProductID value exists */
6033     sz = MAX_PATH;
6034     lstrcpyA(buf, "apple");
6035     r = pMsiGetProductInfoExA(prodcode, usersid,
6036                               MSIINSTALLCONTEXT_USERUNMANAGED,
6037                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
6038     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6039     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
6040     ok(sz == 2, "Expected 2, got %d\n", sz);
6041 
6042     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
6043     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6044 
6045     /* RegCompany value exists */
6046     sz = MAX_PATH;
6047     lstrcpyA(buf, "apple");
6048     r = pMsiGetProductInfoExA(prodcode, usersid,
6049                               MSIINSTALLCONTEXT_USERUNMANAGED,
6050                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
6051     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6052     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
6053     ok(sz == 4, "Expected 4, got %d\n", sz);
6054 
6055     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
6056     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6057 
6058     /* RegOwner value exists */
6059     sz = MAX_PATH;
6060     lstrcpyA(buf, "apple");
6061     r = pMsiGetProductInfoExA(prodcode, usersid,
6062                               MSIINSTALLCONTEXT_USERUNMANAGED,
6063                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
6064     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6065     ok(!lstrcmpA(buf, "owner"), "Expected \"owner\", got \"%s\"\n", buf);
6066     ok(sz == 5, "Expected 5, got %d\n", sz);
6067 
6068     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
6069     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6070 
6071     /* Transforms value exists */
6072     sz = MAX_PATH;
6073     lstrcpyA(buf, "apple");
6074     r = pMsiGetProductInfoExA(prodcode, usersid,
6075                               MSIINSTALLCONTEXT_USERUNMANAGED,
6076                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
6077     ok(r == ERROR_UNKNOWN_PRODUCT,
6078        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6079     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6080     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6081 
6082     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
6083     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6084 
6085     /* Language value exists */
6086     sz = MAX_PATH;
6087     lstrcpyA(buf, "apple");
6088     r = pMsiGetProductInfoExA(prodcode, usersid,
6089                               MSIINSTALLCONTEXT_USERUNMANAGED,
6090                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
6091     ok(r == ERROR_UNKNOWN_PRODUCT,
6092        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6093     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6094     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6095 
6096     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
6097     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6098 
6099     /* ProductName value exists */
6100     sz = MAX_PATH;
6101     lstrcpyA(buf, "apple");
6102     r = pMsiGetProductInfoExA(prodcode, usersid,
6103                               MSIINSTALLCONTEXT_USERUNMANAGED,
6104                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
6105     ok(r == ERROR_UNKNOWN_PRODUCT,
6106        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6107     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6108     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6109 
6110     res = RegSetValueExA(propkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
6111     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6112 
6113     /* FIXME */
6114 
6115     /* AssignmentType value exists */
6116     sz = MAX_PATH;
6117     lstrcpyA(buf, "apple");
6118     r = pMsiGetProductInfoExA(prodcode, usersid,
6119                               MSIINSTALLCONTEXT_USERUNMANAGED,
6120                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
6121     ok(r == ERROR_UNKNOWN_PRODUCT,
6122        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6123     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6124     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6125 
6126     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
6127     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6128 
6129     /* PackageCode value exists */
6130     sz = MAX_PATH;
6131     lstrcpyA(buf, "apple");
6132     r = pMsiGetProductInfoExA(prodcode, usersid,
6133                               MSIINSTALLCONTEXT_USERUNMANAGED,
6134                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
6135     ok(r == ERROR_UNKNOWN_PRODUCT,
6136        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6137     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6138     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6139 
6140     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
6141     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6142 
6143     /* Version value exists */
6144     sz = MAX_PATH;
6145     lstrcpyA(buf, "apple");
6146     r = pMsiGetProductInfoExA(prodcode, usersid,
6147                               MSIINSTALLCONTEXT_USERUNMANAGED,
6148                               INSTALLPROPERTY_VERSIONA, buf, &sz);
6149     ok(r == ERROR_UNKNOWN_PRODUCT,
6150        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6151     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6152     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6153 
6154     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
6155     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6156 
6157     /* ProductIcon value exists */
6158     sz = MAX_PATH;
6159     lstrcpyA(buf, "apple");
6160     r = pMsiGetProductInfoExA(prodcode, usersid,
6161                               MSIINSTALLCONTEXT_USERUNMANAGED,
6162                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
6163     ok(r == ERROR_UNKNOWN_PRODUCT,
6164        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6165     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6166     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6167 
6168     res = RegSetValueExA(propkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
6169     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6170 
6171     /* PackageName value exists */
6172     sz = MAX_PATH;
6173     lstrcpyA(buf, "apple");
6174     r = pMsiGetProductInfoExA(prodcode, usersid,
6175                               MSIINSTALLCONTEXT_USERUNMANAGED,
6176                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
6177     ok(r == ERROR_UNKNOWN_PRODUCT,
6178        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6179     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6180     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6181 
6182     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
6183     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6184 
6185     /* AuthorizedLUAApp value exists */
6186     sz = MAX_PATH;
6187     lstrcpyA(buf, "apple");
6188     r = pMsiGetProductInfoExA(prodcode, usersid,
6189                               MSIINSTALLCONTEXT_USERUNMANAGED,
6190                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
6191     ok(r == ERROR_UNKNOWN_PRODUCT,
6192        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6193     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6194     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6195 
6196     RegDeleteValueA(propkey, "AuthorizedLUAApp");
6197     RegDeleteValueA(propkey, "PackageName");
6198     RegDeleteValueA(propkey, "ProductIcon");
6199     RegDeleteValueA(propkey, "Version");
6200     RegDeleteValueA(propkey, "PackageCode");
6201     RegDeleteValueA(propkey, "AssignmentType");
6202     RegDeleteValueA(propkey, "ProductName");
6203     RegDeleteValueA(propkey, "Language");
6204     RegDeleteValueA(propkey, "Transforms");
6205     RegDeleteValueA(propkey, "RegOwner");
6206     RegDeleteValueA(propkey, "RegCompany");
6207     RegDeleteValueA(propkey, "ProductID");
6208     RegDeleteValueA(propkey, "DisplayVersion");
6209     RegDeleteValueA(propkey, "VersionMajor");
6210     RegDeleteValueA(propkey, "VersionMinor");
6211     RegDeleteValueA(propkey, "URLUpdateInfo");
6212     RegDeleteValueA(propkey, "URLInfoAbout");
6213     RegDeleteValueA(propkey, "Publisher");
6214     RegDeleteValueA(propkey, "LocalPackage");
6215     RegDeleteValueA(propkey, "InstallSource");
6216     RegDeleteValueA(propkey, "InstallLocation");
6217     RegDeleteValueA(propkey, "DisplayName");
6218     RegDeleteValueA(propkey, "InstallDate");
6219     RegDeleteValueA(propkey, "HelpTelephone");
6220     RegDeleteValueA(propkey, "HelpLink");
6221     RegDeleteValueA(propkey, "LocalPackage");
6222     RegDeleteKeyA(propkey, "");
6223     RegCloseKey(propkey);
6224     RegDeleteKeyA(localkey, "");
6225     RegCloseKey(localkey);
6226 
6227     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
6228     lstrcatA(keypath, usersid);
6229     lstrcatA(keypath, "\\Installer\\Products\\");
6230     lstrcatA(keypath, prod_squashed);
6231 
6232     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
6233     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6234 
6235     /* user product key exists */
6236     sz = MAX_PATH;
6237     lstrcpyA(buf, "apple");
6238     r = pMsiGetProductInfoExA(prodcode, usersid,
6239                               MSIINSTALLCONTEXT_USERUNMANAGED,
6240                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6241     ok(r == ERROR_UNKNOWN_PRODUCT,
6242        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6243     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6244     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6245 
6246     RegDeleteKeyA(userkey, "");
6247     RegCloseKey(userkey);
6248 
6249     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
6250     lstrcatA(keypath, prod_squashed);
6251 
6252     res = RegCreateKeyExA(HKEY_CURRENT_USER, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
6253     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6254 
6255     sz = MAX_PATH;
6256     lstrcpyA(buf, "apple");
6257     r = pMsiGetProductInfoExA(prodcode, usersid,
6258                               MSIINSTALLCONTEXT_USERUNMANAGED,
6259                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6260     ok(r == ERROR_SUCCESS || broken(r == ERROR_UNKNOWN_PRODUCT), "Expected ERROR_SUCCESS, got %d\n", r);
6261     if (r == ERROR_UNKNOWN_PRODUCT)
6262     {
6263         win_skip("skipping remaining tests for MsiGetProductInfoEx\n");
6264         delete_key(prodkey, "", access);
6265         RegCloseKey(prodkey);
6266         return;
6267     }
6268     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
6269     ok(sz == 1, "Expected 1, got %d\n", sz);
6270 
6271     res = RegSetValueExA(prodkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
6272     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6273 
6274     /* HelpLink value exists */
6275     sz = MAX_PATH;
6276     lstrcpyA(buf, "apple");
6277     r = pMsiGetProductInfoExA(prodcode, usersid,
6278                               MSIINSTALLCONTEXT_USERUNMANAGED,
6279                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
6280     ok(r == ERROR_UNKNOWN_PROPERTY,
6281        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6282     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6283     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6284 
6285     res = RegSetValueExA(prodkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
6286     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6287 
6288     /* HelpTelephone value exists */
6289     sz = MAX_PATH;
6290     lstrcpyA(buf, "apple");
6291     r = pMsiGetProductInfoExA(prodcode, usersid,
6292                               MSIINSTALLCONTEXT_USERUNMANAGED,
6293                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
6294     ok(r == ERROR_UNKNOWN_PROPERTY,
6295        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6296     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6297     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6298 
6299     res = RegSetValueExA(prodkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
6300     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6301 
6302     /* InstallDate value exists */
6303     sz = MAX_PATH;
6304     lstrcpyA(buf, "apple");
6305     r = pMsiGetProductInfoExA(prodcode, usersid,
6306                               MSIINSTALLCONTEXT_USERUNMANAGED,
6307                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
6308     ok(r == ERROR_UNKNOWN_PROPERTY,
6309        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6310     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6311     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6312 
6313     res = RegSetValueExA(prodkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
6314     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6315 
6316     /* DisplayName value exists */
6317     sz = MAX_PATH;
6318     lstrcpyA(buf, "apple");
6319     r = pMsiGetProductInfoExA(prodcode, usersid,
6320                               MSIINSTALLCONTEXT_USERUNMANAGED,
6321                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
6322     ok(r == ERROR_UNKNOWN_PROPERTY,
6323        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6324     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6325     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6326 
6327     res = RegSetValueExA(prodkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
6328     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6329 
6330     /* InstallLocation value exists */
6331     sz = MAX_PATH;
6332     lstrcpyA(buf, "apple");
6333     r = pMsiGetProductInfoExA(prodcode, usersid,
6334                               MSIINSTALLCONTEXT_USERUNMANAGED,
6335                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
6336     ok(r == ERROR_UNKNOWN_PROPERTY,
6337        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6338     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6339     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6340 
6341     res = RegSetValueExA(prodkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
6342     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6343 
6344     /* InstallSource value exists */
6345     sz = MAX_PATH;
6346     lstrcpyA(buf, "apple");
6347     r = pMsiGetProductInfoExA(prodcode, usersid,
6348                               MSIINSTALLCONTEXT_USERUNMANAGED,
6349                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
6350     ok(r == ERROR_UNKNOWN_PROPERTY,
6351        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6352     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6353     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6354 
6355     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6356     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6357 
6358     /* LocalPackage value exists */
6359     sz = MAX_PATH;
6360     lstrcpyA(buf, "apple");
6361     r = pMsiGetProductInfoExA(prodcode, usersid,
6362                               MSIINSTALLCONTEXT_USERUNMANAGED,
6363                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
6364     ok(r == ERROR_UNKNOWN_PROPERTY,
6365        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6366     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6367     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6368 
6369     res = RegSetValueExA(prodkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
6370     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6371 
6372     /* Publisher value exists */
6373     sz = MAX_PATH;
6374     lstrcpyA(buf, "apple");
6375     r = pMsiGetProductInfoExA(prodcode, usersid,
6376                               MSIINSTALLCONTEXT_USERUNMANAGED,
6377                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
6378     ok(r == ERROR_UNKNOWN_PROPERTY,
6379        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6380     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6381     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6382 
6383     res = RegSetValueExA(prodkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
6384     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6385 
6386     /* URLInfoAbout value exists */
6387     sz = MAX_PATH;
6388     lstrcpyA(buf, "apple");
6389     r = pMsiGetProductInfoExA(prodcode, usersid,
6390                               MSIINSTALLCONTEXT_USERUNMANAGED,
6391                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
6392     ok(r == ERROR_UNKNOWN_PROPERTY,
6393        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6394     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6395     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6396 
6397     res = RegSetValueExA(prodkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
6398     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6399 
6400     /* URLUpdateInfo value exists */
6401     sz = MAX_PATH;
6402     lstrcpyA(buf, "apple");
6403     r = pMsiGetProductInfoExA(prodcode, usersid,
6404                               MSIINSTALLCONTEXT_USERUNMANAGED,
6405                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
6406     ok(r == ERROR_UNKNOWN_PROPERTY,
6407        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6408     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6409     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6410 
6411     res = RegSetValueExA(prodkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
6412     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6413 
6414     /* VersionMinor value exists */
6415     sz = MAX_PATH;
6416     lstrcpyA(buf, "apple");
6417     r = pMsiGetProductInfoExA(prodcode, usersid,
6418                               MSIINSTALLCONTEXT_USERUNMANAGED,
6419                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
6420     ok(r == ERROR_UNKNOWN_PROPERTY,
6421        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6422     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6423     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6424 
6425     res = RegSetValueExA(prodkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
6426     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6427 
6428     /* VersionMajor value exists */
6429     sz = MAX_PATH;
6430     lstrcpyA(buf, "apple");
6431     r = pMsiGetProductInfoExA(prodcode, usersid,
6432                               MSIINSTALLCONTEXT_USERUNMANAGED,
6433                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
6434     ok(r == ERROR_UNKNOWN_PROPERTY,
6435        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6436     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6437     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6438 
6439     res = RegSetValueExA(prodkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
6440     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6441 
6442     /* DisplayVersion value exists */
6443     sz = MAX_PATH;
6444     lstrcpyA(buf, "apple");
6445     r = pMsiGetProductInfoExA(prodcode, usersid,
6446                               MSIINSTALLCONTEXT_USERUNMANAGED,
6447                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
6448     ok(r == ERROR_UNKNOWN_PROPERTY,
6449        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6450     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6451     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6452 
6453     res = RegSetValueExA(prodkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
6454     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6455 
6456     /* ProductID value exists */
6457     sz = MAX_PATH;
6458     lstrcpyA(buf, "apple");
6459     r = pMsiGetProductInfoExA(prodcode, usersid,
6460                               MSIINSTALLCONTEXT_USERUNMANAGED,
6461                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
6462     ok(r == ERROR_UNKNOWN_PROPERTY,
6463        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6464     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6465     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6466 
6467     res = RegSetValueExA(prodkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
6468     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6469 
6470     /* RegCompany value exists */
6471     sz = MAX_PATH;
6472     lstrcpyA(buf, "apple");
6473     r = pMsiGetProductInfoExA(prodcode, usersid,
6474                               MSIINSTALLCONTEXT_USERUNMANAGED,
6475                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
6476     ok(r == ERROR_UNKNOWN_PROPERTY,
6477        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6478     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6479     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6480 
6481     res = RegSetValueExA(prodkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
6482     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6483 
6484     /* RegOwner value exists */
6485     sz = MAX_PATH;
6486     lstrcpyA(buf, "apple");
6487     r = pMsiGetProductInfoExA(prodcode, usersid,
6488                               MSIINSTALLCONTEXT_USERUNMANAGED,
6489                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
6490     ok(r == ERROR_UNKNOWN_PROPERTY,
6491        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6492     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6493     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6494 
6495     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
6496     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6497 
6498     /* Transforms value exists */
6499     sz = MAX_PATH;
6500     lstrcpyA(buf, "apple");
6501     r = pMsiGetProductInfoExA(prodcode, usersid,
6502                               MSIINSTALLCONTEXT_USERUNMANAGED,
6503                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
6504     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6505     ok(!lstrcmpA(buf, "trans"), "Expected \"trans\", got \"%s\"\n", buf);
6506     ok(sz == 5, "Expected 5, got %d\n", sz);
6507 
6508     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
6509     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6510 
6511     /* Language value exists */
6512     sz = MAX_PATH;
6513     lstrcpyA(buf, "apple");
6514     r = pMsiGetProductInfoExA(prodcode, usersid,
6515                               MSIINSTALLCONTEXT_USERUNMANAGED,
6516                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
6517     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6518     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
6519     ok(sz == 4, "Expected 4, got %d\n", sz);
6520 
6521     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
6522     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6523 
6524     /* ProductName value exists */
6525     sz = MAX_PATH;
6526     lstrcpyA(buf, "apple");
6527     r = pMsiGetProductInfoExA(prodcode, usersid,
6528                               MSIINSTALLCONTEXT_USERUNMANAGED,
6529                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
6530     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6531     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
6532     ok(sz == 4, "Expected 4, got %d\n", sz);
6533 
6534     res = RegSetValueExA(prodkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
6535     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6536 
6537     /* FIXME */
6538 
6539     /* AssignmentType value exists */
6540     sz = MAX_PATH;
6541     lstrcpyA(buf, "apple");
6542     r = pMsiGetProductInfoExA(prodcode, usersid,
6543                               MSIINSTALLCONTEXT_USERUNMANAGED,
6544                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
6545     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6546     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
6547     ok(sz == 0, "Expected 0, got %d\n", sz);
6548 
6549     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
6550     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6551 
6552     /* FIXME */
6553 
6554     /* PackageCode value exists */
6555     sz = MAX_PATH;
6556     lstrcpyA(buf, "apple");
6557     r = pMsiGetProductInfoExA(prodcode, usersid,
6558                               MSIINSTALLCONTEXT_USERUNMANAGED,
6559                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
6560     todo_wine
6561     {
6562         ok(r == ERROR_BAD_CONFIGURATION,
6563            "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
6564         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6565         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6566     }
6567 
6568     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
6569     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6570 
6571     /* Version value exists */
6572     sz = MAX_PATH;
6573     lstrcpyA(buf, "apple");
6574     r = pMsiGetProductInfoExA(prodcode, usersid,
6575                               MSIINSTALLCONTEXT_USERUNMANAGED,
6576                               INSTALLPROPERTY_VERSIONA, buf, &sz);
6577     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6578     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
6579     ok(sz == 3, "Expected 3, got %d\n", sz);
6580 
6581     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
6582     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6583 
6584     /* ProductIcon value exists */
6585     sz = MAX_PATH;
6586     lstrcpyA(buf, "apple");
6587     r = pMsiGetProductInfoExA(prodcode, usersid,
6588                               MSIINSTALLCONTEXT_USERUNMANAGED,
6589                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
6590     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6591     ok(!lstrcmpA(buf, "icon"), "Expected \"icon\", got \"%s\"\n", buf);
6592     ok(sz == 4, "Expected 4, got %d\n", sz);
6593 
6594     res = RegSetValueExA(prodkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
6595     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6596 
6597     /* PackageName value exists */
6598     sz = MAX_PATH;
6599     lstrcpyA(buf, "apple");
6600     r = pMsiGetProductInfoExA(prodcode, usersid,
6601                               MSIINSTALLCONTEXT_USERUNMANAGED,
6602                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
6603     todo_wine
6604     {
6605         ok(r == ERROR_UNKNOWN_PRODUCT,
6606            "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6607         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6608         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6609     }
6610 
6611     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
6612     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6613 
6614     /* AuthorizedLUAApp value exists */
6615     sz = MAX_PATH;
6616     lstrcpyA(buf, "apple");
6617     r = pMsiGetProductInfoExA(prodcode, usersid,
6618                               MSIINSTALLCONTEXT_USERUNMANAGED,
6619                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
6620     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6621     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
6622     ok(sz == 4, "Expected 4, got %d\n", sz);
6623 
6624     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
6625     RegDeleteValueA(prodkey, "PackageName");
6626     RegDeleteValueA(prodkey, "ProductIcon");
6627     RegDeleteValueA(prodkey, "Version");
6628     RegDeleteValueA(prodkey, "PackageCode");
6629     RegDeleteValueA(prodkey, "AssignmentType");
6630     RegDeleteValueA(prodkey, "ProductName");
6631     RegDeleteValueA(prodkey, "Language");
6632     RegDeleteValueA(prodkey, "Transforms");
6633     RegDeleteValueA(prodkey, "RegOwner");
6634     RegDeleteValueA(prodkey, "RegCompany");
6635     RegDeleteValueA(prodkey, "ProductID");
6636     RegDeleteValueA(prodkey, "DisplayVersion");
6637     RegDeleteValueA(prodkey, "VersionMajor");
6638     RegDeleteValueA(prodkey, "VersionMinor");
6639     RegDeleteValueA(prodkey, "URLUpdateInfo");
6640     RegDeleteValueA(prodkey, "URLInfoAbout");
6641     RegDeleteValueA(prodkey, "Publisher");
6642     RegDeleteValueA(prodkey, "LocalPackage");
6643     RegDeleteValueA(prodkey, "InstallSource");
6644     RegDeleteValueA(prodkey, "InstallLocation");
6645     RegDeleteValueA(prodkey, "DisplayName");
6646     RegDeleteValueA(prodkey, "InstallDate");
6647     RegDeleteValueA(prodkey, "HelpTelephone");
6648     RegDeleteValueA(prodkey, "HelpLink");
6649     RegDeleteValueA(prodkey, "LocalPackage");
6650     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
6651     RegCloseKey(prodkey);
6652 
6653     /* MSIINSTALLCONTEXT_USERMANAGED */
6654 
6655     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
6656     lstrcatA(keypath, usersid);
6657     lstrcatA(keypath, "\\Products\\");
6658     lstrcatA(keypath, prod_squashed);
6659 
6660     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
6661     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6662 
6663     /* local user product key exists */
6664     sz = MAX_PATH;
6665     lstrcpyA(buf, "apple");
6666     r = pMsiGetProductInfoExA(prodcode, usersid,
6667                               MSIINSTALLCONTEXT_USERMANAGED,
6668                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6669     ok(r == ERROR_UNKNOWN_PRODUCT,
6670        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6671     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6672     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6673 
6674     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
6675     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6676 
6677     /* InstallProperties key exists */
6678     sz = MAX_PATH;
6679     lstrcpyA(buf, "apple");
6680     r = pMsiGetProductInfoExA(prodcode, usersid,
6681                               MSIINSTALLCONTEXT_USERMANAGED,
6682                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6683     ok(r == ERROR_UNKNOWN_PRODUCT,
6684        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6685     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6686     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6687 
6688     res = RegSetValueExA(propkey, "ManagedLocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6689     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6690 
6691     /* ManagedLocalPackage value exists */
6692     sz = MAX_PATH;
6693     lstrcpyA(buf, "apple");
6694     r = pMsiGetProductInfoExA(prodcode, usersid,
6695                               MSIINSTALLCONTEXT_USERMANAGED,
6696                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6697     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6698     ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
6699     ok(sz == 1, "Expected 1, got %d\n", sz);
6700 
6701     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
6702     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6703 
6704     /* HelpLink value exists */
6705     sz = MAX_PATH;
6706     lstrcpyA(buf, "apple");
6707     r = pMsiGetProductInfoExA(prodcode, usersid,
6708                               MSIINSTALLCONTEXT_USERMANAGED,
6709                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
6710     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6711     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
6712     ok(sz == 4, "Expected 4, got %d\n", sz);
6713 
6714     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
6715     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6716 
6717     /* HelpTelephone value exists */
6718     sz = MAX_PATH;
6719     lstrcpyA(buf, "apple");
6720     r = pMsiGetProductInfoExA(prodcode, usersid,
6721                               MSIINSTALLCONTEXT_USERMANAGED,
6722                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
6723     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6724     ok(!lstrcmpA(buf, "phone"), "Expected \"phone\", got \"%s\"\n", buf);
6725     ok(sz == 5, "Expected 5, got %d\n", sz);
6726 
6727     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
6728     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6729 
6730     /* InstallDate value exists */
6731     sz = MAX_PATH;
6732     lstrcpyA(buf, "apple");
6733     r = pMsiGetProductInfoExA(prodcode, usersid,
6734                               MSIINSTALLCONTEXT_USERMANAGED,
6735                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
6736     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6737     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
6738     ok(sz == 4, "Expected 4, got %d\n", sz);
6739 
6740     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
6741     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6742 
6743     /* DisplayName value exists */
6744     sz = MAX_PATH;
6745     lstrcpyA(buf, "apple");
6746     r = pMsiGetProductInfoExA(prodcode, usersid,
6747                               MSIINSTALLCONTEXT_USERMANAGED,
6748                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
6749     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6750     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
6751     ok(sz == 4, "Expected 4, got %d\n", sz);
6752 
6753     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
6754     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6755 
6756     /* InstallLocation value exists */
6757     sz = MAX_PATH;
6758     lstrcpyA(buf, "apple");
6759     r = pMsiGetProductInfoExA(prodcode, usersid,
6760                               MSIINSTALLCONTEXT_USERMANAGED,
6761                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
6762     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6763     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
6764     ok(sz == 3, "Expected 3, got %d\n", sz);
6765 
6766     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
6767     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6768 
6769     /* InstallSource value exists */
6770     sz = MAX_PATH;
6771     lstrcpyA(buf, "apple");
6772     r = pMsiGetProductInfoExA(prodcode, usersid,
6773                               MSIINSTALLCONTEXT_USERMANAGED,
6774                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
6775     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6776     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
6777     ok(sz == 6, "Expected 6, got %d\n", sz);
6778 
6779     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6780     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6781 
6782     /* LocalPackage value exists */
6783     sz = MAX_PATH;
6784     lstrcpyA(buf, "apple");
6785     r = pMsiGetProductInfoExA(prodcode, usersid,
6786                               MSIINSTALLCONTEXT_USERMANAGED,
6787                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
6788     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6789     ok(!lstrcmpA(buf, "local"), "Expected \"local\", got \"%s\"\n", buf);
6790     ok(sz == 5, "Expected 5, got %d\n", sz);
6791 
6792     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
6793     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6794 
6795     /* Publisher value exists */
6796     sz = MAX_PATH;
6797     lstrcpyA(buf, "apple");
6798     r = pMsiGetProductInfoExA(prodcode, usersid,
6799                               MSIINSTALLCONTEXT_USERMANAGED,
6800                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
6801     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6802     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
6803     ok(sz == 3, "Expected 3, got %d\n", sz);
6804 
6805     res = RegSetValueExA(propkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
6806     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6807 
6808     /* URLInfoAbout value exists */
6809     sz = MAX_PATH;
6810     lstrcpyA(buf, "apple");
6811     r = pMsiGetProductInfoExA(prodcode, usersid,
6812                               MSIINSTALLCONTEXT_USERMANAGED,
6813                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
6814     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6815     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
6816     ok(sz == 5, "Expected 5, got %d\n", sz);
6817 
6818     res = RegSetValueExA(propkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
6819     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6820 
6821     /* URLUpdateInfo value exists */
6822     sz = MAX_PATH;
6823     lstrcpyA(buf, "apple");
6824     r = pMsiGetProductInfoExA(prodcode, usersid,
6825                               MSIINSTALLCONTEXT_USERMANAGED,
6826                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
6827     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6828     ok(!lstrcmpA(buf, "update"), "Expected \"update\", got \"%s\"\n", buf);
6829     ok(sz == 6, "Expected 6, got %d\n", sz);
6830 
6831     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
6832     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6833 
6834     /* VersionMinor value exists */
6835     sz = MAX_PATH;
6836     lstrcpyA(buf, "apple");
6837     r = pMsiGetProductInfoExA(prodcode, usersid,
6838                               MSIINSTALLCONTEXT_USERMANAGED,
6839                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
6840     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6841     ok(!lstrcmpA(buf, "2"), "Expected \"2\", got \"%s\"\n", buf);
6842     ok(sz == 1, "Expected 1, got %d\n", sz);
6843 
6844     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
6845     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6846 
6847     /* VersionMajor value exists */
6848     sz = MAX_PATH;
6849     lstrcpyA(buf, "apple");
6850     r = pMsiGetProductInfoExA(prodcode, usersid,
6851                               MSIINSTALLCONTEXT_USERMANAGED,
6852                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
6853     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6854     ok(!lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
6855     ok(sz == 1, "Expected 1, got %d\n", sz);
6856 
6857     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
6858     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6859 
6860     /* DisplayVersion value exists */
6861     sz = MAX_PATH;
6862     lstrcpyA(buf, "apple");
6863     r = pMsiGetProductInfoExA(prodcode, usersid,
6864                               MSIINSTALLCONTEXT_USERMANAGED,
6865                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
6866     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6867     ok(!lstrcmpA(buf, "3.2.1"), "Expected \"3.2.1\", got \"%s\"\n", buf);
6868     ok(sz == 5, "Expected 5, got %d\n", sz);
6869 
6870     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
6871     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6872 
6873     /* ProductID value exists */
6874     sz = MAX_PATH;
6875     lstrcpyA(buf, "apple");
6876     r = pMsiGetProductInfoExA(prodcode, usersid,
6877                               MSIINSTALLCONTEXT_USERMANAGED,
6878                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
6879     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6880     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
6881     ok(sz == 2, "Expected 2, got %d\n", sz);
6882 
6883     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
6884     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6885 
6886     /* RegCompany value exists */
6887     sz = MAX_PATH;
6888     lstrcpyA(buf, "apple");
6889     r = pMsiGetProductInfoExA(prodcode, usersid,
6890                               MSIINSTALLCONTEXT_USERMANAGED,
6891                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
6892     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6893     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
6894     ok(sz == 4, "Expected 4, got %d\n", sz);
6895 
6896     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
6897     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6898 
6899     /* RegOwner value exists */
6900     sz = MAX_PATH;
6901     lstrcpyA(buf, "apple");
6902     r = pMsiGetProductInfoExA(prodcode, usersid,
6903                               MSIINSTALLCONTEXT_USERMANAGED,
6904                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
6905     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6906     ok(!lstrcmpA(buf, "owner"), "Expected \"owner\", got \"%s\"\n", buf);
6907     ok(sz == 5, "Expected 5, got %d\n", sz);
6908 
6909     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
6910     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6911 
6912     /* Transforms value exists */
6913     sz = MAX_PATH;
6914     lstrcpyA(buf, "apple");
6915     r = pMsiGetProductInfoExA(prodcode, usersid,
6916                               MSIINSTALLCONTEXT_USERMANAGED,
6917                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
6918     ok(r == ERROR_UNKNOWN_PRODUCT,
6919        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6920     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6921     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6922 
6923     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
6924     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6925 
6926     /* Language value exists */
6927     sz = MAX_PATH;
6928     lstrcpyA(buf, "apple");
6929     r = pMsiGetProductInfoExA(prodcode, usersid,
6930                               MSIINSTALLCONTEXT_USERMANAGED,
6931                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
6932     ok(r == ERROR_UNKNOWN_PRODUCT,
6933        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6934     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6935     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6936 
6937     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
6938     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6939 
6940     /* ProductName value exists */
6941     sz = MAX_PATH;
6942     lstrcpyA(buf, "apple");
6943     r = pMsiGetProductInfoExA(prodcode, usersid,
6944                               MSIINSTALLCONTEXT_USERMANAGED,
6945                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
6946     ok(r == ERROR_UNKNOWN_PRODUCT,
6947        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6948     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6949     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6950 
6951     res = RegSetValueExA(propkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
6952     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6953 
6954     /* FIXME */
6955 
6956     /* AssignmentType value exists */
6957     sz = MAX_PATH;
6958     lstrcpyA(buf, "apple");
6959     r = pMsiGetProductInfoExA(prodcode, usersid,
6960                               MSIINSTALLCONTEXT_USERMANAGED,
6961                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
6962     ok(r == ERROR_UNKNOWN_PRODUCT,
6963        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6964     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6965     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6966 
6967     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
6968     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6969 
6970     /* PackageCode value exists */
6971     sz = MAX_PATH;
6972     lstrcpyA(buf, "apple");
6973     r = pMsiGetProductInfoExA(prodcode, usersid,
6974                               MSIINSTALLCONTEXT_USERMANAGED,
6975                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
6976     ok(r == ERROR_UNKNOWN_PRODUCT,
6977        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6978     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6979     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6980 
6981     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
6982     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6983 
6984     /* Version value exists */
6985     sz = MAX_PATH;
6986     lstrcpyA(buf, "apple");
6987     r = pMsiGetProductInfoExA(prodcode, usersid,
6988                               MSIINSTALLCONTEXT_USERMANAGED,
6989                               INSTALLPROPERTY_VERSIONA, buf, &sz);
6990     ok(r == ERROR_UNKNOWN_PRODUCT,
6991        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6992     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6993     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6994 
6995     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
6996     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6997 
6998     /* ProductIcon value exists */
6999     sz = MAX_PATH;
7000     lstrcpyA(buf, "apple");
7001     r = pMsiGetProductInfoExA(prodcode, usersid,
7002                               MSIINSTALLCONTEXT_USERMANAGED,
7003                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
7004     ok(r == ERROR_UNKNOWN_PRODUCT,
7005        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7006     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7007     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7008 
7009     res = RegSetValueExA(propkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
7010     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7011 
7012     /* PackageName value exists */
7013     sz = MAX_PATH;
7014     lstrcpyA(buf, "apple");
7015     r = pMsiGetProductInfoExA(prodcode, usersid,
7016                               MSIINSTALLCONTEXT_USERMANAGED,
7017                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
7018     ok(r == ERROR_UNKNOWN_PRODUCT,
7019        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7020     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7021     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7022 
7023     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
7024     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7025 
7026     /* AuthorizedLUAApp value exists */
7027     sz = MAX_PATH;
7028     lstrcpyA(buf, "apple");
7029     r = pMsiGetProductInfoExA(prodcode, usersid,
7030                               MSIINSTALLCONTEXT_USERMANAGED,
7031                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
7032     ok(r == ERROR_UNKNOWN_PRODUCT,
7033        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7034     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7035     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7036 
7037     RegDeleteValueA(propkey, "AuthorizedLUAApp");
7038     RegDeleteValueA(propkey, "PackageName");
7039     RegDeleteValueA(propkey, "ProductIcon");
7040     RegDeleteValueA(propkey, "Version");
7041     RegDeleteValueA(propkey, "PackageCode");
7042     RegDeleteValueA(propkey, "AssignmentType");
7043     RegDeleteValueA(propkey, "ProductName");
7044     RegDeleteValueA(propkey, "Language");
7045     RegDeleteValueA(propkey, "Transforms");
7046     RegDeleteValueA(propkey, "RegOwner");
7047     RegDeleteValueA(propkey, "RegCompany");
7048     RegDeleteValueA(propkey, "ProductID");
7049     RegDeleteValueA(propkey, "DisplayVersion");
7050     RegDeleteValueA(propkey, "VersionMajor");
7051     RegDeleteValueA(propkey, "VersionMinor");
7052     RegDeleteValueA(propkey, "URLUpdateInfo");
7053     RegDeleteValueA(propkey, "URLInfoAbout");
7054     RegDeleteValueA(propkey, "Publisher");
7055     RegDeleteValueA(propkey, "LocalPackage");
7056     RegDeleteValueA(propkey, "InstallSource");
7057     RegDeleteValueA(propkey, "InstallLocation");
7058     RegDeleteValueA(propkey, "DisplayName");
7059     RegDeleteValueA(propkey, "InstallDate");
7060     RegDeleteValueA(propkey, "HelpTelephone");
7061     RegDeleteValueA(propkey, "HelpLink");
7062     RegDeleteValueA(propkey, "ManagedLocalPackage");
7063     delete_key(propkey, "", access & KEY_WOW64_64KEY);
7064     RegCloseKey(propkey);
7065     delete_key(localkey, "", access & KEY_WOW64_64KEY);
7066     RegCloseKey(localkey);
7067 
7068     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
7069     lstrcatA(keypath, usersid);
7070     lstrcatA(keypath, "\\Installer\\Products\\");
7071     lstrcatA(keypath, prod_squashed);
7072 
7073     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
7074     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7075 
7076     /* user product key exists */
7077     sz = MAX_PATH;
7078     lstrcpyA(buf, "apple");
7079     r = pMsiGetProductInfoExA(prodcode, usersid,
7080                               MSIINSTALLCONTEXT_USERMANAGED,
7081                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7082     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7083     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
7084     ok(sz == 1, "Expected 1, got %d\n", sz);
7085 
7086     delete_key(userkey, "", access & KEY_WOW64_64KEY);
7087     RegCloseKey(userkey);
7088 
7089     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
7090     lstrcatA(keypath, prod_squashed);
7091 
7092     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
7093     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7094 
7095     /* current user product key exists */
7096     sz = MAX_PATH;
7097     lstrcpyA(buf, "apple");
7098     r = pMsiGetProductInfoExA(prodcode, usersid,
7099                               MSIINSTALLCONTEXT_USERMANAGED,
7100                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7101     ok(r == ERROR_UNKNOWN_PRODUCT,
7102        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7103     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7104     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7105 
7106     res = RegSetValueExA(prodkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
7107     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7108 
7109     /* HelpLink value exists, user product key does not exist */
7110     sz = MAX_PATH;
7111     lstrcpyA(buf, "apple");
7112     r = pMsiGetProductInfoExA(prodcode, usersid,
7113                               MSIINSTALLCONTEXT_USERMANAGED,
7114                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
7115     ok(r == ERROR_UNKNOWN_PRODUCT,
7116        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7117     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7118     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7119 
7120     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
7121     lstrcatA(keypath, usersid);
7122     lstrcatA(keypath, "\\Installer\\Products\\");
7123     lstrcatA(keypath, prod_squashed);
7124 
7125     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
7126     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7127 
7128     res = RegSetValueExA(userkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
7129     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7130 
7131     /* HelpLink value exists, user product key does exist */
7132     sz = MAX_PATH;
7133     lstrcpyA(buf, "apple");
7134     r = pMsiGetProductInfoExA(prodcode, usersid,
7135                               MSIINSTALLCONTEXT_USERMANAGED,
7136                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
7137     ok(r == ERROR_UNKNOWN_PROPERTY,
7138        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7139     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7140     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7141 
7142     res = RegSetValueExA(userkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
7143     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7144 
7145     /* HelpTelephone value exists */
7146     sz = MAX_PATH;
7147     lstrcpyA(buf, "apple");
7148     r = pMsiGetProductInfoExA(prodcode, usersid,
7149                               MSIINSTALLCONTEXT_USERMANAGED,
7150                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
7151     ok(r == ERROR_UNKNOWN_PROPERTY,
7152        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7153     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7154     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7155 
7156     res = RegSetValueExA(userkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
7157     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7158 
7159     /* InstallDate value exists */
7160     sz = MAX_PATH;
7161     lstrcpyA(buf, "apple");
7162     r = pMsiGetProductInfoExA(prodcode, usersid,
7163                               MSIINSTALLCONTEXT_USERMANAGED,
7164                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
7165     ok(r == ERROR_UNKNOWN_PROPERTY,
7166        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7167     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7168     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7169 
7170     res = RegSetValueExA(userkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
7171     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7172 
7173     /* DisplayName value exists */
7174     sz = MAX_PATH;
7175     lstrcpyA(buf, "apple");
7176     r = pMsiGetProductInfoExA(prodcode, usersid,
7177                               MSIINSTALLCONTEXT_USERMANAGED,
7178                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
7179     ok(r == ERROR_UNKNOWN_PROPERTY,
7180        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7181     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7182     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7183 
7184     res = RegSetValueExA(userkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
7185     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7186 
7187     /* InstallLocation value exists */
7188     sz = MAX_PATH;
7189     lstrcpyA(buf, "apple");
7190     r = pMsiGetProductInfoExA(prodcode, usersid,
7191                               MSIINSTALLCONTEXT_USERMANAGED,
7192                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
7193     ok(r == ERROR_UNKNOWN_PROPERTY,
7194        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7195     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7196     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7197 
7198     res = RegSetValueExA(userkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
7199     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7200 
7201     /* InstallSource value exists */
7202     sz = MAX_PATH;
7203     lstrcpyA(buf, "apple");
7204     r = pMsiGetProductInfoExA(prodcode, usersid,
7205                               MSIINSTALLCONTEXT_USERMANAGED,
7206                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
7207     ok(r == ERROR_UNKNOWN_PROPERTY,
7208        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7209     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7210     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7211 
7212     res = RegSetValueExA(userkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
7213     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7214 
7215     /* LocalPackage value exists */
7216     sz = MAX_PATH;
7217     lstrcpyA(buf, "apple");
7218     r = pMsiGetProductInfoExA(prodcode, usersid,
7219                               MSIINSTALLCONTEXT_USERMANAGED,
7220                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
7221     ok(r == ERROR_UNKNOWN_PROPERTY,
7222        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7223     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7224     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7225 
7226     res = RegSetValueExA(userkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
7227     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7228 
7229     /* Publisher value exists */
7230     sz = MAX_PATH;
7231     lstrcpyA(buf, "apple");
7232     r = pMsiGetProductInfoExA(prodcode, usersid,
7233                               MSIINSTALLCONTEXT_USERMANAGED,
7234                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
7235     ok(r == ERROR_UNKNOWN_PROPERTY,
7236        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7237     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7238     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7239 
7240     res = RegSetValueExA(userkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
7241     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7242 
7243     /* URLInfoAbout value exists */
7244     sz = MAX_PATH;
7245     lstrcpyA(buf, "apple");
7246     r = pMsiGetProductInfoExA(prodcode, usersid,
7247                               MSIINSTALLCONTEXT_USERMANAGED,
7248                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
7249     ok(r == ERROR_UNKNOWN_PROPERTY,
7250        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7251     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7252     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7253 
7254     res = RegSetValueExA(userkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
7255     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7256 
7257     /* URLUpdateInfo value exists */
7258     sz = MAX_PATH;
7259     lstrcpyA(buf, "apple");
7260     r = pMsiGetProductInfoExA(prodcode, usersid,
7261                               MSIINSTALLCONTEXT_USERMANAGED,
7262                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
7263     ok(r == ERROR_UNKNOWN_PROPERTY,
7264        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7265     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7266     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7267 
7268     res = RegSetValueExA(userkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
7269     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7270 
7271     /* VersionMinor value exists */
7272     sz = MAX_PATH;
7273     lstrcpyA(buf, "apple");
7274     r = pMsiGetProductInfoExA(prodcode, usersid,
7275                               MSIINSTALLCONTEXT_USERMANAGED,
7276                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
7277     ok(r == ERROR_UNKNOWN_PROPERTY,
7278        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7279     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7280     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7281 
7282     res = RegSetValueExA(userkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
7283     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7284 
7285     /* VersionMajor value exists */
7286     sz = MAX_PATH;
7287     lstrcpyA(buf, "apple");
7288     r = pMsiGetProductInfoExA(prodcode, usersid,
7289                               MSIINSTALLCONTEXT_USERMANAGED,
7290                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
7291     ok(r == ERROR_UNKNOWN_PROPERTY,
7292        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7293     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7294     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7295 
7296     res = RegSetValueExA(userkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
7297     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7298 
7299     /* DisplayVersion value exists */
7300     sz = MAX_PATH;
7301     lstrcpyA(buf, "apple");
7302     r = pMsiGetProductInfoExA(prodcode, usersid,
7303                               MSIINSTALLCONTEXT_USERMANAGED,
7304                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
7305     ok(r == ERROR_UNKNOWN_PROPERTY,
7306        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7307     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7308     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7309 
7310     res = RegSetValueExA(userkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
7311     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7312 
7313     /* ProductID value exists */
7314     sz = MAX_PATH;
7315     lstrcpyA(buf, "apple");
7316     r = pMsiGetProductInfoExA(prodcode, usersid,
7317                               MSIINSTALLCONTEXT_USERMANAGED,
7318                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
7319     ok(r == ERROR_UNKNOWN_PROPERTY,
7320        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7321     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7322     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7323 
7324     res = RegSetValueExA(userkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
7325     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7326 
7327     /* RegCompany value exists */
7328     sz = MAX_PATH;
7329     lstrcpyA(buf, "apple");
7330     r = pMsiGetProductInfoExA(prodcode, usersid,
7331                               MSIINSTALLCONTEXT_USERMANAGED,
7332                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
7333     ok(r == ERROR_UNKNOWN_PROPERTY,
7334        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7335     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7336     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7337 
7338     res = RegSetValueExA(userkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
7339     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7340 
7341     /* RegOwner value exists */
7342     sz = MAX_PATH;
7343     lstrcpyA(buf, "apple");
7344     r = pMsiGetProductInfoExA(prodcode, usersid,
7345                               MSIINSTALLCONTEXT_USERMANAGED,
7346                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
7347     ok(r == ERROR_UNKNOWN_PROPERTY,
7348        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7349     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7350     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7351 
7352     res = RegSetValueExA(userkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
7353     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7354 
7355     /* Transforms value exists */
7356     sz = MAX_PATH;
7357     lstrcpyA(buf, "apple");
7358     r = pMsiGetProductInfoExA(prodcode, usersid,
7359                               MSIINSTALLCONTEXT_USERMANAGED,
7360                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
7361     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7362     ok(!lstrcmpA(buf, "trans"), "Expected \"trans\", got \"%s\"\n", buf);
7363     ok(sz == 5, "Expected 5, got %d\n", sz);
7364 
7365     res = RegSetValueExA(userkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
7366     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7367 
7368     /* Language value exists */
7369     sz = MAX_PATH;
7370     lstrcpyA(buf, "apple");
7371     r = pMsiGetProductInfoExA(prodcode, usersid,
7372                               MSIINSTALLCONTEXT_USERMANAGED,
7373                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
7374     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7375     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
7376     ok(sz == 4, "Expected 4, got %d\n", sz);
7377 
7378     res = RegSetValueExA(userkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
7379     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7380 
7381     /* ProductName value exists */
7382     sz = MAX_PATH;
7383     lstrcpyA(buf, "apple");
7384     r = pMsiGetProductInfoExA(prodcode, usersid,
7385                               MSIINSTALLCONTEXT_USERMANAGED,
7386                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
7387     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7388     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
7389     ok(sz == 4, "Expected 4, got %d\n", sz);
7390 
7391     res = RegSetValueExA(userkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
7392     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7393 
7394     /* FIXME */
7395 
7396     /* AssignmentType value exists */
7397     sz = MAX_PATH;
7398     lstrcpyA(buf, "apple");
7399     r = pMsiGetProductInfoExA(prodcode, usersid,
7400                               MSIINSTALLCONTEXT_USERMANAGED,
7401                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
7402     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7403     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7404     ok(sz == 0, "Expected 0, got %d\n", sz);
7405 
7406     res = RegSetValueExA(userkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
7407     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7408 
7409     /* FIXME */
7410 
7411     /* PackageCode value exists */
7412     sz = MAX_PATH;
7413     lstrcpyA(buf, "apple");
7414     r = pMsiGetProductInfoExA(prodcode, usersid,
7415                               MSIINSTALLCONTEXT_USERMANAGED,
7416                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
7417     todo_wine
7418     {
7419         ok(r == ERROR_BAD_CONFIGURATION,
7420            "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
7421         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7422         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7423     }
7424 
7425     res = RegSetValueExA(userkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
7426     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7427 
7428     /* Version value exists */
7429     sz = MAX_PATH;
7430     lstrcpyA(buf, "apple");
7431     r = pMsiGetProductInfoExA(prodcode, usersid,
7432                               MSIINSTALLCONTEXT_USERMANAGED,
7433                               INSTALLPROPERTY_VERSIONA, buf, &sz);
7434     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7435     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
7436     ok(sz == 3, "Expected 3, got %d\n", sz);
7437 
7438     res = RegSetValueExA(userkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
7439     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7440 
7441     /* ProductIcon value exists */
7442     sz = MAX_PATH;
7443     lstrcpyA(buf, "apple");
7444     r = pMsiGetProductInfoExA(prodcode, usersid,
7445                               MSIINSTALLCONTEXT_USERMANAGED,
7446                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
7447     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7448     ok(!lstrcmpA(buf, "icon"), "Expected \"icon\", got \"%s\"\n", buf);
7449     ok(sz == 4, "Expected 4, got %d\n", sz);
7450 
7451     res = RegSetValueExA(userkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
7452     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7453 
7454     /* PackageName value exists */
7455     sz = MAX_PATH;
7456     lstrcpyA(buf, "apple");
7457     r = pMsiGetProductInfoExA(prodcode, usersid,
7458                               MSIINSTALLCONTEXT_USERMANAGED,
7459                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
7460     todo_wine
7461     {
7462         ok(r == ERROR_UNKNOWN_PRODUCT,
7463            "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7464         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7465         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7466     }
7467 
7468     res = RegSetValueExA(userkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
7469     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7470 
7471     /* AuthorizedLUAApp value exists */
7472     sz = MAX_PATH;
7473     lstrcpyA(buf, "apple");
7474     r = pMsiGetProductInfoExA(prodcode, usersid,
7475                               MSIINSTALLCONTEXT_USERMANAGED,
7476                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
7477     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7478     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
7479     ok(sz == 4, "Expected 4, got %d\n", sz);
7480 
7481     RegDeleteValueA(userkey, "AuthorizedLUAApp");
7482     RegDeleteValueA(userkey, "PackageName");
7483     RegDeleteValueA(userkey, "ProductIcon");
7484     RegDeleteValueA(userkey, "Version");
7485     RegDeleteValueA(userkey, "PackageCode");
7486     RegDeleteValueA(userkey, "AssignmentType");
7487     RegDeleteValueA(userkey, "ProductName");
7488     RegDeleteValueA(userkey, "Language");
7489     RegDeleteValueA(userkey, "Transforms");
7490     RegDeleteValueA(userkey, "RegOwner");
7491     RegDeleteValueA(userkey, "RegCompany");
7492     RegDeleteValueA(userkey, "ProductID");
7493     RegDeleteValueA(userkey, "DisplayVersion");
7494     RegDeleteValueA(userkey, "VersionMajor");
7495     RegDeleteValueA(userkey, "VersionMinor");
7496     RegDeleteValueA(userkey, "URLUpdateInfo");
7497     RegDeleteValueA(userkey, "URLInfoAbout");
7498     RegDeleteValueA(userkey, "Publisher");
7499     RegDeleteValueA(userkey, "LocalPackage");
7500     RegDeleteValueA(userkey, "InstallSource");
7501     RegDeleteValueA(userkey, "InstallLocation");
7502     RegDeleteValueA(userkey, "DisplayName");
7503     RegDeleteValueA(userkey, "InstallDate");
7504     RegDeleteValueA(userkey, "HelpTelephone");
7505     RegDeleteValueA(userkey, "HelpLink");
7506     delete_key(userkey, "", access & KEY_WOW64_64KEY);
7507     RegCloseKey(userkey);
7508     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
7509     RegCloseKey(prodkey);
7510 
7511     /* MSIINSTALLCONTEXT_MACHINE */
7512 
7513     /* szUserSid is non-NULL */
7514     sz = MAX_PATH;
7515     lstrcpyA(buf, "apple");
7516     r = pMsiGetProductInfoExA(prodcode, usersid,
7517                               MSIINSTALLCONTEXT_MACHINE,
7518                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7519     ok(r == ERROR_INVALID_PARAMETER,
7520        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
7521     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7522     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7523 
7524     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\");
7525     lstrcatA(keypath, prod_squashed);
7526 
7527     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
7528     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7529 
7530     /* local system product key exists */
7531     sz = MAX_PATH;
7532     lstrcpyA(buf, "apple");
7533     r = pMsiGetProductInfoExA(prodcode, NULL,
7534                               MSIINSTALLCONTEXT_MACHINE,
7535                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7536     ok(r == ERROR_UNKNOWN_PRODUCT,
7537        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7538     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7539     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7540 
7541     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
7542     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7543 
7544     /* InstallProperties key exists */
7545     sz = MAX_PATH;
7546     lstrcpyA(buf, "apple");
7547     r = pMsiGetProductInfoExA(prodcode, NULL,
7548                               MSIINSTALLCONTEXT_MACHINE,
7549                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7550     ok(r == ERROR_UNKNOWN_PRODUCT,
7551        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7552     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7553     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7554 
7555     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
7556     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7557 
7558     /* LocalPackage value exists */
7559     sz = MAX_PATH;
7560     lstrcpyA(buf, "apple");
7561     r = pMsiGetProductInfoExA(prodcode, NULL,
7562                               MSIINSTALLCONTEXT_MACHINE,
7563                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7564     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7565     ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
7566     ok(sz == 1, "Expected 1, got %d\n", sz);
7567 
7568     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
7569     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7570 
7571     /* HelpLink value exists */
7572     sz = MAX_PATH;
7573     lstrcpyA(buf, "apple");
7574     r = pMsiGetProductInfoExA(prodcode, NULL,
7575                               MSIINSTALLCONTEXT_MACHINE,
7576                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
7577     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7578     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
7579     ok(sz == 4, "Expected 4, got %d\n", sz);
7580 
7581     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
7582     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7583 
7584     /* HelpTelephone value exists */
7585     sz = MAX_PATH;
7586     lstrcpyA(buf, "apple");
7587     r = pMsiGetProductInfoExA(prodcode, NULL,
7588                               MSIINSTALLCONTEXT_MACHINE,
7589                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
7590     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7591     ok(!lstrcmpA(buf, "phone"), "Expected \"phone\", got \"%s\"\n", buf);
7592     ok(sz == 5, "Expected 5, got %d\n", sz);
7593 
7594     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
7595     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7596 
7597     /* InstallDate value exists */
7598     sz = MAX_PATH;
7599     lstrcpyA(buf, "apple");
7600     r = pMsiGetProductInfoExA(prodcode, NULL,
7601                               MSIINSTALLCONTEXT_MACHINE,
7602                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
7603     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7604     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
7605     ok(sz == 4, "Expected 4, got %d\n", sz);
7606 
7607     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
7608     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7609 
7610     /* DisplayName value exists */
7611     sz = MAX_PATH;
7612     lstrcpyA(buf, "apple");
7613     r = pMsiGetProductInfoExA(prodcode, NULL,
7614                               MSIINSTALLCONTEXT_MACHINE,
7615                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
7616     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7617     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
7618     ok(sz == 4, "Expected 4, got %d\n", sz);
7619 
7620     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
7621     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7622 
7623     /* InstallLocation value exists */
7624     sz = MAX_PATH;
7625     lstrcpyA(buf, "apple");
7626     r = pMsiGetProductInfoExA(prodcode, NULL,
7627                               MSIINSTALLCONTEXT_MACHINE,
7628                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
7629     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7630     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
7631     ok(sz == 3, "Expected 3, got %d\n", sz);
7632 
7633     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
7634     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7635 
7636     /* InstallSource value exists */
7637     sz = MAX_PATH;
7638     lstrcpyA(buf, "apple");
7639     r = pMsiGetProductInfoExA(prodcode, NULL,
7640                               MSIINSTALLCONTEXT_MACHINE,
7641                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
7642     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7643     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
7644     ok(sz == 6, "Expected 6, got %d\n", sz);
7645 
7646     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
7647     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7648 
7649     /* LocalPackage value exists */
7650     sz = MAX_PATH;
7651     lstrcpyA(buf, "apple");
7652     r = pMsiGetProductInfoExA(prodcode, NULL,
7653                               MSIINSTALLCONTEXT_MACHINE,
7654                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
7655     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7656     ok(!lstrcmpA(buf, "local"), "Expected \"local\", got \"%s\"\n", buf);
7657     ok(sz == 5, "Expected 5, got %d\n", sz);
7658 
7659     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
7660     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7661 
7662     /* Publisher value exists */
7663     sz = MAX_PATH;
7664     lstrcpyA(buf, "apple");
7665     r = pMsiGetProductInfoExA(prodcode, NULL,
7666                               MSIINSTALLCONTEXT_MACHINE,
7667                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
7668     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7669     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
7670     ok(sz == 3, "Expected 3, got %d\n", sz);
7671 
7672     res = RegSetValueExA(propkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
7673     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7674 
7675     /* URLInfoAbout value exists */
7676     sz = MAX_PATH;
7677     lstrcpyA(buf, "apple");
7678     r = pMsiGetProductInfoExA(prodcode, NULL,
7679                               MSIINSTALLCONTEXT_MACHINE,
7680                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
7681     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7682     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
7683     ok(sz == 5, "Expected 5, got %d\n", sz);
7684 
7685     res = RegSetValueExA(propkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
7686     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7687 
7688     /* URLUpdateInfo value exists */
7689     sz = MAX_PATH;
7690     lstrcpyA(buf, "apple");
7691     r = pMsiGetProductInfoExA(prodcode, NULL,
7692                               MSIINSTALLCONTEXT_MACHINE,
7693                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
7694     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7695     ok(!lstrcmpA(buf, "update"), "Expected \"update\", got \"%s\"\n", buf);
7696     ok(sz == 6, "Expected 6, got %d\n", sz);
7697 
7698     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
7699     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7700 
7701     /* VersionMinor value exists */
7702     sz = MAX_PATH;
7703     lstrcpyA(buf, "apple");
7704     r = pMsiGetProductInfoExA(prodcode, NULL,
7705                               MSIINSTALLCONTEXT_MACHINE,
7706                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
7707     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7708     ok(!lstrcmpA(buf, "2"), "Expected \"2\", got \"%s\"\n", buf);
7709     ok(sz == 1, "Expected 1, got %d\n", sz);
7710 
7711     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
7712     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7713 
7714     /* VersionMajor value exists */
7715     sz = MAX_PATH;
7716     lstrcpyA(buf, "apple");
7717     r = pMsiGetProductInfoExA(prodcode, NULL,
7718                               MSIINSTALLCONTEXT_MACHINE,
7719                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
7720     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7721     ok(!lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
7722     ok(sz == 1, "Expected 1, got %d\n", sz);
7723 
7724     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
7725     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7726 
7727     /* DisplayVersion value exists */
7728     sz = MAX_PATH;
7729     lstrcpyA(buf, "apple");
7730     r = pMsiGetProductInfoExA(prodcode, NULL,
7731                               MSIINSTALLCONTEXT_MACHINE,
7732                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
7733     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7734     ok(!lstrcmpA(buf, "3.2.1"), "Expected \"3.2.1\", got \"%s\"\n", buf);
7735     ok(sz == 5, "Expected 5, got %d\n", sz);
7736 
7737     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
7738     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7739 
7740     /* ProductID value exists */
7741     sz = MAX_PATH;
7742     lstrcpyA(buf, "apple");
7743     r = pMsiGetProductInfoExA(prodcode, NULL,
7744                               MSIINSTALLCONTEXT_MACHINE,
7745                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
7746     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7747     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
7748     ok(sz == 2, "Expected 2, got %d\n", sz);
7749 
7750     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
7751     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7752 
7753     /* RegCompany value exists */
7754     sz = MAX_PATH;
7755     lstrcpyA(buf, "apple");
7756     r = pMsiGetProductInfoExA(prodcode, NULL,
7757                               MSIINSTALLCONTEXT_MACHINE,
7758                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
7759     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7760     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
7761     ok(sz == 4, "Expected 4, got %d\n", sz);
7762 
7763     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
7764     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7765 
7766     /* RegOwner value exists */
7767     sz = MAX_PATH;
7768     lstrcpyA(buf, "apple");
7769     r = pMsiGetProductInfoExA(prodcode, NULL,
7770                               MSIINSTALLCONTEXT_MACHINE,
7771                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
7772     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7773     ok(!lstrcmpA(buf, "owner"), "Expected \"owner\", got \"%s\"\n", buf);
7774     ok(sz == 5, "Expected 5, got %d\n", sz);
7775 
7776     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
7777     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7778 
7779     /* Transforms value exists */
7780     sz = MAX_PATH;
7781     lstrcpyA(buf, "apple");
7782     r = pMsiGetProductInfoExA(prodcode, NULL,
7783                               MSIINSTALLCONTEXT_MACHINE,
7784                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
7785     ok(r == ERROR_UNKNOWN_PRODUCT,
7786        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7787     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7788     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7789 
7790     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
7791     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7792 
7793     /* Language value exists */
7794     sz = MAX_PATH;
7795     lstrcpyA(buf, "apple");
7796     r = pMsiGetProductInfoExA(prodcode, NULL,
7797                               MSIINSTALLCONTEXT_MACHINE,
7798                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
7799     ok(r == ERROR_UNKNOWN_PRODUCT,
7800        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7801     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7802     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7803 
7804     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
7805     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7806 
7807     /* ProductName value exists */
7808     sz = MAX_PATH;
7809     lstrcpyA(buf, "apple");
7810     r = pMsiGetProductInfoExA(prodcode, NULL,
7811                               MSIINSTALLCONTEXT_MACHINE,
7812                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
7813     ok(r == ERROR_UNKNOWN_PRODUCT,
7814        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7815     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7816     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7817 
7818     res = RegSetValueExA(propkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
7819     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7820 
7821     /* FIXME */
7822 
7823     /* AssignmentType value exists */
7824     sz = MAX_PATH;
7825     lstrcpyA(buf, "apple");
7826     r = pMsiGetProductInfoExA(prodcode, NULL,
7827                               MSIINSTALLCONTEXT_MACHINE,
7828                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
7829     ok(r == ERROR_UNKNOWN_PRODUCT,
7830        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7831     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7832     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7833 
7834     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
7835     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7836 
7837     /* PackageCode value exists */
7838     sz = MAX_PATH;
7839     lstrcpyA(buf, "apple");
7840     r = pMsiGetProductInfoExA(prodcode, NULL,
7841                               MSIINSTALLCONTEXT_MACHINE,
7842                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
7843     ok(r == ERROR_UNKNOWN_PRODUCT,
7844        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7845     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7846     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7847 
7848     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
7849     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7850 
7851     /* Version value exists */
7852     sz = MAX_PATH;
7853     lstrcpyA(buf, "apple");
7854     r = pMsiGetProductInfoExA(prodcode, NULL,
7855                               MSIINSTALLCONTEXT_MACHINE,
7856                               INSTALLPROPERTY_VERSIONA, buf, &sz);
7857     ok(r == ERROR_UNKNOWN_PRODUCT,
7858        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7859     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7860     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7861 
7862     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
7863     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7864 
7865     /* ProductIcon value exists */
7866     sz = MAX_PATH;
7867     lstrcpyA(buf, "apple");
7868     r = pMsiGetProductInfoExA(prodcode, NULL,
7869                               MSIINSTALLCONTEXT_MACHINE,
7870                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
7871     ok(r == ERROR_UNKNOWN_PRODUCT,
7872        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7873     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7874     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7875 
7876     res = RegSetValueExA(propkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
7877     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7878 
7879     /* PackageName value exists */
7880     sz = MAX_PATH;
7881     lstrcpyA(buf, "apple");
7882     r = pMsiGetProductInfoExA(prodcode, NULL,
7883                               MSIINSTALLCONTEXT_MACHINE,
7884                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
7885     ok(r == ERROR_UNKNOWN_PRODUCT,
7886        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7887     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7888     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7889 
7890     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
7891     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7892 
7893     /* AuthorizedLUAApp value exists */
7894     sz = MAX_PATH;
7895     lstrcpyA(buf, "apple");
7896     r = pMsiGetProductInfoExA(prodcode, NULL,
7897                               MSIINSTALLCONTEXT_MACHINE,
7898                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
7899     ok(r == ERROR_UNKNOWN_PRODUCT,
7900        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7901     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7902     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7903 
7904     RegDeleteValueA(propkey, "AuthorizedLUAApp");
7905     RegDeleteValueA(propkey, "PackageName");
7906     RegDeleteValueA(propkey, "ProductIcon");
7907     RegDeleteValueA(propkey, "Version");
7908     RegDeleteValueA(propkey, "PackageCode");
7909     RegDeleteValueA(propkey, "AssignmentType");
7910     RegDeleteValueA(propkey, "ProductName");
7911     RegDeleteValueA(propkey, "Language");
7912     RegDeleteValueA(propkey, "Transforms");
7913     RegDeleteValueA(propkey, "RegOwner");
7914     RegDeleteValueA(propkey, "RegCompany");
7915     RegDeleteValueA(propkey, "ProductID");
7916     RegDeleteValueA(propkey, "DisplayVersion");
7917     RegDeleteValueA(propkey, "VersionMajor");
7918     RegDeleteValueA(propkey, "VersionMinor");
7919     RegDeleteValueA(propkey, "URLUpdateInfo");
7920     RegDeleteValueA(propkey, "URLInfoAbout");
7921     RegDeleteValueA(propkey, "Publisher");
7922     RegDeleteValueA(propkey, "LocalPackage");
7923     RegDeleteValueA(propkey, "InstallSource");
7924     RegDeleteValueA(propkey, "InstallLocation");
7925     RegDeleteValueA(propkey, "DisplayName");
7926     RegDeleteValueA(propkey, "InstallDate");
7927     RegDeleteValueA(propkey, "HelpTelephone");
7928     RegDeleteValueA(propkey, "HelpLink");
7929     RegDeleteValueA(propkey, "LocalPackage");
7930     delete_key(propkey, "", access & KEY_WOW64_64KEY);
7931     RegCloseKey(propkey);
7932     delete_key(localkey, "", access & KEY_WOW64_64KEY);
7933     RegCloseKey(localkey);
7934 
7935     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
7936     lstrcatA(keypath, prod_squashed);
7937 
7938     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
7939     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7940 
7941     /* local classes product key exists */
7942     sz = MAX_PATH;
7943     lstrcpyA(buf, "apple");
7944     r = pMsiGetProductInfoExA(prodcode, NULL,
7945                               MSIINSTALLCONTEXT_MACHINE,
7946                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7947     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7948     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
7949     ok(sz == 1, "Expected 1, got %d\n", sz);
7950 
7951     res = RegSetValueExA(prodkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
7952     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7953 
7954     /* HelpLink value exists */
7955     sz = MAX_PATH;
7956     lstrcpyA(buf, "apple");
7957     r = pMsiGetProductInfoExA(prodcode, NULL,
7958                               MSIINSTALLCONTEXT_MACHINE,
7959                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
7960     ok(r == ERROR_UNKNOWN_PROPERTY,
7961        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7962     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7963     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7964 
7965     res = RegSetValueExA(prodkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
7966     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7967 
7968     /* HelpTelephone value exists */
7969     sz = MAX_PATH;
7970     lstrcpyA(buf, "apple");
7971     r = pMsiGetProductInfoExA(prodcode, NULL,
7972                               MSIINSTALLCONTEXT_MACHINE,
7973                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
7974     ok(r == ERROR_UNKNOWN_PROPERTY,
7975        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7976     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7977     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7978 
7979     res = RegSetValueExA(prodkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
7980     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7981 
7982     /* InstallDate value exists */
7983     sz = MAX_PATH;
7984     lstrcpyA(buf, "apple");
7985     r = pMsiGetProductInfoExA(prodcode, NULL,
7986                               MSIINSTALLCONTEXT_MACHINE,
7987                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
7988     ok(r == ERROR_UNKNOWN_PROPERTY,
7989        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7990     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7991     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7992 
7993     res = RegSetValueExA(prodkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
7994     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7995 
7996     /* DisplayName value exists */
7997     sz = MAX_PATH;
7998     lstrcpyA(buf, "apple");
7999     r = pMsiGetProductInfoExA(prodcode, NULL,
8000                               MSIINSTALLCONTEXT_MACHINE,
8001                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
8002     ok(r == ERROR_UNKNOWN_PROPERTY,
8003        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8004     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8005     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8006 
8007     res = RegSetValueExA(prodkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
8008     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8009 
8010     /* InstallLocation value exists */
8011     sz = MAX_PATH;
8012     lstrcpyA(buf, "apple");
8013     r = pMsiGetProductInfoExA(prodcode, NULL,
8014                               MSIINSTALLCONTEXT_MACHINE,
8015                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
8016     ok(r == ERROR_UNKNOWN_PROPERTY,
8017        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8018     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8019     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8020 
8021     res = RegSetValueExA(prodkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
8022     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8023 
8024     /* InstallSource value exists */
8025     sz = MAX_PATH;
8026     lstrcpyA(buf, "apple");
8027     r = pMsiGetProductInfoExA(prodcode, NULL,
8028                               MSIINSTALLCONTEXT_MACHINE,
8029                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
8030     ok(r == ERROR_UNKNOWN_PROPERTY,
8031        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8032     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8033     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8034 
8035     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
8036     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8037 
8038     /* LocalPackage value exists */
8039     sz = MAX_PATH;
8040     lstrcpyA(buf, "apple");
8041     r = pMsiGetProductInfoExA(prodcode, NULL,
8042                               MSIINSTALLCONTEXT_MACHINE,
8043                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
8044     ok(r == ERROR_UNKNOWN_PROPERTY,
8045        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8046     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8047     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8048 
8049     res = RegSetValueExA(prodkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
8050     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8051 
8052     /* Publisher value exists */
8053     sz = MAX_PATH;
8054     lstrcpyA(buf, "apple");
8055     r = pMsiGetProductInfoExA(prodcode, NULL,
8056                               MSIINSTALLCONTEXT_MACHINE,
8057                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
8058     ok(r == ERROR_UNKNOWN_PROPERTY,
8059        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8060     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8061     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8062 
8063     res = RegSetValueExA(prodkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
8064     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8065 
8066     /* URLInfoAbout value exists */
8067     sz = MAX_PATH;
8068     lstrcpyA(buf, "apple");
8069     r = pMsiGetProductInfoExA(prodcode, NULL,
8070                               MSIINSTALLCONTEXT_MACHINE,
8071                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
8072     ok(r == ERROR_UNKNOWN_PROPERTY,
8073        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8074     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8075     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8076 
8077     res = RegSetValueExA(prodkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
8078     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8079 
8080     /* URLUpdateInfo value exists */
8081     sz = MAX_PATH;
8082     lstrcpyA(buf, "apple");
8083     r = pMsiGetProductInfoExA(prodcode, NULL,
8084                               MSIINSTALLCONTEXT_MACHINE,
8085                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
8086     ok(r == ERROR_UNKNOWN_PROPERTY,
8087        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8088     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8089     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8090 
8091     res = RegSetValueExA(prodkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
8092     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8093 
8094     /* VersionMinor value exists */
8095     sz = MAX_PATH;
8096     lstrcpyA(buf, "apple");
8097     r = pMsiGetProductInfoExA(prodcode, NULL,
8098                               MSIINSTALLCONTEXT_MACHINE,
8099                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
8100     ok(r == ERROR_UNKNOWN_PROPERTY,
8101        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8102     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8103     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8104 
8105     res = RegSetValueExA(prodkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
8106     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8107 
8108     /* VersionMajor value exists */
8109     sz = MAX_PATH;
8110     lstrcpyA(buf, "apple");
8111     r = pMsiGetProductInfoExA(prodcode, NULL,
8112                               MSIINSTALLCONTEXT_MACHINE,
8113                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
8114     ok(r == ERROR_UNKNOWN_PROPERTY,
8115        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8116     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8117     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8118 
8119     res = RegSetValueExA(prodkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
8120     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8121 
8122     /* DisplayVersion value exists */
8123     sz = MAX_PATH;
8124     lstrcpyA(buf, "apple");
8125     r = pMsiGetProductInfoExA(prodcode, NULL,
8126                               MSIINSTALLCONTEXT_MACHINE,
8127                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
8128     ok(r == ERROR_UNKNOWN_PROPERTY,
8129        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8130     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8131     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8132 
8133     res = RegSetValueExA(prodkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
8134     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8135 
8136     /* ProductID value exists */
8137     sz = MAX_PATH;
8138     lstrcpyA(buf, "apple");
8139     r = pMsiGetProductInfoExA(prodcode, NULL,
8140                               MSIINSTALLCONTEXT_MACHINE,
8141                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
8142     ok(r == ERROR_UNKNOWN_PROPERTY,
8143        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8144     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8145     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8146 
8147     res = RegSetValueExA(prodkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
8148     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8149 
8150     /* RegCompany value exists */
8151     sz = MAX_PATH;
8152     lstrcpyA(buf, "apple");
8153     r = pMsiGetProductInfoExA(prodcode, NULL,
8154                               MSIINSTALLCONTEXT_MACHINE,
8155                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
8156     ok(r == ERROR_UNKNOWN_PROPERTY,
8157        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8158     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8159     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8160 
8161     res = RegSetValueExA(prodkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
8162     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8163 
8164     /* RegOwner value exists */
8165     sz = MAX_PATH;
8166     lstrcpyA(buf, "apple");
8167     r = pMsiGetProductInfoExA(prodcode, NULL,
8168                               MSIINSTALLCONTEXT_MACHINE,
8169                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
8170     ok(r == ERROR_UNKNOWN_PROPERTY,
8171        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8172     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8173     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8174 
8175     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
8176     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8177 
8178     /* Transforms value exists */
8179     sz = MAX_PATH;
8180     lstrcpyA(buf, "apple");
8181     r = pMsiGetProductInfoExA(prodcode, NULL,
8182                               MSIINSTALLCONTEXT_MACHINE,
8183                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
8184     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8185     ok(!lstrcmpA(buf, "trans"), "Expected \"trans\", got \"%s\"\n", buf);
8186     ok(sz == 5, "Expected 5, got %d\n", sz);
8187 
8188     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
8189     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8190 
8191     /* Language value exists */
8192     sz = MAX_PATH;
8193     lstrcpyA(buf, "apple");
8194     r = pMsiGetProductInfoExA(prodcode, NULL,
8195                               MSIINSTALLCONTEXT_MACHINE,
8196                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
8197     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8198     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
8199     ok(sz == 4, "Expected 4, got %d\n", sz);
8200 
8201     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
8202     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8203 
8204     /* ProductName value exists */
8205     sz = MAX_PATH;
8206     lstrcpyA(buf, "apple");
8207     r = pMsiGetProductInfoExA(prodcode, NULL,
8208                               MSIINSTALLCONTEXT_MACHINE,
8209                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
8210     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8211     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
8212     ok(sz == 4, "Expected 4, got %d\n", sz);
8213 
8214     res = RegSetValueExA(prodkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
8215     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8216 
8217     /* FIXME */
8218 
8219     /* AssignmentType value exists */
8220     sz = MAX_PATH;
8221     lstrcpyA(buf, "apple");
8222     r = pMsiGetProductInfoExA(prodcode, NULL,
8223                               MSIINSTALLCONTEXT_MACHINE,
8224                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
8225     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8226     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
8227     ok(sz == 0, "Expected 0, got %d\n", sz);
8228 
8229     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
8230     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8231 
8232     /* FIXME */
8233 
8234     /* PackageCode value exists */
8235     sz = MAX_PATH;
8236     lstrcpyA(buf, "apple");
8237     r = pMsiGetProductInfoExA(prodcode, NULL,
8238                               MSIINSTALLCONTEXT_MACHINE,
8239                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
8240     todo_wine
8241     {
8242         ok(r == ERROR_BAD_CONFIGURATION,
8243            "Expected ERROR_BAD_CONFIGURATION, 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 %d\n", sz);
8246     }
8247 
8248     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
8249     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8250 
8251     /* Version value exists */
8252     sz = MAX_PATH;
8253     lstrcpyA(buf, "apple");
8254     r = pMsiGetProductInfoExA(prodcode, NULL,
8255                               MSIINSTALLCONTEXT_MACHINE,
8256                               INSTALLPROPERTY_VERSIONA, buf, &sz);
8257     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8258     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
8259     ok(sz == 3, "Expected 3, got %d\n", sz);
8260 
8261     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
8262     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8263 
8264     /* ProductIcon value exists */
8265     sz = MAX_PATH;
8266     lstrcpyA(buf, "apple");
8267     r = pMsiGetProductInfoExA(prodcode, NULL,
8268                               MSIINSTALLCONTEXT_MACHINE,
8269                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
8270     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8271     ok(!lstrcmpA(buf, "icon"), "Expected \"icon\", got \"%s\"\n", buf);
8272     ok(sz == 4, "Expected 4, got %d\n", sz);
8273 
8274     res = RegSetValueExA(prodkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
8275     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8276 
8277     /* PackageName value exists */
8278     sz = MAX_PATH;
8279     lstrcpyA(buf, "apple");
8280     r = pMsiGetProductInfoExA(prodcode, NULL,
8281                               MSIINSTALLCONTEXT_MACHINE,
8282                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
8283     todo_wine
8284     {
8285         ok(r == ERROR_UNKNOWN_PRODUCT,
8286            "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8287         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8288         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8289     }
8290 
8291     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
8292     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8293 
8294     /* AuthorizedLUAApp value exists */
8295     sz = MAX_PATH;
8296     lstrcpyA(buf, "apple");
8297     r = pMsiGetProductInfoExA(prodcode, NULL,
8298                               MSIINSTALLCONTEXT_MACHINE,
8299                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
8300     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8301     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
8302     ok(sz == 4, "Expected 4, got %d\n", sz);
8303 
8304     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
8305     RegDeleteValueA(prodkey, "PackageName");
8306     RegDeleteValueA(prodkey, "ProductIcon");
8307     RegDeleteValueA(prodkey, "Version");
8308     RegDeleteValueA(prodkey, "PackageCode");
8309     RegDeleteValueA(prodkey, "AssignmentType");
8310     RegDeleteValueA(prodkey, "ProductName");
8311     RegDeleteValueA(prodkey, "Language");
8312     RegDeleteValueA(prodkey, "Transforms");
8313     RegDeleteValueA(prodkey, "RegOwner");
8314     RegDeleteValueA(prodkey, "RegCompany");
8315     RegDeleteValueA(prodkey, "ProductID");
8316     RegDeleteValueA(prodkey, "DisplayVersion");
8317     RegDeleteValueA(prodkey, "VersionMajor");
8318     RegDeleteValueA(prodkey, "VersionMinor");
8319     RegDeleteValueA(prodkey, "URLUpdateInfo");
8320     RegDeleteValueA(prodkey, "URLInfoAbout");
8321     RegDeleteValueA(prodkey, "Publisher");
8322     RegDeleteValueA(prodkey, "LocalPackage");
8323     RegDeleteValueA(prodkey, "InstallSource");
8324     RegDeleteValueA(prodkey, "InstallLocation");
8325     RegDeleteValueA(prodkey, "DisplayName");
8326     RegDeleteValueA(prodkey, "InstallDate");
8327     RegDeleteValueA(prodkey, "HelpTelephone");
8328     RegDeleteValueA(prodkey, "HelpLink");
8329     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
8330     RegCloseKey(prodkey);
8331     LocalFree(usersid);
8332 }
8333 
8334 #define INIT_USERINFO() \
8335     lstrcpyA(user, "apple"); \
8336     lstrcpyA(org, "orange"); \
8337     lstrcpyA(serial, "banana"); \
8338     usersz = orgsz = serialsz = MAX_PATH;
8339 
8340 static void test_MsiGetUserInfo(void)
8341 {
8342     USERINFOSTATE state;
8343     CHAR user[MAX_PATH];
8344     CHAR org[MAX_PATH];
8345     CHAR serial[MAX_PATH];
8346     DWORD usersz, orgsz, serialsz;
8347     CHAR keypath[MAX_PATH * 2];
8348     CHAR prodcode[MAX_PATH];
8349     CHAR prod_squashed[MAX_PATH];
8350     HKEY prodkey, userprod, props;
8351     LPSTR usersid;
8352     LONG res;
8353     REGSAM access = KEY_ALL_ACCESS;
8354 
8355     create_test_guid(prodcode, prod_squashed);
8356     usersid = get_user_sid();
8357 
8358     if (is_wow64)
8359         access |= KEY_WOW64_64KEY;
8360 
8361     /* NULL szProduct */
8362     INIT_USERINFO();
8363     state = MsiGetUserInfoA(NULL, user, &usersz, org, &orgsz, serial, &serialsz);
8364     ok(state == USERINFOSTATE_INVALIDARG,
8365        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8366     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8367     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8368     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8369     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8370     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8371     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8372 
8373     /* empty szProductCode */
8374     INIT_USERINFO();
8375     state = MsiGetUserInfoA("", user, &usersz, org, &orgsz, serial, &serialsz);
8376     ok(state == USERINFOSTATE_INVALIDARG,
8377        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8378     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8379     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8380     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8381     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8382     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8383     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8384 
8385     /* garbage szProductCode */
8386     INIT_USERINFO();
8387     state = MsiGetUserInfoA("garbage", user, &usersz, org, &orgsz, serial, &serialsz);
8388     ok(state == USERINFOSTATE_INVALIDARG,
8389        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8390     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8391     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8392     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8393     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8394     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8395     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8396 
8397     /* guid without brackets */
8398     INIT_USERINFO();
8399     state = MsiGetUserInfoA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
8400                             user, &usersz, org, &orgsz, serial, &serialsz);
8401     ok(state == USERINFOSTATE_INVALIDARG,
8402        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8403     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8404     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8405     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8406     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8407     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8408     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8409 
8410     /* guid with brackets */
8411     INIT_USERINFO();
8412     state = MsiGetUserInfoA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
8413                             user, &usersz, org, &orgsz, serial, &serialsz);
8414     ok(state == USERINFOSTATE_UNKNOWN,
8415        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8416     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8417     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8418     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8419     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8420     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8421     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8422 
8423     /* NULL lpUserNameBuf */
8424     INIT_USERINFO();
8425     state = MsiGetUserInfoA(prodcode, NULL, &usersz, org, &orgsz, serial, &serialsz);
8426     ok(state == USERINFOSTATE_UNKNOWN,
8427        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8428     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8429     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8430     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8431     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8432     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8433 
8434     /* NULL pcchUserNameBuf */
8435     INIT_USERINFO();
8436     state = MsiGetUserInfoA(prodcode, user, NULL, org, &orgsz, serial, &serialsz);
8437     ok(state == USERINFOSTATE_INVALIDARG,
8438        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8439     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8440     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8441     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8442     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8443     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8444 
8445     /* both lpUserNameBuf and pcchUserNameBuf NULL */
8446     INIT_USERINFO();
8447     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
8448     ok(state == USERINFOSTATE_UNKNOWN,
8449        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8450     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8451     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8452     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8453     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8454 
8455     /* NULL lpOrgNameBuf */
8456     INIT_USERINFO();
8457     state = MsiGetUserInfoA(prodcode, user, &usersz, NULL, &orgsz, serial, &serialsz);
8458     ok(state == USERINFOSTATE_UNKNOWN,
8459        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8460     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8461     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8462     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8463     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8464     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8465 
8466     /* NULL pcchOrgNameBuf */
8467     INIT_USERINFO();
8468     state = MsiGetUserInfoA(prodcode, user, &usersz, org, NULL, serial, &serialsz);
8469     ok(state == USERINFOSTATE_INVALIDARG,
8470        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8471     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8472     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8473     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8474     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8475     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8476 
8477     /* both lpOrgNameBuf and pcchOrgNameBuf NULL */
8478     INIT_USERINFO();
8479     state = MsiGetUserInfoA(prodcode, user, &usersz, NULL, NULL, serial, &serialsz);
8480     ok(state == USERINFOSTATE_UNKNOWN,
8481        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8482     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8483     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8484     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8485     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8486 
8487     /* NULL lpSerialBuf */
8488     INIT_USERINFO();
8489     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, NULL, &serialsz);
8490     ok(state == USERINFOSTATE_UNKNOWN,
8491        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8492     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8493     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8494     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8495     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8496     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8497 
8498     /* NULL pcchSerialBuf */
8499     INIT_USERINFO();
8500     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, NULL);
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 %d\n", usersz);
8507     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8508 
8509     /* both lpSerialBuf and pcchSerialBuf NULL */
8510     INIT_USERINFO();
8511     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, NULL, NULL);
8512     ok(state == USERINFOSTATE_UNKNOWN,
8513        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8514     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8515     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8516     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8517     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8518 
8519     /* MSIINSTALLCONTEXT_USERMANAGED */
8520 
8521     /* create local system product key */
8522     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
8523     lstrcatA(keypath, usersid);
8524     lstrcatA(keypath, "\\Installer\\Products\\");
8525     lstrcatA(keypath, prod_squashed);
8526 
8527     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8528     if (res == ERROR_ACCESS_DENIED)
8529     {
8530         skip("Not enough rights to perform tests\n");
8531         LocalFree(usersid);
8532         return;
8533     }
8534     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8535 
8536     /* managed product key exists */
8537     INIT_USERINFO();
8538     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8539     ok(state == USERINFOSTATE_ABSENT,
8540        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8541     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8542     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8543     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8544     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8545     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8546     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8547 
8548     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8549     lstrcatA(keypath, "Installer\\UserData\\");
8550     lstrcatA(keypath, usersid);
8551     lstrcatA(keypath, "\\Products\\");
8552     lstrcatA(keypath, prod_squashed);
8553 
8554     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL);
8555     if (res == ERROR_ACCESS_DENIED)
8556     {
8557         skip("Not enough rights to perform tests\n");
8558         LocalFree(usersid);
8559         return;
8560     }
8561     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8562 
8563     res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8564     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8565 
8566     /* InstallProperties key exists */
8567     INIT_USERINFO();
8568     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8569     ok(state == USERINFOSTATE_ABSENT,
8570        "Expected USERINFOSTATE_ABSENT, 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 - 1, "Expected MAX_PATH - 1, got %d\n", usersz);
8575     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8576     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8577 
8578     /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */
8579     INIT_USERINFO();
8580     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
8581     ok(state == USERINFOSTATE_ABSENT,
8582        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8583     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
8584     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8585     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
8586     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
8587 
8588     /* RegOwner, RegCompany don't exist, out params are NULL */
8589     INIT_USERINFO();
8590     state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz);
8591     ok(state == USERINFOSTATE_ABSENT,
8592        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8593     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8594     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
8595 
8596     res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
8597     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8598 
8599     /* RegOwner value exists */
8600     INIT_USERINFO();
8601     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8602     ok(state == USERINFOSTATE_ABSENT,
8603        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8604     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8605     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
8606     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8607     ok(usersz == 5, "Expected 5, got %d\n", usersz);
8608     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
8609     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
8610 
8611     res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8);
8612     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8613 
8614     /* RegCompany value exists */
8615     INIT_USERINFO();
8616     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8617     ok(state == USERINFOSTATE_ABSENT,
8618        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8619     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8620     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8621     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8622     ok(usersz == 5, "Expected 5, got %d\n", usersz);
8623     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
8624     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
8625 
8626     res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3);
8627     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8628 
8629     /* ProductID value exists */
8630     INIT_USERINFO();
8631     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8632     ok(state == USERINFOSTATE_PRESENT,
8633        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
8634     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8635     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8636     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
8637     ok(usersz == 5, "Expected 5, got %d\n", usersz);
8638     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
8639     ok(serialsz == 2, "Expected 2, got %d\n", serialsz);
8640 
8641     /* pcchUserNameBuf is too small */
8642     INIT_USERINFO();
8643     usersz = 0;
8644     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8645     ok(state == USERINFOSTATE_MOREDATA,
8646        "Expected USERINFOSTATE_MOREDATA, got %d\n", state);
8647     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8648     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8649     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8650     ok(usersz == 5, "Expected 5, got %d\n", usersz);
8651     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8652     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8653 
8654     /* pcchUserNameBuf has no room for NULL terminator */
8655     INIT_USERINFO();
8656     usersz = 5;
8657     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8658     ok(state == USERINFOSTATE_MOREDATA,
8659        "Expected USERINFOSTATE_MOREDATA, got %d\n", state);
8660     todo_wine
8661     {
8662         ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8663     }
8664     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8665     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8666     ok(usersz == 5, "Expected 5, got %d\n", usersz);
8667     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8668     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8669 
8670     /* pcchUserNameBuf is too small, lpUserNameBuf is NULL */
8671     INIT_USERINFO();
8672     usersz = 0;
8673     state = MsiGetUserInfoA(prodcode, NULL, &usersz, org, &orgsz, serial, &serialsz);
8674     ok(state == USERINFOSTATE_PRESENT,
8675        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
8676     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8677     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8678     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
8679     ok(usersz == 5, "Expected 5, got %d\n", usersz);
8680     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
8681     ok(serialsz == 2, "Expected 2, got %d\n", serialsz);
8682 
8683     RegDeleteValueA(props, "ProductID");
8684     RegDeleteValueA(props, "RegCompany");
8685     RegDeleteValueA(props, "RegOwner");
8686     delete_key(props, "", access & KEY_WOW64_64KEY);
8687     RegCloseKey(props);
8688     delete_key(userprod, "", access & KEY_WOW64_64KEY);
8689     RegCloseKey(userprod);
8690     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
8691     RegCloseKey(prodkey);
8692 
8693     /* MSIINSTALLCONTEXT_USERUNMANAGED */
8694 
8695     /* create local system product key */
8696     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
8697     lstrcatA(keypath, prod_squashed);
8698 
8699     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
8700     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8701 
8702     /* product key exists */
8703     INIT_USERINFO();
8704     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8705     ok(state == USERINFOSTATE_ABSENT,
8706        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8707     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8708     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8709     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8710     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8711     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8712     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8713 
8714     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8715     lstrcatA(keypath, "Installer\\UserData\\");
8716     lstrcatA(keypath, usersid);
8717     lstrcatA(keypath, "\\Products\\");
8718     lstrcatA(keypath, prod_squashed);
8719 
8720     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL);
8721     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8722 
8723     res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8724     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8725 
8726     /* InstallProperties key exists */
8727     INIT_USERINFO();
8728     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8729     ok(state == USERINFOSTATE_ABSENT,
8730        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8731     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8732     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8733     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8734     ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", usersz);
8735     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8736     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8737 
8738     /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */
8739     INIT_USERINFO();
8740     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
8741     ok(state == USERINFOSTATE_ABSENT,
8742        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8743     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
8744     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8745     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
8746     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
8747 
8748     /* RegOwner, RegCompany don't exist, out params are NULL */
8749     INIT_USERINFO();
8750     state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz);
8751     ok(state == USERINFOSTATE_ABSENT,
8752        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8753     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8754     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
8755 
8756     res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
8757     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8758 
8759     /* RegOwner value exists */
8760     INIT_USERINFO();
8761     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8762     ok(state == USERINFOSTATE_ABSENT,
8763        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8764     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8765     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
8766     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8767     ok(usersz == 5, "Expected 5, got %d\n", usersz);
8768     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
8769     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
8770 
8771     res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8);
8772     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8773 
8774     /* RegCompany value exists */
8775     INIT_USERINFO();
8776     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8777     ok(state == USERINFOSTATE_ABSENT,
8778        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8779     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8780     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8781     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8782     ok(usersz == 5, "Expected 5, got %d\n", usersz);
8783     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
8784     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
8785 
8786     res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3);
8787     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8788 
8789     /* ProductID value exists */
8790     INIT_USERINFO();
8791     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8792     ok(state == USERINFOSTATE_PRESENT,
8793        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
8794     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8795     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8796     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
8797     ok(usersz == 5, "Expected 5, got %d\n", usersz);
8798     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
8799     ok(serialsz == 2, "Expected 2, got %d\n", serialsz);
8800 
8801     RegDeleteValueA(props, "ProductID");
8802     RegDeleteValueA(props, "RegCompany");
8803     RegDeleteValueA(props, "RegOwner");
8804     delete_key(props, "", access & KEY_WOW64_64KEY);
8805     RegCloseKey(props);
8806     delete_key(userprod, "", access & KEY_WOW64_64KEY);
8807     RegCloseKey(userprod);
8808     RegDeleteKeyA(prodkey, "");
8809     RegCloseKey(prodkey);
8810 
8811     /* MSIINSTALLCONTEXT_MACHINE */
8812 
8813     /* create local system product key */
8814     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
8815     lstrcatA(keypath, prod_squashed);
8816 
8817     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8818     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8819 
8820     /* product key exists */
8821     INIT_USERINFO();
8822     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8823     ok(state == USERINFOSTATE_ABSENT,
8824        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8825     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8826     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8827     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8828     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8829     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8830     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8831 
8832     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8833     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18");
8834     lstrcatA(keypath, "\\Products\\");
8835     lstrcatA(keypath, prod_squashed);
8836 
8837     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL);
8838     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8839 
8840     res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8841     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8842 
8843     /* InstallProperties key exists */
8844     INIT_USERINFO();
8845     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8846     ok(state == USERINFOSTATE_ABSENT,
8847        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8848     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8849     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8850     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8851     ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", usersz);
8852     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8853     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8854 
8855     /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */
8856     INIT_USERINFO();
8857     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
8858     ok(state == USERINFOSTATE_ABSENT,
8859        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8860     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
8861     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8862     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
8863     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
8864 
8865     /* RegOwner, RegCompany don't exist, out params are NULL */
8866     INIT_USERINFO();
8867     state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz);
8868     ok(state == USERINFOSTATE_ABSENT,
8869        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8870     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8871     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
8872 
8873     res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
8874     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8875 
8876     /* RegOwner value exists */
8877     INIT_USERINFO();
8878     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8879     ok(state == USERINFOSTATE_ABSENT,
8880        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8881     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8882     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
8883     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8884     ok(usersz == 5, "Expected 5, got %d\n", usersz);
8885     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
8886     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
8887 
8888     res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8);
8889     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8890 
8891     /* RegCompany value exists */
8892     INIT_USERINFO();
8893     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8894     ok(state == USERINFOSTATE_ABSENT,
8895        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8896     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8897     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8898     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8899     ok(usersz == 5, "Expected 5, got %d\n", usersz);
8900     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
8901     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
8902 
8903     res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3);
8904     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8905 
8906     /* ProductID value exists */
8907     INIT_USERINFO();
8908     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8909     ok(state == USERINFOSTATE_PRESENT,
8910        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
8911     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8912     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8913     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
8914     ok(usersz == 5, "Expected 5, got %d\n", usersz);
8915     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
8916     ok(serialsz == 2, "Expected 2, got %d\n", serialsz);
8917 
8918     RegDeleteValueA(props, "ProductID");
8919     RegDeleteValueA(props, "RegCompany");
8920     RegDeleteValueA(props, "RegOwner");
8921     delete_key(props, "", access & KEY_WOW64_64KEY);
8922     RegCloseKey(props);
8923     delete_key(userprod, "", access & KEY_WOW64_64KEY);
8924     RegCloseKey(userprod);
8925     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
8926     RegCloseKey(prodkey);
8927     LocalFree(usersid);
8928 }
8929 
8930 static void test_MsiOpenProduct(void)
8931 {
8932     MSIHANDLE hprod, hdb;
8933     CHAR val[MAX_PATH];
8934     CHAR path[MAX_PATH];
8935     CHAR keypath[MAX_PATH*2];
8936     CHAR prodcode[MAX_PATH];
8937     CHAR prod_squashed[MAX_PATH];
8938     HKEY prodkey, userkey, props;
8939     LPSTR usersid;
8940     DWORD size;
8941     LONG res;
8942     UINT r;
8943     REGSAM access = KEY_ALL_ACCESS;
8944 
8945     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
8946 
8947     GetCurrentDirectoryA(MAX_PATH, path);
8948     lstrcatA(path, "\\");
8949 
8950     create_test_guid(prodcode, prod_squashed);
8951     usersid = get_user_sid();
8952 
8953     if (is_wow64)
8954         access |= KEY_WOW64_64KEY;
8955 
8956     hdb = create_package_db(prodcode);
8957     MsiCloseHandle(hdb);
8958 
8959     /* NULL szProduct */
8960     hprod = 0xdeadbeef;
8961     r = MsiOpenProductA(NULL, &hprod);
8962     ok(r == ERROR_INVALID_PARAMETER,
8963        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8964     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8965 
8966     /* empty szProduct */
8967     hprod = 0xdeadbeef;
8968     r = MsiOpenProductA("", &hprod);
8969     ok(r == ERROR_INVALID_PARAMETER,
8970        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8971     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8972 
8973     /* garbage szProduct */
8974     hprod = 0xdeadbeef;
8975     r = MsiOpenProductA("garbage", &hprod);
8976     ok(r == ERROR_INVALID_PARAMETER,
8977        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8978     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8979 
8980     /* guid without brackets */
8981     hprod = 0xdeadbeef;
8982     r = MsiOpenProductA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", &hprod);
8983     ok(r == ERROR_INVALID_PARAMETER,
8984        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8985     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8986 
8987     /* guid with brackets */
8988     hprod = 0xdeadbeef;
8989     r = MsiOpenProductA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", &hprod);
8990     ok(r == ERROR_UNKNOWN_PRODUCT,
8991        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8992     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8993 
8994     /* same length as guid, but random */
8995     hprod = 0xdeadbeef;
8996     r = MsiOpenProductA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", &hprod);
8997     ok(r == ERROR_INVALID_PARAMETER,
8998        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8999     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9000 
9001     /* hProduct is NULL */
9002     hprod = 0xdeadbeef;
9003     r = MsiOpenProductA(prodcode, NULL);
9004     ok(r == ERROR_INVALID_PARAMETER,
9005        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9006     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9007 
9008     /* MSIINSTALLCONTEXT_USERMANAGED */
9009 
9010     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9011     lstrcatA(keypath, "Installer\\Managed\\");
9012     lstrcatA(keypath, usersid);
9013     lstrcatA(keypath, "\\Installer\\Products\\");
9014     lstrcatA(keypath, prod_squashed);
9015 
9016     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
9017     if (res == ERROR_ACCESS_DENIED)
9018     {
9019         skip("Not enough rights to perform tests\n");
9020         LocalFree(usersid);
9021         return;
9022     }
9023     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9024 
9025     /* managed product key exists */
9026     hprod = 0xdeadbeef;
9027     r = MsiOpenProductA(prodcode, &hprod);
9028     ok(r == ERROR_UNKNOWN_PRODUCT,
9029        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9030     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9031 
9032     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9033     lstrcatA(keypath, "Installer\\UserData\\");
9034     lstrcatA(keypath, usersid);
9035     lstrcatA(keypath, "\\Products\\");
9036     lstrcatA(keypath, prod_squashed);
9037 
9038     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
9039     if (res == ERROR_ACCESS_DENIED)
9040     {
9041         skip("Not enough rights to perform tests\n");
9042         LocalFree(usersid);
9043         return;
9044     }
9045     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9046 
9047     /* user product key exists */
9048     hprod = 0xdeadbeef;
9049     r = MsiOpenProductA(prodcode, &hprod);
9050     ok(r == ERROR_UNKNOWN_PRODUCT,
9051        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9052     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9053 
9054     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9055     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9056 
9057     /* InstallProperties key exists */
9058     hprod = 0xdeadbeef;
9059     r = MsiOpenProductA(prodcode, &hprod);
9060     ok(r == ERROR_UNKNOWN_PRODUCT,
9061        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9062     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9063 
9064     lstrcpyA(val, path);
9065     lstrcatA(val, "\\winetest.msi");
9066     res = RegSetValueExA(props, "ManagedLocalPackage", 0, REG_SZ,
9067                          (const BYTE *)val, lstrlenA(val) + 1);
9068     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9069 
9070     /* ManagedLocalPackage value exists */
9071     hprod = 0xdeadbeef;
9072     r = MsiOpenProductA(prodcode, &hprod);
9073     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9074     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
9075 
9076     size = MAX_PATH;
9077     r = MsiGetPropertyA(hprod, "ProductCode", val, &size);
9078     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9079     ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val);
9080     ok(size == lstrlenA(prodcode), "Expected %d, got %d\n", lstrlenA(prodcode), size);
9081 
9082     MsiCloseHandle(hprod);
9083 
9084     RegDeleteValueA(props, "ManagedLocalPackage");
9085     delete_key(props, "", access & KEY_WOW64_64KEY);
9086     RegCloseKey(props);
9087     delete_key(userkey, "", access & KEY_WOW64_64KEY);
9088     RegCloseKey(userkey);
9089     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
9090     RegCloseKey(prodkey);
9091 
9092     /* MSIINSTALLCONTEXT_USERUNMANAGED */
9093 
9094     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
9095     lstrcatA(keypath, prod_squashed);
9096 
9097     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
9098     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9099 
9100     /* unmanaged product key exists */
9101     hprod = 0xdeadbeef;
9102     r = MsiOpenProductA(prodcode, &hprod);
9103     ok(r == ERROR_UNKNOWN_PRODUCT,
9104        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9105     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9106 
9107     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9108     lstrcatA(keypath, "Installer\\UserData\\");
9109     lstrcatA(keypath, usersid);
9110     lstrcatA(keypath, "\\Products\\");
9111     lstrcatA(keypath, prod_squashed);
9112 
9113     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
9114     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9115 
9116     /* user product key exists */
9117     hprod = 0xdeadbeef;
9118     r = MsiOpenProductA(prodcode, &hprod);
9119     ok(r == ERROR_UNKNOWN_PRODUCT,
9120        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9121     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9122 
9123     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9124     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9125 
9126     /* InstallProperties key exists */
9127     hprod = 0xdeadbeef;
9128     r = MsiOpenProductA(prodcode, &hprod);
9129     ok(r == ERROR_UNKNOWN_PRODUCT,
9130        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9131     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9132 
9133     lstrcpyA(val, path);
9134     lstrcatA(val, "\\winetest.msi");
9135     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
9136                          (const BYTE *)val, lstrlenA(val) + 1);
9137     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9138 
9139     /* LocalPackage value exists */
9140     hprod = 0xdeadbeef;
9141     r = MsiOpenProductA(prodcode, &hprod);
9142     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9143     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
9144 
9145     size = MAX_PATH;
9146     r = MsiGetPropertyA(hprod, "ProductCode", val, &size);
9147     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9148     ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val);
9149     ok(size == lstrlenA(prodcode), "Expected %d, got %d\n", lstrlenA(prodcode), size);
9150 
9151     MsiCloseHandle(hprod);
9152 
9153     RegDeleteValueA(props, "LocalPackage");
9154     delete_key(props, "", access & KEY_WOW64_64KEY);
9155     RegCloseKey(props);
9156     delete_key(userkey, "", access & KEY_WOW64_64KEY);
9157     RegCloseKey(userkey);
9158     RegDeleteKeyA(prodkey, "");
9159     RegCloseKey(prodkey);
9160 
9161     /* MSIINSTALLCONTEXT_MACHINE */
9162 
9163     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
9164     lstrcatA(keypath, prod_squashed);
9165 
9166     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
9167     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9168 
9169     /* managed product key exists */
9170     hprod = 0xdeadbeef;
9171     r = MsiOpenProductA(prodcode, &hprod);
9172     ok(r == ERROR_UNKNOWN_PRODUCT,
9173        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9174     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9175 
9176     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9177     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
9178     lstrcatA(keypath, prod_squashed);
9179 
9180     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
9181     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9182 
9183     /* user product key exists */
9184     hprod = 0xdeadbeef;
9185     r = MsiOpenProductA(prodcode, &hprod);
9186     ok(r == ERROR_UNKNOWN_PRODUCT,
9187        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9188     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9189 
9190     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9191     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9192 
9193     /* InstallProperties key exists */
9194     hprod = 0xdeadbeef;
9195     r = MsiOpenProductA(prodcode, &hprod);
9196     ok(r == ERROR_UNKNOWN_PRODUCT,
9197        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9198     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9199 
9200     lstrcpyA(val, path);
9201     lstrcatA(val, "\\winetest.msi");
9202     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
9203                          (const BYTE *)val, lstrlenA(val) + 1);
9204     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9205 
9206     /* LocalPackage value exists */
9207     hprod = 0xdeadbeef;
9208     r = MsiOpenProductA(prodcode, &hprod);
9209     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9210     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
9211 
9212     size = MAX_PATH;
9213     r = MsiGetPropertyA(hprod, "ProductCode", val, &size);
9214     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9215     ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val);
9216     ok(size == lstrlenA(prodcode), "Expected %d, got %d\n", lstrlenA(prodcode), size);
9217 
9218     MsiCloseHandle(hprod);
9219 
9220     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
9221                          (const BYTE *)"winetest.msi", 13);
9222     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9223 
9224     lstrcpyA(val, path);
9225     lstrcatA(val, "\\winetest.msi");
9226     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
9227                          (const BYTE *)val, lstrlenA(val) + 1);
9228     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9229 
9230     DeleteFileA(msifile);
9231 
9232     /* local package does not exist */
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     RegDeleteValueA(props, "LocalPackage");
9240     delete_key(props, "", access & KEY_WOW64_64KEY);
9241     RegCloseKey(props);
9242     delete_key(userkey, "", access & KEY_WOW64_64KEY);
9243     RegCloseKey(userkey);
9244     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
9245     RegCloseKey(prodkey);
9246 
9247     DeleteFileA(msifile);
9248     LocalFree(usersid);
9249 }
9250 
9251 static void test_MsiEnumPatchesEx_usermanaged(LPCSTR usersid, LPCSTR expectedsid)
9252 {
9253     MSIINSTALLCONTEXT context;
9254     CHAR keypath[MAX_PATH], patch[MAX_PATH];
9255     CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
9256     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
9257     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
9258     HKEY prodkey, patches, udprod, udpatch, hpatch;
9259     DWORD size, data;
9260     LONG res;
9261     UINT r;
9262     REGSAM access = KEY_ALL_ACCESS;
9263 
9264     create_test_guid(prodcode, prod_squashed);
9265     create_test_guid(patch, patch_squashed);
9266 
9267     if (is_wow64)
9268         access |= KEY_WOW64_64KEY;
9269 
9270     /* MSIPATCHSTATE_APPLIED */
9271 
9272     lstrcpyA(patchcode, "apple");
9273     lstrcpyA(targetprod, "banana");
9274     context = 0xdeadbeef;
9275     lstrcpyA(targetsid, "kiwi");
9276     size = MAX_PATH;
9277     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9278                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9279                            &context, targetsid, &size);
9280     if (r == ERROR_ACCESS_DENIED)
9281     {
9282         skip("Not enough rights to perform tests\n");
9283         return;
9284     }
9285     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9286     ok(!lstrcmpA(patchcode, "apple"),
9287        "Expected patchcode to be unchanged, got %s\n", patchcode);
9288     ok(!lstrcmpA(targetprod, "banana"),
9289        "Expected targetprod to be unchanged, got %s\n", targetprod);
9290     ok(context == 0xdeadbeef,
9291        "Expected context to be unchanged, got %d\n", context);
9292     ok(!lstrcmpA(targetsid, "kiwi"),
9293        "Expected targetsid to be unchanged, got %s\n", targetsid);
9294     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9295 
9296     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
9297     lstrcatA(keypath, expectedsid);
9298     lstrcatA(keypath, "\\Installer\\Products\\");
9299     lstrcatA(keypath, prod_squashed);
9300 
9301     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
9302     if (res == ERROR_ACCESS_DENIED)
9303     {
9304         skip("Not enough rights to perform tests\n");
9305         return;
9306     }
9307     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9308 
9309     /* managed product key exists */
9310     lstrcpyA(patchcode, "apple");
9311     lstrcpyA(targetprod, "banana");
9312     context = 0xdeadbeef;
9313     lstrcpyA(targetsid, "kiwi");
9314     size = MAX_PATH;
9315     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9316                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9317                            &context, targetsid, &size);
9318     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9319     ok(!lstrcmpA(patchcode, "apple"),
9320        "Expected patchcode to be unchanged, got %s\n", patchcode);
9321     ok(!lstrcmpA(targetprod, "banana"),
9322        "Expected targetprod to be unchanged, got %s\n", targetprod);
9323     ok(context == 0xdeadbeef,
9324        "Expected context to be unchanged, got %d\n", context);
9325     ok(!lstrcmpA(targetsid, "kiwi"),
9326        "Expected targetsid to be unchanged, got %s\n", targetsid);
9327     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9328 
9329     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
9330     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9331 
9332     /* patches key exists */
9333     lstrcpyA(patchcode, "apple");
9334     lstrcpyA(targetprod, "banana");
9335     context = 0xdeadbeef;
9336     lstrcpyA(targetsid, "kiwi");
9337     size = MAX_PATH;
9338     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9339                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9340                            &context, targetsid, &size);
9341     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9342     ok(!lstrcmpA(patchcode, "apple"),
9343        "Expected patchcode to be unchanged, got %s\n", patchcode);
9344     ok(!lstrcmpA(targetprod, "banana"),
9345        "Expected targetprod to be unchanged, got %s\n", targetprod);
9346     ok(context == 0xdeadbeef,
9347        "Expected context to be unchanged, got %d\n", context);
9348     ok(!lstrcmpA(targetsid, "kiwi"),
9349        "Expected targetsid to be unchanged, got %s\n", targetsid);
9350     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9351 
9352     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
9353                          (const BYTE *)patch_squashed,
9354                          lstrlenA(patch_squashed) + 1);
9355     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9356 
9357     /* Patches value exists, is not REG_MULTI_SZ */
9358     lstrcpyA(patchcode, "apple");
9359     lstrcpyA(targetprod, "banana");
9360     context = 0xdeadbeef;
9361     lstrcpyA(targetsid, "kiwi");
9362     size = MAX_PATH;
9363     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9364                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9365                            &context, targetsid, &size);
9366     ok(r == ERROR_BAD_CONFIGURATION,
9367        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9368     ok(!lstrcmpA(patchcode, "apple"),
9369        "Expected patchcode to be unchanged, got %s\n", patchcode);
9370     ok(!lstrcmpA(targetprod, "banana"),
9371        "Expected targetprod to be unchanged, got %s\n", targetprod);
9372     ok(context == 0xdeadbeef,
9373        "Expected context to be unchanged, got %d\n", context);
9374     ok(!lstrcmpA(targetsid, "kiwi"),
9375        "Expected targetsid to be unchanged, got %s\n", targetsid);
9376     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9377 
9378     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
9379                          (const BYTE *)"a\0b\0c\0\0", 7);
9380     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9381 
9382     /* Patches value exists, is not a squashed guid */
9383     lstrcpyA(patchcode, "apple");
9384     lstrcpyA(targetprod, "banana");
9385     context = 0xdeadbeef;
9386     lstrcpyA(targetsid, "kiwi");
9387     size = MAX_PATH;
9388     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9389                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9390                            &context, targetsid, &size);
9391     ok(r == ERROR_BAD_CONFIGURATION,
9392        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9393     ok(!lstrcmpA(patchcode, "apple"),
9394        "Expected patchcode to be unchanged, got %s\n", patchcode);
9395     ok(!lstrcmpA(targetprod, "banana"),
9396        "Expected targetprod to be unchanged, got %s\n", targetprod);
9397     ok(context == 0xdeadbeef,
9398        "Expected context to be unchanged, got %d\n", context);
9399     ok(!lstrcmpA(targetsid, "kiwi"),
9400        "Expected targetsid to be unchanged, got %s\n", targetsid);
9401     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9402 
9403     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
9404     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
9405                          (const BYTE *)patch_squashed,
9406                          lstrlenA(patch_squashed) + 2);
9407     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9408 
9409     /* Patches value exists */
9410     lstrcpyA(patchcode, "apple");
9411     lstrcpyA(targetprod, "banana");
9412     context = 0xdeadbeef;
9413     lstrcpyA(targetsid, "kiwi");
9414     size = MAX_PATH;
9415     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9416                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9417                            &context, targetsid, &size);
9418     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9419     ok(!lstrcmpA(patchcode, "apple"),
9420        "Expected patchcode to be unchanged, got %s\n", patchcode);
9421     ok(!lstrcmpA(targetprod, "banana"),
9422        "Expected targetprod to be unchanged, got %s\n", targetprod);
9423     ok(context == 0xdeadbeef,
9424        "Expected context to be unchanged, got %d\n", context);
9425     ok(!lstrcmpA(targetsid, "kiwi"),
9426        "Expected targetsid to be unchanged, got %s\n", targetsid);
9427     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9428 
9429     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
9430                          (const BYTE *)"whatever", 9);
9431     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9432 
9433     /* patch squashed value exists */
9434     lstrcpyA(patchcode, "apple");
9435     lstrcpyA(targetprod, "banana");
9436     context = 0xdeadbeef;
9437     lstrcpyA(targetsid, "kiwi");
9438     size = MAX_PATH;
9439     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9440                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9441                            &context, targetsid, &size);
9442     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9443     ok(!lstrcmpA(patchcode, patch),
9444        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9445     ok(!lstrcmpA(targetprod, prodcode),
9446        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9447     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9448        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9449     ok(!lstrcmpA(targetsid, expectedsid),
9450        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9451     ok(size == lstrlenA(expectedsid),
9452        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9453 
9454     /* increase the index */
9455     lstrcpyA(patchcode, "apple");
9456     lstrcpyA(targetprod, "banana");
9457     context = 0xdeadbeef;
9458     lstrcpyA(targetsid, "kiwi");
9459     size = MAX_PATH;
9460     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9461                            MSIPATCHSTATE_APPLIED, 1, patchcode, targetprod,
9462                            &context, targetsid, &size);
9463     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9464     ok(!lstrcmpA(patchcode, "apple"),
9465        "Expected patchcode to be unchanged, got %s\n", patchcode);
9466     ok(!lstrcmpA(targetprod, "banana"),
9467        "Expected targetprod to be unchanged, got %s\n", targetprod);
9468     ok(context == 0xdeadbeef,
9469        "Expected context to be unchanged, got %d\n", context);
9470     ok(!lstrcmpA(targetsid, "kiwi"),
9471        "Expected targetsid to be unchanged, got %s\n", targetsid);
9472     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9473 
9474     /* increase again */
9475     lstrcpyA(patchcode, "apple");
9476     lstrcpyA(targetprod, "banana");
9477     context = 0xdeadbeef;
9478     lstrcpyA(targetsid, "kiwi");
9479     size = MAX_PATH;
9480     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9481                            MSIPATCHSTATE_APPLIED, 2, patchcode, targetprod,
9482                            &context, targetsid, &size);
9483     ok(r == ERROR_INVALID_PARAMETER,
9484        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9485     ok(!lstrcmpA(patchcode, "apple"),
9486        "Expected patchcode to be unchanged, got %s\n", patchcode);
9487     ok(!lstrcmpA(targetprod, "banana"),
9488        "Expected targetprod to be unchanged, got %s\n", targetprod);
9489     ok(context == 0xdeadbeef,
9490        "Expected context to be unchanged, got %d\n", context);
9491     ok(!lstrcmpA(targetsid, "kiwi"),
9492        "Expected targetsid to be unchanged, got %s\n", targetsid);
9493     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9494 
9495     /* szPatchCode is NULL */
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, NULL, targetprod,
9502                            &context, targetsid, &size);
9503     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9504     ok(!lstrcmpA(targetprod, prodcode),
9505        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9506     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9507        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9508     ok(!lstrcmpA(targetsid, expectedsid),
9509        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9510     ok(size == lstrlenA(expectedsid),
9511        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9512 
9513     /* szTargetProductCode is NULL */
9514     lstrcpyA(patchcode, "apple");
9515     context = 0xdeadbeef;
9516     lstrcpyA(targetsid, "kiwi");
9517     size = MAX_PATH;
9518     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9519                            MSIPATCHSTATE_APPLIED, 0, patchcode, NULL,
9520                            &context, targetsid, &size);
9521     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9522     ok(!lstrcmpA(patchcode, patch),
9523        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9524     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9525        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9526     ok(!lstrcmpA(targetsid, expectedsid),
9527        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9528     ok(size == lstrlenA(expectedsid),
9529        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9530 
9531     /* pdwTargetProductContext is NULL */
9532     lstrcpyA(patchcode, "apple");
9533     lstrcpyA(targetprod, "banana");
9534     lstrcpyA(targetsid, "kiwi");
9535     size = MAX_PATH;
9536     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9537                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9538                            NULL, targetsid, &size);
9539     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9540     ok(!lstrcmpA(patchcode, patch),
9541        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9542     ok(!lstrcmpA(targetprod, prodcode),
9543        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9544     ok(!lstrcmpA(targetsid, expectedsid),
9545        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9546     ok(size == lstrlenA(expectedsid),
9547        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9548 
9549     /* szTargetUserSid is NULL */
9550     lstrcpyA(patchcode, "apple");
9551     lstrcpyA(targetprod, "banana");
9552     context = 0xdeadbeef;
9553     size = MAX_PATH;
9554     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9555                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9556                            &context, NULL, &size);
9557     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9558     ok(!lstrcmpA(patchcode, patch),
9559        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9560     ok(!lstrcmpA(targetprod, prodcode),
9561        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9562     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9563        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9564     ok(size == lstrlenA(expectedsid) * sizeof(WCHAR),
9565        "Expected %d*sizeof(WCHAR), got %d\n", lstrlenA(expectedsid), size);
9566 
9567     /* pcchTargetUserSid is exactly the length of szTargetUserSid */
9568     lstrcpyA(patchcode, "apple");
9569     lstrcpyA(targetprod, "banana");
9570     context = 0xdeadbeef;
9571     lstrcpyA(targetsid, "kiwi");
9572     size = lstrlenA(expectedsid);
9573     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9574                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9575                            &context, targetsid, &size);
9576     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
9577     ok(!lstrcmpA(patchcode, patch),
9578        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9579     ok(!lstrcmpA(targetprod, prodcode),
9580        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9581     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9582        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9583     ok(!strncmp(targetsid, expectedsid, lstrlenA(expectedsid) - 1),
9584        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9585     ok(size == lstrlenA(expectedsid) * sizeof(WCHAR),
9586        "Expected %d*sizeof(WCHAR), got %d\n", lstrlenA(expectedsid), size);
9587 
9588     /* pcchTargetUserSid has enough room for NULL terminator */
9589     lstrcpyA(patchcode, "apple");
9590     lstrcpyA(targetprod, "banana");
9591     context = 0xdeadbeef;
9592     lstrcpyA(targetsid, "kiwi");
9593     size = lstrlenA(expectedsid) + 1;
9594     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9595                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9596                            &context, targetsid, &size);
9597     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9598     ok(!lstrcmpA(patchcode, patch),
9599        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9600     ok(!lstrcmpA(targetprod, prodcode),
9601        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9602     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9603        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9604     ok(!lstrcmpA(targetsid, expectedsid),
9605        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9606     ok(size == lstrlenA(expectedsid),
9607        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9608 
9609     /* both szTargetuserSid and pcchTargetUserSid are NULL */
9610     lstrcpyA(patchcode, "apple");
9611     lstrcpyA(targetprod, "banana");
9612     context = 0xdeadbeef;
9613     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9614                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9615                            &context, NULL, NULL);
9616     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9617     ok(!lstrcmpA(patchcode, patch),
9618        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9619     ok(!lstrcmpA(targetprod, prodcode),
9620        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9621     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9622        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9623 
9624     /* MSIPATCHSTATE_SUPERSEDED */
9625 
9626     lstrcpyA(patchcode, "apple");
9627     lstrcpyA(targetprod, "banana");
9628     context = 0xdeadbeef;
9629     lstrcpyA(targetsid, "kiwi");
9630     size = MAX_PATH;
9631     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9632                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
9633                            &context, targetsid, &size);
9634     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9635     ok(!lstrcmpA(patchcode, "apple"),
9636        "Expected patchcode to be unchanged, got %s\n", patchcode);
9637     ok(!lstrcmpA(targetprod, "banana"),
9638        "Expected targetprod to be unchanged, got %s\n", targetprod);
9639     ok(context == 0xdeadbeef,
9640        "Expected context to be unchanged, got %d\n", context);
9641     ok(!lstrcmpA(targetsid, "kiwi"),
9642        "Expected targetsid to be unchanged, got %s\n", targetsid);
9643     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9644 
9645     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
9646     lstrcatA(keypath, expectedsid);
9647     lstrcatA(keypath, "\\Products\\");
9648     lstrcatA(keypath, prod_squashed);
9649 
9650     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
9651     if (res == ERROR_ACCESS_DENIED)
9652     {
9653         skip("Not enough rights to perform tests\n");
9654         return;
9655     }
9656     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9657 
9658     /* UserData product key exists */
9659     lstrcpyA(patchcode, "apple");
9660     lstrcpyA(targetprod, "banana");
9661     context = 0xdeadbeef;
9662     lstrcpyA(targetsid, "kiwi");
9663     size = MAX_PATH;
9664     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9665                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
9666                            &context, targetsid, &size);
9667     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9668     ok(!lstrcmpA(patchcode, "apple"),
9669        "Expected patchcode to be unchanged, got %s\n", patchcode);
9670     ok(!lstrcmpA(targetprod, "banana"),
9671        "Expected targetprod to be unchanged, got %s\n", targetprod);
9672     ok(context == 0xdeadbeef,
9673        "Expected context to be unchanged, got %d\n", context);
9674     ok(!lstrcmpA(targetsid, "kiwi"),
9675        "Expected targetsid to be unchanged, got %s\n", targetsid);
9676     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9677 
9678     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
9679     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9680 
9681     /* UserData patches key exists */
9682     lstrcpyA(patchcode, "apple");
9683     lstrcpyA(targetprod, "banana");
9684     context = 0xdeadbeef;
9685     lstrcpyA(targetsid, "kiwi");
9686     size = MAX_PATH;
9687     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9688                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
9689                            &context, targetsid, &size);
9690     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9691     ok(!lstrcmpA(patchcode, "apple"),
9692        "Expected patchcode to be unchanged, got %s\n", patchcode);
9693     ok(!lstrcmpA(targetprod, "banana"),
9694        "Expected targetprod to be unchanged, got %s\n", targetprod);
9695     ok(context == 0xdeadbeef,
9696        "Expected context to be unchanged, got %d\n", context);
9697     ok(!lstrcmpA(targetsid, "kiwi"),
9698        "Expected targetsid to be unchanged, got %s\n", targetsid);
9699     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9700 
9701     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
9702     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9703 
9704     /* specific UserData patch key exists */
9705     lstrcpyA(patchcode, "apple");
9706     lstrcpyA(targetprod, "banana");
9707     context = 0xdeadbeef;
9708     lstrcpyA(targetsid, "kiwi");
9709     size = MAX_PATH;
9710     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9711                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
9712                            &context, targetsid, &size);
9713     ok(r == ERROR_BAD_CONFIGURATION,
9714        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9715     ok(!lstrcmpA(patchcode, "apple"),
9716        "Expected patchcode to be unchanged, got %s\n", patchcode);
9717     ok(!lstrcmpA(targetprod, "banana"),
9718        "Expected targetprod to be unchanged, got %s\n", targetprod);
9719     ok(context == 0xdeadbeef,
9720        "Expected context to be unchanged, got %d\n", context);
9721     ok(!lstrcmpA(targetsid, "kiwi"),
9722        "Expected targetsid to be unchanged, got %s\n", targetsid);
9723     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9724 
9725     data = MSIPATCHSTATE_SUPERSEDED;
9726     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
9727                          (const BYTE *)&data, sizeof(DWORD));
9728     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9729 
9730     /* State value exists */
9731     lstrcpyA(patchcode, "apple");
9732     lstrcpyA(targetprod, "banana");
9733     context = 0xdeadbeef;
9734     lstrcpyA(targetsid, "kiwi");
9735     size = MAX_PATH;
9736     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9737                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
9738                            &context, targetsid, &size);
9739     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9740     ok(!lstrcmpA(patchcode, patch),
9741        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9742     ok(!lstrcmpA(targetprod, prodcode),
9743        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9744     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9745        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9746     ok(!lstrcmpA(targetsid, expectedsid),
9747        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9748     ok(size == lstrlenA(expectedsid),
9749        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9750 
9751     /* MSIPATCHSTATE_OBSOLETED */
9752 
9753     lstrcpyA(patchcode, "apple");
9754     lstrcpyA(targetprod, "banana");
9755     context = 0xdeadbeef;
9756     lstrcpyA(targetsid, "kiwi");
9757     size = MAX_PATH;
9758     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9759                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
9760                            &context, targetsid, &size);
9761     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9762     ok(!lstrcmpA(patchcode, "apple"),
9763        "Expected patchcode to be unchanged, got %s\n", patchcode);
9764     ok(!lstrcmpA(targetprod, "banana"),
9765        "Expected targetprod to be unchanged, got %s\n", targetprod);
9766     ok(context == 0xdeadbeef,
9767        "Expected context to be unchanged, got %d\n", context);
9768     ok(!lstrcmpA(targetsid, "kiwi"),
9769        "Expected targetsid to be unchanged, got %s\n", targetsid);
9770     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9771 
9772     data = MSIPATCHSTATE_OBSOLETED;
9773     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
9774                          (const BYTE *)&data, sizeof(DWORD));
9775     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9776 
9777     /* State value is obsoleted */
9778     lstrcpyA(patchcode, "apple");
9779     lstrcpyA(targetprod, "banana");
9780     context = 0xdeadbeef;
9781     lstrcpyA(targetsid, "kiwi");
9782     size = MAX_PATH;
9783     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9784                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
9785                            &context, targetsid, &size);
9786     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9787     ok(!lstrcmpA(patchcode, patch),
9788        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9789     ok(!lstrcmpA(targetprod, prodcode),
9790        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9791     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9792        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9793     ok(!lstrcmpA(targetsid, expectedsid),
9794        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9795     ok(size == lstrlenA(expectedsid),
9796        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9797 
9798     /* MSIPATCHSTATE_REGISTERED */
9799     /* FIXME */
9800 
9801     /* MSIPATCHSTATE_ALL */
9802 
9803     /* 1st */
9804     lstrcpyA(patchcode, "apple");
9805     lstrcpyA(targetprod, "banana");
9806     context = 0xdeadbeef;
9807     lstrcpyA(targetsid, "kiwi");
9808     size = MAX_PATH;
9809     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9810                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
9811                            &context, targetsid, &size);
9812     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9813     ok(!lstrcmpA(patchcode, patch),
9814        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9815     ok(!lstrcmpA(targetprod, prodcode),
9816        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9817     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9818        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9819     ok(!lstrcmpA(targetsid, expectedsid),
9820        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9821     ok(size == lstrlenA(expectedsid),
9822        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9823 
9824     /* same patch in multiple places, only one is enumerated */
9825     lstrcpyA(patchcode, "apple");
9826     lstrcpyA(targetprod, "banana");
9827     context = 0xdeadbeef;
9828     lstrcpyA(targetsid, "kiwi");
9829     size = MAX_PATH;
9830     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9831                            MSIPATCHSTATE_ALL, 1, patchcode, targetprod,
9832                            &context, targetsid, &size);
9833     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9834     ok(!lstrcmpA(patchcode, "apple"),
9835        "Expected patchcode to be unchanged, got %s\n", patchcode);
9836     ok(!lstrcmpA(targetprod, "banana"),
9837        "Expected targetprod to be unchanged, got %s\n", targetprod);
9838     ok(context == 0xdeadbeef,
9839        "Expected context to be unchanged, got %d\n", context);
9840     ok(!lstrcmpA(targetsid, "kiwi"),
9841        "Expected targetsid to be unchanged, got %s\n", targetsid);
9842     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9843 
9844     RegDeleteValueA(hpatch, "State");
9845     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
9846     RegCloseKey(hpatch);
9847     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
9848     RegCloseKey(udpatch);
9849     delete_key(udprod, "", access & KEY_WOW64_64KEY);
9850     RegCloseKey(udprod);
9851     RegDeleteValueA(patches, "Patches");
9852     delete_key(patches, "", access & KEY_WOW64_64KEY);
9853     RegCloseKey(patches);
9854     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
9855     RegCloseKey(prodkey);
9856 }
9857 
9858 static void test_MsiEnumPatchesEx_userunmanaged(LPCSTR usersid, LPCSTR expectedsid)
9859 {
9860     MSIINSTALLCONTEXT context;
9861     CHAR keypath[MAX_PATH], patch[MAX_PATH];
9862     CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
9863     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
9864     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
9865     HKEY prodkey, patches, udprod, udpatch;
9866     HKEY userkey, hpatch;
9867     DWORD size, data;
9868     LONG res;
9869     UINT r;
9870     REGSAM access = KEY_ALL_ACCESS;
9871 
9872     create_test_guid(prodcode, prod_squashed);
9873     create_test_guid(patch, patch_squashed);
9874 
9875     if (is_wow64)
9876         access |= KEY_WOW64_64KEY;
9877 
9878     /* MSIPATCHSTATE_APPLIED */
9879 
9880     lstrcpyA(patchcode, "apple");
9881     lstrcpyA(targetprod, "banana");
9882     context = 0xdeadbeef;
9883     lstrcpyA(targetsid, "kiwi");
9884     size = MAX_PATH;
9885     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9886                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9887                            &context, targetsid, &size);
9888     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9889     ok(!lstrcmpA(patchcode, "apple"),
9890        "Expected patchcode to be unchanged, got %s\n", patchcode);
9891     ok(!lstrcmpA(targetprod, "banana"),
9892        "Expected targetprod to be unchanged, got %s\n", targetprod);
9893     ok(context == 0xdeadbeef,
9894        "Expected context to be unchanged, got %d\n", context);
9895     ok(!lstrcmpA(targetsid, "kiwi"),
9896        "Expected targetsid to be unchanged, got %s\n", targetsid);
9897     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9898 
9899     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
9900     lstrcatA(keypath, prod_squashed);
9901 
9902     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
9903     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9904 
9905     /* current user product key exists */
9906     lstrcpyA(patchcode, "apple");
9907     lstrcpyA(targetprod, "banana");
9908     context = 0xdeadbeef;
9909     lstrcpyA(targetsid, "kiwi");
9910     size = MAX_PATH;
9911     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9912                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9913                            &context, targetsid, &size);
9914     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9915     ok(!lstrcmpA(patchcode, "apple"),
9916        "Expected patchcode to be unchanged, got %s\n", patchcode);
9917     ok(!lstrcmpA(targetprod, "banana"),
9918        "Expected targetprod to be unchanged, got %s\n", targetprod);
9919     ok(context == 0xdeadbeef,
9920        "Expected context to be unchanged, got %d\n", context);
9921     ok(!lstrcmpA(targetsid, "kiwi"),
9922        "Expected targetsid to be unchanged, got %s\n", targetsid);
9923     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9924 
9925     res = RegCreateKeyA(prodkey, "Patches", &patches);
9926     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9927 
9928     /* Patches key exists */
9929     lstrcpyA(patchcode, "apple");
9930     lstrcpyA(targetprod, "banana");
9931     context = 0xdeadbeef;
9932     lstrcpyA(targetsid, "kiwi");
9933     size = MAX_PATH;
9934     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9935                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9936                            &context, targetsid, &size);
9937     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9938     ok(!lstrcmpA(patchcode, "apple"),
9939        "Expected patchcode to be unchanged, got %s\n", patchcode);
9940     ok(!lstrcmpA(targetprod, "banana"),
9941        "Expected targetprod to be unchanged, got %s\n", targetprod);
9942     ok(context == 0xdeadbeef,
9943        "Expected context to be unchanged, got %d\n", context);
9944     ok(!lstrcmpA(targetsid, "kiwi"),
9945        "Expected targetsid to be unchanged, got %s\n", targetsid);
9946     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9947 
9948     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
9949                          (const BYTE *)patch_squashed,
9950                          lstrlenA(patch_squashed) + 1);
9951     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9952 
9953     /* Patches value exists, is not REG_MULTI_SZ */
9954     lstrcpyA(patchcode, "apple");
9955     lstrcpyA(targetprod, "banana");
9956     context = 0xdeadbeef;
9957     lstrcpyA(targetsid, "kiwi");
9958     size = MAX_PATH;
9959     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9960                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9961                            &context, targetsid, &size);
9962     ok(r == ERROR_BAD_CONFIGURATION,
9963        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9964     ok(!lstrcmpA(patchcode, "apple"),
9965        "Expected patchcode to be unchanged, got %s\n", patchcode);
9966     ok(!lstrcmpA(targetprod, "banana"),
9967        "Expected targetprod to be unchanged, got %s\n", targetprod);
9968     ok(context == 0xdeadbeef,
9969        "Expected context to be unchanged, got %d\n", context);
9970     ok(!lstrcmpA(targetsid, "kiwi"),
9971        "Expected targetsid to be unchanged, got %s\n", targetsid);
9972     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9973 
9974     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
9975                          (const BYTE *)"a\0b\0c\0\0", 7);
9976     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9977 
9978     /* Patches value exists, is not a squashed guid */
9979     lstrcpyA(patchcode, "apple");
9980     lstrcpyA(targetprod, "banana");
9981     context = 0xdeadbeef;
9982     lstrcpyA(targetsid, "kiwi");
9983     size = MAX_PATH;
9984     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9985                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9986                            &context, targetsid, &size);
9987     ok(r == ERROR_BAD_CONFIGURATION,
9988        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9989     ok(!lstrcmpA(patchcode, "apple"),
9990        "Expected patchcode to be unchanged, got %s\n", patchcode);
9991     ok(!lstrcmpA(targetprod, "banana"),
9992        "Expected targetprod to be unchanged, got %s\n", targetprod);
9993     ok(context == 0xdeadbeef,
9994        "Expected context to be unchanged, got %d\n", context);
9995     ok(!lstrcmpA(targetsid, "kiwi"),
9996        "Expected targetsid to be unchanged, got %s\n", targetsid);
9997     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9998 
9999     patch_squashed[lstrlenA(patch_squashed) + 1] = 0;
10000     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10001                          (const BYTE *)patch_squashed,
10002                          lstrlenA(patch_squashed) + 2);
10003     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10004 
10005     /* Patches value exists */
10006     lstrcpyA(patchcode, "apple");
10007     lstrcpyA(targetprod, "banana");
10008     context = 0xdeadbeef;
10009     lstrcpyA(targetsid, "kiwi");
10010     size = MAX_PATH;
10011     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10012                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10013                            &context, targetsid, &size);
10014     ok(r == ERROR_NO_MORE_ITEMS ||
10015        broken(r == ERROR_BAD_CONFIGURATION), /* Windows Installer 3.0 */
10016        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10017     ok(!lstrcmpA(patchcode, "apple"),
10018        "Expected patchcode to be unchanged, got %s\n", patchcode);
10019     ok(!lstrcmpA(targetprod, "banana"),
10020        "Expected targetprod to be unchanged, got %s\n", targetprod);
10021     ok(context == 0xdeadbeef,
10022        "Expected context to be unchanged, got %d\n", context);
10023     ok(!lstrcmpA(targetsid, "kiwi"),
10024        "Expected targetsid to be unchanged, got %s\n", targetsid);
10025     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10026 
10027     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
10028                          (const BYTE *)"whatever", 9);
10029     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10030 
10031     /* patch code value exists */
10032     lstrcpyA(patchcode, "apple");
10033     lstrcpyA(targetprod, "banana");
10034     context = 0xdeadbeef;
10035     lstrcpyA(targetsid, "kiwi");
10036     size = MAX_PATH;
10037     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10038                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10039                            &context, targetsid, &size);
10040     ok(r == ERROR_NO_MORE_ITEMS ||
10041        broken(r == ERROR_BAD_CONFIGURATION), /* Windows Installer 3.0 */
10042        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10043     ok(!lstrcmpA(patchcode, "apple"),
10044        "Expected patchcode to be unchanged, got %s\n", patchcode);
10045     ok(!lstrcmpA(targetprod, "banana"),
10046        "Expected targetprod to be unchanged, got %s\n", targetprod);
10047     ok(context == 0xdeadbeef,
10048        "Expected context to be unchanged, got %d\n", context);
10049     ok(!lstrcmpA(targetsid, "kiwi"),
10050        "Expected targetsid to be unchanged, got %s\n", targetsid);
10051     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10052 
10053     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
10054     lstrcatA(keypath, expectedsid);
10055     lstrcatA(keypath, "\\Patches\\");
10056     lstrcatA(keypath, patch_squashed);
10057 
10058     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
10059     if (res == ERROR_ACCESS_DENIED)
10060     {
10061         skip("Not enough rights to perform tests\n");
10062         goto error;
10063     }
10064     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10065 
10066     /* userdata patch key exists */
10067     lstrcpyA(patchcode, "apple");
10068     lstrcpyA(targetprod, "banana");
10069     context = 0xdeadbeef;
10070     lstrcpyA(targetsid, "kiwi");
10071     size = MAX_PATH;
10072     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10073                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10074                            &context, targetsid, &size);
10075     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10076     ok(!lstrcmpA(patchcode, patch),
10077        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10078     ok(!lstrcmpA(targetprod, prodcode),
10079        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10080     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
10081        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
10082     ok(!lstrcmpA(targetsid, expectedsid),
10083        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10084     ok(size == lstrlenA(expectedsid),
10085        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10086 
10087     /* MSIPATCHSTATE_SUPERSEDED */
10088 
10089     lstrcpyA(patchcode, "apple");
10090     lstrcpyA(targetprod, "banana");
10091     context = 0xdeadbeef;
10092     lstrcpyA(targetsid, "kiwi");
10093     size = MAX_PATH;
10094     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10095                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10096                            &context, targetsid, &size);
10097     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10098     ok(!lstrcmpA(patchcode, "apple"),
10099        "Expected patchcode to be unchanged, got %s\n", patchcode);
10100     ok(!lstrcmpA(targetprod, "banana"),
10101        "Expected targetprod to be unchanged, got %s\n", targetprod);
10102     ok(context == 0xdeadbeef,
10103        "Expected context to be unchanged, got %d\n", context);
10104     ok(!lstrcmpA(targetsid, "kiwi"),
10105        "Expected targetsid to be unchanged, got %s\n", targetsid);
10106     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10107 
10108     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
10109     lstrcatA(keypath, expectedsid);
10110     lstrcatA(keypath, "\\Products\\");
10111     lstrcatA(keypath, prod_squashed);
10112 
10113     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
10114     if (res == ERROR_ACCESS_DENIED)
10115     {
10116         skip("Not enough rights to perform tests\n");
10117         goto error;
10118     }
10119     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10120 
10121     /* UserData product key exists */
10122     lstrcpyA(patchcode, "apple");
10123     lstrcpyA(targetprod, "banana");
10124     context = 0xdeadbeef;
10125     lstrcpyA(targetsid, "kiwi");
10126     size = MAX_PATH;
10127     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10128                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10129                            &context, targetsid, &size);
10130     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10131     ok(!lstrcmpA(patchcode, "apple"),
10132        "Expected patchcode to be unchanged, got %s\n", patchcode);
10133     ok(!lstrcmpA(targetprod, "banana"),
10134        "Expected targetprod to be unchanged, got %s\n", targetprod);
10135     ok(context == 0xdeadbeef,
10136        "Expected context to be unchanged, got %d\n", context);
10137     ok(!lstrcmpA(targetsid, "kiwi"),
10138        "Expected targetsid to be unchanged, got %s\n", targetsid);
10139     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10140 
10141     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
10142     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10143 
10144     /* UserData patches key exists */
10145     lstrcpyA(patchcode, "apple");
10146     lstrcpyA(targetprod, "banana");
10147     context = 0xdeadbeef;
10148     lstrcpyA(targetsid, "kiwi");
10149     size = MAX_PATH;
10150     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10151                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10152                            &context, targetsid, &size);
10153     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10154     ok(!lstrcmpA(patchcode, "apple"),
10155        "Expected patchcode to be unchanged, got %s\n", patchcode);
10156     ok(!lstrcmpA(targetprod, "banana"),
10157        "Expected targetprod to be unchanged, got %s\n", targetprod);
10158     ok(context == 0xdeadbeef,
10159        "Expected context to be unchanged, got %d\n", context);
10160     ok(!lstrcmpA(targetsid, "kiwi"),
10161        "Expected targetsid to be unchanged, got %s\n", targetsid);
10162     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10163 
10164     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
10165     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10166 
10167     /* specific UserData patch key exists */
10168     lstrcpyA(patchcode, "apple");
10169     lstrcpyA(targetprod, "banana");
10170     context = 0xdeadbeef;
10171     lstrcpyA(targetsid, "kiwi");
10172     size = MAX_PATH;
10173     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10174                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10175                            &context, targetsid, &size);
10176     ok(r == ERROR_BAD_CONFIGURATION,
10177        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10178     ok(!lstrcmpA(patchcode, "apple"),
10179        "Expected patchcode to be unchanged, got %s\n", patchcode);
10180     ok(!lstrcmpA(targetprod, "banana"),
10181        "Expected targetprod to be unchanged, got %s\n", targetprod);
10182     ok(context == 0xdeadbeef,
10183        "Expected context to be unchanged, got %d\n", context);
10184     ok(!lstrcmpA(targetsid, "kiwi"),
10185        "Expected targetsid to be unchanged, got %s\n", targetsid);
10186     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10187 
10188     data = MSIPATCHSTATE_SUPERSEDED;
10189     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10190                          (const BYTE *)&data, sizeof(DWORD));
10191     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10192 
10193     /* State value exists */
10194     lstrcpyA(patchcode, "apple");
10195     lstrcpyA(targetprod, "banana");
10196     context = 0xdeadbeef;
10197     lstrcpyA(targetsid, "kiwi");
10198     size = MAX_PATH;
10199     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10200                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10201                            &context, targetsid, &size);
10202     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10203     ok(!lstrcmpA(patchcode, patch),
10204        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10205     ok(!lstrcmpA(targetprod, prodcode),
10206        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10207     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
10208        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
10209     ok(!lstrcmpA(targetsid, expectedsid),
10210        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10211     ok(size == lstrlenA(expectedsid),
10212        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10213 
10214     /* MSIPATCHSTATE_OBSOLETED */
10215 
10216     lstrcpyA(patchcode, "apple");
10217     lstrcpyA(targetprod, "banana");
10218     context = 0xdeadbeef;
10219     lstrcpyA(targetsid, "kiwi");
10220     size = MAX_PATH;
10221     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10222                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
10223                            &context, targetsid, &size);
10224     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10225     ok(!lstrcmpA(patchcode, "apple"),
10226        "Expected patchcode to be unchanged, got %s\n", patchcode);
10227     ok(!lstrcmpA(targetprod, "banana"),
10228        "Expected targetprod to be unchanged, got %s\n", targetprod);
10229     ok(context == 0xdeadbeef,
10230        "Expected context to be unchanged, got %d\n", context);
10231     ok(!lstrcmpA(targetsid, "kiwi"),
10232        "Expected targetsid to be unchanged, got %s\n", targetsid);
10233     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10234 
10235     data = MSIPATCHSTATE_OBSOLETED;
10236     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10237                          (const BYTE *)&data, sizeof(DWORD));
10238     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10239 
10240     /* State value is obsoleted */
10241     lstrcpyA(patchcode, "apple");
10242     lstrcpyA(targetprod, "banana");
10243     context = 0xdeadbeef;
10244     lstrcpyA(targetsid, "kiwi");
10245     size = MAX_PATH;
10246     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10247                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
10248                            &context, targetsid, &size);
10249     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10250     ok(!lstrcmpA(patchcode, patch),
10251        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10252     ok(!lstrcmpA(targetprod, prodcode),
10253        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10254     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
10255        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
10256     ok(!lstrcmpA(targetsid, expectedsid),
10257        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10258     ok(size == lstrlenA(expectedsid),
10259        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10260 
10261     /* MSIPATCHSTATE_REGISTERED */
10262     /* FIXME */
10263 
10264     /* MSIPATCHSTATE_ALL */
10265 
10266     /* 1st */
10267     lstrcpyA(patchcode, "apple");
10268     lstrcpyA(targetprod, "banana");
10269     context = 0xdeadbeef;
10270     lstrcpyA(targetsid, "kiwi");
10271     size = MAX_PATH;
10272     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10273                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
10274                            &context, targetsid, &size);
10275     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10276     ok(!lstrcmpA(patchcode, patch),
10277        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10278     ok(!lstrcmpA(targetprod, prodcode),
10279        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10280     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
10281        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
10282     ok(!lstrcmpA(targetsid, expectedsid),
10283        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10284     ok(size == lstrlenA(expectedsid),
10285        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10286 
10287     /* same patch in multiple places, only one is enumerated */
10288     lstrcpyA(patchcode, "apple");
10289     lstrcpyA(targetprod, "banana");
10290     context = 0xdeadbeef;
10291     lstrcpyA(targetsid, "kiwi");
10292     size = MAX_PATH;
10293     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10294                            MSIPATCHSTATE_ALL, 1, patchcode, targetprod,
10295                            &context, targetsid, &size);
10296     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10297     ok(!lstrcmpA(patchcode, "apple"),
10298        "Expected patchcode to be unchanged, got %s\n", patchcode);
10299     ok(!lstrcmpA(targetprod, "banana"),
10300        "Expected targetprod to be unchanged, got %s\n", targetprod);
10301     ok(context == 0xdeadbeef,
10302        "Expected context to be unchanged, got %d\n", context);
10303     ok(!lstrcmpA(targetsid, "kiwi"),
10304        "Expected targetsid to be unchanged, got %s\n", targetsid);
10305     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10306 
10307     RegDeleteValueA(hpatch, "State");
10308     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
10309     RegCloseKey(hpatch);
10310     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
10311     RegCloseKey(udpatch);
10312     delete_key(udprod, "", access & KEY_WOW64_64KEY);
10313     RegCloseKey(udprod);
10314     delete_key(userkey, "", access & KEY_WOW64_64KEY);
10315     RegCloseKey(userkey);
10316     RegDeleteValueA(patches, patch_squashed);
10317     RegDeleteValueA(patches, "Patches");
10318 
10319 error:
10320     RegDeleteKeyA(patches, "");
10321     RegCloseKey(patches);
10322     RegDeleteKeyA(prodkey, "");
10323     RegCloseKey(prodkey);
10324 }
10325 
10326 static void test_MsiEnumPatchesEx_machine(void)
10327 {
10328     CHAR keypath[MAX_PATH], patch[MAX_PATH];
10329     CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
10330     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
10331     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
10332     HKEY prodkey, patches, udprod, udpatch;
10333     HKEY hpatch;
10334     MSIINSTALLCONTEXT context;
10335     DWORD size, data;
10336     LONG res;
10337     UINT r;
10338     REGSAM access = KEY_ALL_ACCESS;
10339 
10340     create_test_guid(prodcode, prod_squashed);
10341     create_test_guid(patch, patch_squashed);
10342 
10343     if (is_wow64)
10344         access |= KEY_WOW64_64KEY;
10345 
10346     /* MSIPATCHSTATE_APPLIED */
10347 
10348     lstrcpyA(patchcode, "apple");
10349     lstrcpyA(targetprod, "banana");
10350     context = 0xdeadbeef;
10351     lstrcpyA(targetsid, "kiwi");
10352     size = MAX_PATH;
10353     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10354                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10355                            &context, targetsid, &size);
10356     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10357     ok(!lstrcmpA(patchcode, "apple"),
10358        "Expected patchcode to be unchanged, got %s\n", patchcode);
10359     ok(!lstrcmpA(targetprod, "banana"),
10360        "Expected targetprod to be unchanged, got %s\n", targetprod);
10361     ok(context == 0xdeadbeef,
10362        "Expected context to be unchanged, got %d\n", context);
10363     ok(!lstrcmpA(targetsid, "kiwi"),
10364        "Expected targetsid to be unchanged, got %s\n", targetsid);
10365     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10366 
10367     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
10368     lstrcatA(keypath, prod_squashed);
10369 
10370     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
10371     if (res == ERROR_ACCESS_DENIED)
10372     {
10373         skip("Not enough rights to perform tests\n");
10374         return;
10375     }
10376     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10377 
10378     /* local product key exists */
10379     lstrcpyA(patchcode, "apple");
10380     lstrcpyA(targetprod, "banana");
10381     context = 0xdeadbeef;
10382     lstrcpyA(targetsid, "kiwi");
10383     size = MAX_PATH;
10384     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10385                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10386                            &context, targetsid, &size);
10387     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10388     ok(!lstrcmpA(patchcode, "apple"),
10389        "Expected patchcode to be unchanged, got %s\n", patchcode);
10390     ok(!lstrcmpA(targetprod, "banana"),
10391        "Expected targetprod to be unchanged, got %s\n", targetprod);
10392     ok(context == 0xdeadbeef,
10393        "Expected context to be unchanged, got %d\n", context);
10394     ok(!lstrcmpA(targetsid, "kiwi"),
10395        "Expected targetsid to be unchanged, got %s\n", targetsid);
10396     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10397 
10398     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
10399     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10400 
10401     /* Patches key exists */
10402     lstrcpyA(patchcode, "apple");
10403     lstrcpyA(targetprod, "banana");
10404     context = 0xdeadbeef;
10405     lstrcpyA(targetsid, "kiwi");
10406     size = MAX_PATH;
10407     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10408                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10409                            &context, targetsid, &size);
10410     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10411     ok(!lstrcmpA(patchcode, "apple"),
10412        "Expected patchcode to be unchanged, got %s\n", patchcode);
10413     ok(!lstrcmpA(targetprod, "banana"),
10414        "Expected targetprod to be unchanged, got %s\n", targetprod);
10415     ok(context == 0xdeadbeef,
10416        "Expected context to be unchanged, got %d\n", context);
10417     ok(!lstrcmpA(targetsid, "kiwi"),
10418        "Expected targetsid to be unchanged, got %s\n", targetsid);
10419     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10420 
10421     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
10422                          (const BYTE *)patch_squashed,
10423                          lstrlenA(patch_squashed) + 1);
10424     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10425 
10426     /* Patches value exists, is not REG_MULTI_SZ */
10427     lstrcpyA(patchcode, "apple");
10428     lstrcpyA(targetprod, "banana");
10429     context = 0xdeadbeef;
10430     lstrcpyA(targetsid, "kiwi");
10431     size = MAX_PATH;
10432     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10433                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10434                            &context, targetsid, &size);
10435     ok(r == ERROR_BAD_CONFIGURATION,
10436        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10437     ok(!lstrcmpA(patchcode, "apple"),
10438        "Expected patchcode to be unchanged, got %s\n", patchcode);
10439     ok(!lstrcmpA(targetprod, "banana"),
10440        "Expected targetprod to be unchanged, got %s\n", targetprod);
10441     ok(context == 0xdeadbeef,
10442        "Expected context to be unchanged, got %d\n", context);
10443     ok(!lstrcmpA(targetsid, "kiwi"),
10444        "Expected targetsid to be unchanged, got %s\n", targetsid);
10445     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10446 
10447     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10448                          (const BYTE *)"a\0b\0c\0\0", 7);
10449     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10450 
10451     /* Patches value exists, is not a squashed guid */
10452     lstrcpyA(patchcode, "apple");
10453     lstrcpyA(targetprod, "banana");
10454     context = 0xdeadbeef;
10455     lstrcpyA(targetsid, "kiwi");
10456     size = MAX_PATH;
10457     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10458                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10459                            &context, targetsid, &size);
10460     ok(r == ERROR_BAD_CONFIGURATION,
10461        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10462     ok(!lstrcmpA(patchcode, "apple"),
10463        "Expected patchcode to be unchanged, got %s\n", patchcode);
10464     ok(!lstrcmpA(targetprod, "banana"),
10465        "Expected targetprod to be unchanged, got %s\n", targetprod);
10466     ok(context == 0xdeadbeef,
10467        "Expected context to be unchanged, got %d\n", context);
10468     ok(!lstrcmpA(targetsid, "kiwi"),
10469        "Expected targetsid to be unchanged, got %s\n", targetsid);
10470     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10471 
10472     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
10473     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10474                          (const BYTE *)patch_squashed,
10475                          lstrlenA(patch_squashed) + 2);
10476     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10477 
10478     /* Patches value exists */
10479     lstrcpyA(patchcode, "apple");
10480     lstrcpyA(targetprod, "banana");
10481     context = 0xdeadbeef;
10482     lstrcpyA(targetsid, "kiwi");
10483     size = MAX_PATH;
10484     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10485                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10486                            &context, targetsid, &size);
10487     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10488     ok(!lstrcmpA(patchcode, "apple"),
10489        "Expected patchcode to be unchanged, got %s\n", patchcode);
10490     ok(!lstrcmpA(targetprod, "banana"),
10491        "Expected targetprod to be unchanged, got %s\n", targetprod);
10492     ok(context == 0xdeadbeef,
10493        "Expected context to be unchanged, got %d\n", context);
10494     ok(!lstrcmpA(targetsid, "kiwi"),
10495        "Expected targetsid to be unchanged, got %s\n", targetsid);
10496     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10497 
10498     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
10499                          (const BYTE *)"whatever", 9);
10500     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10501 
10502     /* patch code value exists */
10503     lstrcpyA(patchcode, "apple");
10504     lstrcpyA(targetprod, "banana");
10505     context = 0xdeadbeef;
10506     lstrcpyA(targetsid, "kiwi");
10507     size = MAX_PATH;
10508     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10509                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10510                            &context, targetsid, &size);
10511     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10512     ok(!lstrcmpA(patchcode, patch),
10513        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10514     ok(!lstrcmpA(targetprod, prodcode),
10515        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10516     ok(context == MSIINSTALLCONTEXT_MACHINE,
10517        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10518     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
10519     ok(size == 0, "Expected 0, got %d\n", size);
10520 
10521     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
10522     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
10523     lstrcatA(keypath, prod_squashed);
10524 
10525     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
10526     if (res == ERROR_ACCESS_DENIED)
10527     {
10528         skip("Not enough rights to perform tests\n");
10529         goto done;
10530     }
10531     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10532 
10533     /* local UserData product key exists */
10534     lstrcpyA(patchcode, "apple");
10535     lstrcpyA(targetprod, "banana");
10536     context = 0xdeadbeef;
10537     lstrcpyA(targetsid, "kiwi");
10538     size = MAX_PATH;
10539     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10540                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10541                            &context, targetsid, &size);
10542     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10543     ok(!lstrcmpA(patchcode, patch),
10544        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10545     ok(!lstrcmpA(targetprod, prodcode),
10546        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10547     ok(context == MSIINSTALLCONTEXT_MACHINE,
10548        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10549     ok(!lstrcmpA(targetsid, ""),
10550        "Expected \"\", got \"%s\"\n", targetsid);
10551     ok(size == 0, "Expected 0, got %d\n", size);
10552 
10553     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
10554     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10555 
10556     /* local UserData Patches key exists */
10557     lstrcpyA(patchcode, "apple");
10558     lstrcpyA(targetprod, "banana");
10559     context = 0xdeadbeef;
10560     lstrcpyA(targetsid, "kiwi");
10561     size = MAX_PATH;
10562     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10563                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10564                            &context, targetsid, &size);
10565     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10566     ok(!lstrcmpA(patchcode, patch),
10567        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10568     ok(!lstrcmpA(targetprod, prodcode),
10569        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10570     ok(context == MSIINSTALLCONTEXT_MACHINE,
10571        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10572     ok(!lstrcmpA(targetsid, ""),
10573        "Expected \"\", got \"%s\"\n", targetsid);
10574     ok(size == 0, "Expected 0, got %d\n", size);
10575 
10576     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
10577     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10578 
10579     /* local UserData Product patch key exists */
10580     lstrcpyA(patchcode, "apple");
10581     lstrcpyA(targetprod, "banana");
10582     context = 0xdeadbeef;
10583     lstrcpyA(targetsid, "kiwi");
10584     size = MAX_PATH;
10585     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10586                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10587                            &context, targetsid, &size);
10588     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10589     ok(!lstrcmpA(patchcode, "apple"),
10590        "Expected patchcode to be unchanged, got %s\n", patchcode);
10591     ok(!lstrcmpA(targetprod, "banana"),
10592        "Expected targetprod to be unchanged, got %s\n", targetprod);
10593     ok(context == 0xdeadbeef,
10594        "Expected context to be unchanged, got %d\n", context);
10595     ok(!lstrcmpA(targetsid, "kiwi"),
10596        "Expected targetsid to be unchanged, got %s\n", targetsid);
10597     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10598 
10599     data = MSIPATCHSTATE_APPLIED;
10600     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10601                          (const BYTE *)&data, sizeof(DWORD));
10602     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10603 
10604     /* State value exists */
10605     lstrcpyA(patchcode, "apple");
10606     lstrcpyA(targetprod, "banana");
10607     context = 0xdeadbeef;
10608     lstrcpyA(targetsid, "kiwi");
10609     size = MAX_PATH;
10610     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10611                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10612                            &context, targetsid, &size);
10613     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10614     ok(!lstrcmpA(patchcode, patch),
10615        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10616     ok(!lstrcmpA(targetprod, prodcode),
10617        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10618     ok(context == MSIINSTALLCONTEXT_MACHINE,
10619        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10620     ok(!lstrcmpA(targetsid, ""),
10621        "Expected \"\", got \"%s\"\n", targetsid);
10622     ok(size == 0, "Expected 0, got %d\n", size);
10623 
10624     /* MSIPATCHSTATE_SUPERSEDED */
10625 
10626     lstrcpyA(patchcode, "apple");
10627     lstrcpyA(targetprod, "banana");
10628     context = 0xdeadbeef;
10629     lstrcpyA(targetsid, "kiwi");
10630     size = MAX_PATH;
10631     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10632                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10633                            &context, targetsid, &size);
10634     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10635     ok(!lstrcmpA(patchcode, "apple"),
10636        "Expected patchcode to be unchanged, got %s\n", patchcode);
10637     ok(!lstrcmpA(targetprod, "banana"),
10638        "Expected targetprod to be unchanged, got %s\n", targetprod);
10639     ok(context == 0xdeadbeef,
10640        "Expected context to be unchanged, got %d\n", context);
10641     ok(!lstrcmpA(targetsid, "kiwi"),
10642        "Expected targetsid to be unchanged, got %s\n", targetsid);
10643     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10644 
10645     data = MSIPATCHSTATE_SUPERSEDED;
10646     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10647                          (const BYTE *)&data, sizeof(DWORD));
10648     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10649 
10650     /* State value is MSIPATCHSTATE_SUPERSEDED */
10651     lstrcpyA(patchcode, "apple");
10652     lstrcpyA(targetprod, "banana");
10653     context = 0xdeadbeef;
10654     lstrcpyA(targetsid, "kiwi");
10655     size = MAX_PATH;
10656     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10657                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10658                            &context, targetsid, &size);
10659     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10660     ok(!lstrcmpA(patchcode, patch),
10661        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10662     ok(!lstrcmpA(targetprod, prodcode),
10663        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10664     ok(context == MSIINSTALLCONTEXT_MACHINE,
10665        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10666     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
10667     ok(size == 0, "Expected 0, got %d\n", size);
10668 
10669     /* MSIPATCHSTATE_OBSOLETED */
10670 
10671     lstrcpyA(patchcode, "apple");
10672     lstrcpyA(targetprod, "banana");
10673     context = 0xdeadbeef;
10674     lstrcpyA(targetsid, "kiwi");
10675     size = MAX_PATH;
10676     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10677                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
10678                            &context, targetsid, &size);
10679     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10680     ok(!lstrcmpA(patchcode, "apple"),
10681        "Expected patchcode to be unchanged, got %s\n", patchcode);
10682     ok(!lstrcmpA(targetprod, "banana"),
10683        "Expected targetprod to be unchanged, got %s\n", targetprod);
10684     ok(context == 0xdeadbeef,
10685        "Expected context to be unchanged, got %d\n", context);
10686     ok(!lstrcmpA(targetsid, "kiwi"),
10687        "Expected targetsid to be unchanged, got %s\n", targetsid);
10688     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10689 
10690     data = MSIPATCHSTATE_OBSOLETED;
10691     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10692                          (const BYTE *)&data, sizeof(DWORD));
10693     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10694 
10695     /* State value is obsoleted */
10696     lstrcpyA(patchcode, "apple");
10697     lstrcpyA(targetprod, "banana");
10698     context = 0xdeadbeef;
10699     lstrcpyA(targetsid, "kiwi");
10700     size = MAX_PATH;
10701     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10702                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
10703                            &context, targetsid, &size);
10704     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10705     ok(!lstrcmpA(patchcode, patch),
10706        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10707     ok(!lstrcmpA(targetprod, prodcode),
10708        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10709     ok(context == MSIINSTALLCONTEXT_MACHINE,
10710        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10711     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
10712     ok(size == 0, "Expected 0, got %d\n", size);
10713 
10714     /* MSIPATCHSTATE_REGISTERED */
10715     /* FIXME */
10716 
10717     /* MSIPATCHSTATE_ALL */
10718 
10719     /* 1st */
10720     lstrcpyA(patchcode, "apple");
10721     lstrcpyA(targetprod, "banana");
10722     context = 0xdeadbeef;
10723     lstrcpyA(targetsid, "kiwi");
10724     size = MAX_PATH;
10725     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10726                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
10727                            &context, targetsid, &size);
10728     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10729     ok(!lstrcmpA(patchcode, patch),
10730        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10731     ok(!lstrcmpA(targetprod, prodcode),
10732        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10733     ok(context == MSIINSTALLCONTEXT_MACHINE,
10734        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10735     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
10736     ok(size == 0, "Expected 0, got %d\n", size);
10737 
10738     /* same patch in multiple places, only one is enumerated */
10739     lstrcpyA(patchcode, "apple");
10740     lstrcpyA(targetprod, "banana");
10741     context = 0xdeadbeef;
10742     lstrcpyA(targetsid, "kiwi");
10743     size = MAX_PATH;
10744     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10745                            MSIPATCHSTATE_ALL, 1, patchcode, targetprod,
10746                            &context, targetsid, &size);
10747     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10748     ok(!lstrcmpA(patchcode, "apple"),
10749        "Expected patchcode to be unchanged, got %s\n", patchcode);
10750     ok(!lstrcmpA(targetprod, "banana"),
10751        "Expected targetprod to be unchanged, got %s\n", targetprod);
10752     ok(context == 0xdeadbeef,
10753        "Expected context to be unchanged, got %d\n", context);
10754     ok(!lstrcmpA(targetsid, "kiwi"),
10755        "Expected targetsid to be unchanged, got %s\n", targetsid);
10756     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10757 
10758     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
10759     RegDeleteValueA(hpatch, "State");
10760     RegCloseKey(hpatch);
10761     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
10762     RegCloseKey(udpatch);
10763     delete_key(udprod, "", access & KEY_WOW64_64KEY);
10764     RegCloseKey(udprod);
10765 
10766 done:
10767     RegDeleteValueA(patches, patch_squashed);
10768     RegDeleteValueA(patches, "Patches");
10769     delete_key(patches, "", access & KEY_WOW64_64KEY);
10770     RegCloseKey(patches);
10771     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
10772     RegCloseKey(prodkey);
10773 }
10774 
10775 static void test_MsiEnumPatchesEx(void)
10776 {
10777     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
10778     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
10779     CHAR patchcode[MAX_PATH];
10780     MSIINSTALLCONTEXT context;
10781     LPSTR usersid;
10782     DWORD size;
10783     UINT r;
10784 
10785     if (!pMsiEnumPatchesExA)
10786     {
10787         win_skip("MsiEnumPatchesExA not implemented\n");
10788         return;
10789     }
10790 
10791     create_test_guid(prodcode, prod_squashed);
10792     usersid = get_user_sid();
10793 
10794     /* empty szProductCode */
10795     lstrcpyA(patchcode, "apple");
10796     lstrcpyA(targetprod, "banana");
10797     context = 0xdeadbeef;
10798     lstrcpyA(targetsid, "kiwi");
10799     size = MAX_PATH;
10800     r = pMsiEnumPatchesExA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10801                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod, &context,
10802                            targetsid, &size);
10803     ok(r == ERROR_INVALID_PARAMETER,
10804        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10805     ok(!lstrcmpA(patchcode, "apple"),
10806        "Expected patchcode to be unchanged, got %s\n", patchcode);
10807     ok(!lstrcmpA(targetprod, "banana"),
10808        "Expected targetprod to be unchanged, got %s\n", targetprod);
10809     ok(context == 0xdeadbeef,
10810        "Expected context to be unchanged, got %d\n", context);
10811     ok(!lstrcmpA(targetsid, "kiwi"),
10812        "Expected targetsid to be unchanged, got %s\n", targetsid);
10813     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10814 
10815     /* garbage szProductCode */
10816     lstrcpyA(patchcode, "apple");
10817     lstrcpyA(targetprod, "banana");
10818     context = 0xdeadbeef;
10819     lstrcpyA(targetsid, "kiwi");
10820     size = MAX_PATH;
10821     r = pMsiEnumPatchesExA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10822                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod, &context,
10823                            targetsid, &size);
10824     ok(r == ERROR_INVALID_PARAMETER,
10825        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10826     ok(!lstrcmpA(patchcode, "apple"),
10827        "Expected patchcode to be unchanged, got %s\n", patchcode);
10828     ok(!lstrcmpA(targetprod, "banana"),
10829        "Expected targetprod to be unchanged, got %s\n", targetprod);
10830     ok(context == 0xdeadbeef,
10831        "Expected context to be unchanged, got %d\n", context);
10832     ok(!lstrcmpA(targetsid, "kiwi"),
10833        "Expected targetsid to be unchanged, got %s\n", targetsid);
10834     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10835 
10836     /* guid without brackets */
10837     lstrcpyA(patchcode, "apple");
10838     lstrcpyA(targetprod, "banana");
10839     context = 0xdeadbeef;
10840     lstrcpyA(targetsid, "kiwi");
10841     size = MAX_PATH;
10842     r = pMsiEnumPatchesExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", usersid,
10843                            MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
10844                            0, patchcode, targetprod, &context,
10845                            targetsid, &size);
10846     ok(r == ERROR_INVALID_PARAMETER,
10847        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10848     ok(!lstrcmpA(patchcode, "apple"),
10849        "Expected patchcode to be unchanged, got %s\n", patchcode);
10850     ok(!lstrcmpA(targetprod, "banana"),
10851        "Expected targetprod to be unchanged, got %s\n", targetprod);
10852     ok(context == 0xdeadbeef,
10853        "Expected context to be unchanged, got %d\n", context);
10854     ok(!lstrcmpA(targetsid, "kiwi"),
10855        "Expected targetsid to be unchanged, got %s\n", targetsid);
10856     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10857 
10858     /* guid with brackets */
10859     lstrcpyA(patchcode, "apple");
10860     lstrcpyA(targetprod, "banana");
10861     context = 0xdeadbeef;
10862     lstrcpyA(targetsid, "kiwi");
10863     size = MAX_PATH;
10864     r = pMsiEnumPatchesExA("{6700E8CF-95AB-4D9C-BC2C-15840DDA7A5D}", usersid,
10865                            MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
10866                            0, patchcode, targetprod, &context,
10867                            targetsid, &size);
10868     ok(r == ERROR_NO_MORE_ITEMS,
10869        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10870     ok(!lstrcmpA(patchcode, "apple"),
10871        "Expected patchcode to be unchanged, got %s\n", patchcode);
10872     ok(!lstrcmpA(targetprod, "banana"),
10873        "Expected targetprod to be unchanged, got %s\n", targetprod);
10874     ok(context == 0xdeadbeef,
10875        "Expected context to be unchanged, got %d\n", context);
10876     ok(!lstrcmpA(targetsid, "kiwi"),
10877        "Expected targetsid to be unchanged, got %s\n", targetsid);
10878     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10879 
10880     /* szUserSid is S-1-5-18 */
10881     lstrcpyA(patchcode, "apple");
10882     lstrcpyA(targetprod, "banana");
10883     context = 0xdeadbeef;
10884     lstrcpyA(targetsid, "kiwi");
10885     size = MAX_PATH;
10886     r = pMsiEnumPatchesExA(prodcode, "S-1-5-18",
10887                            MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
10888                            0, patchcode, targetprod, &context,
10889                            targetsid, &size);
10890     ok(r == ERROR_INVALID_PARAMETER,
10891        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10892     ok(!lstrcmpA(patchcode, "apple"),
10893        "Expected patchcode to be unchanged, got %s\n", patchcode);
10894     ok(!lstrcmpA(targetprod, "banana"),
10895        "Expected targetprod to be unchanged, got %s\n", targetprod);
10896     ok(context == 0xdeadbeef,
10897        "Expected context to be unchanged, got %d\n", context);
10898     ok(!lstrcmpA(targetsid, "kiwi"),
10899        "Expected targetsid to be unchanged, got %s\n", targetsid);
10900     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10901 
10902     /* dwContext is MSIINSTALLCONTEXT_MACHINE, but szUserSid is non-NULL */
10903     lstrcpyA(patchcode, "apple");
10904     lstrcpyA(targetprod, "banana");
10905     context = 0xdeadbeef;
10906     lstrcpyA(targetsid, "kiwi");
10907     size = MAX_PATH;
10908     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_MACHINE,
10909                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
10910                            &context, targetsid, &size);
10911     ok(r == ERROR_INVALID_PARAMETER,
10912        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10913     ok(!lstrcmpA(patchcode, "apple"),
10914        "Expected patchcode to be unchanged, got %s\n", patchcode);
10915     ok(!lstrcmpA(targetprod, "banana"),
10916        "Expected targetprod to be unchanged, got %s\n", targetprod);
10917     ok(context == 0xdeadbeef,
10918        "Expected context to be unchanged, got %d\n", context);
10919     ok(!lstrcmpA(targetsid, "kiwi"),
10920        "Expected targetsid to be unchanged, got %s\n", targetsid);
10921     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10922 
10923     /* dwContext is out of bounds */
10924     lstrcpyA(patchcode, "apple");
10925     lstrcpyA(targetprod, "banana");
10926     context = 0xdeadbeef;
10927     lstrcpyA(targetsid, "kiwi");
10928     size = MAX_PATH;
10929     r = pMsiEnumPatchesExA(prodcode, usersid, 0,
10930                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
10931                            &context, targetsid, &size);
10932     ok(r == ERROR_INVALID_PARAMETER,
10933        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10934     ok(!lstrcmpA(patchcode, "apple"),
10935        "Expected patchcode to be unchanged, got %s\n", patchcode);
10936     ok(!lstrcmpA(targetprod, "banana"),
10937        "Expected targetprod to be unchanged, got %s\n", targetprod);
10938     ok(context == 0xdeadbeef,
10939        "Expected context to be unchanged, got %d\n", context);
10940     ok(!lstrcmpA(targetsid, "kiwi"),
10941        "Expected targetsid to be unchanged, got %s\n", targetsid);
10942     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10943 
10944     /* dwContext is out of bounds */
10945     lstrcpyA(patchcode, "apple");
10946     lstrcpyA(targetprod, "banana");
10947     context = 0xdeadbeef;
10948     lstrcpyA(targetsid, "kiwi");
10949     size = MAX_PATH;
10950     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_ALL + 1,
10951                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
10952                            &context, targetsid, &size);
10953     ok(r == ERROR_INVALID_PARAMETER,
10954        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10955     ok(!lstrcmpA(patchcode, "apple"),
10956        "Expected patchcode to be unchanged, got %s\n", patchcode);
10957     ok(!lstrcmpA(targetprod, "banana"),
10958        "Expected targetprod to be unchanged, got %s\n", targetprod);
10959     ok(context == 0xdeadbeef,
10960        "Expected context to be unchanged, got %d\n", context);
10961     ok(!lstrcmpA(targetsid, "kiwi"),
10962        "Expected targetsid to be unchanged, got %s\n", targetsid);
10963     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10964 
10965     /* dwFilter is out of bounds */
10966     lstrcpyA(patchcode, "apple");
10967     lstrcpyA(targetprod, "banana");
10968     context = 0xdeadbeef;
10969     lstrcpyA(targetsid, "kiwi");
10970     size = MAX_PATH;
10971     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10972                            MSIPATCHSTATE_INVALID, 0, patchcode, targetprod,
10973                            &context, targetsid, &size);
10974     ok(r == ERROR_INVALID_PARAMETER,
10975        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10976     ok(!lstrcmpA(patchcode, "apple"),
10977        "Expected patchcode to be unchanged, got %s\n", patchcode);
10978     ok(!lstrcmpA(targetprod, "banana"),
10979        "Expected targetprod to be unchanged, got %s\n", targetprod);
10980     ok(context == 0xdeadbeef,
10981        "Expected context to be unchanged, got %d\n", context);
10982     ok(!lstrcmpA(targetsid, "kiwi"),
10983        "Expected targetsid to be unchanged, got %s\n", targetsid);
10984     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10985 
10986     /* dwFilter is out of bounds */
10987     lstrcpyA(patchcode, "apple");
10988     lstrcpyA(targetprod, "banana");
10989     context = 0xdeadbeef;
10990     lstrcpyA(targetsid, "kiwi");
10991     size = MAX_PATH;
10992     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10993                            MSIPATCHSTATE_ALL + 1, 0, patchcode, targetprod,
10994                            &context, targetsid, &size);
10995     ok(r == ERROR_INVALID_PARAMETER,
10996        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10997     ok(!lstrcmpA(patchcode, "apple"),
10998        "Expected patchcode to be unchanged, got %s\n", patchcode);
10999     ok(!lstrcmpA(targetprod, "banana"),
11000        "Expected targetprod to be unchanged, got %s\n", targetprod);
11001     ok(context == 0xdeadbeef,
11002        "Expected context to be unchanged, got %d\n", context);
11003     ok(!lstrcmpA(targetsid, "kiwi"),
11004        "Expected targetsid to be unchanged, got %s\n", targetsid);
11005     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11006 
11007     /* pcchTargetUserSid is NULL while szTargetUserSid is non-NULL */
11008     lstrcpyA(patchcode, "apple");
11009     lstrcpyA(targetprod, "banana");
11010     context = 0xdeadbeef;
11011     lstrcpyA(targetsid, "kiwi");
11012     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
11013                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
11014                            &context, targetsid, NULL);
11015     ok(r == ERROR_INVALID_PARAMETER,
11016        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11017     ok(!lstrcmpA(patchcode, "apple"),
11018        "Expected patchcode to be unchanged, got %s\n", patchcode);
11019     ok(!lstrcmpA(targetprod, "banana"),
11020        "Expected targetprod to be unchanged, got %s\n", targetprod);
11021     ok(context == 0xdeadbeef,
11022        "Expected context to be unchanged, got %d\n", context);
11023     ok(!lstrcmpA(targetsid, "kiwi"),
11024        "Expected targetsid to be unchanged, got %s\n", targetsid);
11025 
11026     test_MsiEnumPatchesEx_usermanaged(usersid, usersid);
11027     test_MsiEnumPatchesEx_usermanaged(NULL, usersid);
11028     test_MsiEnumPatchesEx_usermanaged("S-1-2-34", "S-1-2-34");
11029     test_MsiEnumPatchesEx_userunmanaged(usersid, usersid);
11030     test_MsiEnumPatchesEx_userunmanaged(NULL, usersid);
11031     /* FIXME: Successfully test userunmanaged with a different user */
11032     test_MsiEnumPatchesEx_machine();
11033     LocalFree(usersid);
11034 }
11035 
11036 static void test_MsiEnumPatches(void)
11037 {
11038     CHAR keypath[MAX_PATH], patch[MAX_PATH];
11039     CHAR patchcode[MAX_PATH], patch_squashed[MAX_PATH];
11040     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
11041     CHAR transforms[MAX_PATH];
11042     WCHAR patchW[MAX_PATH], prodcodeW[MAX_PATH], transformsW[MAX_PATH];
11043     HKEY prodkey, patches, udprod;
11044     HKEY userkey, hpatch, udpatch;
11045     DWORD size, data;
11046     LPSTR usersid;
11047     LONG res;
11048     UINT r;
11049     REGSAM access = KEY_ALL_ACCESS;
11050 
11051     create_test_guid(prodcode, prod_squashed);
11052     create_test_guid(patchcode, patch_squashed);
11053     usersid = get_user_sid();
11054 
11055     if (is_wow64)
11056         access |= KEY_WOW64_64KEY;
11057 
11058     /* NULL szProduct */
11059     size = MAX_PATH;
11060     lstrcpyA(patch, "apple");
11061     lstrcpyA(transforms, "banana");
11062     r = MsiEnumPatchesA(NULL, 0, patch, transforms, &size);
11063     ok(r == ERROR_INVALID_PARAMETER,
11064        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11065     ok(!lstrcmpA(patch, "apple"),
11066        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11067     ok(!lstrcmpA(transforms, "banana"),
11068        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11069     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11070 
11071     /* empty szProduct */
11072     size = MAX_PATH;
11073     lstrcpyA(patch, "apple");
11074     lstrcpyA(transforms, "banana");
11075     r = MsiEnumPatchesA("", 0, patch, transforms, &size);
11076     ok(r == ERROR_INVALID_PARAMETER,
11077        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11078     ok(!lstrcmpA(patch, "apple"),
11079        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11080     ok(!lstrcmpA(transforms, "banana"),
11081        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11082     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11083 
11084     /* garbage szProduct */
11085     size = MAX_PATH;
11086     lstrcpyA(patch, "apple");
11087     lstrcpyA(transforms, "banana");
11088     r = MsiEnumPatchesA("garbage", 0, patch, transforms, &size);
11089     ok(r == ERROR_INVALID_PARAMETER,
11090        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11091     ok(!lstrcmpA(patch, "apple"),
11092        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11093     ok(!lstrcmpA(transforms, "banana"),
11094        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11095     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11096 
11097     /* guid without brackets */
11098     size = MAX_PATH;
11099     lstrcpyA(patch, "apple");
11100     lstrcpyA(transforms, "banana");
11101     r = MsiEnumPatchesA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", 0, patch,
11102                         transforms, &size);
11103     ok(r == ERROR_INVALID_PARAMETER,
11104        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11105     ok(!lstrcmpA(patch, "apple"),
11106        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11107     ok(!lstrcmpA(transforms, "banana"),
11108        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11109     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11110 
11111     /* guid with brackets */
11112     size = MAX_PATH;
11113     lstrcpyA(patch, "apple");
11114     lstrcpyA(transforms, "banana");
11115     r = MsiEnumPatchesA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", 0, patch,
11116                         transforms, &size);
11117     ok(r == ERROR_UNKNOWN_PRODUCT,
11118        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11119     ok(!lstrcmpA(patch, "apple"),
11120        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11121     ok(!lstrcmpA(transforms, "banana"),
11122        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11123     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11124 
11125     /* same length as guid, but random */
11126     size = MAX_PATH;
11127     lstrcpyA(patch, "apple");
11128     lstrcpyA(transforms, "banana");
11129     r = MsiEnumPatchesA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", 0, patch,
11130                         transforms, &size);
11131     ok(r == ERROR_INVALID_PARAMETER,
11132        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11133     ok(!lstrcmpA(patch, "apple"),
11134        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11135     ok(!lstrcmpA(transforms, "banana"),
11136        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11137     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11138 
11139     /* MSIINSTALLCONTEXT_USERMANAGED */
11140 
11141     size = MAX_PATH;
11142     lstrcpyA(patch, "apple");
11143     lstrcpyA(transforms, "banana");
11144     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11145     ok(r == ERROR_UNKNOWN_PRODUCT,
11146        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11147     ok(!lstrcmpA(patch, "apple"),
11148        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11149     ok(!lstrcmpA(transforms, "banana"),
11150        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11151     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11152 
11153     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
11154     lstrcatA(keypath, usersid);
11155     lstrcatA(keypath, "\\Installer\\Products\\");
11156     lstrcatA(keypath, prod_squashed);
11157 
11158     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
11159     if (res == ERROR_ACCESS_DENIED)
11160     {
11161         skip("Not enough rights to perform tests\n");
11162         LocalFree(usersid);
11163         return;
11164     }
11165     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11166 
11167     /* managed product key exists */
11168     size = MAX_PATH;
11169     lstrcpyA(patch, "apple");
11170     lstrcpyA(transforms, "banana");
11171     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11172     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11173     ok(!lstrcmpA(patch, "apple"),
11174        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11175     ok(!lstrcmpA(transforms, "banana"),
11176        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11177     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11178 
11179     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
11180     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11181 
11182     /* patches key exists */
11183     size = MAX_PATH;
11184     lstrcpyA(patch, "apple");
11185     lstrcpyA(transforms, "banana");
11186     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11187     ok(r == ERROR_NO_MORE_ITEMS ||
11188        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11189        "Expected ERROR_NO_MORE_ITEMS, 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 %d\n", size);
11195 
11196     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
11197                          (const BYTE *)patch_squashed,
11198                          lstrlenA(patch_squashed) + 1);
11199     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11200 
11201     /* Patches value exists, is not REG_MULTI_SZ */
11202     size = MAX_PATH;
11203     lstrcpyA(patch, "apple");
11204     lstrcpyA(transforms, "banana");
11205     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11206     ok(r == ERROR_BAD_CONFIGURATION ||
11207        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
11208        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11209     ok(!lstrcmpA(patch, "apple"),
11210        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11211     ok(!lstrcmpA(transforms, "banana"),
11212        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11213     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11214 
11215     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11216                          (const BYTE *)"a\0b\0c\0\0", 7);
11217     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11218 
11219     /* Patches value exists, is not a squashed guid */
11220     size = MAX_PATH;
11221     lstrcpyA(patch, "apple");
11222     lstrcpyA(transforms, "banana");
11223     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11224     ok(r == ERROR_BAD_CONFIGURATION,
11225        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11226     ok(!lstrcmpA(patch, "apple"),
11227        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11228     ok(!lstrcmpA(transforms, "banana"),
11229        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11230     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11231 
11232     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
11233     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11234                          (const BYTE *)patch_squashed,
11235                          lstrlenA(patch_squashed) + 2);
11236     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11237 
11238     /* Patches value exists */
11239     size = MAX_PATH;
11240     lstrcpyA(patch, "apple");
11241     lstrcpyA(transforms, "banana");
11242     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11243     ok(r == ERROR_NO_MORE_ITEMS ||
11244        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11245        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11246     ok(!lstrcmpA(patch, "apple") ||
11247        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
11248        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11249     ok(!lstrcmpA(transforms, "banana"),
11250        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11251     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11252 
11253     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
11254                          (const BYTE *)"whatever", 9);
11255     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11256 
11257     /* patch squashed value exists */
11258     size = MAX_PATH;
11259     lstrcpyA(patch, "apple");
11260     lstrcpyA(transforms, "banana");
11261     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11262     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11263     ok(!lstrcmpA(patch, patchcode),
11264        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11265     ok(!lstrcmpA(transforms, "whatever"),
11266        "Expected \"whatever\", got \"%s\"\n", transforms);
11267     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
11268 
11269     /* lpPatchBuf is NULL */
11270     size = MAX_PATH;
11271     lstrcpyA(transforms, "banana");
11272     r = MsiEnumPatchesA(prodcode, 0, NULL, transforms, &size);
11273     ok(r == ERROR_INVALID_PARAMETER,
11274        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11275     ok(!lstrcmpA(transforms, "banana"),
11276        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11277     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11278 
11279     /* lpTransformsBuf is NULL, pcchTransformsBuf is not */
11280     size = MAX_PATH;
11281     lstrcpyA(patch, "apple");
11282     r = MsiEnumPatchesA(prodcode, 0, patch, NULL, &size);
11283     ok(r == ERROR_INVALID_PARAMETER,
11284        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11285     ok(!lstrcmpA(patch, "apple"),
11286        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11287     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11288 
11289     /* pcchTransformsBuf is NULL, lpTransformsBuf is not */
11290     lstrcpyA(patch, "apple");
11291     lstrcpyA(transforms, "banana");
11292     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, NULL);
11293     ok(r == ERROR_INVALID_PARAMETER,
11294        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11295     ok(!lstrcmpA(patch, "apple"),
11296        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11297     ok(!lstrcmpA(transforms, "banana"),
11298        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11299 
11300     /* pcchTransformsBuf is too small */
11301     size = 6;
11302     lstrcpyA(patch, "apple");
11303     lstrcpyA(transforms, "banana");
11304     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11305     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
11306     ok(!lstrcmpA(patch, patchcode),
11307        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11308     ok(!lstrcmpA(transforms, "whate") ||
11309        broken(!lstrcmpA(transforms, "banana")), /* Windows Installer < 3.0 */
11310        "Expected \"whate\", got \"%s\"\n", transforms);
11311     ok(size == 8 || size == 16, "Expected 8 or 16, got %d\n", size);
11312 
11313     /* increase the index */
11314     size = MAX_PATH;
11315     lstrcpyA(patch, "apple");
11316     lstrcpyA(transforms, "banana");
11317     r = MsiEnumPatchesA(prodcode, 1, patch, transforms, &size);
11318     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11319     ok(!lstrcmpA(patch, "apple"),
11320        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11321     ok(!lstrcmpA(transforms, "banana"),
11322        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11323     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11324 
11325     /* increase again */
11326     size = MAX_PATH;
11327     lstrcpyA(patch, "apple");
11328     lstrcpyA(transforms, "banana");
11329     r = MsiEnumPatchesA(prodcode, 2, patch, transforms, &size);
11330     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11331     ok(!lstrcmpA(patch, "apple"),
11332        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11333     ok(!lstrcmpA(transforms, "banana"),
11334        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11335     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11336 
11337     RegDeleteValueA(patches, "Patches");
11338     delete_key(patches, "", access & KEY_WOW64_64KEY);
11339     RegCloseKey(patches);
11340     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
11341     RegCloseKey(prodkey);
11342 
11343     /* MSIINSTALLCONTEXT_USERUNMANAGED */
11344 
11345     size = MAX_PATH;
11346     lstrcpyA(patch, "apple");
11347     lstrcpyA(transforms, "banana");
11348     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11349     ok(r == ERROR_UNKNOWN_PRODUCT,
11350        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11351     ok(!lstrcmpA(patch, "apple"),
11352        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11353     ok(!lstrcmpA(transforms, "banana"),
11354        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11355     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11356 
11357     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
11358     lstrcatA(keypath, prod_squashed);
11359 
11360     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
11361     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11362 
11363     /* current user product key exists */
11364     size = MAX_PATH;
11365     lstrcpyA(patch, "apple");
11366     lstrcpyA(transforms, "banana");
11367     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11368     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11369     ok(!lstrcmpA(patch, "apple"),
11370        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11371     ok(!lstrcmpA(transforms, "banana"),
11372        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11373     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11374 
11375     res = RegCreateKeyA(prodkey, "Patches", &patches);
11376     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11377 
11378     /* Patches key exists */
11379     size = MAX_PATH;
11380     lstrcpyA(patch, "apple");
11381     lstrcpyA(transforms, "banana");
11382     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11383     ok(r == ERROR_NO_MORE_ITEMS ||
11384        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11385        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11386     ok(!lstrcmpA(patch, "apple"),
11387        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11388     ok(!lstrcmpA(transforms, "banana"),
11389        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11390     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11391 
11392     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
11393                          (const BYTE *)patch_squashed,
11394                          lstrlenA(patch_squashed) + 1);
11395     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11396 
11397     /* Patches value exists, is not REG_MULTI_SZ */
11398     size = MAX_PATH;
11399     lstrcpyA(patch, "apple");
11400     lstrcpyA(transforms, "banana");
11401     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11402     ok(r == ERROR_BAD_CONFIGURATION ||
11403        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
11404        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11405     ok(!lstrcmpA(patch, "apple"),
11406        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11407     ok(!lstrcmpA(transforms, "banana"),
11408        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11409     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11410 
11411     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11412                          (const BYTE *)"a\0b\0c\0\0", 7);
11413     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11414 
11415     /* Patches value exists, is not a squashed guid */
11416     size = MAX_PATH;
11417     lstrcpyA(patch, "apple");
11418     lstrcpyA(transforms, "banana");
11419     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11420     ok(r == ERROR_BAD_CONFIGURATION,
11421        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11422     ok(!lstrcmpA(patch, "apple"),
11423        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11424     ok(!lstrcmpA(transforms, "banana"),
11425        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11426     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11427 
11428     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
11429     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11430                          (const BYTE *)patch_squashed,
11431                          lstrlenA(patch_squashed) + 2);
11432     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11433 
11434     /* Patches value exists */
11435     size = MAX_PATH;
11436     lstrcpyA(patch, "apple");
11437     lstrcpyA(transforms, "banana");
11438     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11439     ok(r == ERROR_NO_MORE_ITEMS ||
11440        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11441        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11442     ok(!lstrcmpA(patch, "apple") ||
11443        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
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 %d\n", size);
11448 
11449     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
11450                          (const BYTE *)"whatever", 9);
11451     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11452 
11453     /* patch code value exists */
11454     size = MAX_PATH;
11455     lstrcpyA(patch, "apple");
11456     lstrcpyA(transforms, "banana");
11457     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11458     ok(r == ERROR_NO_MORE_ITEMS ||
11459        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
11460        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11461     ok(!lstrcmpA(patch, "apple") ||
11462        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
11463        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11464     ok(!lstrcmpA(transforms, "banana") ||
11465        broken(!lstrcmpA(transforms, "whatever")), /* Windows Installer < 3.0 */
11466        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11467     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11468 
11469     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
11470     lstrcatA(keypath, usersid);
11471     lstrcatA(keypath, "\\Patches\\");
11472     lstrcatA(keypath, patch_squashed);
11473 
11474     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
11475     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11476 
11477     /* userdata patch key exists */
11478     size = MAX_PATH;
11479     lstrcpyA(patch, "apple");
11480     lstrcpyA(transforms, "banana");
11481     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11482     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11483     ok(!lstrcmpA(patch, patchcode),
11484        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11485     ok(!lstrcmpA(transforms, "whatever"),
11486        "Expected \"whatever\", got \"%s\"\n", transforms);
11487     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
11488 
11489     delete_key(userkey, "", access & KEY_WOW64_64KEY);
11490     RegCloseKey(userkey);
11491     RegDeleteValueA(patches, patch_squashed);
11492     RegDeleteValueA(patches, "Patches");
11493     RegDeleteKeyA(patches, "");
11494     RegCloseKey(patches);
11495     RegDeleteKeyA(prodkey, "");
11496     RegCloseKey(prodkey);
11497 
11498     /* MSIINSTALLCONTEXT_MACHINE */
11499 
11500     size = MAX_PATH;
11501     lstrcpyA(patch, "apple");
11502     lstrcpyA(transforms, "banana");
11503     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11504     ok(r == ERROR_UNKNOWN_PRODUCT,
11505        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11506     ok(!lstrcmpA(patch, "apple"),
11507        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11508     ok(!lstrcmpA(transforms, "banana"),
11509        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11510     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11511 
11512     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
11513     lstrcatA(keypath, prod_squashed);
11514 
11515     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
11516     if (res == ERROR_ACCESS_DENIED)
11517     {
11518         skip("Not enough rights to perform tests\n");
11519         LocalFree(usersid);
11520         return;
11521     }
11522     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11523 
11524     /* local product key exists */
11525     size = MAX_PATH;
11526     lstrcpyA(patch, "apple");
11527     lstrcpyA(transforms, "banana");
11528     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11529     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11530     ok(!lstrcmpA(patch, "apple"),
11531        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11532     ok(!lstrcmpA(transforms, "banana"),
11533        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11534     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11535 
11536     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
11537     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11538 
11539     /* Patches key exists */
11540     size = MAX_PATH;
11541     lstrcpyA(patch, "apple");
11542     lstrcpyA(transforms, "banana");
11543     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11544     ok(r == ERROR_NO_MORE_ITEMS ||
11545        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11546        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11547     ok(!lstrcmpA(patch, "apple"),
11548        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11549     ok(!lstrcmpA(transforms, "banana"),
11550        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11551     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11552 
11553     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
11554                          (const BYTE *)patch_squashed,
11555                          lstrlenA(patch_squashed) + 1);
11556     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11557 
11558     /* Patches value exists, is not REG_MULTI_SZ */
11559     size = MAX_PATH;
11560     lstrcpyA(patch, "apple");
11561     lstrcpyA(transforms, "banana");
11562     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11563     ok(r == ERROR_BAD_CONFIGURATION ||
11564        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
11565        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11566     ok(!lstrcmpA(patch, "apple"),
11567        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11568     ok(!lstrcmpA(transforms, "banana"),
11569        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11570     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11571 
11572     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11573                          (const BYTE *)"a\0b\0c\0\0", 7);
11574     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11575 
11576     /* Patches value exists, is not a squashed guid */
11577     size = MAX_PATH;
11578     lstrcpyA(patch, "apple");
11579     lstrcpyA(transforms, "banana");
11580     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11581     ok(r == ERROR_BAD_CONFIGURATION,
11582        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11583     ok(!lstrcmpA(patch, "apple"),
11584        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11585     ok(!lstrcmpA(transforms, "banana"),
11586        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11587     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11588 
11589     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
11590     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11591                          (const BYTE *)patch_squashed,
11592                          lstrlenA(patch_squashed) + 2);
11593     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11594 
11595     /* Patches value exists */
11596     size = MAX_PATH;
11597     lstrcpyA(patch, "apple");
11598     lstrcpyA(transforms, "banana");
11599     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11600     ok(r == ERROR_NO_MORE_ITEMS ||
11601        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11602        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11603     ok(!lstrcmpA(patch, "apple") ||
11604        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
11605        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11606     ok(!lstrcmpA(transforms, "banana"),
11607        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11608     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11609 
11610     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
11611                          (const BYTE *)"whatever", 9);
11612     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11613 
11614     /* patch code value exists */
11615     size = MAX_PATH;
11616     lstrcpyA(patch, "apple");
11617     lstrcpyA(transforms, "banana");
11618     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11619     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11620     ok(!lstrcmpA(patch, patchcode),
11621        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11622     ok(!lstrcmpA(transforms, "whatever"),
11623        "Expected \"whatever\", got \"%s\"\n", transforms);
11624     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
11625 
11626     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
11627     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
11628     lstrcatA(keypath, prod_squashed);
11629 
11630     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
11631     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11632 
11633     /* local UserData product key exists */
11634     size = MAX_PATH;
11635     lstrcpyA(patch, "apple");
11636     lstrcpyA(transforms, "banana");
11637     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11638     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11639     ok(!lstrcmpA(patch, patchcode),
11640        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11641     ok(!lstrcmpA(transforms, "whatever"),
11642        "Expected \"whatever\", got \"%s\"\n", transforms);
11643     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
11644 
11645     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
11646     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11647 
11648     /* local UserData Patches key exists */
11649     size = MAX_PATH;
11650     lstrcpyA(patch, "apple");
11651     lstrcpyA(transforms, "banana");
11652     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11653     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11654     ok(!lstrcmpA(patch, patchcode),
11655        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11656     ok(!lstrcmpA(transforms, "whatever"),
11657        "Expected \"whatever\", got \"%s\"\n", transforms);
11658     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
11659 
11660     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
11661     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11662 
11663     /* local UserData Product patch key exists */
11664     size = MAX_PATH;
11665     lstrcpyA(patch, "apple");
11666     lstrcpyA(transforms, "banana");
11667     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11668     ok(r == ERROR_NO_MORE_ITEMS ||
11669        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
11670        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11671     ok(!lstrcmpA(patch, "apple") ||
11672        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
11673        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11674     ok(!lstrcmpA(transforms, "banana") ||
11675        broken(!lstrcmpA(transforms, "whatever")), /* Windows Installer < 3.0 */
11676        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11677     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11678 
11679     data = MSIPATCHSTATE_APPLIED;
11680     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
11681                          (const BYTE *)&data, sizeof(DWORD));
11682     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11683 
11684     /* State value exists */
11685     size = MAX_PATH;
11686     lstrcpyA(patch, "apple");
11687     lstrcpyA(transforms, "banana");
11688     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11689     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11690     ok(!lstrcmpA(patch, patchcode),
11691        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11692     ok(!lstrcmpA(transforms, "whatever"),
11693        "Expected \"whatever\", got \"%s\"\n", transforms);
11694     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
11695 
11696     /* now duplicate some of the tests for the W version */
11697 
11698     /* pcchTransformsBuf is too small */
11699     size = 6;
11700     MultiByteToWideChar( CP_ACP, 0, prodcode, -1, prodcodeW, MAX_PATH );
11701     MultiByteToWideChar( CP_ACP, 0, "apple", -1, patchW, MAX_PATH );
11702     MultiByteToWideChar( CP_ACP, 0, "banana", -1, transformsW, MAX_PATH );
11703     r = MsiEnumPatchesW(prodcodeW, 0, patchW, transformsW, &size);
11704     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
11705     WideCharToMultiByte( CP_ACP, 0, patchW, -1, patch, MAX_PATH, NULL, NULL );
11706     WideCharToMultiByte( CP_ACP, 0, transformsW, -1, transforms, MAX_PATH, NULL, NULL );
11707     ok(!lstrcmpA(patch, patchcode),
11708        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11709     ok(!lstrcmpA(transforms, "whate") ||
11710        broken(!lstrcmpA(transforms, "banana")), /* Windows Installer < 3.0 */
11711        "Expected \"whate\", got \"%s\"\n", transforms);
11712     ok(size == 8, "Expected 8, got %d\n", size);
11713 
11714     /* patch code value exists */
11715     size = MAX_PATH;
11716     MultiByteToWideChar( CP_ACP, 0, "apple", -1, patchW, MAX_PATH );
11717     MultiByteToWideChar( CP_ACP, 0, "banana", -1, transformsW, MAX_PATH );
11718     r = MsiEnumPatchesW(prodcodeW, 0, patchW, transformsW, &size);
11719     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11720     WideCharToMultiByte( CP_ACP, 0, patchW, -1, patch, MAX_PATH, NULL, NULL );
11721     WideCharToMultiByte( CP_ACP, 0, transformsW, -1, transforms, MAX_PATH, NULL, NULL );
11722     ok(!lstrcmpA(patch, patchcode),
11723        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11724     ok(!lstrcmpA(transforms, "whatever"),
11725        "Expected \"whatever\", got \"%s\"\n", transforms);
11726     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
11727 
11728     RegDeleteValueA(patches, patch_squashed);
11729     RegDeleteValueA(patches, "Patches");
11730     delete_key(patches, "", access & KEY_WOW64_64KEY);
11731     RegCloseKey(patches);
11732     RegDeleteValueA(hpatch, "State");
11733     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
11734     RegCloseKey(hpatch);
11735     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
11736     RegCloseKey(udpatch);
11737     delete_key(udprod, "", access & KEY_WOW64_64KEY);
11738     RegCloseKey(udprod);
11739     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
11740     RegCloseKey(prodkey);
11741     LocalFree(usersid);
11742 }
11743 
11744 static void test_MsiGetPatchInfoEx(void)
11745 {
11746     CHAR keypath[MAX_PATH], val[MAX_PATH];
11747     CHAR patchcode[MAX_PATH], patch_squashed[MAX_PATH];
11748     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
11749     HKEY prodkey, patches, udprod, props;
11750     HKEY hpatch, udpatch, prodpatches;
11751     LPSTR usersid;
11752     DWORD size;
11753     LONG res;
11754     UINT r;
11755     REGSAM access = KEY_ALL_ACCESS;
11756 
11757     if (!pMsiGetPatchInfoExA)
11758     {
11759         win_skip("MsiGetPatchInfoEx not implemented\n");
11760         return;
11761     }
11762 
11763     create_test_guid(prodcode, prod_squashed);
11764     create_test_guid(patchcode, patch_squashed);
11765     usersid = get_user_sid();
11766 
11767     if (is_wow64)
11768         access |= KEY_WOW64_64KEY;
11769 
11770     /* NULL szPatchCode */
11771     lstrcpyA(val, "apple");
11772     size = MAX_PATH;
11773     r = pMsiGetPatchInfoExA(NULL, prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED,
11774                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11775     ok(r == ERROR_INVALID_PARAMETER,
11776        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11777     ok(!lstrcmpA(val, "apple"),
11778        "Expected val to be unchanged, got \"%s\"\n", val);
11779     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11780 
11781     /* empty szPatchCode */
11782     size = MAX_PATH;
11783     lstrcpyA(val, "apple");
11784     r = pMsiGetPatchInfoExA("", prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED,
11785                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11786     ok(r == ERROR_INVALID_PARAMETER,
11787        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11788     ok(!lstrcmpA(val, "apple"),
11789        "Expected val to be unchanged, got \"%s\"\n", val);
11790     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11791 
11792     /* garbage szPatchCode */
11793     size = MAX_PATH;
11794     lstrcpyA(val, "apple");
11795     r = pMsiGetPatchInfoExA("garbage", prodcode, NULL,
11796                             MSIINSTALLCONTEXT_USERMANAGED,
11797                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11798     ok(r == ERROR_INVALID_PARAMETER,
11799        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11800     ok(!lstrcmpA(val, "apple"),
11801        "Expected val to be unchanged, got \"%s\"\n", val);
11802     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11803 
11804     /* guid without brackets */
11805     size = MAX_PATH;
11806     lstrcpyA(val, "apple");
11807     r = pMsiGetPatchInfoExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", prodcode,
11808                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
11809                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11810     ok(r == ERROR_INVALID_PARAMETER,
11811        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11812     ok(!lstrcmpA(val, "apple"),
11813        "Expected val to be unchanged, got \"%s\"\n", val);
11814     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11815 
11816     /* guid with brackets */
11817     size = MAX_PATH;
11818     lstrcpyA(val, "apple");
11819     r = pMsiGetPatchInfoExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", prodcode,
11820                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
11821                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11822     ok(r == ERROR_UNKNOWN_PRODUCT,
11823        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11824     ok(!lstrcmpA(val, "apple"),
11825        "Expected val to be unchanged, got \"%s\"\n", val);
11826     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11827 
11828     /* same length as guid, but random */
11829     size = MAX_PATH;
11830     lstrcpyA(val, "apple");
11831     r = pMsiGetPatchInfoExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", prodcode,
11832                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
11833                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11834     ok(r == ERROR_INVALID_PARAMETER,
11835        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11836     ok(!lstrcmpA(val, "apple"),
11837        "Expected val to be unchanged, got \"%s\"\n", val);
11838     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11839 
11840     /* NULL szProductCode */
11841     lstrcpyA(val, "apple");
11842     size = MAX_PATH;
11843     r = pMsiGetPatchInfoExA(patchcode, NULL, NULL, MSIINSTALLCONTEXT_USERMANAGED,
11844                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11845     ok(r == ERROR_INVALID_PARAMETER,
11846        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11847     ok(!lstrcmpA(val, "apple"),
11848        "Expected val to be unchanged, got \"%s\"\n", val);
11849     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11850 
11851     /* empty szProductCode */
11852     size = MAX_PATH;
11853     lstrcpyA(val, "apple");
11854     r = pMsiGetPatchInfoExA(patchcode, "", NULL, MSIINSTALLCONTEXT_USERMANAGED,
11855                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11856     ok(r == ERROR_INVALID_PARAMETER,
11857        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11858     ok(!lstrcmpA(val, "apple"),
11859        "Expected val to be unchanged, got \"%s\"\n", val);
11860     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11861 
11862     /* garbage szProductCode */
11863     size = MAX_PATH;
11864     lstrcpyA(val, "apple");
11865     r = pMsiGetPatchInfoExA(patchcode, "garbage", NULL,
11866                             MSIINSTALLCONTEXT_USERMANAGED,
11867                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11868     ok(r == ERROR_INVALID_PARAMETER,
11869        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11870     ok(!lstrcmpA(val, "apple"),
11871        "Expected val to be unchanged, got \"%s\"\n", val);
11872     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11873 
11874     /* guid without brackets */
11875     size = MAX_PATH;
11876     lstrcpyA(val, "apple");
11877     r = pMsiGetPatchInfoExA(patchcode, "6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
11878                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
11879                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11880     ok(r == ERROR_INVALID_PARAMETER,
11881        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11882     ok(!lstrcmpA(val, "apple"),
11883        "Expected val to be unchanged, got \"%s\"\n", val);
11884     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11885 
11886     /* guid with brackets */
11887     size = MAX_PATH;
11888     lstrcpyA(val, "apple");
11889     r = pMsiGetPatchInfoExA(patchcode, "{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
11890                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
11891                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11892     ok(r == ERROR_UNKNOWN_PRODUCT,
11893        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11894     ok(!lstrcmpA(val, "apple"),
11895        "Expected val to be unchanged, got \"%s\"\n", val);
11896     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11897 
11898     /* same length as guid, but random */
11899     size = MAX_PATH;
11900     lstrcpyA(val, "apple");
11901     r = pMsiGetPatchInfoExA(patchcode, "A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
11902                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
11903                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11904     ok(r == ERROR_INVALID_PARAMETER,
11905        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11906     ok(!lstrcmpA(val, "apple"),
11907        "Expected val to be unchanged, got \"%s\"\n", val);
11908     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11909 
11910     /* szUserSid cannot be S-1-5-18 for MSIINSTALLCONTEXT_USERMANAGED */
11911     size = MAX_PATH;
11912     lstrcpyA(val, "apple");
11913     r = pMsiGetPatchInfoExA(patchcode, prodcode, "S-1-5-18",
11914                             MSIINSTALLCONTEXT_USERMANAGED,
11915                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11916     ok(r == ERROR_INVALID_PARAMETER,
11917        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11918     ok(!lstrcmpA(val, "apple"),
11919        "Expected val to be unchanged, got \"%s\"\n", val);
11920     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11921 
11922     /* szUserSid cannot be S-1-5-18 for MSIINSTALLCONTEXT_USERUNMANAGED */
11923     size = MAX_PATH;
11924     lstrcpyA(val, "apple");
11925     r = pMsiGetPatchInfoExA(patchcode, prodcode, "S-1-5-18",
11926                             MSIINSTALLCONTEXT_USERUNMANAGED,
11927                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11928     ok(r == ERROR_INVALID_PARAMETER,
11929        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11930     ok(!lstrcmpA(val, "apple"),
11931        "Expected val to be unchanged, got \"%s\"\n", val);
11932     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11933 
11934     /* szUserSid cannot be S-1-5-18 for MSIINSTALLCONTEXT_MACHINE */
11935     size = MAX_PATH;
11936     lstrcpyA(val, "apple");
11937     r = pMsiGetPatchInfoExA(patchcode, prodcode, "S-1-5-18",
11938                             MSIINSTALLCONTEXT_MACHINE,
11939                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11940     ok(r == ERROR_INVALID_PARAMETER,
11941        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11942     ok(!lstrcmpA(val, "apple"),
11943        "Expected val to be unchanged, got \"%s\"\n", val);
11944     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11945 
11946     /* szUserSid must be NULL for MSIINSTALLCONTEXT_MACHINE */
11947     size = MAX_PATH;
11948     lstrcpyA(val, "apple");
11949     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11950                             MSIINSTALLCONTEXT_MACHINE,
11951                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11952     ok(r == ERROR_INVALID_PARAMETER,
11953        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11954     ok(!lstrcmpA(val, "apple"),
11955        "Expected val to be unchanged, got \"%s\"\n", val);
11956     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11957 
11958     /* dwContext is out of range */
11959     size = MAX_PATH;
11960     lstrcpyA(val, "apple");
11961     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11962                             MSIINSTALLCONTEXT_NONE,
11963                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11964     ok(r == ERROR_INVALID_PARAMETER,
11965        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11966     ok(!lstrcmpA(val, "apple"),
11967        "Expected val to be unchanged, got \"%s\"\n", val);
11968     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11969 
11970     /* dwContext is out of range */
11971     size = MAX_PATH;
11972     lstrcpyA(val, "apple");
11973     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11974                             MSIINSTALLCONTEXT_ALL,
11975                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11976     ok(r == ERROR_INVALID_PARAMETER,
11977        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11978     ok(!lstrcmpA(val, "apple"),
11979        "Expected val to be unchanged, got \"%s\"\n", val);
11980     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11981 
11982     /* dwContext is invalid */
11983     size = MAX_PATH;
11984     lstrcpyA(val, "apple");
11985     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid, 3,
11986                            INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11987     ok(r == ERROR_INVALID_PARAMETER,
11988        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11989     ok(!lstrcmpA(val, "apple"),
11990        "Expected val to be unchanged, got \"%s\"\n", val);
11991     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11992 
11993     /* MSIINSTALLCONTEXT_USERMANAGED */
11994 
11995     size = MAX_PATH;
11996     lstrcpyA(val, "apple");
11997     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11998                             MSIINSTALLCONTEXT_USERMANAGED,
11999                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12000     ok(r == ERROR_UNKNOWN_PRODUCT,
12001        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12002     ok(!lstrcmpA(val, "apple"),
12003        "Expected val to be unchanged, got \"%s\"\n", val);
12004     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12005 
12006     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
12007     lstrcatA(keypath, usersid);
12008     lstrcatA(keypath, "\\Products\\");
12009     lstrcatA(keypath, prod_squashed);
12010 
12011     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
12012     if (res == ERROR_ACCESS_DENIED)
12013     {
12014         skip("Not enough rights to perform tests\n");
12015         LocalFree(usersid);
12016         return;
12017     }
12018     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12019 
12020     /* local UserData product key exists */
12021     size = MAX_PATH;
12022     lstrcpyA(val, "apple");
12023     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12024                             MSIINSTALLCONTEXT_USERMANAGED,
12025                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12026     ok(r == ERROR_UNKNOWN_PRODUCT,
12027        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12028     ok(!lstrcmpA(val, "apple"),
12029        "Expected val to be unchanged, got \"%s\"\n", val);
12030     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12031 
12032     res = RegCreateKeyExA(udprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
12033     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12034 
12035     /* InstallProperties key exists */
12036     size = MAX_PATH;
12037     lstrcpyA(val, "apple");
12038     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12039                             MSIINSTALLCONTEXT_USERMANAGED,
12040                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12041     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, 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 %d\n", size);
12045 
12046     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
12047     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12048 
12049     /* Patches key exists */
12050     size = MAX_PATH;
12051     lstrcpyA(val, "apple");
12052     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12053                             MSIINSTALLCONTEXT_USERMANAGED,
12054                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12055     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCHA, got %d\n", r);
12056     ok(!lstrcmpA(val, "apple"),
12057        "Expected val to be unchanged, got \"%s\"\n", val);
12058     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12059 
12060     res = RegCreateKeyExA(patches, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
12061     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12062 
12063     /* Patches key exists */
12064     size = MAX_PATH;
12065     lstrcpyA(val, "apple");
12066     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12067                             MSIINSTALLCONTEXT_USERMANAGED,
12068                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12069     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12070     ok(!lstrcmpA(val, "apple"),
12071        "Expected val to be unchanged, got \"%s\"\n", val);
12072     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12073 
12074     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
12075     lstrcatA(keypath, usersid);
12076     lstrcatA(keypath, "\\Installer\\Products\\");
12077     lstrcatA(keypath, prod_squashed);
12078 
12079     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
12080     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12081 
12082     /* managed product key exists */
12083     size = MAX_PATH;
12084     lstrcpyA(val, "apple");
12085     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12086                             MSIINSTALLCONTEXT_USERMANAGED,
12087                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12088     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12089     ok(!lstrcmpA(val, "apple"),
12090        "Expected val to be unchanged, got \"%s\"\n", val);
12091     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12092 
12093     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &prodpatches, NULL);
12094     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12095 
12096     /* Patches key exists */
12097     size = MAX_PATH;
12098     lstrcpyA(val, "apple");
12099     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12100                             MSIINSTALLCONTEXT_USERMANAGED,
12101                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12102     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12103     ok(!lstrcmpA(val, "apple"),
12104        "Expected val to be unchanged, got \"%s\"\n", val);
12105     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12106 
12107     res = RegSetValueExA(prodpatches, patch_squashed, 0, REG_SZ,
12108                          (const BYTE *)"transforms", 11);
12109     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12110 
12111     /* specific patch value exists */
12112     size = MAX_PATH;
12113     lstrcpyA(val, "apple");
12114     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12115                             MSIINSTALLCONTEXT_USERMANAGED,
12116                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12117     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12118     ok(!lstrcmpA(val, "apple"),
12119        "Expected val to be unchanged, got \"%s\"\n", val);
12120     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12121 
12122     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
12123     lstrcatA(keypath, usersid);
12124     lstrcatA(keypath, "\\Patches\\");
12125     lstrcatA(keypath, patch_squashed);
12126 
12127     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udpatch, NULL);
12128     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12129 
12130     /* UserData Patches key exists */
12131     size = MAX_PATH;
12132     lstrcpyA(val, "apple");
12133     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12134                             MSIINSTALLCONTEXT_USERMANAGED,
12135                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12136     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12137     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
12138     ok(size == 0, "Expected 0, got %d\n", size);
12139 
12140     res = RegSetValueExA(udpatch, "ManagedLocalPackage", 0, REG_SZ,
12141                          (const BYTE *)"pack", 5);
12142     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12143 
12144     /* ManagedLocalPatch value exists */
12145     size = MAX_PATH;
12146     lstrcpyA(val, "apple");
12147     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12148                             MSIINSTALLCONTEXT_USERMANAGED,
12149                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12150     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12151     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12152     ok(size == 4, "Expected 4, got %d\n", size);
12153 
12154     size = MAX_PATH;
12155     lstrcpyA(val, "apple");
12156     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12157                             MSIINSTALLCONTEXT_USERMANAGED,
12158                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12159     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12160     ok(!lstrcmpA(val, "transforms"), "Expected \"transforms\", got \"%s\"\n", val);
12161     ok(size == 10, "Expected 10, got %d\n", size);
12162 
12163     res = RegSetValueExA(hpatch, "Installed", 0, REG_SZ,
12164                          (const BYTE *)"mydate", 7);
12165     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12166 
12167     /* Installed value exists */
12168     size = MAX_PATH;
12169     lstrcpyA(val, "apple");
12170     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12171                             MSIINSTALLCONTEXT_USERMANAGED,
12172                             INSTALLPROPERTY_INSTALLDATEA, val, &size);
12173     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12174     ok(!lstrcmpA(val, "mydate"), "Expected \"mydate\", got \"%s\"\n", val);
12175     ok(size == 6, "Expected 6, got %d\n", size);
12176 
12177     res = RegSetValueExA(hpatch, "Uninstallable", 0, REG_SZ,
12178                          (const BYTE *)"yes", 4);
12179     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12180 
12181     /* Uninstallable value exists */
12182     size = MAX_PATH;
12183     lstrcpyA(val, "apple");
12184     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12185                             MSIINSTALLCONTEXT_USERMANAGED,
12186                             INSTALLPROPERTY_UNINSTALLABLEA, val, &size);
12187     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12188     ok(!lstrcmpA(val, "yes"), "Expected \"yes\", got \"%s\"\n", val);
12189     ok(size == 3, "Expected 3, got %d\n", size);
12190 
12191     res = RegSetValueExA(hpatch, "State", 0, REG_SZ,
12192                          (const BYTE *)"good", 5);
12193     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12194 
12195     /* State value exists */
12196     size = MAX_PATH;
12197     lstrcpyA(val, "apple");
12198     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12199                             MSIINSTALLCONTEXT_USERMANAGED,
12200                             INSTALLPROPERTY_PATCHSTATEA, val, &size);
12201     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12202     ok(!lstrcmpA(val, "good"), "Expected \"good\", got \"%s\"\n", val);
12203     ok(size == 4, "Expected 4, got %d\n", size);
12204 
12205     size = 1;
12206     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
12207                          (const BYTE *)&size, sizeof(DWORD));
12208     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12209 
12210     /* State value exists */
12211     size = MAX_PATH;
12212     lstrcpyA(val, "apple");
12213     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12214                             MSIINSTALLCONTEXT_USERMANAGED,
12215                             INSTALLPROPERTY_PATCHSTATEA, val, &size);
12216     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12217     ok(!lstrcmpA(val, "1"), "Expected \"1\", got \"%s\"\n", val);
12218     ok(size == 1, "Expected 1, got %d\n", size);
12219 
12220     size = 1;
12221     res = RegSetValueExA(hpatch, "Uninstallable", 0, REG_DWORD,
12222                          (const BYTE *)&size, sizeof(DWORD));
12223     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12224 
12225     /* Uninstallable value exists */
12226     size = MAX_PATH;
12227     lstrcpyA(val, "apple");
12228     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12229                             MSIINSTALLCONTEXT_USERMANAGED,
12230                             INSTALLPROPERTY_UNINSTALLABLEA, val, &size);
12231     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12232     ok(!lstrcmpA(val, "1"), "Expected \"1\", got \"%s\"\n", val);
12233     ok(size == 1, "Expected 1, got %d\n", size);
12234 
12235     res = RegSetValueExA(hpatch, "DisplayName", 0, REG_SZ,
12236                          (const BYTE *)"display", 8);
12237     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12238 
12239     /* DisplayName value exists */
12240     size = MAX_PATH;
12241     lstrcpyA(val, "apple");
12242     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12243                             MSIINSTALLCONTEXT_USERMANAGED,
12244                             INSTALLPROPERTY_DISPLAYNAMEA, val, &size);
12245     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12246     ok(!lstrcmpA(val, "display"), "Expected \"display\", got \"%s\"\n", val);
12247     ok(size == 7, "Expected 7, got %d\n", size);
12248 
12249     res = RegSetValueExA(hpatch, "MoreInfoURL", 0, REG_SZ,
12250                          (const BYTE *)"moreinfo", 9);
12251     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12252 
12253     /* MoreInfoURL value exists */
12254     size = MAX_PATH;
12255     lstrcpyA(val, "apple");
12256     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12257                             MSIINSTALLCONTEXT_USERMANAGED,
12258                             INSTALLPROPERTY_MOREINFOURLA, val, &size);
12259     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12260     ok(!lstrcmpA(val, "moreinfo"), "Expected \"moreinfo\", got \"%s\"\n", val);
12261     ok(size == 8, "Expected 8, got %d\n", size);
12262 
12263     /* szProperty is invalid */
12264     size = MAX_PATH;
12265     lstrcpyA(val, "apple");
12266     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12267                             MSIINSTALLCONTEXT_USERMANAGED,
12268                             "IDontExist", val, &size);
12269     ok(r == ERROR_UNKNOWN_PROPERTY,
12270        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
12271     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
12272     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
12273 
12274     /* lpValue is NULL, while pcchValue is non-NULL */
12275     size = MAX_PATH;
12276     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12277                             MSIINSTALLCONTEXT_USERMANAGED,
12278                             INSTALLPROPERTY_MOREINFOURLA, NULL, &size);
12279     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12280     ok(size == 16, "Expected 16, got %d\n", size);
12281 
12282     /* pcchValue is NULL, while lpValue is non-NULL */
12283     lstrcpyA(val, "apple");
12284     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12285                             MSIINSTALLCONTEXT_USERMANAGED,
12286                             INSTALLPROPERTY_MOREINFOURLA, val, NULL);
12287     ok(r == ERROR_INVALID_PARAMETER,
12288        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12289     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
12290 
12291     /* both lpValue and pcchValue are NULL */
12292     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12293                             MSIINSTALLCONTEXT_USERMANAGED,
12294                             INSTALLPROPERTY_MOREINFOURLA, NULL, NULL);
12295     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12296 
12297     /* pcchValue doesn't have enough room for NULL terminator */
12298     size = 8;
12299     lstrcpyA(val, "apple");
12300     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12301                             MSIINSTALLCONTEXT_USERMANAGED,
12302                             INSTALLPROPERTY_MOREINFOURLA, val, &size);
12303     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
12304     ok(!lstrcmpA(val, "moreinf"),
12305        "Expected \"moreinf\", got \"%s\"\n", val);
12306     ok(size == 16, "Expected 16, got %d\n", size);
12307 
12308     /* pcchValue has exactly enough room for NULL terminator */
12309     size = 9;
12310     lstrcpyA(val, "apple");
12311     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12312                             MSIINSTALLCONTEXT_USERMANAGED,
12313                             INSTALLPROPERTY_MOREINFOURLA, val, &size);
12314     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12315     ok(!lstrcmpA(val, "moreinfo"),
12316        "Expected \"moreinfo\", got \"%s\"\n", val);
12317     ok(size == 8, "Expected 8, got %d\n", size);
12318 
12319     /* pcchValue is too small, lpValue is NULL */
12320     size = 0;
12321     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12322                             MSIINSTALLCONTEXT_USERMANAGED,
12323                             INSTALLPROPERTY_MOREINFOURLA, NULL, &size);
12324     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12325     ok(size == 16, "Expected 16, got %d\n", size);
12326 
12327     RegDeleteValueA(prodpatches, patch_squashed);
12328     delete_key(prodpatches, "", access & KEY_WOW64_64KEY);
12329     RegCloseKey(prodpatches);
12330     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
12331     RegCloseKey(prodkey);
12332 
12333     /* UserData is sufficient for all properties
12334      * except INSTALLPROPERTY_TRANSFORMS
12335      */
12336     size = MAX_PATH;
12337     lstrcpyA(val, "apple");
12338     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12339                             MSIINSTALLCONTEXT_USERMANAGED,
12340                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12341     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12342     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12343     ok(size == 4, "Expected 4, got %d\n", size);
12344 
12345     /* UserData is sufficient for all properties
12346      * except INSTALLPROPERTY_TRANSFORMS
12347      */
12348     size = MAX_PATH;
12349     lstrcpyA(val, "apple");
12350     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12351                             MSIINSTALLCONTEXT_USERMANAGED,
12352                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12353     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12354     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
12355     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
12356 
12357     RegDeleteValueA(hpatch, "MoreInfoURL");
12358     RegDeleteValueA(hpatch, "Display");
12359     RegDeleteValueA(hpatch, "State");
12360     RegDeleteValueA(hpatch, "Uninstallable");
12361     RegDeleteValueA(hpatch, "Installed");
12362     RegDeleteValueA(udpatch, "ManagedLocalPackage");
12363     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
12364     RegCloseKey(udpatch);
12365     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
12366     RegCloseKey(hpatch);
12367     delete_key(patches, "", access & KEY_WOW64_64KEY);
12368     RegCloseKey(patches);
12369     delete_key(props, "", access & KEY_WOW64_64KEY);
12370     RegCloseKey(props);
12371     delete_key(udprod, "", access & KEY_WOW64_64KEY);
12372     RegCloseKey(udprod);
12373 
12374     /* MSIINSTALLCONTEXT_USERUNMANAGED */
12375 
12376     size = MAX_PATH;
12377     lstrcpyA(val, "apple");
12378     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12379                             MSIINSTALLCONTEXT_USERUNMANAGED,
12380                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12381     ok(r == ERROR_UNKNOWN_PRODUCT,
12382        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12383     ok(!lstrcmpA(val, "apple"),
12384        "Expected val to be unchanged, got \"%s\"\n", val);
12385     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12386 
12387     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
12388     lstrcatA(keypath, usersid);
12389     lstrcatA(keypath, "\\Products\\");
12390     lstrcatA(keypath, prod_squashed);
12391 
12392     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
12393     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12394 
12395     /* local UserData product key exists */
12396     size = MAX_PATH;
12397     lstrcpyA(val, "apple");
12398     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12399                             MSIINSTALLCONTEXT_USERUNMANAGED,
12400                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12401     ok(r == ERROR_UNKNOWN_PRODUCT,
12402        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12403     ok(!lstrcmpA(val, "apple"),
12404        "Expected val to be unchanged, got \"%s\"\n", val);
12405     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12406 
12407     res = RegCreateKeyExA(udprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
12408     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12409 
12410     /* InstallProperties key exists */
12411     size = MAX_PATH;
12412     lstrcpyA(val, "apple");
12413     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12414                             MSIINSTALLCONTEXT_USERUNMANAGED,
12415                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12416     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12417     ok(!lstrcmpA(val, "apple"),
12418        "Expected val to be unchanged, got \"%s\"\n", val);
12419     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12420 
12421     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
12422     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12423 
12424     /* Patches key exists */
12425     size = MAX_PATH;
12426     lstrcpyA(val, "apple");
12427     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12428                             MSIINSTALLCONTEXT_USERUNMANAGED,
12429                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12430     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12431     ok(!lstrcmpA(val, "apple"),
12432        "Expected val to be unchanged, got \"%s\"\n", val);
12433     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12434 
12435     res = RegCreateKeyExA(patches, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
12436     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12437 
12438     /* Patches key exists */
12439     size = MAX_PATH;
12440     lstrcpyA(val, "apple");
12441     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12442                             MSIINSTALLCONTEXT_USERUNMANAGED,
12443                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12444     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12445     ok(!lstrcmpA(val, "apple"),
12446        "Expected val to be unchanged, got \"%s\"\n", val);
12447     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12448 
12449     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
12450     lstrcatA(keypath, prod_squashed);
12451 
12452     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
12453     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12454 
12455     /* current user product key exists */
12456     size = MAX_PATH;
12457     lstrcpyA(val, "apple");
12458     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12459                             MSIINSTALLCONTEXT_USERUNMANAGED,
12460                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12461     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12462     ok(!lstrcmpA(val, "apple"),
12463        "Expected val to be unchanged, got \"%s\"\n", val);
12464     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12465 
12466     res = RegCreateKeyA(prodkey, "Patches", &prodpatches);
12467     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12468 
12469     /* Patches key exists */
12470     size = MAX_PATH;
12471     lstrcpyA(val, "apple");
12472     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12473                             MSIINSTALLCONTEXT_USERUNMANAGED,
12474                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12475     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12476     ok(!lstrcmpA(val, "apple"),
12477        "Expected val to be unchanged, got \"%s\"\n", val);
12478     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12479 
12480     res = RegSetValueExA(prodpatches, patch_squashed, 0, REG_SZ,
12481                          (const BYTE *)"transforms", 11);
12482     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12483 
12484     /* specific patch value exists */
12485     size = MAX_PATH;
12486     lstrcpyA(val, "apple");
12487     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12488                             MSIINSTALLCONTEXT_USERUNMANAGED,
12489                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12490     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12491     ok(!lstrcmpA(val, "apple"),
12492        "Expected val to be unchanged, got \"%s\"\n", val);
12493     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12494 
12495     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
12496     lstrcatA(keypath, usersid);
12497     lstrcatA(keypath, "\\Patches\\");
12498     lstrcatA(keypath, patch_squashed);
12499 
12500     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udpatch, NULL);
12501     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12502 
12503     /* UserData Patches key exists */
12504     size = MAX_PATH;
12505     lstrcpyA(val, "apple");
12506     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12507                             MSIINSTALLCONTEXT_USERUNMANAGED,
12508                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12509     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12510     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
12511     ok(size == 0, "Expected 0, got %d\n", size);
12512 
12513     res = RegSetValueExA(udpatch, "LocalPackage", 0, REG_SZ,
12514                          (const BYTE *)"pack", 5);
12515     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12516 
12517     /* LocalPatch value exists */
12518     size = MAX_PATH;
12519     lstrcpyA(val, "apple");
12520     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12521                             MSIINSTALLCONTEXT_USERUNMANAGED,
12522                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12523     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12524     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12525     ok(size == 4, "Expected 4, got %d\n", size);
12526 
12527     size = MAX_PATH;
12528     lstrcpyA(val, "apple");
12529     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12530                             MSIINSTALLCONTEXT_USERUNMANAGED,
12531                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12532     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12533     ok(!lstrcmpA(val, "transforms"), "Expected \"transforms\", got \"%s\"\n", val);
12534     ok(size == 10, "Expected 10, got %d\n", size);
12535 
12536     RegDeleteValueA(prodpatches, patch_squashed);
12537     delete_key(prodpatches, "", access & KEY_WOW64_64KEY);
12538     RegCloseKey(prodpatches);
12539     RegDeleteKeyA(prodkey, "");
12540     RegCloseKey(prodkey);
12541 
12542     /* UserData is sufficient for all properties
12543      * except INSTALLPROPERTY_TRANSFORMS
12544      */
12545     size = MAX_PATH;
12546     lstrcpyA(val, "apple");
12547     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12548                             MSIINSTALLCONTEXT_USERUNMANAGED,
12549                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12550     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12551     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12552     ok(size == 4, "Expected 4, got %d\n", size);
12553 
12554     /* UserData is sufficient for all properties
12555      * except INSTALLPROPERTY_TRANSFORMS
12556      */
12557     size = MAX_PATH;
12558     lstrcpyA(val, "apple");
12559     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12560                             MSIINSTALLCONTEXT_USERUNMANAGED,
12561                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12562     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12563     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
12564     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
12565 
12566     RegDeleteValueA(udpatch, "LocalPackage");
12567     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
12568     RegCloseKey(udpatch);
12569     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
12570     RegCloseKey(hpatch);
12571     delete_key(patches, "", access & KEY_WOW64_64KEY);
12572     RegCloseKey(patches);
12573     delete_key(props, "", access & KEY_WOW64_64KEY);
12574     RegCloseKey(props);
12575     delete_key(udprod, "", access & KEY_WOW64_64KEY);
12576     RegCloseKey(udprod);
12577 
12578     /* MSIINSTALLCONTEXT_MACHINE */
12579 
12580     size = MAX_PATH;
12581     lstrcpyA(val, "apple");
12582     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12583                             MSIINSTALLCONTEXT_MACHINE,
12584                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12585     ok(r == ERROR_UNKNOWN_PRODUCT,
12586        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12587     ok(!lstrcmpA(val, "apple"),
12588        "Expected val to be unchanged, got \"%s\"\n", val);
12589     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12590 
12591     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
12592     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Products\\");
12593     lstrcatA(keypath, prod_squashed);
12594 
12595     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
12596     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12597 
12598     /* local UserData product key exists */
12599     size = MAX_PATH;
12600     lstrcpyA(val, "apple");
12601     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12602                             MSIINSTALLCONTEXT_MACHINE,
12603                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12604     ok(r == ERROR_UNKNOWN_PRODUCT,
12605        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12606     ok(!lstrcmpA(val, "apple"),
12607        "Expected val to be unchanged, got \"%s\"\n", val);
12608     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12609 
12610     res = RegCreateKeyExA(udprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
12611     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12612 
12613     /* InstallProperties key exists */
12614     size = MAX_PATH;
12615     lstrcpyA(val, "apple");
12616     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12617                             MSIINSTALLCONTEXT_MACHINE,
12618                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12619     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12620     ok(!lstrcmpA(val, "apple"),
12621        "Expected val to be unchanged, got \"%s\"\n", val);
12622     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12623 
12624     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
12625     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12626 
12627     /* Patches key exists */
12628     size = MAX_PATH;
12629     lstrcpyA(val, "apple");
12630     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12631                             MSIINSTALLCONTEXT_MACHINE,
12632                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12633     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12634     ok(!lstrcmpA(val, "apple"),
12635        "Expected val to be unchanged, got \"%s\"\n", val);
12636     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12637 
12638     res = RegCreateKeyExA(patches, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
12639     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12640 
12641     /* Patches key exists */
12642     size = MAX_PATH;
12643     lstrcpyA(val, "apple");
12644     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12645                             MSIINSTALLCONTEXT_MACHINE,
12646                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12647     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12648     ok(!lstrcmpA(val, "apple"),
12649        "Expected val to be unchanged, got \"%s\"\n", val);
12650     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12651 
12652     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
12653     lstrcatA(keypath, prod_squashed);
12654 
12655     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
12656     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12657 
12658     /* local product key exists */
12659     size = MAX_PATH;
12660     lstrcpyA(val, "apple");
12661     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12662                             MSIINSTALLCONTEXT_MACHINE,
12663                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12664     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12665     ok(!lstrcmpA(val, "apple"),
12666        "Expected val to be unchanged, got \"%s\"\n", val);
12667     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12668 
12669     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &prodpatches, NULL);
12670     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12671 
12672     /* Patches key exists */
12673     size = MAX_PATH;
12674     lstrcpyA(val, "apple");
12675     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12676                             MSIINSTALLCONTEXT_MACHINE,
12677                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12678     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12679     ok(!lstrcmpA(val, "apple"),
12680        "Expected val to be unchanged, got \"%s\"\n", val);
12681     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12682 
12683     res = RegSetValueExA(prodpatches, patch_squashed, 0, REG_SZ,
12684                          (const BYTE *)"transforms", 11);
12685     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12686 
12687     /* specific patch value exists */
12688     size = MAX_PATH;
12689     lstrcpyA(val, "apple");
12690     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12691                             MSIINSTALLCONTEXT_MACHINE,
12692                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12693     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12694     ok(!lstrcmpA(val, "apple"),
12695        "Expected val to be unchanged, got \"%s\"\n", val);
12696     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12697 
12698     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
12699     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Patches\\");
12700     lstrcatA(keypath, patch_squashed);
12701 
12702     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udpatch, NULL);
12703     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12704 
12705     /* UserData Patches key exists */
12706     size = MAX_PATH;
12707     lstrcpyA(val, "apple");
12708     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12709                             MSIINSTALLCONTEXT_MACHINE,
12710                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12711     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12712     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
12713     ok(size == 0, "Expected 0, got %d\n", size);
12714 
12715     res = RegSetValueExA(udpatch, "LocalPackage", 0, REG_SZ,
12716                          (const BYTE *)"pack", 5);
12717     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12718 
12719     /* LocalPatch value exists */
12720     size = MAX_PATH;
12721     lstrcpyA(val, "apple");
12722     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12723                             MSIINSTALLCONTEXT_MACHINE,
12724                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12725     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12726     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12727     ok(size == 4, "Expected 4, got %d\n", size);
12728 
12729     size = MAX_PATH;
12730     lstrcpyA(val, "apple");
12731     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12732                             MSIINSTALLCONTEXT_MACHINE,
12733                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12734     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12735     ok(!lstrcmpA(val, "transforms"), "Expected \"transforms\", got \"%s\"\n", val);
12736     ok(size == 10, "Expected 10, got %d\n", size);
12737 
12738     RegDeleteValueA(prodpatches, patch_squashed);
12739     delete_key(prodpatches, "", access & KEY_WOW64_64KEY);
12740     RegCloseKey(prodpatches);
12741     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
12742     RegCloseKey(prodkey);
12743 
12744     /* UserData is sufficient for all properties
12745      * except INSTALLPROPERTY_TRANSFORMS
12746      */
12747     size = MAX_PATH;
12748     lstrcpyA(val, "apple");
12749     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12750                             MSIINSTALLCONTEXT_MACHINE,
12751                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12752     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12753     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12754     ok(size == 4, "Expected 4, got %d\n", size);
12755 
12756     /* UserData is sufficient for all properties
12757      * except INSTALLPROPERTY_TRANSFORMS
12758      */
12759     size = MAX_PATH;
12760     lstrcpyA(val, "apple");
12761     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
12762                             MSIINSTALLCONTEXT_MACHINE,
12763                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12764     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12765     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
12766     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
12767 
12768     RegDeleteValueA(udpatch, "LocalPackage");
12769     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
12770     RegCloseKey(udpatch);
12771     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
12772     RegCloseKey(hpatch);
12773     delete_key(patches, "", access & KEY_WOW64_64KEY);
12774     RegCloseKey(patches);
12775     delete_key(props, "", access & KEY_WOW64_64KEY);
12776     RegCloseKey(props);
12777     delete_key(udprod, "", access & KEY_WOW64_64KEY);
12778     RegCloseKey(udprod);
12779     LocalFree(usersid);
12780 }
12781 
12782 static void test_MsiGetPatchInfo(void)
12783 {
12784     UINT r;
12785     char prod_code[MAX_PATH], prod_squashed[MAX_PATH], val[MAX_PATH];
12786     char patch_code[MAX_PATH], patch_squashed[MAX_PATH], keypath[MAX_PATH];
12787     WCHAR valW[MAX_PATH], patch_codeW[MAX_PATH];
12788     HKEY hkey_product, hkey_patch, hkey_patches, hkey_udprops, hkey_udproduct;
12789     HKEY hkey_udpatch, hkey_udpatches, hkey_udproductpatches, hkey_udproductpatch;
12790     DWORD size;
12791     LONG res;
12792     REGSAM access = KEY_ALL_ACCESS;
12793 
12794     create_test_guid(patch_code, patch_squashed);
12795     create_test_guid(prod_code, prod_squashed);
12796     MultiByteToWideChar(CP_ACP, 0, patch_code, -1, patch_codeW, MAX_PATH);
12797 
12798     if (is_wow64)
12799         access |= KEY_WOW64_64KEY;
12800 
12801     r = MsiGetPatchInfoA(NULL, NULL, NULL, NULL);
12802     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
12803 
12804     r = MsiGetPatchInfoA(patch_code, NULL, NULL, NULL);
12805     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
12806 
12807     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, NULL, NULL);
12808     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
12809 
12810     size = 0;
12811     r = MsiGetPatchInfoA(patch_code, NULL, NULL, &size);
12812     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
12813 
12814     r = MsiGetPatchInfoA(patch_code, "", NULL, &size);
12815     ok(r == ERROR_UNKNOWN_PROPERTY, "expected ERROR_UNKNOWN_PROPERTY, got %u\n", r);
12816 
12817     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
12818     lstrcatA(keypath, prod_squashed);
12819 
12820     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey_product, NULL);
12821     if (res == ERROR_ACCESS_DENIED)
12822     {
12823         skip("Not enough rights to perform tests\n");
12824         return;
12825     }
12826     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
12827 
12828     /* product key exists */
12829     size = MAX_PATH;
12830     lstrcpyA(val, "apple");
12831     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12832     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
12833     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged, got \"%s\"\n", val);
12834     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
12835 
12836     res = RegCreateKeyExA(hkey_product, "Patches", 0, NULL, 0, access, NULL, &hkey_patches, NULL);
12837     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
12838 
12839     /* patches key exists */
12840     size = MAX_PATH;
12841     lstrcpyA(val, "apple");
12842     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12843     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
12844     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
12845     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
12846 
12847     res = RegCreateKeyExA(hkey_patches, patch_squashed, 0, NULL, 0, access, NULL, &hkey_patch, NULL);
12848     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
12849 
12850     /* patch key exists */
12851     size = MAX_PATH;
12852     lstrcpyA(val, "apple");
12853     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12854     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
12855     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
12856     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
12857 
12858     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
12859     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Products\\");
12860     lstrcatA(keypath, prod_squashed);
12861 
12862     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey_udproduct, NULL);
12863     if (res == ERROR_ACCESS_DENIED)
12864     {
12865         skip("Not enough rights to perform tests\n");
12866         goto done;
12867     }
12868     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
12869 
12870     /* UserData product key exists */
12871     size = MAX_PATH;
12872     lstrcpyA(val, "apple");
12873     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12874     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
12875     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
12876     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
12877 
12878     res = RegCreateKeyExA(hkey_udproduct, "InstallProperties", 0, NULL, 0, access, NULL, &hkey_udprops, NULL);
12879     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
12880 
12881     /* InstallProperties key exists */
12882     size = MAX_PATH;
12883     lstrcpyA(val, "apple");
12884     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12885     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
12886     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged, got \"%s\"\n", val);
12887     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
12888 
12889     res = RegCreateKeyExA(hkey_udproduct, "Patches", 0, NULL, 0, access, NULL, &hkey_udpatches, NULL);
12890     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
12891 
12892     /* UserData Patches key exists */
12893     size = MAX_PATH;
12894     lstrcpyA(val, "apple");
12895     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12896     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
12897     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
12898     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
12899 
12900     res = RegCreateKeyExA(hkey_udproduct, "Patches", 0, NULL, 0, access, NULL, &hkey_udproductpatches, NULL);
12901     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12902 
12903     res = RegCreateKeyExA(hkey_udproductpatches, patch_squashed, 0, NULL, 0, access, NULL, &hkey_udproductpatch, NULL);
12904     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12905 
12906     /* UserData product patch key exists */
12907     size = MAX_PATH;
12908     lstrcpyA(val, "apple");
12909     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12910     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
12911     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
12912     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
12913 
12914     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
12915     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Patches\\");
12916     lstrcatA(keypath, patch_squashed);
12917 
12918     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey_udpatch, NULL);
12919     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
12920 
12921     res = RegSetValueExA(hkey_udpatch, "LocalPackage", 0, REG_SZ, (const BYTE *)"c:\\test.msp", 12);
12922     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
12923 
12924     /* UserData Patch key exists */
12925     size = 0;
12926     lstrcpyA(val, "apple");
12927     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12928     ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", r);
12929     ok(!lstrcmpA(val, "apple"), "expected \"apple\", got \"%s\"\n", val);
12930     ok(size == 11, "expected 11 got %u\n", size);
12931 
12932     size = MAX_PATH;
12933     lstrcpyA(val, "apple");
12934     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12935     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS got %u\n", r);
12936     ok(!lstrcmpA(val, "c:\\test.msp"), "expected \"c:\\test.msp\", got \"%s\"\n", val);
12937     ok(size == 11, "expected 11 got %u\n", size);
12938 
12939     size = 0;
12940     valW[0] = 0;
12941     r = MsiGetPatchInfoW(patch_codeW, INSTALLPROPERTY_LOCALPACKAGEW, valW, &size);
12942     ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", r);
12943     ok(!valW[0], "expected 0 got %u\n", valW[0]);
12944     ok(size == 11, "expected 11 got %u\n", size);
12945 
12946     size = MAX_PATH;
12947     valW[0] = 0;
12948     r = MsiGetPatchInfoW(patch_codeW, INSTALLPROPERTY_LOCALPACKAGEW, valW, &size);
12949     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS got %u\n", r);
12950     ok(valW[0], "expected > 0 got %u\n", valW[0]);
12951     ok(size == 11, "expected 11 got %u\n", size);
12952 
12953     delete_key(hkey_udproductpatch, "", access & KEY_WOW64_64KEY);
12954     RegCloseKey(hkey_udproductpatch);
12955     delete_key(hkey_udproductpatches, "", access & KEY_WOW64_64KEY);
12956     RegCloseKey(hkey_udproductpatches);
12957     delete_key(hkey_udpatch, "", access & KEY_WOW64_64KEY);
12958     RegCloseKey(hkey_udpatch);
12959     delete_key(hkey_udpatches, "", access & KEY_WOW64_64KEY);
12960     RegCloseKey(hkey_udpatches);
12961     delete_key(hkey_udprops, "", access & KEY_WOW64_64KEY);
12962     RegCloseKey(hkey_udprops);
12963     delete_key(hkey_udproduct, "", access & KEY_WOW64_64KEY);
12964     RegCloseKey(hkey_udproduct);
12965 
12966 done:
12967     delete_key(hkey_patches, "", access & KEY_WOW64_64KEY);
12968     RegCloseKey(hkey_patches);
12969     delete_key(hkey_product, "", access & KEY_WOW64_64KEY);
12970     RegCloseKey(hkey_product);
12971     delete_key(hkey_patch, "", access & KEY_WOW64_64KEY);
12972     RegCloseKey(hkey_patch);
12973 }
12974 
12975 static void test_MsiEnumProducts(void)
12976 {
12977     UINT r;
12978     BOOL found1, found2, found3;
12979     DWORD index;
12980     char product1[39], product2[39], product3[39], guid[39];
12981     char product_squashed1[33], product_squashed2[33], product_squashed3[33];
12982     char keypath1[MAX_PATH], keypath2[MAX_PATH], keypath3[MAX_PATH];
12983     char *usersid;
12984     HKEY key1, key2, key3;
12985     REGSAM access = KEY_ALL_ACCESS;
12986 
12987     create_test_guid(product1, product_squashed1);
12988     create_test_guid(product2, product_squashed2);
12989     create_test_guid(product3, product_squashed3);
12990     usersid = get_user_sid();
12991 
12992     if (is_wow64)
12993         access |= KEY_WOW64_64KEY;
12994 
12995     strcpy(keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
12996     strcat(keypath2, usersid);
12997     strcat(keypath2, "\\Installer\\Products\\");
12998     strcat(keypath2, product_squashed2);
12999 
13000     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL);
13001     if (r == ERROR_ACCESS_DENIED)
13002     {
13003         skip("Not enough rights to perform tests\n");
13004         LocalFree(usersid);
13005         return;
13006     }
13007     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13008 
13009     strcpy(keypath1, "Software\\Classes\\Installer\\Products\\");
13010     strcat(keypath1, product_squashed1);
13011 
13012     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL);
13013     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13014 
13015     strcpy(keypath3, "Software\\Microsoft\\Installer\\Products\\");
13016     strcat(keypath3, product_squashed3);
13017 
13018     r = RegCreateKeyA(HKEY_CURRENT_USER, keypath3, &key3);
13019     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13020 
13021     index = 0;
13022     r = MsiEnumProductsA(index, guid);
13023     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13024 
13025     r = MsiEnumProductsA(index, NULL);
13026     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
13027 
13028     index = 2;
13029     r = MsiEnumProductsA(index, guid);
13030     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
13031 
13032     index = 0;
13033     r = MsiEnumProductsA(index, guid);
13034     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13035 
13036     found1 = found2 = found3 = FALSE;
13037     while ((r = MsiEnumProductsA(index, guid)) == ERROR_SUCCESS)
13038     {
13039         if (!strcmp(product1, guid)) found1 = TRUE;
13040         if (!strcmp(product2, guid)) found2 = TRUE;
13041         if (!strcmp(product3, guid)) found3 = TRUE;
13042         index++;
13043     }
13044     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %u\n", r);
13045     ok(found1, "product1 not found\n");
13046     ok(found2, "product2 not found\n");
13047     ros_skip_flaky
13048     ok(found3, "product3 not found\n");
13049 
13050     delete_key(key1, "", access & KEY_WOW64_64KEY);
13051     delete_key(key2, "", access & KEY_WOW64_64KEY);
13052     RegDeleteKeyA(key3, "");
13053     RegCloseKey(key1);
13054     RegCloseKey(key2);
13055     RegCloseKey(key3);
13056     LocalFree(usersid);
13057 }
13058 
13059 static void test_MsiGetFileSignatureInformation(void)
13060 {
13061     HRESULT hr;
13062     const CERT_CONTEXT *cert;
13063     DWORD len;
13064 
13065     hr = MsiGetFileSignatureInformationA( NULL, 0, NULL, NULL, NULL );
13066     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13067 
13068     hr = MsiGetFileSignatureInformationA( NULL, 0, NULL, NULL, &len );
13069     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13070 
13071     hr = MsiGetFileSignatureInformationA( NULL, 0, &cert, NULL, &len );
13072     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13073 
13074     hr = MsiGetFileSignatureInformationA( "", 0, NULL, NULL, NULL );
13075     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13076 
13077     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, NULL );
13078     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13079 
13080     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, &len );
13081     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13082 
13083     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, &cert, NULL, &len );
13084     todo_wine ok(hr == CRYPT_E_FILE_ERROR, "expected CRYPT_E_FILE_ERROR got 0x%08x\n", hr);
13085 
13086     create_file_data( "signature.bin", "signature", sizeof("signature") );
13087 
13088     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, NULL );
13089     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13090 
13091     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, &len );
13092     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13093 
13094     cert = (const CERT_CONTEXT *)0xdeadbeef;
13095     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, &cert, NULL, &len );
13096     todo_wine ok(hr == HRESULT_FROM_WIN32(ERROR_FUNCTION_FAILED), "got 0x%08x\n", hr);
13097     ok(cert == NULL, "got %p\n", cert);
13098 
13099     DeleteFileA( "signature.bin" );
13100 }
13101 
13102 static void test_MsiEnumProductsEx(void)
13103 {
13104     UINT r;
13105     DWORD len, index;
13106     MSIINSTALLCONTEXT context;
13107     char product0[39], product1[39], product2[39], product3[39], guid[39], sid[128];
13108     char product_squashed1[33], product_squashed2[33], product_squashed3[33];
13109     char keypath1[MAX_PATH], keypath2[MAX_PATH], keypath3[MAX_PATH];
13110     HKEY key1 = NULL, key2 = NULL, key3 = NULL;
13111     REGSAM access = KEY_ALL_ACCESS;
13112     char *usersid = get_user_sid();
13113 
13114     if (!pMsiEnumProductsExA)
13115     {
13116         win_skip("MsiEnumProductsExA not implemented\n");
13117         return;
13118     }
13119 
13120     create_test_guid( product0, NULL );
13121     create_test_guid( product1, product_squashed1 );
13122     create_test_guid( product2, product_squashed2 );
13123     create_test_guid( product3, product_squashed3 );
13124 
13125     if (is_wow64) access |= KEY_WOW64_64KEY;
13126 
13127     strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\" );
13128     strcat( keypath2, usersid );
13129     strcat( keypath2, "\\Installer\\Products\\" );
13130     strcat( keypath2, product_squashed2 );
13131 
13132     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
13133     if (r == ERROR_ACCESS_DENIED)
13134     {
13135         skip( "insufficient rights\n" );
13136         goto done;
13137     }
13138     ok( r == ERROR_SUCCESS, "got %u\n", r );
13139 
13140     strcpy( keypath1, "Software\\Classes\\Installer\\Products\\" );
13141     strcat( keypath1, product_squashed1 );
13142 
13143     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
13144     ok( r == ERROR_SUCCESS, "got %u\n", r );
13145 
13146     strcpy( keypath3, usersid );
13147     strcat( keypath3, "\\Software\\Microsoft\\Installer\\Products\\" );
13148     strcat( keypath3, product_squashed3 );
13149 
13150     r = RegCreateKeyExA( HKEY_USERS, keypath3, 0, NULL, 0, access, NULL, &key3, NULL );
13151     ok( r == ERROR_SUCCESS, "got %u\n", r );
13152 
13153     r = pMsiEnumProductsExA( NULL, NULL, 0, 0, NULL, NULL, NULL, NULL );
13154     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13155 
13156     len = sizeof(sid);
13157     r = pMsiEnumProductsExA( NULL, NULL, 0, 0, NULL, NULL, NULL, &len );
13158     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13159     ok( len == sizeof(sid), "got %u\n", len );
13160 
13161     r = pMsiEnumProductsExA( NULL, NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, NULL, NULL );
13162     ok( r == ERROR_SUCCESS, "got %u\n", r );
13163 
13164     sid[0] = 0;
13165     len = sizeof(sid);
13166     r = pMsiEnumProductsExA( product0, NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, &len );
13167     ok( r == ERROR_NO_MORE_ITEMS, "got %u\n", r );
13168     ok( len == sizeof(sid), "got %u\n", len );
13169     ok( !sid[0], "got %s\n", sid );
13170 
13171     sid[0] = 0;
13172     len = sizeof(sid);
13173     r = pMsiEnumProductsExA( product0, usersid, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, &len );
13174     ok( r == ERROR_NO_MORE_ITEMS, "got %u\n", r );
13175     ok( len == sizeof(sid), "got %u\n", len );
13176     ok( !sid[0], "got %s\n", sid );
13177 
13178     sid[0] = 0;
13179     len = 0;
13180     r = pMsiEnumProductsExA( NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, 0, NULL, NULL, sid, &len );
13181     ok( r == ERROR_MORE_DATA, "got %u\n", r );
13182     ok( len, "length unchanged\n" );
13183     ok( !sid[0], "got %s\n", sid );
13184 
13185     guid[0] = 0;
13186     context = 0xdeadbeef;
13187     sid[0] = 0;
13188     len = sizeof(sid);
13189     r = pMsiEnumProductsExA( NULL, NULL, MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
13190     ok( r == ERROR_SUCCESS, "got %u\n", r );
13191     ok( guid[0], "empty guid\n" );
13192     ok( context != 0xdeadbeef, "context unchanged\n" );
13193     ok( !len, "got %u\n", len );
13194     ok( !sid[0], "got %s\n", sid );
13195 
13196     guid[0] = 0;
13197     context = 0xdeadbeef;
13198     sid[0] = 0;
13199     len = sizeof(sid);
13200     r = pMsiEnumProductsExA( NULL, usersid, MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
13201     ok( r == ERROR_SUCCESS, "got %u\n", r );
13202     ok( guid[0], "empty guid\n" );
13203     ok( context != 0xdeadbeef, "context unchanged\n" );
13204     ok( !len, "got %u\n", len );
13205     ok( !sid[0], "got %s\n", sid );
13206 
13207     guid[0] = 0;
13208     context = 0xdeadbeef;
13209     sid[0] = 0;
13210     len = sizeof(sid);
13211     r = pMsiEnumProductsExA( NULL, "S-1-1-0", MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
13212     if (r == ERROR_ACCESS_DENIED)
13213     {
13214         skip( "insufficient rights\n" );
13215         goto done;
13216     }
13217     ok( r == ERROR_SUCCESS, "got %u\n", r );
13218     ok( guid[0], "empty guid\n" );
13219     ok( context != 0xdeadbeef, "context unchanged\n" );
13220     ok( !len, "got %u\n", len );
13221     ok( !sid[0], "got %s\n", sid );
13222 
13223     index = 0;
13224     guid[0] = 0;
13225     context = 0xdeadbeef;
13226     sid[0] = 0;
13227     len = sizeof(sid);
13228     while (!pMsiEnumProductsExA( NULL, "S-1-1-0", MSIINSTALLCONTEXT_ALL, index, guid, &context, sid, &len ))
13229     {
13230         if (!strcmp( product1, guid ))
13231         {
13232             ok( context == MSIINSTALLCONTEXT_MACHINE, "got %u\n", context );
13233             ok( !sid[0], "got \"%s\"\n", sid );
13234             ok( !len, "unexpected length %u\n", len );
13235         }
13236         else if (!strcmp( product2, guid ))
13237         {
13238             ok( context == MSIINSTALLCONTEXT_USERMANAGED, "got %u\n", context );
13239             ok( sid[0], "empty sid\n" );
13240             ok( len == strlen(sid), "unexpected length %u\n", len );
13241         }
13242         else if (!strcmp( product3, guid ))
13243         {
13244             ok( context == MSIINSTALLCONTEXT_USERUNMANAGED, "got %u\n", context );
13245             ok( sid[0], "empty sid\n" );
13246             ok( len == strlen(sid), "unexpected length %u\n", len );
13247         }
13248         else
13249         {
13250             trace("Unexpected guid: %s (have %s | %s | %s)\n", guid, product1, product2, product3);
13251             ok(context != MSIINSTALLCONTEXT_NONE, "got %u\n", context);
13252             ok(sid[0], "empty sid\n");
13253             ok(len == strlen(sid), "unexpected length %u\n", len);
13254         }
13255         index++;
13256         guid[0] = 0;
13257         context = 0xdeadbeef;
13258         sid[0] = 0;
13259         len = sizeof(sid);
13260     }
13261 
13262 done:
13263     delete_key( key1, "", access );
13264     delete_key( key2, "", access );
13265     delete_key( key3, "", access );
13266     RegCloseKey( key1 );
13267     RegCloseKey( key2 );
13268     RegCloseKey( key3 );
13269     LocalFree( usersid );
13270 }
13271 
13272 static void test_MsiEnumComponents(void)
13273 {
13274     UINT r;
13275     BOOL found1, found2;
13276     DWORD index;
13277     char comp1[39], comp2[39], guid[39];
13278     char comp_squashed1[33], comp_squashed2[33];
13279     char keypath1[MAX_PATH], keypath2[MAX_PATH];
13280     REGSAM access = KEY_ALL_ACCESS;
13281     char *usersid = get_user_sid();
13282     HKEY key1 = NULL, key2 = NULL;
13283 
13284     create_test_guid( comp1, comp_squashed1 );
13285     create_test_guid( comp2, comp_squashed2 );
13286 
13287     if (is_wow64) access |= KEY_WOW64_64KEY;
13288 
13289     strcpy( keypath1, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
13290     strcat( keypath1, "S-1-5-18\\Components\\" );
13291     strcat( keypath1, comp_squashed1 );
13292 
13293     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
13294     if (r == ERROR_ACCESS_DENIED)
13295     {
13296         skip( "insufficient rights\n" );
13297         goto done;
13298     }
13299     ok( r == ERROR_SUCCESS, "got %u\n", r );
13300 
13301     strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
13302     strcat( keypath2, usersid );
13303     strcat( keypath2, "\\Components\\" );
13304     strcat( keypath2, comp_squashed2 );
13305 
13306     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
13307     if (r == ERROR_ACCESS_DENIED)
13308     {
13309         skip( "insufficient rights\n" );
13310         goto done;
13311     }
13312 
13313     r = MsiEnumComponentsA( 0, NULL );
13314     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13315 
13316     index = 0;
13317     guid[0] = 0;
13318     found1 = found2 = FALSE;
13319     while (!MsiEnumComponentsA( index, guid ))
13320     {
13321         if (!strcmp( guid, comp1 )) found1 = TRUE;
13322         if (!strcmp( guid, comp2 )) found2 = TRUE;
13323         ok( guid[0], "empty guid\n" );
13324         guid[0] = 0;
13325         index++;
13326     }
13327     ok( found1, "comp1 not found\n" );
13328     ok( found2, "comp2 not found\n" );
13329 
13330 done:
13331     delete_key( key1, "", access );
13332     delete_key( key2, "", access );
13333     RegCloseKey( key1 );
13334     RegCloseKey( key2 );
13335     LocalFree( usersid );
13336 }
13337 
13338 static void test_MsiEnumComponentsEx(void)
13339 {
13340     UINT r;
13341     BOOL found1, found2;
13342     DWORD len, index;
13343     MSIINSTALLCONTEXT context;
13344     char comp1[39], comp2[39], guid[39], sid[128];
13345     char comp_squashed1[33], comp_squashed2[33];
13346     char keypath1[MAX_PATH], keypath2[MAX_PATH];
13347     HKEY key1 = NULL, key2 = NULL;
13348     REGSAM access = KEY_ALL_ACCESS;
13349     char *usersid = get_user_sid();
13350 
13351     if (!pMsiEnumComponentsExA)
13352     {
13353         win_skip( "MsiEnumComponentsExA not implemented\n" );
13354         return;
13355     }
13356     create_test_guid( comp1, comp_squashed1 );
13357     create_test_guid( comp2, comp_squashed2 );
13358 
13359     if (is_wow64) access |= KEY_WOW64_64KEY;
13360 
13361     strcpy( keypath1, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
13362     strcat( keypath1, "S-1-5-18\\Components\\" );
13363     strcat( keypath1, comp_squashed1 );
13364 
13365     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
13366     if (r == ERROR_ACCESS_DENIED)
13367     {
13368         skip( "insufficient rights\n" );
13369         goto done;
13370     }
13371     ok( r == ERROR_SUCCESS, "got %u\n", r );
13372 
13373     strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
13374     strcat( keypath2, usersid );
13375     strcat( keypath2, "\\Components\\" );
13376     strcat( keypath2, comp_squashed2 );
13377 
13378     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
13379     if (r == ERROR_ACCESS_DENIED)
13380     {
13381         skip( "insufficient rights\n" );
13382         goto done;
13383     }
13384     ok( r == ERROR_SUCCESS, "got %u\n", r );
13385     r = RegSetValueExA( key2, comp_squashed2, 0, REG_SZ, (const BYTE *)"c:\\doesnotexist",
13386                         sizeof("c:\\doesnotexist"));
13387     ok( r == ERROR_SUCCESS, "got %u\n", r );
13388 
13389     index = 0;
13390     guid[0] = 0;
13391     context = 0xdeadbeef;
13392     sid[0] = 0;
13393     len = sizeof(sid);
13394     found1 = found2 = FALSE;
13395     while (!pMsiEnumComponentsExA( "S-1-1-0", MSIINSTALLCONTEXT_ALL, index, guid, &context, sid, &len ))
13396     {
13397         if (!strcmp( comp1, guid ))
13398         {
13399             ok( context == MSIINSTALLCONTEXT_MACHINE, "got %u\n", context );
13400             ok( !sid[0], "got \"%s\"\n", sid );
13401             ok( !len, "unexpected length %u\n", len );
13402             found1 = TRUE;
13403         }
13404         if (!strcmp( comp2, guid ))
13405         {
13406             ok( context == MSIINSTALLCONTEXT_USERUNMANAGED, "got %u\n", context );
13407             ok( sid[0], "empty sid\n" );
13408             ok( len == strlen(sid), "unexpected length %u\n", len );
13409             found2 = TRUE;
13410         }
13411         index++;
13412         guid[0] = 0;
13413         context = 0xdeadbeef;
13414         sid[0] = 0;
13415         len = sizeof(sid);
13416     }
13417     ok( found1, "comp1 not found\n" );
13418     ok( found2, "comp2 not found\n" );
13419 
13420     r = pMsiEnumComponentsExA( NULL, 0, 0, NULL, NULL, NULL, NULL );
13421     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13422 
13423     r = pMsiEnumComponentsExA( NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, NULL );
13424     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13425 
13426 done:
13427     RegDeleteValueA( key2, comp_squashed2 );
13428     delete_key( key1, "", access );
13429     delete_key( key2, "", access );
13430     RegCloseKey( key1 );
13431     RegCloseKey( key2 );
13432     LocalFree( usersid );
13433 }
13434 
13435 static void test_MsiConfigureProductEx(void)
13436 {
13437     UINT r;
13438     LONG res;
13439     DWORD type, size;
13440     HKEY props, source;
13441     CHAR keypath[MAX_PATH * 2], localpackage[MAX_PATH], packagename[MAX_PATH];
13442     REGSAM access = KEY_ALL_ACCESS;
13443 
13444     if (is_process_limited())
13445     {
13446         skip("process is limited\n");
13447         return;
13448     }
13449 
13450     CreateDirectoryA("msitest", NULL);
13451     create_file_data("msitest\\hydrogen", "hydrogen", 500);
13452     create_file_data("msitest\\helium", "helium", 500);
13453     create_file_data("msitest\\lithium", "lithium", 500);
13454 
13455     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
13456 
13457     if (is_wow64)
13458         access |= KEY_WOW64_64KEY;
13459 
13460     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
13461 
13462     /* NULL szProduct */
13463     r = MsiConfigureProductExA(NULL, INSTALLLEVEL_DEFAULT,
13464                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
13465     ok(r == ERROR_INVALID_PARAMETER,
13466        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
13467 
13468     /* empty szProduct */
13469     r = MsiConfigureProductExA("", INSTALLLEVEL_DEFAULT,
13470                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
13471     ok(r == ERROR_INVALID_PARAMETER,
13472        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
13473 
13474     /* garbage szProduct */
13475     r = MsiConfigureProductExA("garbage", INSTALLLEVEL_DEFAULT,
13476                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
13477     ok(r == ERROR_INVALID_PARAMETER,
13478        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
13479 
13480     /* guid without brackets */
13481     r = MsiConfigureProductExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
13482                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13483                                "PROPVAR=42");
13484     ok(r == ERROR_INVALID_PARAMETER,
13485        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
13486 
13487     /* guid with brackets */
13488     r = MsiConfigureProductExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
13489                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13490                                "PROPVAR=42");
13491     ok(r == ERROR_UNKNOWN_PRODUCT,
13492        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
13493 
13494     /* same length as guid, but random */
13495     r = MsiConfigureProductExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
13496                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13497                                "PROPVAR=42");
13498     ok(r == ERROR_UNKNOWN_PRODUCT,
13499        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
13500 
13501     /* product not installed yet */
13502     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
13503                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13504                                "PROPVAR=42");
13505     ok(r == ERROR_UNKNOWN_PRODUCT,
13506        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
13507 
13508     /* install the product, per-user unmanaged */
13509     r = MsiInstallProductA(msifile, "INSTALLLEVEL=10 PROPVAR=42");
13510     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
13511     {
13512         skip("Not enough rights to perform tests\n");
13513         goto error;
13514     }
13515     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13516     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13517     ok(pf_exists("msitest\\helium"), "File not installed\n");
13518     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13519     ok(pf_exists("msitest"), "File not installed\n");
13520 
13521     /* product is installed per-user managed, remove it */
13522     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13523                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13524                                "PROPVAR=42");
13525     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13526     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
13527     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
13528     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
13529     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
13530 
13531     /* product has been removed */
13532     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13533                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13534                                "PROPVAR=42");
13535     ok(r == ERROR_UNKNOWN_PRODUCT,
13536        "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
13537 
13538     /* install the product, machine */
13539     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
13540     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13541     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13542     ok(pf_exists("msitest\\helium"), "File not installed\n");
13543     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13544     ok(pf_exists("msitest"), "File not installed\n");
13545 
13546     /* product is installed machine, remove it */
13547     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13548                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13549                                "PROPVAR=42");
13550     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13551     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
13552     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
13553     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
13554     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
13555 
13556     /* product has been removed */
13557     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13558                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13559                                "PROPVAR=42");
13560     ok(r == ERROR_UNKNOWN_PRODUCT,
13561        "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
13562 
13563     /* install the product, machine */
13564     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
13565     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13566     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13567     ok(pf_exists("msitest\\helium"), "File not installed\n");
13568     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13569     ok(pf_exists("msitest"), "File not installed\n");
13570 
13571     DeleteFileA(msifile);
13572 
13573     /* msifile is removed */
13574     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13575                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13576                                "PROPVAR=42");
13577     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13578     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
13579     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
13580     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
13581     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
13582 
13583     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
13584 
13585     /* install the product, machine */
13586     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
13587     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13588     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13589     ok(pf_exists("msitest\\helium"), "File not installed\n");
13590     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13591     ok(pf_exists("msitest"), "File not installed\n");
13592 
13593     DeleteFileA(msifile);
13594 
13595     lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
13596     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
13597     lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\InstallProperties");
13598 
13599     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &props);
13600     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13601 
13602     type = REG_SZ;
13603     size = MAX_PATH;
13604     res = RegQueryValueExA(props, "LocalPackage", NULL, &type,
13605                            (LPBYTE)localpackage, &size);
13606     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13607 
13608     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
13609                          (const BYTE *)"C:\\idontexist.msi", 18);
13610     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13611 
13612     /* LocalPackage is used to find the cached msi package */
13613     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13614                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13615                                "PROPVAR=42");
13616     ok(r == ERROR_INSTALL_SOURCE_ABSENT,
13617        "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
13618     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13619     ok(pf_exists("msitest\\helium"), "File not installed\n");
13620     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13621     ok(pf_exists("msitest"), "File not installed\n");
13622 
13623     RegCloseKey(props);
13624     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
13625 
13626     /* LastUsedSource can be used as a last resort */
13627     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13628                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13629                                "PROPVAR=42");
13630     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13631     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
13632     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
13633     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
13634     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
13635     DeleteFileA( localpackage );
13636 
13637     /* install the product, machine */
13638     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
13639     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13640     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13641     ok(pf_exists("msitest\\helium"), "File not installed\n");
13642     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13643     ok(pf_exists("msitest"), "File not installed\n");
13644 
13645     lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
13646     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
13647     lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\InstallProperties");
13648 
13649     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &props);
13650     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13651 
13652     type = REG_SZ;
13653     size = MAX_PATH;
13654     res = RegQueryValueExA(props, "LocalPackage", NULL, &type,
13655                            (LPBYTE)localpackage, &size);
13656     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13657 
13658     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
13659                          (const BYTE *)"C:\\idontexist.msi", 18);
13660     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13661 
13662     lstrcpyA(keypath, "SOFTWARE\\Classes\\Installer\\Products\\");
13663     lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\SourceList");
13664 
13665     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &source);
13666     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13667 
13668     type = REG_SZ;
13669     size = MAX_PATH;
13670     res = RegQueryValueExA(source, "PackageName", NULL, &type,
13671                            (LPBYTE)packagename, &size);
13672     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13673 
13674     res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
13675                          (const BYTE *)"idontexist.msi", 15);
13676     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13677 
13678     /* SourceList is altered */
13679     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13680                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13681                                "PROPVAR=42");
13682     ok(r == ERROR_INSTALL_SOURCE_ABSENT,
13683        "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
13684     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13685     ok(pf_exists("msitest\\helium"), "File not installed\n");
13686     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13687     ok(pf_exists("msitest"), "File not installed\n");
13688 
13689     /* restore PackageName */
13690     res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
13691                          (const BYTE *)packagename, lstrlenA(packagename) + 1);
13692     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13693 
13694     /* restore LocalPackage */
13695     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
13696                          (const BYTE *)localpackage, lstrlenA(localpackage) + 1);
13697     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13698 
13699     /* finally remove the product */
13700     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13701                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13702                                "PROPVAR=42");
13703     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13704     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
13705     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
13706     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
13707     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
13708 
13709     RegCloseKey(source);
13710     RegCloseKey(props);
13711 
13712 error:
13713     DeleteFileA("msitest\\hydrogen");
13714     DeleteFileA("msitest\\helium");
13715     DeleteFileA("msitest\\lithium");
13716     RemoveDirectoryA("msitest");
13717     DeleteFileA(msifile);
13718 }
13719 
13720 static void test_MsiSetFeatureAttributes(void)
13721 {
13722     UINT r;
13723     DWORD attrs;
13724     char path[MAX_PATH];
13725     MSIHANDLE package;
13726 
13727     if (is_process_limited())
13728     {
13729         skip("process is limited\n");
13730         return;
13731     }
13732     create_database( msifile, tables, sizeof(tables) / sizeof(tables[0]) );
13733 
13734     strcpy( path, CURR_DIR );
13735     strcat( path, "\\" );
13736     strcat( path, msifile );
13737 
13738     r = MsiOpenPackageA( path, &package );
13739     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
13740     {
13741         skip("Not enough rights to perform tests\n");
13742         DeleteFileA( msifile );
13743         return;
13744     }
13745     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13746 
13747     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
13748     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %u\n", r);
13749 
13750     r = MsiDoActionA( package, "CostInitialize" );
13751     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13752 
13753     r = MsiSetFeatureAttributesA( 0, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
13754     ok(r == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", r);
13755 
13756     r = MsiSetFeatureAttributesA( package, "", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
13757     ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
13758 
13759     r = MsiSetFeatureAttributesA( package, NULL, INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
13760     ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
13761 
13762     r = MsiSetFeatureAttributesA( package, "One", 0 );
13763     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13764 
13765     attrs = 0xdeadbeef;
13766     r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL );
13767     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13768     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL,
13769        "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got 0x%08x\n", attrs);
13770 
13771     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
13772     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13773 
13774     attrs = 0;
13775     r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL );
13776     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13777     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL,
13778        "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got 0x%08x\n", attrs);
13779 
13780     r = MsiDoActionA( package, "FileCost" );
13781     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13782 
13783     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORSOURCE );
13784     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13785 
13786     attrs = 0;
13787     r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL );
13788     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13789     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORSOURCE,
13790        "expected INSTALLFEATUREATTRIBUTE_FAVORSOURCE, got 0x%08x\n", attrs);
13791 
13792     r = MsiDoActionA( package, "CostFinalize" );
13793     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13794 
13795     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
13796     ok(r == ERROR_FUNCTION_FAILED, "expected ERROR_FUNCTION_FAILED, got %u\n", r);
13797 
13798     MsiCloseHandle( package );
13799     DeleteFileA( msifile );
13800 }
13801 
13802 static void test_MsiGetFeatureInfo(void)
13803 {
13804     UINT r;
13805     MSIHANDLE package;
13806     char title[32], help[32], path[MAX_PATH];
13807     DWORD attrs, title_len, help_len;
13808 
13809     if (is_process_limited())
13810     {
13811         skip("process is limited\n");
13812         return;
13813     }
13814     create_database( msifile, tables, sizeof(tables) / sizeof(tables[0]) );
13815 
13816     strcpy( path, CURR_DIR );
13817     strcat( path, "\\" );
13818     strcat( path, msifile );
13819 
13820     r = MsiOpenPackageA( path, &package );
13821     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
13822     {
13823         skip("Not enough rights to perform tests\n");
13824         DeleteFileA( msifile );
13825         return;
13826     }
13827     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13828 
13829     r = MsiGetFeatureInfoA( 0, NULL, NULL, NULL, NULL, NULL, NULL );
13830     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
13831 
13832     r = MsiGetFeatureInfoA( package, NULL, NULL, NULL, NULL, NULL, NULL );
13833     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
13834 
13835     r = MsiGetFeatureInfoA( package, "", NULL, NULL, NULL, NULL, NULL );
13836     ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
13837 
13838     r = MsiGetFeatureInfoA( package, "One", NULL, NULL, NULL, NULL, NULL );
13839     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13840 
13841     r = MsiGetFeatureInfoA( 0, "One", NULL, NULL, NULL, NULL, NULL );
13842     ok(r == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", r);
13843 
13844     title_len = help_len = 0;
13845     r = MsiGetFeatureInfoA( package, "One", NULL, NULL, &title_len, NULL, &help_len );
13846     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13847     ok(title_len == 3, "expected 3, got %u\n", title_len);
13848     ok(help_len == 3, "expected 3, got %u\n", help_len);
13849 
13850     title[0] = help[0] = 0;
13851     title_len = help_len = 0;
13852     r = MsiGetFeatureInfoA( package, "One", NULL, title, &title_len, help, &help_len );
13853     ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %u\n", r);
13854     ok(title_len == 3, "expected 3, got %u\n", title_len);
13855     ok(help_len == 3, "expected 3, got %u\n", help_len);
13856 
13857     attrs = 0;
13858     title[0] = help[0] = 0;
13859     title_len = sizeof(title);
13860     help_len = sizeof(help);
13861     r = MsiGetFeatureInfoA( package, "One", &attrs, title, &title_len, help, &help_len );
13862     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13863     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %u\n", attrs);
13864     ok(title_len == 3, "expected 3, got %u\n", title_len);
13865     ok(help_len == 3, "expected 3, got %u\n", help_len);
13866     ok(!strcmp(title, "One"), "expected \"One\", got \"%s\"\n", title);
13867     ok(!strcmp(help, "One"), "expected \"One\", got \"%s\"\n", help);
13868 
13869     attrs = 0;
13870     title[0] = help[0] = 0;
13871     title_len = sizeof(title);
13872     help_len = sizeof(help);
13873     r = MsiGetFeatureInfoA( package, "Two", &attrs, title, &title_len, help, &help_len );
13874     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13875     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %u\n", attrs);
13876     ok(!title_len, "expected 0, got %u\n", title_len);
13877     ok(!help_len, "expected 0, got %u\n", help_len);
13878     ok(!title[0], "expected \"\", got \"%s\"\n", title);
13879     ok(!help[0], "expected \"\", got \"%s\"\n", help);
13880 
13881     MsiCloseHandle( package );
13882     DeleteFileA( msifile );
13883 }
13884 
13885 static INT CALLBACK handler_a(LPVOID context, UINT type, LPCSTR msg)
13886 {
13887     return IDOK;
13888 }
13889 
13890 static INT CALLBACK handler_w(LPVOID context, UINT type, LPCWSTR msg)
13891 {
13892     return IDOK;
13893 }
13894 
13895 static INT CALLBACK handler_record(LPVOID context, UINT type, MSIHANDLE record)
13896 {
13897     return IDOK;
13898 }
13899 
13900 static void test_MsiSetInternalUI(void)
13901 {
13902     INSTALLUILEVEL level;
13903 
13904     level = MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
13905     ok(level == INSTALLUILEVEL_DEFAULT, "expected INSTALLUILEVEL_DEFAULT, got %d\n", level);
13906 
13907     level = MsiSetInternalUI(INSTALLUILEVEL_DEFAULT, NULL);
13908     ok(level == INSTALLUILEVEL_FULL, "expected INSTALLUILEVEL_FULL, got %d\n", level);
13909 
13910     level = MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE, NULL);
13911     ok(level == INSTALLUILEVEL_DEFAULT, "expected INSTALLUILEVEL_DEFAULT, got %d\n", level);
13912 
13913     level = MsiSetInternalUI(0xdeadbeef, NULL);
13914     ok(level == INSTALLUILEVEL_NOCHANGE, "expected INSTALLUILEVEL_NOCHANGE, got %d\n", level);
13915 }
13916 
13917 static void test_MsiSetExternalUI(void)
13918 {
13919     INSTALLUI_HANDLERA ret_a;
13920     INSTALLUI_HANDLERW ret_w;
13921     INSTALLUI_HANDLER_RECORD prev;
13922     UINT error;
13923 
13924     ret_a = MsiSetExternalUIA(handler_a, INSTALLLOGMODE_ERROR, NULL);
13925     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
13926 
13927     ret_a = MsiSetExternalUIA(NULL, 0, NULL);
13928     ok(ret_a == handler_a, "expected %p, got %p\n", handler_a, ret_a);
13929 
13930     /* Not present before Installer 3.1 */
13931     if (!pMsiSetExternalUIRecord) {
13932         win_skip("MsiSetExternalUIRecord is not available\n");
13933         return;
13934     }
13935 
13936     error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, &prev);
13937     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
13938     ok(prev == NULL, "expected NULL, got %p\n", prev);
13939 
13940     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
13941     error = pMsiSetExternalUIRecord(NULL, INSTALLLOGMODE_ERROR, NULL, &prev);
13942     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
13943     ok(prev == handler_record, "expected %p, got %p\n", handler_record, prev);
13944 
13945     ret_w = MsiSetExternalUIW(handler_w, INSTALLLOGMODE_ERROR, NULL);
13946     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
13947 
13948     ret_w = MsiSetExternalUIW(NULL, 0, NULL);
13949     ok(ret_w == handler_w, "expected %p, got %p\n", handler_w, ret_w);
13950 
13951     ret_a = MsiSetExternalUIA(handler_a, INSTALLLOGMODE_ERROR, NULL);
13952     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
13953 
13954     ret_w = MsiSetExternalUIW(handler_w, INSTALLLOGMODE_ERROR, NULL);
13955     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
13956 
13957     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
13958     error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, &prev);
13959     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
13960     ok(prev == NULL, "expected NULL, got %p\n", prev);
13961 
13962     ret_a = MsiSetExternalUIA(NULL, 0, NULL);
13963     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
13964 
13965     ret_w = MsiSetExternalUIW(NULL, 0, NULL);
13966     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
13967 
13968     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
13969     error = pMsiSetExternalUIRecord(NULL, 0, NULL, &prev);
13970     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
13971     ok(prev == handler_record, "expected %p, got %p\n", handler_record, prev);
13972 
13973     error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, NULL);
13974     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
13975 
13976     error = pMsiSetExternalUIRecord(NULL, 0, NULL, NULL);
13977     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
13978 }
13979 
13980 static void test_lastusedsource(void)
13981 {
13982     static const char prodcode[] = "{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}";
13983     char value[MAX_PATH], path[MAX_PATH];
13984     DWORD size;
13985     UINT r;
13986 
13987     if (!pMsiSourceListGetInfoA)
13988     {
13989         win_skip("MsiSourceListGetInfoA is not available\n");
13990         return;
13991     }
13992 
13993     CreateDirectoryA("msitest", NULL);
13994     create_file("maximus", 500);
13995     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
13996     DeleteFileA("maximus");
13997 
13998     create_database("msifile0.msi", lus0_tables, sizeof(lus0_tables) / sizeof(msi_table));
13999     create_database("msifile1.msi", lus1_tables, sizeof(lus1_tables) / sizeof(msi_table));
14000     create_database("msifile2.msi", lus2_tables, sizeof(lus2_tables) / sizeof(msi_table));
14001 
14002     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
14003 
14004     /* no cabinet file */
14005 
14006     size = MAX_PATH;
14007     lstrcpyA(value, "aaa");
14008     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14009                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14010     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14011     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
14012 
14013     r = MsiInstallProductA("msifile0.msi", "PUBLISH_PRODUCT=1");
14014     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14015     {
14016         skip("Not enough rights to perform tests\n");
14017         goto error;
14018     }
14019     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14020 
14021     lstrcpyA(path, CURR_DIR);
14022     lstrcatA(path, "\\");
14023 
14024     size = MAX_PATH;
14025     lstrcpyA(value, "aaa");
14026     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14027                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14028     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14029     ok(!lstrcmpA(value, path), "expected \"%s\", got \"%s\"\n", path, value);
14030     ok(size == lstrlenA(path), "expected %d, got %d\n", lstrlenA(path), size);
14031 
14032     r = MsiInstallProductA("msifile0.msi", "REMOVE=ALL");
14033     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14034 
14035     /* separate cabinet file */
14036 
14037     size = MAX_PATH;
14038     lstrcpyA(value, "aaa");
14039     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14040                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14041     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14042     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
14043 
14044     r = MsiInstallProductA("msifile1.msi", "PUBLISH_PRODUCT=1");
14045     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14046 
14047     lstrcpyA(path, CURR_DIR);
14048     lstrcatA(path, "\\");
14049 
14050     size = MAX_PATH;
14051     lstrcpyA(value, "aaa");
14052     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14053                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14054     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14055     ok(!lstrcmpA(value, path), "expected \"%s\", got \"%s\"\n", path, value);
14056     ok(size == lstrlenA(path), "expected %d, got %d\n", lstrlenA(path), size);
14057 
14058     r = MsiInstallProductA("msifile1.msi", "REMOVE=ALL");
14059     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14060 
14061     size = MAX_PATH;
14062     lstrcpyA(value, "aaa");
14063     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14064                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14065     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14066     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
14067 
14068     /* embedded cabinet stream */
14069 
14070     add_cabinet_storage("msifile2.msi", "test1.cab");
14071 
14072     r = MsiInstallProductA("msifile2.msi", "PUBLISH_PRODUCT=1");
14073     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14074 
14075     size = MAX_PATH;
14076     lstrcpyA(value, "aaa");
14077     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14078                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14079     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14080     ok(!lstrcmpA(value, path), "expected \"%s\", got \"%s\"\n", path, value);
14081     ok(size == lstrlenA(path), "expected %d, got %d\n", lstrlenA(path), size);
14082 
14083     r = MsiInstallProductA("msifile2.msi", "REMOVE=ALL");
14084     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14085 
14086     size = MAX_PATH;
14087     lstrcpyA(value, "aaa");
14088     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14089                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14090     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14091     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
14092 
14093 error:
14094     delete_cab_files();
14095     DeleteFileA("msitest\\maximus");
14096     RemoveDirectoryA("msitest");
14097     DeleteFileA("msifile0.msi");
14098     DeleteFileA("msifile1.msi");
14099     DeleteFileA("msifile2.msi");
14100 }
14101 
14102 static void test_setpropertyfolder(void)
14103 {
14104     UINT r;
14105     CHAR path[MAX_PATH];
14106     DWORD attr;
14107 
14108     if (is_process_limited())
14109     {
14110         skip("process is limited\n");
14111         return;
14112     }
14113 
14114     lstrcpyA(path, PROG_FILES_DIR);
14115     lstrcatA(path, "\\msitest\\added");
14116 
14117     CreateDirectoryA("msitest", NULL);
14118     create_file("msitest\\maximus", 500);
14119 
14120     create_database(msifile, spf_tables, sizeof(spf_tables) / sizeof(msi_table));
14121 
14122     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
14123 
14124     r = MsiInstallProductA(msifile, NULL);
14125     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14126     {
14127         skip("Not enough rights to perform tests\n");
14128         goto error;
14129     }
14130     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14131     attr = GetFileAttributesA(path);
14132     if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY))
14133     {
14134         ok(delete_pf("msitest\\added\\maximus", TRUE), "File not installed\n");
14135         ok(delete_pf("msitest\\added", FALSE), "Directory not created\n");
14136         ok(delete_pf("msitest", FALSE), "Directory not created\n");
14137     }
14138     else
14139     {
14140         trace("changing folder property not supported\n");
14141         ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
14142         ok(delete_pf("msitest", FALSE), "Directory not created\n");
14143     }
14144 
14145 error:
14146     DeleteFileA(msifile);
14147     DeleteFileA("msitest\\maximus");
14148     RemoveDirectoryA("msitest");
14149 }
14150 
14151 static void test_sourcedir_props(void)
14152 {
14153     UINT r;
14154 
14155     if (is_process_limited())
14156     {
14157         skip("process is limited\n");
14158         return;
14159     }
14160 
14161     create_test_files();
14162     create_file("msitest\\sourcedir.txt", 1000);
14163     create_database(msifile, sd_tables, sizeof(sd_tables) / sizeof(msi_table));
14164 
14165     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
14166 
14167     /* full UI, no ResolveSource action */
14168     r = MsiInstallProductA(msifile, NULL);
14169     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14170 
14171     r = MsiInstallProductA(msifile, "REMOVE=ALL");
14172     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14173 
14174     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
14175     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
14176 
14177     /* full UI, ResolveSource action */
14178     r = MsiInstallProductA(msifile, "ResolveSource=1");
14179     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14180 
14181     r = MsiInstallProductA(msifile, "REMOVE=ALL");
14182     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14183 
14184     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
14185     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
14186 
14187     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
14188 
14189     /* no UI, no ResolveSource action */
14190     r = MsiInstallProductA(msifile, NULL);
14191     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14192 
14193     r = MsiInstallProductA(msifile, "REMOVE=ALL");
14194     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14195 
14196     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
14197     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
14198 
14199     /* no UI, ResolveSource action */
14200     r = MsiInstallProductA(msifile, "ResolveSource=1");
14201     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14202 
14203     r = MsiInstallProductA(msifile, "REMOVE=ALL");
14204     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14205 
14206     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
14207     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
14208 
14209     DeleteFileA("msitest\\sourcedir.txt");
14210     delete_test_files();
14211     DeleteFileA(msifile);
14212 }
14213 
14214 static void test_concurrentinstall(void)
14215 {
14216     UINT r;
14217     CHAR path[MAX_PATH];
14218 
14219     if (is_process_limited())
14220     {
14221         skip("process is limited\n");
14222         return;
14223     }
14224 
14225     CreateDirectoryA("msitest", NULL);
14226     CreateDirectoryA("msitest\\msitest", NULL);
14227     create_file("msitest\\maximus", 500);
14228     create_file("msitest\\msitest\\augustus", 500);
14229 
14230     create_database(msifile, ci_tables, sizeof(ci_tables) / sizeof(msi_table));
14231 
14232     lstrcpyA(path, CURR_DIR);
14233     lstrcatA(path, "\\msitest\\concurrent.msi");
14234     create_database(path, ci2_tables, sizeof(ci2_tables) / sizeof(msi_table));
14235 
14236     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
14237 
14238     r = MsiInstallProductA(msifile, NULL);
14239     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14240     {
14241         skip("Not enough rights to perform tests\n");
14242         goto error;
14243     }
14244     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14245     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
14246     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
14247     ok(delete_pf("msitest", FALSE), "Directory not created\n");
14248 
14249     r = MsiConfigureProductA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", INSTALLLEVEL_DEFAULT,
14250                              INSTALLSTATE_ABSENT);
14251     ok(r == ERROR_SUCCESS, "got %u\n", r);
14252 
14253     r = MsiConfigureProductA("{FF4AFE9C-6AC2-44F9-A060-9EA6BD16C75E}", INSTALLLEVEL_DEFAULT,
14254                              INSTALLSTATE_ABSENT);
14255     ok(r == ERROR_SUCCESS, "got %u\n", r);
14256 
14257 error:
14258     DeleteFileA(path);
14259     DeleteFileA(msifile);
14260     DeleteFileA("msitest\\msitest\\augustus");
14261     DeleteFileA("msitest\\maximus");
14262     RemoveDirectoryA("msitest\\msitest");
14263     RemoveDirectoryA("msitest");
14264 }
14265 
14266 static void test_command_line_parsing(void)
14267 {
14268     UINT r;
14269     const char *cmd;
14270 
14271     if (is_process_limited())
14272     {
14273         skip("process is limited\n");
14274         return;
14275     }
14276 
14277     create_test_files();
14278     create_database(msifile, cl_tables, sizeof(cl_tables)/sizeof(msi_table));
14279 
14280     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
14281 
14282     cmd = " ";
14283     r = MsiInstallProductA(msifile, cmd);
14284     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14285 
14286     cmd = "=";
14287     r = MsiInstallProductA(msifile, cmd);
14288     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14289 
14290     cmd = "==";
14291     r = MsiInstallProductA(msifile, cmd);
14292     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14293 
14294     cmd = "one";
14295     r = MsiInstallProductA(msifile, cmd);
14296     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14297 
14298     cmd = "=one";
14299     r = MsiInstallProductA(msifile, cmd);
14300     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14301 
14302     cmd = "P=";
14303     r = MsiInstallProductA(msifile, cmd);
14304     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14305 
14306     cmd = "  P=";
14307     r = MsiInstallProductA(msifile, cmd);
14308     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14309 
14310     cmd = "P=  ";
14311     r = MsiInstallProductA(msifile, cmd);
14312     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14313 
14314     cmd = "P=\"";
14315     r = MsiInstallProductA(msifile, cmd);
14316     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14317 
14318     cmd = "P=\"\"";
14319     r = MsiInstallProductA(msifile, cmd);
14320     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14321 
14322     cmd = "P=\"\"\"";
14323     r = MsiInstallProductA(msifile, cmd);
14324     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14325 
14326     cmd = "P=\"\"\"\"";
14327     r = MsiInstallProductA(msifile, cmd);
14328     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14329 
14330     cmd = "P=\" ";
14331     r = MsiInstallProductA(msifile, cmd);
14332     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14333 
14334     cmd = "P= \"";
14335     r = MsiInstallProductA(msifile, cmd);
14336     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14337 
14338     cmd = "P= \"\" ";
14339     r = MsiInstallProductA(msifile, cmd);
14340     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14341 
14342     cmd = "P=\"  \"";
14343     r = MsiInstallProductA(msifile, cmd);
14344     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14345 
14346     cmd = "P=one";
14347     r = MsiInstallProductA(msifile, cmd);
14348     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14349 
14350     cmd = "P= one";
14351     r = MsiInstallProductA(msifile, cmd);
14352     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14353 
14354     cmd = "P=\"one";
14355     r = MsiInstallProductA(msifile, cmd);
14356     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14357 
14358     cmd = "P=one\"";
14359     r = MsiInstallProductA(msifile, cmd);
14360     todo_wine ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14361 
14362     cmd = "P=\"one\"";
14363     r = MsiInstallProductA(msifile, cmd);
14364     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14365 
14366     cmd = "P= \"one\" ";
14367     r = MsiInstallProductA(msifile, cmd);
14368     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14369 
14370     cmd = "P=\"one\"\"";
14371     r = MsiInstallProductA(msifile, cmd);
14372     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14373 
14374     cmd = "P=\"\"one\"";
14375     r = MsiInstallProductA(msifile, cmd);
14376     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14377 
14378     cmd = "P=\"\"one\"\"";
14379     r = MsiInstallProductA(msifile, cmd);
14380     todo_wine ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14381 
14382     cmd = "P=\"one two\"";
14383     r = MsiInstallProductA(msifile, cmd);
14384     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14385 
14386     cmd = "P=\"\"\"one\"\" two\"";
14387     r = MsiInstallProductA(msifile, cmd);
14388     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14389 
14390     cmd = "P=\"\"\"one\"\" two\" Q=three";
14391     r = MsiInstallProductA(msifile, cmd);
14392     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14393 
14394     cmd = "P=\"\" Q=\"two\"";
14395     r = MsiInstallProductA(msifile, cmd);
14396     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14397 
14398     cmd = "P=\"one\" Q=\"two\"";
14399     r = MsiInstallProductA(msifile, cmd);
14400     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14401 
14402     cmd = "P=\"one=two\"";
14403     r = MsiInstallProductA(msifile, cmd);
14404     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14405 
14406     cmd = "Q=\"\" P=\"one\"";
14407     r = MsiInstallProductA(msifile, cmd);
14408     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14409 
14410     cmd = "P=\"\"\"one\"\"\" Q=\"two\"";
14411     r = MsiInstallProductA(msifile, cmd);
14412     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14413 
14414     cmd = "P=\"one \"\"two\"\"\" Q=\"three\"";
14415     r = MsiInstallProductA(msifile, cmd);
14416     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14417 
14418     cmd = "P=\"\"\"one\"\" two\" Q=\"three\"";
14419     r = MsiInstallProductA(msifile, cmd);
14420     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14421 
14422     DeleteFileA(msifile);
14423     delete_test_files();
14424 }
14425 
14426 START_TEST(msi)
14427 {
14428     DWORD len;
14429     char temp_path[MAX_PATH], prev_path[MAX_PATH];
14430 
14431 #ifdef __REACTOS__
14432     if (!winetest_interactive &&
14433         !strcmp(winetest_platform, "windows"))
14434     {
14435         skip("ROSTESTS-180: Skipping msi_winetest:msi because it hangs on WHS-Testbot. Set winetest_interactive to run it anyway.\n");
14436         return;
14437     }
14438 #endif
14439 
14440     init_functionpointers();
14441 
14442     if (pIsWow64Process)
14443         pIsWow64Process(GetCurrentProcess(), &is_wow64);
14444 
14445     GetCurrentDirectoryA(MAX_PATH, prev_path);
14446     GetTempPathA(MAX_PATH, temp_path);
14447     SetCurrentDirectoryA(temp_path);
14448 
14449     lstrcpyA(CURR_DIR, temp_path);
14450     len = lstrlenA(CURR_DIR);
14451 
14452     if(len && (CURR_DIR[len - 1] == '\\'))
14453         CURR_DIR[len - 1] = 0;
14454 
14455     ok(get_system_dirs(), "failed to retrieve system dirs\n");
14456 
14457     test_usefeature();
14458     test_null();
14459     test_getcomponentpath();
14460     test_MsiGetFileHash();
14461     test_MsiSetInternalUI();
14462     test_MsiSetExternalUI();
14463 
14464     if (!pConvertSidToStringSidA)
14465         win_skip("ConvertSidToStringSidA not implemented\n");
14466     else
14467     {
14468         /* These tests rely on get_user_sid that needs ConvertSidToStringSidA */
14469         test_MsiQueryProductState();
14470         test_MsiQueryFeatureState();
14471         test_MsiQueryComponentState();
14472         test_MsiGetComponentPath();
14473         test_MsiGetComponentPathEx();
14474         test_MsiProvideComponent();
14475         test_MsiGetProductCode();
14476         test_MsiEnumClients();
14477         test_MsiGetProductInfo();
14478         test_MsiGetProductInfoEx();
14479         test_MsiGetUserInfo();
14480         test_MsiOpenProduct();
14481         test_MsiEnumPatchesEx();
14482         test_MsiEnumPatches();
14483         test_MsiGetPatchInfoEx();
14484         test_MsiGetPatchInfo();
14485         test_MsiEnumProducts();
14486         test_MsiEnumProductsEx();
14487         test_MsiEnumComponents();
14488         test_MsiEnumComponentsEx();
14489     }
14490     test_MsiGetFileVersion();
14491     test_MsiGetFileSignatureInformation();
14492     test_MsiConfigureProductEx();
14493     test_MsiSetFeatureAttributes();
14494     test_MsiGetFeatureInfo();
14495     test_lastusedsource();
14496     test_setpropertyfolder();
14497     test_sourcedir_props();
14498     if (pMsiGetComponentPathExA)
14499         test_concurrentinstall();
14500     test_command_line_parsing();
14501     test_MsiProvideQualifiedComponentEx();
14502 
14503     SetCurrentDirectoryA(prev_path);
14504 }
14505