xref: /reactos/modules/rostests/winetests/msi/msi.c (revision f4be6dc3)
1 /*
2  * tests for Microsoft Installer functionality
3  *
4  * Copyright 2005 Mike McCormack for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #define _WIN32_MSI 300
22 #define COBJMACROS
23 
24 #include <stdio.h>
25 #include <windows.h>
26 #include <msi.h>
27 #include <msiquery.h>
28 #include <msidefs.h>
29 #include <sddl.h>
30 #include <fci.h>
31 #include <shellapi.h>
32 #include <objidl.h>
33 
34 #include "wine/test.h"
35 #include "utils.h"
36 
37 #define GUID_SIZE (39)
38 #define SQUASHED_GUID_SIZE (33)
39 
40 static BOOL is_wow64;
41 static const char msifile[] = "winetest.msi";
42 static const WCHAR msifileW[] = L"winetest.msi";
43 
44 /* cabinet definitions */
45 
46 /* make the max size large so there is only one cab file */
47 #define MEDIA_SIZE          0x7FFFFFFF
48 #define FOLDER_THRESHOLD    900000
49 
add_cabinet_storage(LPCSTR db,LPCSTR cabinet)50 static BOOL add_cabinet_storage(LPCSTR db, LPCSTR cabinet)
51 {
52     WCHAR dbW[MAX_PATH], cabinetW[MAX_PATH];
53     IStorage *stg;
54     IStream *stm;
55     HRESULT hr;
56     HANDLE handle;
57 
58     MultiByteToWideChar(CP_ACP, 0, db, -1, dbW, MAX_PATH);
59     hr = StgOpenStorage(dbW, NULL, STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
60     if (FAILED(hr))
61         return FALSE;
62 
63     MultiByteToWideChar(CP_ACP, 0, cabinet, -1, cabinetW, MAX_PATH);
64     hr = IStorage_CreateStream(stg, cabinetW, STGM_WRITE|STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
65     if (FAILED(hr))
66     {
67         IStorage_Release(stg);
68         return FALSE;
69     }
70 
71     handle = CreateFileW(cabinetW, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
72     if (handle != INVALID_HANDLE_VALUE)
73     {
74         DWORD count;
75         char buffer[1024];
76         if (ReadFile(handle, buffer, sizeof(buffer), &count, NULL))
77             IStream_Write(stm, buffer, count, &count);
78         CloseHandle(handle);
79     }
80 
81     IStream_Release(stm);
82     IStorage_Release(stg);
83 
84     return TRUE;
85 }
86 
87 /* msi database data */
88 
89 static const char directory_dat[] =
90     "Directory\tDirectory_Parent\tDefaultDir\n"
91     "s72\tS72\tl255\n"
92     "Directory\tDirectory\n"
93     "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
94     "ProgramFilesFolder\tTARGETDIR\t.\n"
95     "TARGETDIR\t\tSourceDir";
96 
97 static const char component_dat[] =
98     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
99     "s72\tS38\ts72\ti2\tS255\tS72\n"
100     "Component\tComponent\n"
101     "One\t{8F5BAEEF-DD92-40AC-9397-BE3CF9F97C81}\tMSITESTDIR\t2\tNOT REINSTALL\tone.txt\n";
102 
103 static const char feature_dat[] =
104     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
105     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
106     "Feature\tFeature\n"
107     "One\t\tOne\tOne\t1\t3\tMSITESTDIR\t0\n"
108     "Two\t\t\t\t2\t1\tTARGETDIR\t0\n";
109 
110 static const char feature_comp_dat[] =
111     "Feature_\tComponent_\n"
112     "s38\ts72\n"
113     "FeatureComponents\tFeature_\tComponent_\n"
114     "One\tOne\n";
115 
116 static const char file_dat[] =
117     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
118     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
119     "File\tFile\n"
120     "one.txt\tOne\tone.txt\t1000\t\t\t0\t1\n";
121 
122 static const char install_exec_seq_dat[] =
123     "Action\tCondition\tSequence\n"
124     "s72\tS255\tI2\n"
125     "InstallExecuteSequence\tAction\n"
126     "ValidateProductID\t\t700\n"
127     "CostInitialize\t\t800\n"
128     "FileCost\t\t900\n"
129     "CostFinalize\t\t1000\n"
130     "InstallValidate\t\t1400\n"
131     "InstallInitialize\t\t1500\n"
132     "ProcessComponents\t\t1600\n"
133     "UnpublishFeatures\t\t1800\n"
134     "RemoveFiles\t\t3500\n"
135     "InstallFiles\t\t4000\n"
136     "RegisterProduct\t\t6100\n"
137     "PublishFeatures\t\t6300\n"
138     "PublishProduct\t\t6400\n"
139     "InstallFinalize\t\t6600";
140 
141 static const char media_dat[] =
142     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
143     "i2\ti4\tL64\tS255\tS32\tS72\n"
144     "Media\tDiskId\n"
145     "1\t1\t\t\tDISK1\t\n";
146 
147 static const char property_dat[] =
148     "Property\tValue\n"
149     "s72\tl0\n"
150     "Property\tProperty\n"
151     "INSTALLLEVEL\t3\n"
152     "Manufacturer\tWine\n"
153     "ProductCode\t{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}\n"
154     "ProductName\tMSITEST\n"
155     "ProductVersion\t1.1.1\n"
156     "UpgradeCode\t{9574448F-9B86-4E07-B6F6-8D199DA12127}\n"
157     "MSIFASTINSTALL\t1\n";
158 
159 static const char ci2_property_dat[] =
160     "Property\tValue\n"
161     "s72\tl0\n"
162     "Property\tProperty\n"
163     "INSTALLLEVEL\t3\n"
164     "Manufacturer\tWine\n"
165     "ProductCode\t{FF4AFE9C-6AC2-44F9-A060-9EA6BD16C75E}\n"
166     "ProductName\tMSITEST2\n"
167     "ProductVersion\t1.1.1\n"
168     "UpgradeCode\t{6B60C3CA-B8CA-4FB7-A395-092D98FF5D2A}\n"
169     "MSIFASTINSTALL\t1\n";
170 
171 static const char mcp_component_dat[] =
172     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
173     "s72\tS38\ts72\ti2\tS255\tS72\n"
174     "Component\tComponent\n"
175     "hydrogen\t{C844BD1E-1907-4C00-8BC9-150BD70DF0A1}\tMSITESTDIR\t2\t\thydrogen\n"
176     "helium\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t2\t\thelium\n"
177     "lithium\t{4AF28FFC-71C7-4307-BDE4-B77C5338F56F}\tMSITESTDIR\t2\tPROPVAR=42\tlithium\n";
178 
179 static const char mcp_feature_dat[] =
180     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
181     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
182     "Feature\tFeature\n"
183     "hydroxyl\t\thydroxyl\thydroxyl\t2\t1\tTARGETDIR\t0\n"
184     "heliox\t\theliox\theliox\t2\t5\tTARGETDIR\t0\n"
185     "lithia\t\tlithia\tlithia\t2\t10\tTARGETDIR\t0";
186 
187 static const char mcp_feature_comp_dat[] =
188     "Feature_\tComponent_\n"
189     "s38\ts72\n"
190     "FeatureComponents\tFeature_\tComponent_\n"
191     "hydroxyl\thydrogen\n"
192     "heliox\thelium\n"
193     "lithia\tlithium";
194 
195 static const char mcp_file_dat[] =
196     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
197     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
198     "File\tFile\n"
199     "hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n"
200     "helium\thelium\thelium\t0\t\t\t8192\t1\n"
201     "lithium\tlithium\tlithium\t0\t\t\t8192\t1";
202 
203 static const char lus_component_dat[] =
204     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
205     "s72\tS38\ts72\ti2\tS255\tS72\n"
206     "Component\tComponent\n"
207     "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
208 
209 static const char lus_feature_dat[] =
210     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
211     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
212     "Feature\tFeature\n"
213     "feature\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0\n"
214     "montecristo\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0";
215 
216 static const char lus_file_dat[] =
217     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
218     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
219     "File\tFile\n"
220     "maximus\tmaximus\tmaximus\t500\t\t\t8192\t1";
221 
222 static const char lus_feature_comp_dat[] =
223     "Feature_\tComponent_\n"
224     "s38\ts72\n"
225     "FeatureComponents\tFeature_\tComponent_\n"
226     "feature\tmaximus\n"
227     "montecristo\tmaximus";
228 
229 static const char lus_install_exec_seq_dat[] =
230     "Action\tCondition\tSequence\n"
231     "s72\tS255\tI2\n"
232     "InstallExecuteSequence\tAction\n"
233     "ValidateProductID\t\t700\n"
234     "CostInitialize\t\t800\n"
235     "FileCost\t\t900\n"
236     "CostFinalize\t\t1000\n"
237     "InstallValidate\t\t1400\n"
238     "InstallInitialize\t\t1500\n"
239     "ProcessComponents\tPROCESS_COMPONENTS=1 Or FULL=1\t1600\n"
240     "UnpublishFeatures\tUNPUBLISH_FEATURES=1 Or FULL=1\t1800\n"
241     "RemoveFiles\t\t3500\n"
242     "InstallFiles\t\t4000\n"
243     "RegisterUser\tREGISTER_USER=1 Or FULL=1\t6000\n"
244     "RegisterProduct\tREGISTER_PRODUCT=1 Or FULL=1\t6100\n"
245     "PublishFeatures\tPUBLISH_FEATURES=1 Or FULL=1\t6300\n"
246     "PublishProduct\tPUBLISH_PRODUCT=1 Or FULL=1\t6400\n"
247     "InstallFinalize\t\t6600";
248 
249 static const char lus0_media_dat[] =
250     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
251     "i2\ti4\tL64\tS255\tS32\tS72\n"
252     "Media\tDiskId\n"
253     "1\t1\t\t\tDISK1\t\n";
254 
255 static const char lus1_media_dat[] =
256     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
257     "i2\ti4\tL64\tS255\tS32\tS72\n"
258     "Media\tDiskId\n"
259     "1\t1\t\ttest1.cab\tDISK1\t\n";
260 
261 static const char lus2_media_dat[] =
262     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
263     "i2\ti4\tL64\tS255\tS32\tS72\n"
264     "Media\tDiskId\n"
265     "1\t1\t\t#test1.cab\tDISK1\t\n";
266 
267 static const char spf_custom_action_dat[] =
268     "Action\tType\tSource\tTarget\tISComments\n"
269     "s72\ti2\tS64\tS0\tS255\n"
270     "CustomAction\tAction\n"
271     "SetFolderProp\t51\tMSITESTDIR\t[ProgramFilesFolder]\\msitest\\added\t\n"
272     "SetFolderProp2\t51\tMSITESTDIR\t[ProgramFilesFolder]\\msitest\\added\\added2\t\n";
273 
274 static const char spf_install_exec_seq_dat[] =
275     "Action\tCondition\tSequence\n"
276     "s72\tS255\tI2\n"
277     "InstallExecuteSequence\tAction\n"
278     "CostInitialize\t\t800\n"
279     "FileCost\t\t900\n"
280     "SetFolderProp\t\t950\n"
281     "SetFolderProp2\t\t960\n"
282     "CostFinalize\t\t1000\n"
283     "InstallValidate\t\t1400\n"
284     "InstallInitialize\t\t1500\n"
285     "InstallFiles\t\t4000\n"
286     "InstallServices\t\t5000\n"
287     "InstallFinalize\t\t6600\n";
288 
289 static const char spf_install_ui_seq_dat[] =
290     "Action\tCondition\tSequence\n"
291     "s72\tS255\tI2\n"
292     "InstallUISequence\tAction\n"
293     "CostInitialize\t\t800\n"
294     "FileCost\t\t900\n"
295     "CostFinalize\t\t1000\n"
296     "ExecuteAction\t\t1100\n";
297 
298 static const char spf_directory_dat[] =
299     "Directory\tDirectory_Parent\tDefaultDir\n"
300     "s72\tS72\tl255\n"
301     "Directory\tDirectory\n"
302     "PARENTDIR\tTARGETDIR\tparent\n"
303     "CHILDDIR\tPARENTDIR\tchild\n"
304     "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
305     "ProgramFilesFolder\tTARGETDIR\t.\n"
306     "TARGETDIR\t\tSourceDir";
307 
308 static const char spf_component_dat[] =
309     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
310     "s72\tS38\ts72\ti2\tS255\tS72\n"
311     "Component\tComponent\n"
312     "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
313 
314 static const char spf2_install_exec_seq_dat[] =
315     "Action\tCondition\tSequence\n"
316     "s72\tS255\tI2\n"
317     "InstallExecuteSequence\tAction\n"
318     "CostInitialize\t\t800\n"
319     "FileCost\t\t900\n"
320     "FormatParentFolderCheck\t\t910\n"
321     "FormatChildFolderCheck\t\t920\n"
322     "CheckParentFolder\tNOT PARENTDIR=PARENTDIRCHECK\t930\n"
323     "CheckChildFolder\tNOT CHILDDIR=CHILDDIRCHECK\t940\n"
324     "FormatParentFolderCheck2\t\t945\n"
325     "SetParentFolder\t\t950\n"
326     "CheckParentFolder2\tNOT PARENTDIR=PARENTDIRCHECK\t960\n"
327     "CheckChildFolder2\tNOT CHILDDIR=CHILDDIRCHECK\t970\n"
328     "CostFinalize\t\t1000\n"
329     "FormatParentFolderCheck3\t\t1005\n"
330     "CheckParentFolder3\tNOT PARENTDIR=PARENTDIRCHECK\t1010\n"
331     "CheckChildFolder3\tNOT CHILDDIR=CHILDDIRCHECK\t1020\n"
332     "InstallValidate\t\t1400\n"
333     "InstallInitialize\t\t1500\n"
334     "InstallFiles\t\t4000\n"
335     "CreateShortcuts\t\t4100\n"
336     "InstallFinalize\t\t6600\n";
337 
338 static const char spf2_custom_action_dat[] =
339     "Action\tType\tSource\tTarget\tISComments\n"
340     "s72\ti2\tS64\tS0\tS255\n"
341     "CustomAction\tAction\n"
342     "FormatParentFolderCheck\t51\tPARENTDIRCHECK\t[TARGETDIR]parent\\\t\n"
343     "FormatChildFolderCheck\t51\tCHILDDIRCHECK\t[TARGETDIR]parent\\child\\\t\n"
344     "CheckParentFolder\t19\tPARENTDIR\tparent prop wrong before set: [PARENTDIR]\t\n"
345     "CheckChildFolder\t19\tCHILDDIR\tchild prop wrong before set: [CHILDDIR]\t\n"
346     "FormatParentFolderCheck2\t51\tPARENTDIRCHECK\t[ProgramFilesFolder]msitest\\parent\t\n"
347     "SetParentFolder\t51\tPARENTDIR\t[PARENTDIRCHECK]\t\n"
348     "CheckParentFolder2\t19\tPARENTDIR\tparent prop wrong after set: [PARENTDIR]\t\n"
349     "CheckChildFolder2\t19\tCHILDDIR\tchild prop wrong after set: [CHILDDIR]\t\n"
350     "FormatParentFolderCheck3\t51\tPARENTDIRCHECK\t[ProgramFilesFolder]msitest\\parent\\\t\n"
351     "CheckParentFolder3\t19\tPARENTDIR\tparent prop wrong after CostFinalize: [PARENTDIR]\t\n"
352     "CheckChildFolder3\t19\tCHILDDIR\tchild prop wrong after CostFinalize: [CHILDDIR]\t\n";
353 
354 static const char shortcut_dat[] =
355     "Shortcut\tDirectory_\tName\tComponent_\tTarget\tArguments\tDescription\tHotkey\tIcon_\tIconIndex\tShowCmd\tWkDir\n"
356     "s72\ts72\tl128\ts72\ts72\tS255\tL255\tI2\tS72\tI2\tI2\tS72\n"
357     "Shortcut\tShortcut\n"
358     "Shortcut\tCHILDDIR\tShortcut\tmaximus\t[#maximus]\t\tShortcut\t\t\t\t\tMSITESTDIR\n";
359 
360 static const char sd_file_dat[] =
361     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
362     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
363     "File\tFile\n"
364     "sourcedir.txt\tsourcedir\tsourcedir.txt\t1000\t\t\t8192\t1\n";
365 
366 static const char sd_feature_dat[] =
367     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
368     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
369     "Feature\tFeature\n"
370     "sourcedir\t\t\tsourcedir feature\t1\t2\tMSITESTDIR\t0\n";
371 
372 static const char sd_feature_comp_dat[] =
373     "Feature_\tComponent_\n"
374     "s38\ts72\n"
375     "FeatureComponents\tFeature_\tComponent_\n"
376     "sourcedir\tsourcedir\n";
377 
378 static const char sd_component_dat[] =
379     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
380     "s72\tS38\ts72\ti2\tS255\tS72\n"
381     "Component\tComponent\n"
382     "sourcedir\t{DD422F92-3ED8-49B5-A0B7-F266F98357DF}\tMSITESTDIR\t0\t\tsourcedir.txt\n";
383 
384 static const char sd_install_ui_seq_dat[] =
385     "Action\tCondition\tSequence\n"
386     "s72\tS255\tI2\n"
387     "InstallUISequence\tAction\n"
388     "TestSourceDirProp1\tnot SourceDir and not SOURCEDIR and not Installed\t99\n"
389     "AppSearch\t\t100\n"
390     "TestSourceDirProp2\tnot SourceDir and not SOURCEDIR and not Installed\t101\n"
391     "LaunchConditions\tnot Installed \t110\n"
392     "TestSourceDirProp3\tnot SourceDir and not SOURCEDIR and not Installed\t111\n"
393     "FindRelatedProducts\t\t120\n"
394     "TestSourceDirProp4\tnot SourceDir and not SOURCEDIR and not Installed\t121\n"
395     "CCPSearch\t\t130\n"
396     "TestSourceDirProp5\tnot SourceDir and not SOURCEDIR and not Installed\t131\n"
397     "RMCCPSearch\t\t140\n"
398     "TestSourceDirProp6\tnot SourceDir and not SOURCEDIR and not Installed\t141\n"
399     "ValidateProductID\t\t150\n"
400     "TestSourceDirProp7\tnot SourceDir and not SOURCEDIR and not Installed\t151\n"
401     "CostInitialize\t\t800\n"
402     "TestSourceDirProp8\tnot SourceDir and not SOURCEDIR and not Installed\t801\n"
403     "FileCost\t\t900\n"
404     "TestSourceDirProp9\tnot SourceDir and not SOURCEDIR and not Installed\t901\n"
405     "IsolateComponents\t\t1000\n"
406     "TestSourceDirProp10\tnot SourceDir and not SOURCEDIR and not Installed\t1001\n"
407     "CostFinalize\t\t1100\n"
408     "TestSourceDirProp11\tnot SourceDir and not SOURCEDIR and not Installed\t1101\n"
409     "MigrateFeatureStates\t\t1200\n"
410     "TestSourceDirProp12\tnot SourceDir and not SOURCEDIR and not Installed\t1201\n"
411     "ExecuteAction\t\t1300\n"
412     "TestSourceDirProp13\tnot SourceDir and not SOURCEDIR and not Installed\t1301\n";
413 
414 static const char sd_install_exec_seq_dat[] =
415     "Action\tCondition\tSequence\n"
416     "s72\tS255\tI2\n"
417     "InstallExecuteSequence\tAction\n"
418     "TestSourceDirProp14\tSourceDir and SOURCEDIR and not Installed\t99\n"
419     "LaunchConditions\t\t100\n"
420     "TestSourceDirProp15\tSourceDir and SOURCEDIR and not Installed\t101\n"
421     "ValidateProductID\t\t700\n"
422     "TestSourceDirProp16\tSourceDir and SOURCEDIR and not Installed\t701\n"
423     "CostInitialize\t\t800\n"
424     "TestSourceDirProp17\tSourceDir and SOURCEDIR and not Installed\t801\n"
425     "ResolveSource\tResolveSource and not Installed\t850\n"
426     "TestSourceDirProp18\tResolveSource and not SourceDir and not SOURCEDIR and not Installed\t851\n"
427     "TestSourceDirProp19\tnot ResolveSource and SourceDir and SOURCEDIR and not Installed\t852\n"
428     "FileCost\t\t900\n"
429     "TestSourceDirProp20\tSourceDir and SOURCEDIR and not Installed\t901\n"
430     "IsolateComponents\t\t1000\n"
431     "TestSourceDirProp21\tSourceDir and SOURCEDIR and not Installed\t1001\n"
432     "CostFinalize\t\t1100\n"
433     "TestSourceDirProp22\tSourceDir and SOURCEDIR and not Installed\t1101\n"
434     "MigrateFeatureStates\t\t1200\n"
435     "TestSourceDirProp23\tSourceDir and SOURCEDIR and not Installed\t1201\n"
436     "InstallValidate\t\t1400\n"
437     "TestSourceDirProp24\tSourceDir and SOURCEDIR and not Installed\t1401\n"
438     "InstallInitialize\t\t1500\n"
439     "TestSourceDirProp25\tSourceDir and SOURCEDIR and not Installed\t1501\n"
440     "ProcessComponents\t\t1600\n"
441     "TestSourceDirProp26\tnot SourceDir and not SOURCEDIR and not Installed\t1601\n"
442     "UnpublishFeatures\t\t1800\n"
443     "TestSourceDirProp27\tnot SourceDir and not SOURCEDIR and not Installed\t1801\n"
444     "RemoveFiles\t\t3500\n"
445     "TestSourceDirProp28\tnot SourceDir and not SOURCEDIR and not Installed\t3501\n"
446     "InstallFiles\t\t4000\n"
447     "TestSourceDirProp29\tnot SourceDir and not SOURCEDIR and not Installed\t4001\n"
448     "RegisterUser\t\t6000\n"
449     "TestSourceDirProp30\tnot SourceDir and not SOURCEDIR and not Installed\t6001\n"
450     "RegisterProduct\t\t6100\n"
451     "TestSourceDirProp31\tnot SourceDir and not SOURCEDIR and not Installed\t6101\n"
452     "PublishFeatures\t\t6300\n"
453     "TestSourceDirProp32\tnot SourceDir and not SOURCEDIR and not Installed\t6301\n"
454     "PublishProduct\t\t6400\n"
455     "TestSourceDirProp33\tnot SourceDir and not SOURCEDIR and not Installed\t6401\n"
456     "InstallExecute\t\t6500\n"
457     "TestSourceDirProp34\tnot SourceDir and not SOURCEDIR and not Installed\t6501\n"
458     "InstallFinalize\t\t6600\n"
459     "TestSourceDirProp35\tnot SourceDir and not SOURCEDIR and not Installed\t6601\n";
460 
461 static const char sd_custom_action_dat[] =
462     "Action\tType\tSource\tTarget\tISComments\n"
463     "s72\ti2\tS64\tS0\tS255\n"
464     "CustomAction\tAction\n"
465     "TestSourceDirProp1\t19\t\tTest 1 failed\t\n"
466     "TestSourceDirProp2\t19\t\tTest 2 failed\t\n"
467     "TestSourceDirProp3\t19\t\tTest 3 failed\t\n"
468     "TestSourceDirProp4\t19\t\tTest 4 failed\t\n"
469     "TestSourceDirProp5\t19\t\tTest 5 failed\t\n"
470     "TestSourceDirProp6\t19\t\tTest 6 failed\t\n"
471     "TestSourceDirProp7\t19\t\tTest 7 failed\t\n"
472     "TestSourceDirProp8\t19\t\tTest 8 failed\t\n"
473     "TestSourceDirProp9\t19\t\tTest 9 failed\t\n"
474     "TestSourceDirProp10\t19\t\tTest 10 failed\t\n"
475     "TestSourceDirProp11\t19\t\tTest 11 failed\t\n"
476     "TestSourceDirProp12\t19\t\tTest 12 failed\t\n"
477     "TestSourceDirProp13\t19\t\tTest 13 failed\t\n"
478     "TestSourceDirProp14\t19\t\tTest 14 failed\t\n"
479     "TestSourceDirProp15\t19\t\tTest 15 failed\t\n"
480     "TestSourceDirProp16\t19\t\tTest 16 failed\t\n"
481     "TestSourceDirProp17\t19\t\tTest 17 failed\t\n"
482     "TestSourceDirProp18\t19\t\tTest 18 failed\t\n"
483     "TestSourceDirProp19\t19\t\tTest 19 failed\t\n"
484     "TestSourceDirProp20\t19\t\tTest 20 failed\t\n"
485     "TestSourceDirProp21\t19\t\tTest 21 failed\t\n"
486     "TestSourceDirProp22\t19\t\tTest 22 failed\t\n"
487     "TestSourceDirProp23\t19\t\tTest 23 failed\t\n"
488     "TestSourceDirProp24\t19\t\tTest 24 failed\t\n"
489     "TestSourceDirProp25\t19\t\tTest 25 failed\t\n"
490     "TestSourceDirProp26\t19\t\tTest 26 failed\t\n"
491     "TestSourceDirProp27\t19\t\tTest 27 failed\t\n"
492     "TestSourceDirProp28\t19\t\tTest 28 failed\t\n"
493     "TestSourceDirProp29\t19\t\tTest 29 failed\t\n"
494     "TestSourceDirProp30\t19\t\tTest 30 failed\t\n"
495     "TestSourceDirProp31\t19\t\tTest 31 failed\t\n"
496     "TestSourceDirProp32\t19\t\tTest 32 failed\t\n"
497     "TestSourceDirProp33\t19\t\tTest 33 failed\t\n"
498     "TestSourceDirProp34\t19\t\tTest 34 failed\t\n"
499     "TestSourceDirProp35\t19\t\tTest 35 failed\t\n";
500 
501 static const char ci_install_exec_seq_dat[] =
502     "Action\tCondition\tSequence\n"
503     "s72\tS255\tI2\n"
504     "InstallExecuteSequence\tAction\n"
505     "CostInitialize\t\t800\n"
506     "FileCost\t\t900\n"
507     "CostFinalize\t\t1000\n"
508     "InstallValidate\t\t1400\n"
509     "InstallInitialize\t\t1500\n"
510     "RunInstall\tnot Installed\t1550\n"
511     "ProcessComponents\t\t1600\n"
512     "UnpublishFeatures\t\t1800\n"
513     "RemoveFiles\t\t3500\n"
514     "InstallFiles\t\t4000\n"
515     "RegisterProduct\t\t6100\n"
516     "PublishFeatures\t\t6300\n"
517     "PublishProduct\t\t6400\n"
518     "InstallFinalize\t\t6600\n";
519 
520 static const char ci_custom_action_dat[] =
521     "Action\tType\tSource\tTarget\tISComments\n"
522     "s72\ti2\tS64\tS0\tS255\n"
523     "CustomAction\tAction\n"
524     "RunInstall\t23\tmsitest\\concurrent.msi\tMYPROP=[UILevel]\t\n";
525 
526 static const char ci_component_dat[] =
527     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
528     "s72\tS38\ts72\ti2\tS255\tS72\n"
529     "Component\tComponent\n"
530     "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
531 
532 static const char ci2_component_dat[] =
533     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
534     "s72\tS38\ts72\ti2\tS255\tS72\n"
535     "Component\tComponent\n"
536     "augustus\t\tMSITESTDIR\t0\tUILevel=3 AND MYPROP=5\taugustus\n";
537 
538 static const char ci2_feature_comp_dat[] =
539     "Feature_\tComponent_\n"
540     "s38\ts72\n"
541     "FeatureComponents\tFeature_\tComponent_\n"
542     "feature\taugustus";
543 
544 static const char ci2_file_dat[] =
545     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
546     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
547     "File\tFile\n"
548     "augustus\taugustus\taugustus\t500\t\t\t8192\t1";
549 
550 static const char cl_custom_action_dat[] =
551     "Action\tType\tSource\tTarget\tISComments\n"
552     "s72\ti2\tS64\tS0\tS255\n"
553     "CustomAction\tAction\n"
554     "TestCommandlineProp\t19\t\tTest1\t\n";
555 
556 static const char cl_install_exec_seq_dat[] =
557     "Action\tCondition\tSequence\n"
558     "s72\tS255\tI2\n"
559     "InstallExecuteSequence\tAction\n"
560     "LaunchConditions\t\t100\n"
561     "ValidateProductID\t\t700\n"
562     "CostInitialize\t\t800\n"
563     "FileCost\t\t900\n"
564     "CostFinalize\t\t1000\n"
565     "TestCommandlineProp\tP=\"one\"\t1100\n"
566     "InstallInitialize\t\t1500\n"
567     "ProcessComponents\t\t1600\n"
568     "InstallValidate\t\t1400\n"
569     "InstallFinalize\t\t5000\n";
570 
571 static const msi_table tables[] =
572 {
573     ADD_TABLE(directory),
574     ADD_TABLE(component),
575     ADD_TABLE(feature),
576     ADD_TABLE(feature_comp),
577     ADD_TABLE(file),
578     ADD_TABLE(install_exec_seq),
579     ADD_TABLE(media),
580     ADD_TABLE(property),
581 };
582 
583 static const msi_table mcp_tables[] =
584 {
585     ADD_TABLE(directory),
586     ADD_TABLE(mcp_component),
587     ADD_TABLE(mcp_feature),
588     ADD_TABLE(mcp_feature_comp),
589     ADD_TABLE(mcp_file),
590     ADD_TABLE(install_exec_seq),
591     ADD_TABLE(media),
592     ADD_TABLE(property)
593 };
594 
595 static const msi_table lus0_tables[] =
596 {
597     ADD_TABLE(lus_component),
598     ADD_TABLE(directory),
599     ADD_TABLE(lus_feature),
600     ADD_TABLE(lus_feature_comp),
601     ADD_TABLE(lus_file),
602     ADD_TABLE(lus_install_exec_seq),
603     ADD_TABLE(lus0_media),
604     ADD_TABLE(property)
605 };
606 
607 static const msi_table lus1_tables[] =
608 {
609     ADD_TABLE(lus_component),
610     ADD_TABLE(directory),
611     ADD_TABLE(lus_feature),
612     ADD_TABLE(lus_feature_comp),
613     ADD_TABLE(lus_file),
614     ADD_TABLE(lus_install_exec_seq),
615     ADD_TABLE(lus1_media),
616     ADD_TABLE(property)
617 };
618 
619 static const msi_table lus2_tables[] =
620 {
621     ADD_TABLE(lus_component),
622     ADD_TABLE(directory),
623     ADD_TABLE(lus_feature),
624     ADD_TABLE(lus_feature_comp),
625     ADD_TABLE(lus_file),
626     ADD_TABLE(lus_install_exec_seq),
627     ADD_TABLE(lus2_media),
628     ADD_TABLE(property)
629 };
630 
631 static const msi_table spf_tables[] =
632 {
633     ADD_TABLE(lus_component),
634     ADD_TABLE(directory),
635     ADD_TABLE(lus_feature),
636     ADD_TABLE(lus_feature_comp),
637     ADD_TABLE(lus_file),
638     ADD_TABLE(lus0_media),
639     ADD_TABLE(property),
640     ADD_TABLE(spf_custom_action),
641     ADD_TABLE(spf_install_exec_seq),
642     ADD_TABLE(spf_install_ui_seq)
643 };
644 
645 static const msi_table spf2_tables[] =
646 {
647     ADD_TABLE(spf_component),
648     ADD_TABLE(spf_directory),
649     ADD_TABLE(lus_feature),
650     ADD_TABLE(lus_feature_comp),
651     ADD_TABLE(lus_file),
652     ADD_TABLE(lus0_media),
653     ADD_TABLE(property),
654     ADD_TABLE(spf2_custom_action),
655     ADD_TABLE(spf2_install_exec_seq),
656     ADD_TABLE(spf_install_ui_seq),
657     ADD_TABLE(shortcut)
658 };
659 
660 static const msi_table sd_tables[] =
661 {
662     ADD_TABLE(directory),
663     ADD_TABLE(sd_component),
664     ADD_TABLE(sd_feature),
665     ADD_TABLE(sd_feature_comp),
666     ADD_TABLE(sd_file),
667     ADD_TABLE(sd_install_exec_seq),
668     ADD_TABLE(sd_install_ui_seq),
669     ADD_TABLE(sd_custom_action),
670     ADD_TABLE(media),
671     ADD_TABLE(property)
672 };
673 
674 static const msi_table ci_tables[] =
675 {
676     ADD_TABLE(ci_component),
677     ADD_TABLE(directory),
678     ADD_TABLE(lus_feature),
679     ADD_TABLE(lus_feature_comp),
680     ADD_TABLE(lus_file),
681     ADD_TABLE(ci_install_exec_seq),
682     ADD_TABLE(lus0_media),
683     ADD_TABLE(property),
684     ADD_TABLE(ci_custom_action),
685 };
686 
687 static const msi_table ci2_tables[] =
688 {
689     ADD_TABLE(ci2_component),
690     ADD_TABLE(directory),
691     ADD_TABLE(lus_feature),
692     ADD_TABLE(ci2_feature_comp),
693     ADD_TABLE(ci2_file),
694     ADD_TABLE(install_exec_seq),
695     ADD_TABLE(lus0_media),
696     ADD_TABLE(ci2_property),
697 };
698 
699 static const msi_table cl_tables[] =
700 {
701     ADD_TABLE(component),
702     ADD_TABLE(directory),
703     ADD_TABLE(feature),
704     ADD_TABLE(feature_comp),
705     ADD_TABLE(file),
706     ADD_TABLE(cl_custom_action),
707     ADD_TABLE(cl_install_exec_seq),
708     ADD_TABLE(media),
709     ADD_TABLE(property)
710 };
711 
set_summary_info(MSIHANDLE hdb,LPSTR prodcode)712 static UINT set_summary_info(MSIHANDLE hdb, LPSTR prodcode)
713 {
714     UINT res;
715     MSIHANDLE suminfo;
716 
717     /* build summary info */
718     res = MsiGetSummaryInformationA(hdb, NULL, 7, &suminfo);
719     ok(res == ERROR_SUCCESS, "Failed to open summaryinfo\n");
720 
721     res = MsiSummaryInfoSetPropertyA(suminfo, 2, VT_LPSTR, 0, NULL,
722                                     "Installation Database");
723     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
724 
725     res = MsiSummaryInfoSetPropertyA(suminfo, 3, VT_LPSTR, 0, NULL,
726                                     "Installation Database");
727     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
728 
729     res = MsiSummaryInfoSetPropertyA(suminfo, 4, VT_LPSTR, 0, NULL,
730                                     "Wine Hackers");
731     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
732 
733     res = MsiSummaryInfoSetPropertyA(suminfo, 7, VT_LPSTR, 0, NULL,
734                                     ";1033");
735     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
736 
737     res = MsiSummaryInfoSetPropertyA(suminfo, PID_REVNUMBER, VT_LPSTR, 0, NULL,
738                                     "{A2078D65-94D6-4205-8DEE-F68D6FD622AA}");
739     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
740 
741     res = MsiSummaryInfoSetPropertyA(suminfo, 14, VT_I4, 100, NULL, NULL);
742     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
743 
744     res = MsiSummaryInfoSetPropertyA(suminfo, 15, VT_I4, 0, NULL, NULL);
745     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
746 
747     res = MsiSummaryInfoPersist(suminfo);
748     ok(res == ERROR_SUCCESS, "Failed to make summary info persist\n");
749 
750     res = MsiCloseHandle(suminfo);
751     ok(res == ERROR_SUCCESS, "Failed to close suminfo\n");
752 
753     return res;
754 }
755 
create_package_db(LPSTR prodcode)756 static MSIHANDLE create_package_db(LPSTR prodcode)
757 {
758     MSIHANDLE hdb = 0;
759     CHAR query[MAX_PATH + 72];
760     UINT res;
761 
762     DeleteFileA(msifile);
763 
764     /* create an empty database */
765     res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
766     ok( res == ERROR_SUCCESS , "Failed to create database\n" );
767     if (res != ERROR_SUCCESS)
768         return hdb;
769 
770     res = MsiDatabaseCommit(hdb);
771     ok(res == ERROR_SUCCESS, "Failed to commit database\n");
772 
773     set_summary_info(hdb, prodcode);
774 
775     res = run_query(hdb, 0,
776             "CREATE TABLE `Directory` ( "
777             "`Directory` CHAR(255) NOT NULL, "
778             "`Directory_Parent` CHAR(255), "
779             "`DefaultDir` CHAR(255) NOT NULL "
780             "PRIMARY KEY `Directory`)");
781     ok(res == ERROR_SUCCESS , "Failed to create directory table\n");
782 
783     res = run_query(hdb, 0,
784             "CREATE TABLE `Property` ( "
785             "`Property` CHAR(72) NOT NULL, "
786             "`Value` CHAR(255) "
787             "PRIMARY KEY `Property`)");
788     ok(res == ERROR_SUCCESS , "Failed to create directory table\n");
789 
790     sprintf(query, "INSERT INTO `Property` "
791             "(`Property`, `Value`) "
792             "VALUES( 'ProductCode', '%s' )", prodcode);
793     res = run_query(hdb, 0, query);
794     ok(res == ERROR_SUCCESS , "Failed\n");
795 
796     res = MsiDatabaseCommit(hdb);
797     ok(res == ERROR_SUCCESS, "Failed to commit database\n");
798 
799     return hdb;
800 }
801 
test_usefeature(void)802 static void test_usefeature(void)
803 {
804     INSTALLSTATE r;
805 
806     r = MsiQueryFeatureStateA(NULL, NULL);
807     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
808 
809     r = MsiQueryFeatureStateA("{9085040-6000-11d3-8cfe-0150048383c9}" ,NULL);
810     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
811 
812     r = MsiUseFeatureExA(NULL,NULL,0,0);
813     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
814 
815     r = MsiUseFeatureExA(NULL, "WORDVIEWFiles", -2, 1 );
816     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
817 
818     r = MsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}",
819                          NULL, -2, 0 );
820     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
821 
822     r = MsiUseFeatureExA("{9085040-6000-11d3-8cfe-0150048383c9}",
823                          "WORDVIEWFiles", -2, 0 );
824     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
825 
826     r = MsiUseFeatureExA("{0085040-6000-11d3-8cfe-0150048383c9}",
827                          "WORDVIEWFiles", -2, 0 );
828     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
829 
830     r = MsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}",
831                          "WORDVIEWFiles", -2, 1 );
832     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
833 }
834 
test_null(void)835 static void test_null(void)
836 {
837     MSIHANDLE hpkg;
838     UINT r;
839     HKEY hkey;
840     DWORD dwType, cbData;
841     LPBYTE lpData = NULL;
842     INSTALLSTATE state;
843     REGSAM access = KEY_ALL_ACCESS;
844 
845     if (is_wow64)
846         access |= KEY_WOW64_64KEY;
847 
848     r = MsiOpenPackageExW(NULL, 0, &hpkg);
849     ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
850 
851     state = MsiQueryProductStateW(NULL);
852     ok( state == INSTALLSTATE_INVALIDARG, "wrong return\n");
853 
854     r = MsiEnumFeaturesW(NULL,0,NULL,NULL);
855     ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
856 
857     r = MsiConfigureFeatureW(NULL, NULL, 0);
858     ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
859 
860     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", NULL, 0);
861     ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
862 
863     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000001}", "foo", 0);
864     ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
865 
866     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000002}", "foo", INSTALLSTATE_DEFAULT);
867     ok( r == ERROR_UNKNOWN_PRODUCT, "wrong error %d\n", r);
868 
869     /* make sure empty string to MsiGetProductInfo is not a handle to default registry value, saving and restoring the
870      * necessary registry values */
871 
872     /* empty product string */
873     r = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", 0, access, &hkey);
874     if (r == ERROR_ACCESS_DENIED)
875     {
876         skip("Not enough rights to perform tests\n");
877         return;
878     }
879     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
880 
881     r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
882     ok ( r == ERROR_SUCCESS || r == ERROR_FILE_NOT_FOUND, "wrong error %d\n", r);
883     if ( r == ERROR_SUCCESS )
884     {
885         if (!(lpData = malloc(cbData))) skip("Out of memory\n");
886         else
887         {
888             r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
889             ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
890         }
891     }
892 
893     r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
894     if (r == ERROR_ACCESS_DENIED)
895     {
896         skip("Not enough rights to perform tests\n");
897         free(lpData);
898         RegCloseKey(hkey);
899         return;
900     }
901     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
902 
903     r = MsiGetProductInfoA("", "", NULL, NULL);
904     ok ( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
905 
906     if (lpData)
907     {
908         r = RegSetValueExA(hkey, NULL, 0, dwType, lpData, cbData);
909         ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
910         free(lpData);
911     }
912     else
913     {
914         r = RegDeleteValueA(hkey, NULL);
915         ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
916     }
917 
918     r = RegCloseKey(hkey);
919     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
920 
921     /* empty attribute */
922     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}",
923                         0, NULL, 0, access, NULL, &hkey, NULL);
924     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
925 
926     r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
927     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
928 
929     r = MsiGetProductInfoA("{F1C3AF50-8B56-4A69-A00C-00773FE42F30}", "", NULL, NULL);
930     ok ( r == ERROR_UNKNOWN_PROPERTY, "wrong error %d\n", r);
931 
932     r = RegCloseKey(hkey);
933     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
934 
935     r = RegDeleteKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}",
936                         access & KEY_WOW64_64KEY, 0);
937     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
938 }
939 
test_getcomponentpath(void)940 static void test_getcomponentpath(void)
941 {
942     INSTALLSTATE r;
943     char buffer[0x100];
944     DWORD sz;
945 
946     r = MsiGetComponentPathA( NULL, NULL, NULL, NULL );
947     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
948 
949     r = MsiGetComponentPathA( "bogus", "bogus", NULL, NULL );
950     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
951 
952     r = MsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", NULL, NULL );
953     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
954 
955     sz = sizeof buffer;
956     buffer[0]=0;
957     r = MsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", buffer, &sz );
958     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
959 
960     r = MsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C998E7}",
961         "{00000000-0000-0000-0000-000000000000}", buffer, &sz );
962     ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
963 
964     r = MsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
965         "{00000000-0000-0000-0000-00000000}", buffer, &sz );
966     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
967 
968     r = MsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
969         "{029E403D-A86A-1D11-5B5B0006799C897E}", buffer, &sz );
970     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
971 
972     r = MsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C9987e}",
973                             "{00000000-A68A-11d1-5B5B-0006799C897E}", buffer, &sz );
974     ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
975 }
976 
create_test_files(void)977 static void create_test_files(void)
978 {
979     CreateDirectoryA("msitest", NULL);
980     create_file("msitest\\one.txt", 100);
981     CreateDirectoryA("msitest\\first", NULL);
982     create_file("msitest\\first\\two.txt", 100);
983     CreateDirectoryA("msitest\\second", NULL);
984     create_file("msitest\\second\\three.txt", 100);
985 
986     create_file("four.txt", 100);
987     create_file("five.txt", 100);
988     create_cab_file("msitest.cab", MEDIA_SIZE, "four.txt\0five.txt\0");
989 
990     create_file("msitest\\filename", 100);
991     create_file("msitest\\service.exe", 100);
992 
993     DeleteFileA("four.txt");
994     DeleteFileA("five.txt");
995 }
996 
delete_test_files(void)997 static void delete_test_files(void)
998 {
999     DeleteFileA("msitest.msi");
1000     DeleteFileA("msitest.cab");
1001     DeleteFileA("msitest\\second\\three.txt");
1002     DeleteFileA("msitest\\first\\two.txt");
1003     DeleteFileA("msitest\\one.txt");
1004     DeleteFileA("msitest\\service.exe");
1005     DeleteFileA("msitest\\filename");
1006     RemoveDirectoryA("msitest\\second");
1007     RemoveDirectoryA("msitest\\first");
1008     RemoveDirectoryA("msitest");
1009 }
1010 
1011 #define HASHSIZE sizeof(MSIFILEHASHINFO)
1012 
1013 static const struct
1014 {
1015     LPCSTR data;
1016     DWORD size;
1017     MSIFILEHASHINFO hash;
1018 } hash_data[] =
1019 {
1020     { "", 0,
1021       { HASHSIZE,
1022         { 0, 0, 0, 0 },
1023       },
1024     },
1025 
1026     { "abc", 0,
1027       { HASHSIZE,
1028         { 0x98500190, 0xb04fd23c, 0x7d3f96d6, 0x727fe128 },
1029       },
1030     },
1031 
1032     { "C:\\Program Files\\msitest\\caesar\n", 0,
1033       { HASHSIZE,
1034         { 0x2b566794, 0xfd42181b, 0x2514d6e4, 0x5768b4e2 },
1035       },
1036     },
1037 
1038     { "C:\\Program Files\\msitest\\caesar\n", 500,
1039       { HASHSIZE,
1040         { 0x58095058, 0x805efeff, 0x10f3483e, 0x0147d653 },
1041       },
1042     },
1043 };
1044 
test_MsiGetFileHash(void)1045 static void test_MsiGetFileHash(void)
1046 {
1047     const char name[] = "msitest.bin";
1048     UINT r;
1049     MSIFILEHASHINFO hash;
1050     DWORD i;
1051 
1052     hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
1053 
1054     /* szFilePath is NULL */
1055     r = MsiGetFileHashA(NULL, 0, &hash);
1056     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1057 
1058     /* szFilePath is empty */
1059     r = MsiGetFileHashA("", 0, &hash);
1060     ok(r == ERROR_PATH_NOT_FOUND || r == ERROR_BAD_PATHNAME,
1061        "Expected ERROR_PATH_NOT_FOUND or ERROR_BAD_PATHNAME, got %d\n", r);
1062 
1063     /* szFilePath is nonexistent */
1064     r = MsiGetFileHashA(name, 0, &hash);
1065     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
1066 
1067     /* dwOptions is non-zero */
1068     r = MsiGetFileHashA(name, 1, &hash);
1069     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1070 
1071     /* pHash.dwFileHashInfoSize is not correct */
1072     hash.dwFileHashInfoSize = 0;
1073     r = MsiGetFileHashA(name, 0, &hash);
1074     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1075 
1076     /* pHash is NULL */
1077     r = MsiGetFileHashA(name, 0, NULL);
1078     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1079 
1080     for (i = 0; i < ARRAY_SIZE(hash_data); i++)
1081     {
1082         int ret;
1083 
1084         create_file_data(name, hash_data[i].data, hash_data[i].size);
1085 
1086         memset(&hash, 0, sizeof(MSIFILEHASHINFO));
1087         hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
1088 
1089         r = MsiGetFileHashA(name, 0, &hash);
1090         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1091 
1092         ret = memcmp(&hash, &hash_data[i].hash, HASHSIZE);
1093         ok(!ret, "Hash incorrect\n");
1094 
1095         DeleteFileA(name);
1096     }
1097 }
1098 
1099 /* copied from dlls/msi/registry.c */
squash_guid(LPCWSTR in,LPWSTR out)1100 static BOOL squash_guid(LPCWSTR in, LPWSTR out)
1101 {
1102     DWORD i,n=1;
1103     GUID guid;
1104 
1105     if (FAILED(CLSIDFromString((LPCOLESTR)in, &guid)))
1106         return FALSE;
1107 
1108     for(i=0; i<8; i++)
1109         out[7-i] = in[n++];
1110     n++;
1111     for(i=0; i<4; i++)
1112         out[11-i] = in[n++];
1113     n++;
1114     for(i=0; i<4; i++)
1115         out[15-i] = in[n++];
1116     n++;
1117     for(i=0; i<2; i++)
1118     {
1119         out[17+i*2] = in[n++];
1120         out[16+i*2] = in[n++];
1121     }
1122     n++;
1123     for( ; i<8; i++)
1124     {
1125         out[17+i*2] = in[n++];
1126         out[16+i*2] = in[n++];
1127     }
1128     out[32]=0;
1129     return TRUE;
1130 }
1131 
create_test_guid(LPSTR prodcode,LPSTR squashed)1132 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
1133 {
1134     WCHAR guidW[GUID_SIZE];
1135     WCHAR squashedW[SQUASHED_GUID_SIZE];
1136     GUID guid;
1137     HRESULT hr;
1138     int size;
1139 
1140     hr = CoCreateGuid(&guid);
1141     ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
1142 
1143     size = StringFromGUID2(&guid, guidW, ARRAY_SIZE(guidW));
1144     ok(size == GUID_SIZE, "Expected %d, got %d.\n", GUID_SIZE, size);
1145 
1146     WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, GUID_SIZE, NULL, NULL);
1147     if (squashed)
1148     {
1149         squash_guid(guidW, squashedW);
1150         WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, SQUASHED_GUID_SIZE, NULL, NULL);
1151     }
1152 }
1153 
get_user_sid(void)1154 static char *get_user_sid(void)
1155 {
1156     HANDLE token;
1157     DWORD size = 0;
1158     TOKEN_USER *user;
1159     char *usersid = NULL;
1160 
1161     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
1162     GetTokenInformation(token, TokenUser, NULL, size, &size);
1163 
1164     user = malloc(size);
1165     GetTokenInformation(token, TokenUser, user, size, &size);
1166     ConvertSidToStringSidA(user->User.Sid, &usersid);
1167     free(user);
1168 
1169     CloseHandle(token);
1170     return usersid;
1171 }
1172 
test_MsiQueryProductState(void)1173 static void test_MsiQueryProductState(void)
1174 {
1175     CHAR prodcode[MAX_PATH];
1176     CHAR prod_squashed[MAX_PATH];
1177     CHAR keypath[MAX_PATH*2];
1178     LPSTR usersid;
1179     INSTALLSTATE state;
1180     LONG res;
1181     HKEY userkey, localkey, props;
1182     HKEY prodkey;
1183     DWORD data, error;
1184     REGSAM access = KEY_ALL_ACCESS;
1185 
1186     create_test_guid(prodcode, prod_squashed);
1187     usersid = get_user_sid();
1188 
1189     if (is_wow64)
1190         access |= KEY_WOW64_64KEY;
1191 
1192     /* NULL prodcode */
1193     SetLastError(0xdeadbeef);
1194     state = MsiQueryProductStateA(NULL);
1195     error = GetLastError();
1196     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1197     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
1198 
1199     /* empty prodcode */
1200     SetLastError(0xdeadbeef);
1201     state = MsiQueryProductStateA("");
1202     error = GetLastError();
1203     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1204     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
1205 
1206     /* garbage prodcode */
1207     SetLastError(0xdeadbeef);
1208     state = MsiQueryProductStateA("garbage");
1209     error = GetLastError();
1210     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1211     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
1212 
1213     /* guid without brackets */
1214     SetLastError(0xdeadbeef);
1215     state = MsiQueryProductStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D");
1216     error = GetLastError();
1217     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1218     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
1219 
1220     /* guid with brackets */
1221     SetLastError(0xdeadbeef);
1222     state = MsiQueryProductStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}");
1223     error = GetLastError();
1224     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1225     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1226 
1227     /* same length as guid, but random */
1228     SetLastError(0xdeadbeef);
1229     state = MsiQueryProductStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93");
1230     error = GetLastError();
1231     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1232     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
1233 
1234     /* MSIINSTALLCONTEXT_USERUNMANAGED */
1235 
1236     SetLastError(0xdeadbeef);
1237     state = MsiQueryProductStateA(prodcode);
1238     error = GetLastError();
1239     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1240     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1241 
1242     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
1243     lstrcatA(keypath, prod_squashed);
1244 
1245     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
1246     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1247 
1248     /* user product key exists */
1249     SetLastError(0xdeadbeef);
1250     state = MsiQueryProductStateA(prodcode);
1251     error = GetLastError();
1252     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1253     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1254 
1255     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
1256     lstrcatA(keypath, prodcode);
1257 
1258     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1259     if (res == ERROR_ACCESS_DENIED)
1260     {
1261         skip("Not enough rights to perform tests\n");
1262         RegDeleteKeyA(userkey, "");
1263         RegCloseKey(userkey);
1264         LocalFree(usersid);
1265         return;
1266     }
1267     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1268 
1269     /* local uninstall key exists */
1270     SetLastError(0xdeadbeef);
1271     state = MsiQueryProductStateA(prodcode);
1272     error = GetLastError();
1273     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1274     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1275 
1276     data = 1;
1277     res = RegSetValueExA(localkey, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1278     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1279 
1280     /* WindowsInstaller value exists */
1281     SetLastError(0xdeadbeef);
1282     state = MsiQueryProductStateA(prodcode);
1283     error = GetLastError();
1284     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1285     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1286 
1287     RegDeleteValueA(localkey, "WindowsInstaller");
1288     RegDeleteKeyExA(localkey, "", access & KEY_WOW64_64KEY, 0);
1289 
1290     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1291     lstrcatA(keypath, usersid);
1292     lstrcatA(keypath, "\\Products\\");
1293     lstrcatA(keypath, prod_squashed);
1294 
1295     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1296     if (res == ERROR_ACCESS_DENIED)
1297     {
1298         skip("Not enough rights to perform tests\n");
1299         RegDeleteKeyA(userkey, "");
1300         RegCloseKey(userkey);
1301         LocalFree(usersid);
1302         return;
1303     }
1304     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1305 
1306     /* local product key exists */
1307     SetLastError(0xdeadbeef);
1308     state = MsiQueryProductStateA(prodcode);
1309     error = GetLastError();
1310     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1311     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1312 
1313     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1314     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1315 
1316     /* install properties key exists */
1317     SetLastError(0xdeadbeef);
1318     state = MsiQueryProductStateA(prodcode);
1319     error = GetLastError();
1320     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1321     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1322 
1323     data = 1;
1324     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1325     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1326 
1327     /* WindowsInstaller value exists */
1328     SetLastError(0xdeadbeef);
1329     state = MsiQueryProductStateA(prodcode);
1330     error = GetLastError();
1331     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1332     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1333 
1334     data = 2;
1335     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1336     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1337 
1338     /* WindowsInstaller value is not 1 */
1339     SetLastError(0xdeadbeef);
1340     state = MsiQueryProductStateA(prodcode);
1341     error = GetLastError();
1342     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1343     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1344 
1345     RegDeleteKeyA(userkey, "");
1346 
1347     /* user product key does not exist */
1348     SetLastError(0xdeadbeef);
1349     state = MsiQueryProductStateA(prodcode);
1350     error = GetLastError();
1351     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1352     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1353 
1354     RegDeleteValueA(props, "WindowsInstaller");
1355     RegDeleteKeyExA(props, "", access & KEY_WOW64_64KEY, 0);
1356     RegCloseKey(props);
1357     RegDeleteKeyExA(localkey, "", access & KEY_WOW64_64KEY, 0);
1358     RegCloseKey(localkey);
1359     RegDeleteKeyA(userkey, "");
1360     RegCloseKey(userkey);
1361 
1362     /* MSIINSTALLCONTEXT_USERMANAGED */
1363 
1364     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
1365     lstrcatA(keypath, usersid);
1366     lstrcatA(keypath, "\\Installer\\Products\\");
1367     lstrcatA(keypath, prod_squashed);
1368 
1369     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
1370     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1371 
1372     state = MsiQueryProductStateA(prodcode);
1373     ok(state == INSTALLSTATE_ADVERTISED,
1374        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1375 
1376     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1377     lstrcatA(keypath, usersid);
1378     lstrcatA(keypath, "\\Products\\");
1379     lstrcatA(keypath, prod_squashed);
1380 
1381     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1382     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1383 
1384     state = MsiQueryProductStateA(prodcode);
1385     ok(state == INSTALLSTATE_ADVERTISED,
1386        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1387 
1388     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1389     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1390 
1391     state = MsiQueryProductStateA(prodcode);
1392     ok(state == INSTALLSTATE_ADVERTISED,
1393        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1394 
1395     data = 1;
1396     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1397     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1398 
1399     /* WindowsInstaller value exists */
1400     state = MsiQueryProductStateA(prodcode);
1401     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1402 
1403     RegDeleteValueA(props, "WindowsInstaller");
1404     RegDeleteKeyExA(props, "", access & KEY_WOW64_64KEY, 0);
1405     RegCloseKey(props);
1406     RegDeleteKeyExA(localkey, "", access & KEY_WOW64_64KEY, 0);
1407     RegCloseKey(localkey);
1408     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
1409     RegCloseKey(prodkey);
1410 
1411     /* MSIINSTALLCONTEXT_MACHINE */
1412 
1413     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
1414     lstrcatA(keypath, prod_squashed);
1415 
1416     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
1417     if (res == ERROR_ACCESS_DENIED)
1418     {
1419         skip( "insufficient rights\n" );
1420         LocalFree( usersid );
1421         return;
1422     }
1423     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1424 
1425     state = MsiQueryProductStateA(prodcode);
1426     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1427 
1428     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1429     lstrcatA(keypath, "S-1-5-18\\Products\\");
1430     lstrcatA(keypath, prod_squashed);
1431 
1432     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1433     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1434 
1435     state = MsiQueryProductStateA(prodcode);
1436     ok(state == INSTALLSTATE_ADVERTISED,
1437        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1438 
1439     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1440     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1441 
1442     state = MsiQueryProductStateA(prodcode);
1443     ok(state == INSTALLSTATE_ADVERTISED,
1444        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1445 
1446     data = 1;
1447     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1448     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1449 
1450     /* WindowsInstaller value exists */
1451     state = MsiQueryProductStateA(prodcode);
1452     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1453 
1454     RegDeleteValueA(props, "WindowsInstaller");
1455     RegDeleteKeyExA(props, "", access & KEY_WOW64_64KEY, 0);
1456     RegCloseKey(props);
1457     RegDeleteKeyExA(localkey, "", access & KEY_WOW64_64KEY, 0);
1458     RegCloseKey(localkey);
1459     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
1460     RegCloseKey(prodkey);
1461 
1462     LocalFree(usersid);
1463 }
1464 
1465 static const char table_enc85[] =
1466 "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
1467 "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
1468 "yz{}~";
1469 
1470 /*
1471  *  Encodes a base85 guid given a GUID pointer
1472  *  Caller should provide a 21 character buffer for the encoded string.
1473  */
encode_base85_guid(GUID * guid,LPWSTR str)1474 static void encode_base85_guid( GUID *guid, LPWSTR str )
1475 {
1476     unsigned int x, *p, i;
1477 
1478     p = (unsigned int*) guid;
1479     for( i=0; i<4; i++ )
1480     {
1481         x = p[i];
1482         *str++ = table_enc85[x%85];
1483         x = x/85;
1484         *str++ = table_enc85[x%85];
1485         x = x/85;
1486         *str++ = table_enc85[x%85];
1487         x = x/85;
1488         *str++ = table_enc85[x%85];
1489         x = x/85;
1490         *str++ = table_enc85[x%85];
1491     }
1492     *str = 0;
1493 }
1494 
compose_base85_guid(LPSTR component,LPSTR comp_base85,LPSTR squashed)1495 static void compose_base85_guid(LPSTR component, LPSTR comp_base85, LPSTR squashed)
1496 {
1497     WCHAR guidW[MAX_PATH];
1498     WCHAR base85W[MAX_PATH];
1499     WCHAR squashedW[MAX_PATH];
1500     GUID guid;
1501     HRESULT hr;
1502     int size;
1503 
1504     hr = CoCreateGuid(&guid);
1505     ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
1506 
1507     size = StringFromGUID2(&guid, guidW, MAX_PATH);
1508     ok(size == 39, "Expected 39, got %d\n", size);
1509 
1510     WideCharToMultiByte(CP_ACP, 0, guidW, size, component, MAX_PATH, NULL, NULL);
1511     encode_base85_guid(&guid, base85W);
1512     WideCharToMultiByte(CP_ACP, 0, base85W, -1, comp_base85, MAX_PATH, NULL, NULL);
1513     squash_guid(guidW, squashedW);
1514     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
1515 }
1516 
test_MsiQueryFeatureState(void)1517 static void test_MsiQueryFeatureState(void)
1518 {
1519     HKEY userkey, localkey, compkey, compkey2;
1520     CHAR prodcode[MAX_PATH];
1521     CHAR prod_squashed[MAX_PATH];
1522     CHAR component[MAX_PATH];
1523     CHAR comp_base85[MAX_PATH];
1524     CHAR comp_squashed[MAX_PATH], comp_squashed2[MAX_PATH];
1525     CHAR keypath[MAX_PATH*2];
1526     INSTALLSTATE state;
1527     LPSTR usersid;
1528     LONG res;
1529     REGSAM access = KEY_ALL_ACCESS;
1530     DWORD error;
1531 
1532     create_test_guid(prodcode, prod_squashed);
1533     compose_base85_guid(component, comp_base85, comp_squashed);
1534     compose_base85_guid(component, comp_base85 + 20, comp_squashed2);
1535     usersid = get_user_sid();
1536 
1537     if (is_wow64)
1538         access |= KEY_WOW64_64KEY;
1539 
1540     /* NULL prodcode */
1541     SetLastError(0xdeadbeef);
1542     state = MsiQueryFeatureStateA(NULL, "feature");
1543     error = GetLastError();
1544     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1545     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
1546 
1547     /* empty prodcode */
1548     SetLastError(0xdeadbeef);
1549     state = MsiQueryFeatureStateA("", "feature");
1550     error = GetLastError();
1551     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1552     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
1553 
1554     /* garbage prodcode */
1555     SetLastError(0xdeadbeef);
1556     state = MsiQueryFeatureStateA("garbage", "feature");
1557     error = GetLastError();
1558     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1559     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
1560 
1561     /* guid without brackets */
1562     SetLastError(0xdeadbeef);
1563     state = MsiQueryFeatureStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", "feature");
1564     error = GetLastError();
1565     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1566     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
1567 
1568     /* guid with brackets */
1569     SetLastError(0xdeadbeef);
1570     state = MsiQueryFeatureStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", "feature");
1571     error = GetLastError();
1572     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1573     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1574 
1575     /* same length as guid, but random */
1576     SetLastError(0xdeadbeef);
1577     state = MsiQueryFeatureStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", "feature");
1578     error = GetLastError();
1579     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1580     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
1581 
1582     /* NULL szFeature */
1583     SetLastError(0xdeadbeef);
1584     state = MsiQueryFeatureStateA(prodcode, NULL);
1585     error = GetLastError();
1586     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1587     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
1588 
1589     /* empty szFeature */
1590     SetLastError(0xdeadbeef);
1591     state = MsiQueryFeatureStateA(prodcode, "");
1592     error = GetLastError();
1593     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1594     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1595 
1596     /* feature key does not exist yet */
1597     SetLastError(0xdeadbeef);
1598     state = MsiQueryFeatureStateA(prodcode, "feature");
1599     error = GetLastError();
1600     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1601     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1602 
1603     /* MSIINSTALLCONTEXT_USERUNMANAGED */
1604 
1605     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Features\\");
1606     lstrcatA(keypath, prod_squashed);
1607 
1608     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
1609     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1610 
1611     /* feature key exists */
1612     SetLastError(0xdeadbeef);
1613     state = MsiQueryFeatureStateA(prodcode, "feature");
1614     error = GetLastError();
1615     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1616     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1617 
1618     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 2);
1619     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1620 
1621     /* feature value exists */
1622     SetLastError(0xdeadbeef);
1623     state = MsiQueryFeatureStateA(prodcode, "feature");
1624     error = GetLastError();
1625     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1626     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1627 
1628     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1629     lstrcatA(keypath, usersid);
1630     lstrcatA(keypath, "\\Products\\");
1631     lstrcatA(keypath, prod_squashed);
1632     lstrcatA(keypath, "\\Features");
1633 
1634     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1635     if (res == ERROR_ACCESS_DENIED)
1636     {
1637         skip("Not enough rights to perform tests\n");
1638         RegDeleteKeyA(userkey, "");
1639         RegCloseKey(userkey);
1640         LocalFree(usersid);
1641         return;
1642     }
1643     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1644 
1645     /* userdata features key exists */
1646     SetLastError(0xdeadbeef);
1647     state = MsiQueryFeatureStateA(prodcode, "feature");
1648     error = GetLastError();
1649     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1650     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1651 
1652     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
1653     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1654 
1655     SetLastError(0xdeadbeef);
1656     state = MsiQueryFeatureStateA(prodcode, "feature");
1657     error = GetLastError();
1658     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
1659     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1660 
1661     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
1662     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1663 
1664     SetLastError(0xdeadbeef);
1665     state = MsiQueryFeatureStateA(prodcode, "feature");
1666     error = GetLastError();
1667     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1668     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1669 
1670     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
1671     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1672 
1673     SetLastError(0xdeadbeef);
1674     state = MsiQueryFeatureStateA(prodcode, "feature");
1675     error = GetLastError();
1676     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1677     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1678 
1679     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
1680     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1681 
1682     SetLastError(0xdeadbeef);
1683     state = MsiQueryFeatureStateA(prodcode, "feature");
1684     error = GetLastError();
1685     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1686     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1687 
1688     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1689     lstrcatA(keypath, usersid);
1690     lstrcatA(keypath, "\\Components\\");
1691     lstrcatA(keypath, comp_squashed);
1692 
1693     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
1694     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1695 
1696     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1697     lstrcatA(keypath, usersid);
1698     lstrcatA(keypath, "\\Components\\");
1699     lstrcatA(keypath, comp_squashed2);
1700 
1701     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
1702     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1703 
1704     SetLastError(0xdeadbeef);
1705     state = MsiQueryFeatureStateA(prodcode, "feature");
1706     error = GetLastError();
1707     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1708     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1709 
1710     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
1711     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1712 
1713     SetLastError(0xdeadbeef);
1714     state = MsiQueryFeatureStateA(prodcode, "feature");
1715     error = GetLastError();
1716     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1717     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1718 
1719     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
1720     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1721 
1722     SetLastError(0xdeadbeef);
1723     state = MsiQueryFeatureStateA(prodcode, "feature");
1724     error = GetLastError();
1725     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1726     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1727 
1728     res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
1729     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1730 
1731     /* INSTALLSTATE_LOCAL */
1732     SetLastError(0xdeadbeef);
1733     state = MsiQueryFeatureStateA(prodcode, "feature");
1734     error = GetLastError();
1735     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1736     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1737 
1738     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01\\", 4);
1739     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1740 
1741     /* INSTALLSTATE_SOURCE */
1742     SetLastError(0xdeadbeef);
1743     state = MsiQueryFeatureStateA(prodcode, "feature");
1744     error = GetLastError();
1745     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
1746     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1747 
1748     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
1749     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1750 
1751     /* bad INSTALLSTATE_SOURCE */
1752     SetLastError(0xdeadbeef);
1753     state = MsiQueryFeatureStateA(prodcode, "feature");
1754     error = GetLastError();
1755     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1756     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1757 
1758     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01a", 4);
1759     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1760 
1761     /* INSTALLSTATE_SOURCE */
1762     SetLastError(0xdeadbeef);
1763     state = MsiQueryFeatureStateA(prodcode, "feature");
1764     error = GetLastError();
1765     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
1766     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1767 
1768     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
1769     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1770 
1771     /* bad INSTALLSTATE_SOURCE */
1772     SetLastError(0xdeadbeef);
1773     state = MsiQueryFeatureStateA(prodcode, "feature");
1774     error = GetLastError();
1775     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1776     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", error);
1777 
1778     RegDeleteValueA(compkey, prod_squashed);
1779     RegDeleteValueA(compkey2, prod_squashed);
1780     RegDeleteKeyExA(compkey, "", access & KEY_WOW64_64KEY, 0);
1781     RegDeleteKeyExA(compkey2, "", access & KEY_WOW64_64KEY, 0);
1782     RegDeleteValueA(localkey, "feature");
1783     RegDeleteValueA(userkey, "feature");
1784     RegDeleteKeyA(userkey, "");
1785     RegCloseKey(compkey);
1786     RegCloseKey(compkey2);
1787     RegCloseKey(localkey);
1788     RegCloseKey(userkey);
1789 
1790     /* MSIINSTALLCONTEXT_USERMANAGED */
1791 
1792     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
1793     lstrcatA(keypath, usersid);
1794     lstrcatA(keypath, "\\Installer\\Features\\");
1795     lstrcatA(keypath, prod_squashed);
1796 
1797     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
1798     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1799 
1800     /* feature key exists */
1801     state = MsiQueryFeatureStateA(prodcode, "feature");
1802     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1803 
1804     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 1);
1805     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1806 
1807     /* feature value exists */
1808     state = MsiQueryFeatureStateA(prodcode, "feature");
1809     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1810 
1811     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1812     lstrcatA(keypath, usersid);
1813     lstrcatA(keypath, "\\Products\\");
1814     lstrcatA(keypath, prod_squashed);
1815     lstrcatA(keypath, "\\Features");
1816 
1817     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1818     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1819 
1820     /* userdata features key exists */
1821     state = MsiQueryFeatureStateA(prodcode, "feature");
1822     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1823 
1824     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
1825     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1826 
1827     state = MsiQueryFeatureStateA(prodcode, "feature");
1828     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
1829 
1830     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
1831     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1832 
1833     state = MsiQueryFeatureStateA(prodcode, "feature");
1834     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1835 
1836     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
1837     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1838 
1839     state = MsiQueryFeatureStateA(prodcode, "feature");
1840     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1841 
1842     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
1843     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1844 
1845     state = MsiQueryFeatureStateA(prodcode, "feature");
1846     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1847 
1848     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1849     lstrcatA(keypath, usersid);
1850     lstrcatA(keypath, "\\Components\\");
1851     lstrcatA(keypath, comp_squashed);
1852 
1853     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
1854     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1855 
1856     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1857     lstrcatA(keypath, usersid);
1858     lstrcatA(keypath, "\\Components\\");
1859     lstrcatA(keypath, comp_squashed2);
1860 
1861     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
1862     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1863 
1864     state = MsiQueryFeatureStateA(prodcode, "feature");
1865     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1866 
1867     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
1868     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1869 
1870     state = MsiQueryFeatureStateA(prodcode, "feature");
1871     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1872 
1873     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
1874     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1875 
1876     state = MsiQueryFeatureStateA(prodcode, "feature");
1877     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1878 
1879     res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
1880     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1881 
1882     state = MsiQueryFeatureStateA(prodcode, "feature");
1883     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1884 
1885     RegDeleteValueA(compkey, prod_squashed);
1886     RegDeleteValueA(compkey2, prod_squashed);
1887     RegDeleteKeyExA(compkey, "", access & KEY_WOW64_64KEY, 0);
1888     RegDeleteKeyExA(compkey2, "", access & KEY_WOW64_64KEY, 0);
1889     RegDeleteValueA(localkey, "feature");
1890     RegDeleteValueA(userkey, "feature");
1891     RegDeleteKeyExA(userkey, "", access & KEY_WOW64_64KEY, 0);
1892     RegCloseKey(compkey);
1893     RegCloseKey(compkey2);
1894     RegCloseKey(localkey);
1895     RegCloseKey(userkey);
1896 
1897     /* MSIINSTALLCONTEXT_MACHINE */
1898 
1899     lstrcpyA(keypath, "Software\\Classes\\Installer\\Features\\");
1900     lstrcatA(keypath, prod_squashed);
1901 
1902     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
1903     if (res == ERROR_ACCESS_DENIED)
1904     {
1905         skip( "insufficient rights\n" );
1906         LocalFree( usersid );
1907         return;
1908     }
1909     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1910 
1911     /* feature key exists */
1912     state = MsiQueryFeatureStateA(prodcode, "feature");
1913     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1914 
1915     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 1);
1916     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1917 
1918     /* feature value exists */
1919     state = MsiQueryFeatureStateA(prodcode, "feature");
1920     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1921 
1922     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1923     lstrcatA(keypath, "S-1-5-18\\Products\\");
1924     lstrcatA(keypath, prod_squashed);
1925     lstrcatA(keypath, "\\Features");
1926 
1927     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1928     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1929 
1930     /* userdata features key exists */
1931     state = MsiQueryFeatureStateA(prodcode, "feature");
1932     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1933 
1934     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
1935     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1936 
1937     state = MsiQueryFeatureStateA(prodcode, "feature");
1938     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
1939 
1940     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
1941     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1942 
1943     state = MsiQueryFeatureStateA(prodcode, "feature");
1944     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1945 
1946     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
1947     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1948 
1949     state = MsiQueryFeatureStateA(prodcode, "feature");
1950     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1951 
1952     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
1953     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1954 
1955     state = MsiQueryFeatureStateA(prodcode, "feature");
1956     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1957 
1958     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1959     lstrcatA(keypath, "S-1-5-18\\Components\\");
1960     lstrcatA(keypath, comp_squashed);
1961 
1962     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
1963     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1964 
1965     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1966     lstrcatA(keypath, "S-1-5-18\\Components\\");
1967     lstrcatA(keypath, comp_squashed2);
1968 
1969     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
1970     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1971 
1972     state = MsiQueryFeatureStateA(prodcode, "feature");
1973     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1974 
1975     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
1976     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1977 
1978     state = MsiQueryFeatureStateA(prodcode, "feature");
1979     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1980 
1981     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
1982     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1983 
1984     state = MsiQueryFeatureStateA(prodcode, "feature");
1985     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1986 
1987     res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
1988     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
1989 
1990     state = MsiQueryFeatureStateA(prodcode, "feature");
1991     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1992 
1993     RegDeleteValueA(compkey, prod_squashed);
1994     RegDeleteValueA(compkey2, prod_squashed);
1995     RegDeleteKeyExA(compkey, "", access & KEY_WOW64_64KEY, 0);
1996     RegDeleteKeyExA(compkey2, "", access & KEY_WOW64_64KEY, 0);
1997     RegDeleteValueA(localkey, "feature");
1998     RegDeleteValueA(userkey, "feature");
1999     RegDeleteKeyExA(userkey, "", access & KEY_WOW64_64KEY, 0);
2000     RegCloseKey(compkey);
2001     RegCloseKey(compkey2);
2002     RegCloseKey(localkey);
2003     RegCloseKey(userkey);
2004     LocalFree(usersid);
2005 }
2006 
test_MsiQueryComponentState(void)2007 static void test_MsiQueryComponentState(void)
2008 {
2009     HKEY compkey, prodkey;
2010     CHAR prodcode[MAX_PATH];
2011     CHAR prod_squashed[MAX_PATH];
2012     CHAR component[MAX_PATH];
2013     CHAR comp_base85[MAX_PATH];
2014     CHAR comp_squashed[MAX_PATH];
2015     CHAR keypath[MAX_PATH];
2016     INSTALLSTATE state;
2017     LPSTR usersid;
2018     LONG res;
2019     UINT r;
2020     REGSAM access = KEY_ALL_ACCESS;
2021     DWORD error;
2022 
2023     static const INSTALLSTATE MAGIC_ERROR = 0xdeadbeef;
2024 
2025     create_test_guid(prodcode, prod_squashed);
2026     compose_base85_guid(component, comp_base85, comp_squashed);
2027     usersid = get_user_sid();
2028 
2029     if (is_wow64)
2030         access |= KEY_WOW64_64KEY;
2031 
2032     /* NULL szProductCode */
2033     state = MAGIC_ERROR;
2034     SetLastError(0xdeadbeef);
2035     r = MsiQueryComponentStateA(NULL, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2036     error = GetLastError();
2037     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2038     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2039     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2040 
2041     /* empty szProductCode */
2042     state = MAGIC_ERROR;
2043     SetLastError(0xdeadbeef);
2044     r = MsiQueryComponentStateA("", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2045     error = GetLastError();
2046     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2047     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2048     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2049 
2050     /* random szProductCode */
2051     state = MAGIC_ERROR;
2052     SetLastError(0xdeadbeef);
2053     r = MsiQueryComponentStateA("random", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2054     error = GetLastError();
2055     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2056     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2057     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2058 
2059     /* GUID-length szProductCode */
2060     state = MAGIC_ERROR;
2061     SetLastError(0xdeadbeef);
2062     r = MsiQueryComponentStateA("DJANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KDE", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2063     error = GetLastError();
2064     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2065     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2066     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2067 
2068     /* GUID-length with brackets */
2069     state = MAGIC_ERROR;
2070     SetLastError(0xdeadbeef);
2071     r = MsiQueryComponentStateA("{JANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KD}", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2072     error = GetLastError();
2073     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2074     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2075     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2076 
2077     /* actual GUID */
2078     state = MAGIC_ERROR;
2079     SetLastError(0xdeadbeef);
2080     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2081     error = GetLastError();
2082     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2083     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2084     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2085 
2086     state = MAGIC_ERROR;
2087     SetLastError(0xdeadbeef);
2088     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2089     error = GetLastError();
2090     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2091     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2092     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2093 
2094     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
2095     lstrcatA(keypath, prod_squashed);
2096 
2097     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2098     if (res == ERROR_ACCESS_DENIED)
2099     {
2100         skip("Not enough rights to perform tests\n");
2101         LocalFree(usersid);
2102         return;
2103     }
2104     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2105 
2106     state = MAGIC_ERROR;
2107     SetLastError(0xdeadbeef);
2108     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2109     error = GetLastError();
2110     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2111     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2112     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2113 
2114     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
2115     RegCloseKey(prodkey);
2116 
2117     /* create local system product key */
2118     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\");
2119     lstrcatA(keypath, prod_squashed);
2120     lstrcatA(keypath, "\\InstallProperties");
2121 
2122     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2123     if (res == ERROR_ACCESS_DENIED)
2124     {
2125         skip("Not enough rights to perform tests\n");
2126         LocalFree(usersid);
2127         return;
2128     }
2129     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2130 
2131     /* local system product key exists */
2132     state = MAGIC_ERROR;
2133     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2134     error = GetLastError();
2135     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2136     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2137     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2138 
2139     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2140     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2141 
2142     /* LocalPackage value exists */
2143     state = MAGIC_ERROR;
2144     SetLastError(0xdeadbeef);
2145     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2146     error = GetLastError();
2147     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2148     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2149     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2150 
2151     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\");
2152     lstrcatA(keypath, comp_squashed);
2153 
2154     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2155     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2156 
2157     /* component key exists */
2158     state = MAGIC_ERROR;
2159     SetLastError(0xdeadbeef);
2160     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2161     error = GetLastError();
2162     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2163     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2164     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2165 
2166     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
2167     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2168 
2169     /* component\product exists */
2170     state = MAGIC_ERROR;
2171     SetLastError(0xdeadbeef);
2172     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2173     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2174     error = GetLastError();
2175     ok(state == INSTALLSTATE_NOTUSED || state == INSTALLSTATE_LOCAL,
2176        "Expected INSTALLSTATE_NOTUSED or INSTALLSTATE_LOCAL, got %d\n", state);
2177     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2178 
2179     /* NULL component, product exists */
2180     state = MAGIC_ERROR;
2181     SetLastError(0xdeadbeef);
2182     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, NULL, &state);
2183     error = GetLastError();
2184     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2185     ok(state == MAGIC_ERROR, "Expected state not changed, got %d\n", state);
2186     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2187 
2188     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
2189     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2190 
2191     /* INSTALLSTATE_LOCAL */
2192     state = MAGIC_ERROR;
2193     SetLastError(0xdeadbeef);
2194     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2195     error = GetLastError();
2196     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2197     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2198     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2199 
2200     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01\\", 4);
2201     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2202 
2203     /* INSTALLSTATE_SOURCE */
2204     state = MAGIC_ERROR;
2205     SetLastError(0xdeadbeef);
2206     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2207     error = GetLastError();
2208     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2209     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2210     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2211 
2212     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
2213     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2214 
2215     /* bad INSTALLSTATE_SOURCE */
2216     state = MAGIC_ERROR;
2217     SetLastError(0xdeadbeef);
2218     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2219     error = GetLastError();
2220     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2221     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2222     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2223 
2224     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01a", 4);
2225     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2226 
2227     /* INSTALLSTATE_SOURCE */
2228     state = MAGIC_ERROR;
2229     SetLastError(0xdeadbeef);
2230     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2231     error = GetLastError();
2232     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2233     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2234     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2235 
2236     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01:", 4);
2237     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2238 
2239     /* registry component */
2240     state = MAGIC_ERROR;
2241     SetLastError(0xdeadbeef);
2242     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2243     error = GetLastError();
2244     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2245     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2246     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", error);
2247 
2248     RegDeleteValueA(prodkey, "LocalPackage");
2249     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
2250     RegDeleteValueA(compkey, prod_squashed);
2251     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
2252     RegCloseKey(prodkey);
2253     RegCloseKey(compkey);
2254 
2255     /* MSIINSTALLCONTEXT_USERUNMANAGED */
2256 
2257     state = MAGIC_ERROR;
2258     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2259     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2260     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2261 
2262     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2263     lstrcatA(keypath, prod_squashed);
2264 
2265     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
2266     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2267 
2268     state = MAGIC_ERROR;
2269     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2270     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2271     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2272 
2273     RegDeleteKeyA(prodkey, "");
2274     RegCloseKey(prodkey);
2275 
2276     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2277     lstrcatA(keypath, usersid);
2278     lstrcatA(keypath, "\\Products\\");
2279     lstrcatA(keypath, prod_squashed);
2280     lstrcatA(keypath, "\\InstallProperties");
2281 
2282     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2283     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2284 
2285     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2286     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2287 
2288     RegCloseKey(prodkey);
2289 
2290     state = MAGIC_ERROR;
2291     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2292     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2293     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2294 
2295     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2296     lstrcatA(keypath, usersid);
2297     lstrcatA(keypath, "\\Components\\");
2298     lstrcatA(keypath, comp_squashed);
2299 
2300     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2301     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2302 
2303     /* component key exists */
2304     state = MAGIC_ERROR;
2305     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2306     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2307     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2308 
2309     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
2310     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2311 
2312     /* component\product exists */
2313     state = MAGIC_ERROR;
2314     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2315     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2316     ok(state == INSTALLSTATE_NOTUSED || state == INSTALLSTATE_LOCAL,
2317        "Expected INSTALLSTATE_NOTUSED or INSTALLSTATE_LOCAL, got %d\n", state);
2318 
2319     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
2320     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2321 
2322     state = MAGIC_ERROR;
2323     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2324     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2325     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2326 
2327     /* MSIINSTALLCONTEXT_USERMANAGED */
2328 
2329     state = MAGIC_ERROR;
2330     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2331     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2332     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2333 
2334     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2335     lstrcatA(keypath, prod_squashed);
2336 
2337     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
2338     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2339 
2340     state = MAGIC_ERROR;
2341     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2342     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2343     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2344 
2345     RegDeleteKeyA(prodkey, "");
2346     RegCloseKey(prodkey);
2347 
2348     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
2349     lstrcatA(keypath, usersid);
2350     lstrcatA(keypath, "\\Installer\\Products\\");
2351     lstrcatA(keypath, prod_squashed);
2352 
2353     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2354     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2355 
2356     state = MAGIC_ERROR;
2357     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2358     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2359     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2360 
2361     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
2362     RegCloseKey(prodkey);
2363 
2364     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2365     lstrcatA(keypath, usersid);
2366     lstrcatA(keypath, "\\Products\\");
2367     lstrcatA(keypath, prod_squashed);
2368     lstrcatA(keypath, "\\InstallProperties");
2369 
2370     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2371     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2372 
2373     res = RegSetValueExA(prodkey, "ManagedLocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2374     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2375 
2376     state = MAGIC_ERROR;
2377     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2378     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2379     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2380 
2381     RegDeleteValueA(prodkey, "LocalPackage");
2382     RegDeleteValueA(prodkey, "ManagedLocalPackage");
2383     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
2384     RegDeleteValueA(compkey, prod_squashed);
2385     RegDeleteKeyExA(compkey, "", access & KEY_WOW64_64KEY, 0);
2386     RegCloseKey(prodkey);
2387     RegCloseKey(compkey);
2388     LocalFree(usersid);
2389 }
2390 
test_MsiGetComponentPath(void)2391 static void test_MsiGetComponentPath(void)
2392 {
2393     HKEY compkey, prodkey, installprop;
2394     CHAR prodcode[MAX_PATH];
2395     CHAR prod_squashed[MAX_PATH];
2396     CHAR component[MAX_PATH];
2397     CHAR comp_base85[MAX_PATH];
2398     CHAR comp_squashed[MAX_PATH];
2399     CHAR keypath[MAX_PATH];
2400     CHAR path[MAX_PATH];
2401     INSTALLSTATE state;
2402     LPSTR usersid;
2403     DWORD size, val;
2404     REGSAM access = KEY_ALL_ACCESS;
2405     LONG res;
2406 
2407     create_test_guid(prodcode, prod_squashed);
2408     compose_base85_guid(component, comp_base85, comp_squashed);
2409     usersid = get_user_sid();
2410 
2411     if (is_wow64)
2412         access |= KEY_WOW64_64KEY;
2413 
2414     /* NULL szProduct */
2415     size = MAX_PATH;
2416     state = MsiGetComponentPathA(NULL, component, path, &size);
2417     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2418     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2419 
2420     /* NULL szComponent */
2421     size = MAX_PATH;
2422     state = MsiGetComponentPathA(prodcode, NULL, path, &size);
2423     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2424     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2425 
2426     size = MAX_PATH;
2427     state = MsiLocateComponentA(NULL, path, &size);
2428     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2429     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2430 
2431     /* NULL lpPathBuf */
2432     size = MAX_PATH;
2433     state = MsiGetComponentPathA(prodcode, component, NULL, &size);
2434     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2435     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2436 
2437     size = MAX_PATH;
2438     state = MsiLocateComponentA(component, NULL, &size);
2439     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2440     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2441 
2442     /* NULL pcchBuf */
2443     size = MAX_PATH;
2444     state = MsiGetComponentPathA(prodcode, component, path, NULL);
2445     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2446     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2447 
2448     size = MAX_PATH;
2449     state = MsiLocateComponentA(component, path, NULL);
2450     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2451     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2452 
2453     /* all params valid */
2454     size = MAX_PATH;
2455     state = MsiGetComponentPathA(prodcode, component, path, &size);
2456     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2457     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2458 
2459     size = MAX_PATH;
2460     state = MsiLocateComponentA(component, path, &size);
2461     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2462     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2463 
2464     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2465     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
2466     lstrcatA(keypath, comp_squashed);
2467 
2468     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2469     if (res == ERROR_ACCESS_DENIED)
2470     {
2471         skip("Not enough rights to perform tests\n");
2472         LocalFree(usersid);
2473         return;
2474     }
2475     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2476 
2477     /* local system component key exists */
2478     size = MAX_PATH;
2479     state = MsiGetComponentPathA(prodcode, component, path, &size);
2480     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2481     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2482 
2483     size = MAX_PATH;
2484     state = MsiLocateComponentA(component, path, &size);
2485     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2486     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2487 
2488     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2489     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2490 
2491     /* product value exists */
2492     path[0] = 0;
2493     size = MAX_PATH;
2494     state = MsiGetComponentPathA(prodcode, component, path, &size);
2495     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2496     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2497     ok(size == 10, "Expected 10, got %lu\n", size);
2498 
2499     path[0] = 0;
2500     size = MAX_PATH;
2501     state = MsiLocateComponentA(component, path, &size);
2502     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2503     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2504     ok(size == 10, "Expected 10, got %lu\n", size);
2505 
2506     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2507     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
2508     lstrcatA(keypath, prod_squashed);
2509     lstrcatA(keypath, "\\InstallProperties");
2510 
2511     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &installprop, NULL);
2512     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2513 
2514     val = 1;
2515     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
2516     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2517 
2518     /* install properties key exists */
2519     path[0] = 0;
2520     size = MAX_PATH;
2521     state = MsiGetComponentPathA(prodcode, component, path, &size);
2522     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2523     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2524     ok(size == 10, "Expected 10, got %lu\n", size);
2525 
2526     path[0] = 0;
2527     size = MAX_PATH;
2528     state = MsiLocateComponentA(component, path, &size);
2529     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2530     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2531     ok(size == 10, "Expected 10, got %lu\n", size);
2532 
2533     create_file("C:\\imapath", 11);
2534 
2535     /* file exists */
2536     path[0] = 'a';
2537     size = 0;
2538     state = MsiGetComponentPathA(prodcode, component, path, &size);
2539     ok(state == INSTALLSTATE_MOREDATA, "Expected INSTALLSTATE_MOREDATA, got %d\n", state);
2540     ok(path[0] == 'a', "got %s\n", path);
2541     ok(size == 10, "Expected 10, got %lu\n", size);
2542 
2543     path[0] = 0;
2544     size = MAX_PATH;
2545     state = MsiGetComponentPathA(prodcode, component, path, &size);
2546     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2547     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2548     ok(size == 10, "Expected 10, got %lu\n", size);
2549 
2550     size = 0;
2551     path[0] = 'a';
2552     state = MsiLocateComponentA(component, path, &size);
2553     ok(state == INSTALLSTATE_MOREDATA, "Expected INSTALLSTATE_MOREDATA, got %d\n", state);
2554     ok(path[0] == 'a', "got %s\n", path);
2555     ok(size == 10, "Expected 10, got %lu\n", size);
2556 
2557     path[0] = 0;
2558     size = MAX_PATH;
2559     state = MsiLocateComponentA(component, path, &size);
2560     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2561     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2562     ok(size == 10, "Expected 10, got %lu\n", size);
2563 
2564     RegDeleteValueA(compkey, prod_squashed);
2565     RegDeleteKeyExA(compkey, "", access & KEY_WOW64_64KEY, 0);
2566     RegDeleteValueA(installprop, "WindowsInstaller");
2567     RegDeleteKeyExA(installprop, "", access & KEY_WOW64_64KEY, 0);
2568     RegCloseKey(compkey);
2569     RegCloseKey(installprop);
2570     DeleteFileA("C:\\imapath");
2571 
2572     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2573     lstrcatA(keypath, "Installer\\UserData\\");
2574     lstrcatA(keypath, usersid);
2575     lstrcatA(keypath, "\\Components\\");
2576     lstrcatA(keypath, comp_squashed);
2577 
2578     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2579     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2580 
2581     /* user managed component key exists */
2582     size = MAX_PATH;
2583     state = MsiGetComponentPathA(prodcode, component, path, &size);
2584     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2585     ok(size == MAX_PATH, "Expected size to be unchanged, got %ld\n", size);
2586 
2587     size = MAX_PATH;
2588     state = MsiLocateComponentA(component, path, &size);
2589     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2590     ok(size == MAX_PATH, "Expected size to be unchanged, got %ld\n", size);
2591 
2592     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2593     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2594 
2595     /* product value exists */
2596     path[0] = 0;
2597     size = MAX_PATH;
2598     state = MsiGetComponentPathA(prodcode, component, path, &size);
2599     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2600     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2601     ok(size == 10, "Expected 10, got %lu\n", size);
2602 
2603     path[0] = 0;
2604     size = MAX_PATH;
2605     state = MsiLocateComponentA(component, path, &size);
2606     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2607     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2608     ok(size == 10, "Expected 10, got %lu\n", size);
2609 
2610     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2611     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
2612     lstrcatA(keypath, prod_squashed);
2613     lstrcatA(keypath, "\\InstallProperties");
2614 
2615     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &installprop, NULL);
2616     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2617 
2618     val = 1;
2619     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
2620     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2621 
2622     /* install properties key exists */
2623     path[0] = 0;
2624     size = MAX_PATH;
2625     state = MsiGetComponentPathA(prodcode, component, path, &size);
2626     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2627     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2628     ok(size == 10, "Expected 10, got %lu\n", size);
2629 
2630     path[0] = 0;
2631     size = MAX_PATH;
2632     state = MsiLocateComponentA(component, path, &size);
2633     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2634     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2635     ok(size == 10, "Expected 10, got %lu\n", size);
2636 
2637     create_file("C:\\imapath", 11);
2638 
2639     /* file exists */
2640     path[0] = 0;
2641     size = MAX_PATH;
2642     state = MsiGetComponentPathA(prodcode, component, path, &size);
2643     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2644     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2645     ok(size == 10, "Expected 10, got %lu\n", size);
2646 
2647     path[0] = 0;
2648     size = MAX_PATH;
2649     state = MsiLocateComponentA(component, path, &size);
2650     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2651     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2652     ok(size == 10, "Expected 10, got %lu\n", size);
2653 
2654     RegDeleteValueA(compkey, prod_squashed);
2655     RegDeleteKeyExA(compkey, "", access & KEY_WOW64_64KEY, 0);
2656     RegDeleteValueA(installprop, "WindowsInstaller");
2657     RegDeleteKeyExA(installprop, "", access & KEY_WOW64_64KEY, 0);
2658     RegCloseKey(compkey);
2659     RegCloseKey(installprop);
2660     DeleteFileA("C:\\imapath");
2661 
2662     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2663     lstrcatA(keypath, "Installer\\Managed\\");
2664     lstrcatA(keypath, usersid);
2665     lstrcatA(keypath, "\\Installer\\Products\\");
2666     lstrcatA(keypath, prod_squashed);
2667 
2668     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2669     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2670 
2671     /* user managed product key exists */
2672     size = MAX_PATH;
2673     state = MsiGetComponentPathA(prodcode, component, path, &size);
2674     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2675     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2676 
2677     size = MAX_PATH;
2678     state = MsiLocateComponentA(component, path, &size);
2679     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2680     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2681 
2682     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2683     lstrcatA(keypath, "Installer\\UserData\\");
2684     lstrcatA(keypath, usersid);
2685     lstrcatA(keypath, "\\Components\\");
2686     lstrcatA(keypath, comp_squashed);
2687 
2688     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2689     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2690 
2691     /* user managed component key exists */
2692     size = MAX_PATH;
2693     state = MsiGetComponentPathA(prodcode, component, path, &size);
2694     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2695     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2696 
2697     size = MAX_PATH;
2698     state = MsiLocateComponentA(component, path, &size);
2699     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2700     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2701 
2702     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2703     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2704 
2705     /* product value exists */
2706     path[0] = 0;
2707     size = MAX_PATH;
2708     state = MsiGetComponentPathA(prodcode, component, path, &size);
2709     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2710     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2711     ok(size == 10, "Expected 10, got %lu\n", size);
2712 
2713     path[0] = 0;
2714     size = MAX_PATH;
2715     state = MsiLocateComponentA(component, path, &size);
2716     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2717     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2718     ok(size == 10, "Expected 10, got %lu\n", size);
2719 
2720     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2721     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
2722     lstrcatA(keypath, prod_squashed);
2723     lstrcatA(keypath, "\\InstallProperties");
2724 
2725     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &installprop, NULL);
2726     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2727 
2728     val = 1;
2729     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
2730     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2731 
2732     /* install properties key exists */
2733     path[0] = 0;
2734     size = MAX_PATH;
2735     state = MsiGetComponentPathA(prodcode, component, path, &size);
2736     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2737     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2738     ok(size == 10, "Expected 10, got %lu\n", size);
2739 
2740     path[0] = 0;
2741     size = MAX_PATH;
2742     state = MsiLocateComponentA(component, path, &size);
2743     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2744     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2745     ok(size == 10, "Expected 10, got %lu\n", size);
2746 
2747     create_file("C:\\imapath", 11);
2748 
2749     /* file exists */
2750     path[0] = 0;
2751     size = MAX_PATH;
2752     state = MsiGetComponentPathA(prodcode, component, path, &size);
2753     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2754     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2755     ok(size == 10, "Expected 10, got %lu\n", size);
2756 
2757     path[0] = 0;
2758     size = MAX_PATH;
2759     state = MsiLocateComponentA(component, path, &size);
2760     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2761     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2762     ok(size == 10, "Expected 10, got %lu\n", size);
2763 
2764     RegDeleteValueA(compkey, prod_squashed);
2765     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
2766     RegDeleteKeyExA(compkey, "", access & KEY_WOW64_64KEY, 0);
2767     RegDeleteValueA(installprop, "WindowsInstaller");
2768     RegDeleteKeyExA(installprop, "", access & KEY_WOW64_64KEY, 0);
2769     RegCloseKey(prodkey);
2770     RegCloseKey(compkey);
2771     RegCloseKey(installprop);
2772     DeleteFileA("C:\\imapath");
2773 
2774     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2775     lstrcatA(keypath, prod_squashed);
2776 
2777     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
2778     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2779 
2780     /* user unmanaged product key exists */
2781     size = MAX_PATH;
2782     state = MsiGetComponentPathA(prodcode, component, path, &size);
2783     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2784     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2785 
2786     size = MAX_PATH;
2787     state = MsiLocateComponentA(component, path, &size);
2788     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2789     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2790 
2791     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2792     lstrcatA(keypath, "Installer\\UserData\\");
2793     lstrcatA(keypath, usersid);
2794     lstrcatA(keypath, "\\Components\\");
2795     lstrcatA(keypath, comp_squashed);
2796 
2797     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2798     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2799 
2800     /* user unmanaged component key exists */
2801     size = MAX_PATH;
2802     state = MsiGetComponentPathA(prodcode, component, path, &size);
2803     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2804     ok(size == MAX_PATH, "Expected size to be unchanged, got %ld\n", size);
2805 
2806     size = MAX_PATH;
2807     state = MsiLocateComponentA(component, path, &size);
2808     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2809     ok(size == MAX_PATH, "Expected size to be unchanged, got %ld\n", size);
2810 
2811     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2812     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2813 
2814     /* product value exists */
2815     path[0] = 0;
2816     size = MAX_PATH;
2817     state = MsiGetComponentPathA(prodcode, component, path, &size);
2818     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2819     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2820     ok(size == 10, "Expected 10, got %lu\n", size);
2821 
2822     path[0] = 0;
2823     size = MAX_PATH;
2824     state = MsiLocateComponentA(component, path, &size);
2825     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2826     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2827     ok(size == 10, "Expected 10, got %lu\n", size);
2828 
2829     create_file("C:\\imapath", 11);
2830 
2831     /* file exists */
2832     path[0] = 0;
2833     size = MAX_PATH;
2834     state = MsiGetComponentPathA(prodcode, component, path, &size);
2835     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2836     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2837     ok(size == 10, "Expected 10, got %lu\n", size);
2838 
2839     path[0] = 0;
2840     size = MAX_PATH;
2841     state = MsiLocateComponentA(component, path, &size);
2842     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2843     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2844     ok(size == 10, "Expected 10, got %lu\n", size);
2845 
2846     RegDeleteValueA(compkey, prod_squashed);
2847     RegDeleteKeyA(prodkey, "");
2848     RegDeleteKeyExA(compkey, "", access & KEY_WOW64_64KEY, 0);
2849     RegCloseKey(prodkey);
2850     RegCloseKey(compkey);
2851     DeleteFileA("C:\\imapath");
2852 
2853     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
2854     lstrcatA(keypath, prod_squashed);
2855 
2856     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2857     if (res == ERROR_ACCESS_DENIED)
2858     {
2859         skip( "insufficient rights\n" );
2860         LocalFree( usersid );
2861         return;
2862     }
2863     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2864 
2865     /* local classes product key exists */
2866     size = MAX_PATH;
2867     state = MsiGetComponentPathA(prodcode, component, path, &size);
2868     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2869     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2870 
2871     size = MAX_PATH;
2872     state = MsiLocateComponentA(component, path, &size);
2873     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2874     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
2875 
2876     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2877     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
2878     lstrcatA(keypath, comp_squashed);
2879 
2880     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2881     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2882 
2883     /* local user component key exists */
2884     size = MAX_PATH;
2885     state = MsiGetComponentPathA(prodcode, component, path, &size);
2886     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2887     ok(size == MAX_PATH, "Expected size to be unchanged, got %ld\n", size);
2888 
2889     size = MAX_PATH;
2890     state = MsiLocateComponentA(component, path, &size);
2891     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2892     ok(size == MAX_PATH, "Expected size to be unchanged, got %ld\n", size);
2893 
2894     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2895     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2896 
2897     /* product value exists */
2898     path[0] = 0;
2899     size = MAX_PATH;
2900     state = MsiGetComponentPathA(prodcode, component, path, &size);
2901     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2902     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2903     ok(size == 10, "Expected 10, got %lu\n", size);
2904 
2905     path[0] = 0;
2906     size = MAX_PATH;
2907     state = MsiLocateComponentA(component, path, &size);
2908     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2909     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2910     ok(size == 10, "Expected 10, got %lu\n", size);
2911 
2912     create_file("C:\\imapath", 11);
2913 
2914     /* file exists */
2915     path[0] = 0;
2916     size = MAX_PATH;
2917     state = MsiGetComponentPathA(prodcode, component, path, &size);
2918     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2919     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2920     ok(size == 10, "Expected 10, got %lu\n", size);
2921 
2922     path[0] = 0;
2923     size = MAX_PATH;
2924     state = MsiLocateComponentA(component, path, &size);
2925     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2926     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2927     ok(size == 10, "Expected 10, got %lu\n", size);
2928 
2929     RegDeleteValueA(compkey, prod_squashed);
2930     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
2931     RegDeleteKeyExA(compkey, "", access & KEY_WOW64_64KEY, 0);
2932     RegCloseKey(prodkey);
2933     RegCloseKey(compkey);
2934     DeleteFileA("C:\\imapath");
2935     LocalFree(usersid);
2936 }
2937 
test_MsiGetComponentPathEx(void)2938 static void test_MsiGetComponentPathEx(void)
2939 {
2940     HKEY key_comp, key_installprop, key_prod;
2941     char prod[MAX_PATH], prod_squashed[MAX_PATH];
2942     char comp[MAX_PATH], comp_base85[MAX_PATH], comp_squashed[MAX_PATH];
2943     char path[MAX_PATH], path_key[MAX_PATH], *usersid;
2944     INSTALLSTATE state;
2945     DWORD size, val;
2946     REGSAM access = KEY_ALL_ACCESS;
2947     LONG res;
2948 
2949     if (is_wow64) access |= KEY_WOW64_64KEY;
2950 
2951     create_test_guid( prod, prod_squashed );
2952     compose_base85_guid( comp, comp_base85, comp_squashed );
2953     usersid = get_user_sid();
2954 
2955     /* NULL product */
2956     size = MAX_PATH;
2957     state = MsiGetComponentPathExA( NULL, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
2958     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
2959     todo_wine ok( !size, "got %lu\n", size );
2960 
2961     /* NULL component */
2962     size = MAX_PATH;
2963     state = MsiGetComponentPathExA( prod, NULL, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
2964     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
2965     todo_wine ok( !size, "got %lu\n", size );
2966 
2967     /* non-NULL usersid, MSIINSTALLCONTEXT_MACHINE */
2968     size = MAX_PATH;
2969     state = MsiGetComponentPathExA( prod, comp, usersid, MSIINSTALLCONTEXT_MACHINE, path, &size);
2970     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
2971     todo_wine ok( !size, "got %lu\n", size );
2972 
2973     /* NULL buf */
2974     size = MAX_PATH;
2975     state = MsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, NULL, &size );
2976     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
2977     todo_wine ok( size == MAX_PATH * 2, "got %lu\n", size );
2978 
2979     /* NULL buflen */
2980     size = MAX_PATH;
2981     state = MsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, NULL );
2982     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
2983     ok( size == MAX_PATH, "got %lu\n", size );
2984 
2985     /* all params valid */
2986     size = MAX_PATH;
2987     state = MsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
2988     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
2989     todo_wine ok( !size, "got %lu\n", size );
2990 
2991     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
2992     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Components\\" );
2993     lstrcatA( path_key, comp_squashed );
2994 
2995     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
2996     if (res == ERROR_ACCESS_DENIED)
2997     {
2998         skip( "insufficient rights\n" );
2999         LocalFree( usersid );
3000         return;
3001     }
3002     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3003 
3004     /* local system component key exists */
3005     size = MAX_PATH;
3006     state = MsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3007     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3008 
3009     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3010     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3011 
3012     /* product value exists */
3013     path[0] = 0;
3014     size = MAX_PATH;
3015     state = MsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3016     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3017     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3018     ok( size == 20, "got %lu\n", size );
3019 
3020     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3021     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Products\\" );
3022     lstrcatA( path_key, prod_squashed );
3023     lstrcatA( path_key, "\\InstallProperties" );
3024 
3025     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_installprop, NULL );
3026     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3027 
3028     val = 1;
3029     res = RegSetValueExA( key_installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(val) );
3030     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3031 
3032     /* install properties key exists */
3033     path[0] = 0;
3034     size = MAX_PATH;
3035     state = MsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3036     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3037     ok( !lstrcmpA( path, "c:\\testcomponentpath"), "got %s\n", path );
3038     ok( size == 20, "got %lu\n", size );
3039 
3040     create_file( "c:\\testcomponentpath", 21 );
3041 
3042     /* file exists */
3043     path[0] = 0;
3044     size = 0;
3045     state = MsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3046     ok( state == INSTALLSTATE_MOREDATA, "got %d\n", state );
3047     ok( !path[0], "got %s\n", path );
3048     todo_wine ok( size == 40, "got %lu\n", size );
3049 
3050     path[0] = 0;
3051     size = MAX_PATH;
3052     state = MsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3053     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3054     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3055     ok( size == 20, "got %lu\n", size );
3056 
3057     RegDeleteValueA( key_comp, prod_squashed );
3058     RegDeleteKeyExA( key_comp, "", access & KEY_WOW64_64KEY, 0 );
3059     RegDeleteValueA( key_installprop, "WindowsInstaller" );
3060     RegDeleteKeyExA( key_installprop, "", access & KEY_WOW64_64KEY, 0 );
3061     RegCloseKey( key_comp );
3062     RegCloseKey( key_installprop );
3063     DeleteFileA( "c:\\testcomponentpath" );
3064 
3065     lstrcpyA( path_key, "Software\\Microsoft\\Installer\\Products\\" );
3066     lstrcatA( path_key, prod_squashed );
3067 
3068     res = RegCreateKeyA( HKEY_CURRENT_USER, path_key, &key_prod );
3069     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3070 
3071     /* user unmanaged product key exists */
3072     size = MAX_PATH;
3073     state = MsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3074     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3075     todo_wine ok(!size, "got %lu\n", size);
3076 
3077     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3078     lstrcatA( path_key, "Installer\\UserData\\" );
3079     lstrcatA( path_key, usersid );
3080     lstrcatA( path_key, "\\Components\\" );
3081     lstrcatA( path_key, comp_squashed );
3082 
3083     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3084     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3085 
3086     /* user unmanaged component key exists */
3087     size = MAX_PATH;
3088     state = MsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3089     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3090     todo_wine ok(!size, "got %lu\n", size);
3091 
3092     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3093     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3094 
3095     /* product value exists */
3096     path[0] = 0;
3097     size = MAX_PATH;
3098     state = MsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3099     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3100     ok( !lstrcmpA( path, "c:\\testcomponentpath"), "got %s\n", path );
3101     ok( size == 20, "got %lu\n", size );
3102 
3103     create_file( "c:\\testcomponentpath", 21 );
3104 
3105     /* file exists */
3106     path[0] = 0;
3107     size = MAX_PATH;
3108     state = MsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3109     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3110     ok( !lstrcmpA( path, "c:\\testcomponentpath"), "got %s\n", path );
3111     ok( size == 20, "got %lu\n", size );
3112 
3113     RegDeleteValueA( key_comp, prod_squashed );
3114     RegDeleteKeyA( key_prod, "" );
3115     RegDeleteKeyExA( key_comp, "", access & KEY_WOW64_64KEY, 0 );
3116     RegCloseKey( key_prod );
3117     RegCloseKey( key_comp );
3118     DeleteFileA( "c:\\testcomponentpath" );
3119 
3120     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3121     lstrcatA( path_key, "Installer\\Managed\\" );
3122     lstrcatA( path_key, usersid );
3123     lstrcatA( path_key, "\\Installer\\Products\\" );
3124     lstrcatA( path_key, prod_squashed );
3125 
3126     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_prod, NULL );
3127     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3128 
3129     /* user managed product key exists */
3130     size = MAX_PATH;
3131     state = MsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3132     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3133 
3134     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3135     lstrcatA( path_key, "Installer\\UserData\\" );
3136     lstrcatA( path_key, usersid );
3137     lstrcatA( path_key, "\\Components\\" );
3138     lstrcatA( path_key, comp_squashed );
3139 
3140     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3141     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3142 
3143     /* user managed component key exists */
3144     size = MAX_PATH;
3145     state = MsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3146     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3147 
3148     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3149     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3150 
3151     /* product value exists */
3152     path[0] = 0;
3153     size = MAX_PATH;
3154     state = MsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3155     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3156     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3157     ok( size == 20, "got %lu\n", size );
3158 
3159     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3160     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Products\\" );
3161     lstrcatA( path_key, prod_squashed );
3162     lstrcatA( path_key, "\\InstallProperties" );
3163 
3164     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_installprop, NULL );
3165     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3166 
3167     val = 1;
3168     res = RegSetValueExA( key_installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(val) );
3169     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3170 
3171     /* install properties key exists */
3172     path[0] = 0;
3173     size = MAX_PATH;
3174     state = MsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3175     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3176     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3177     ok( size == 20, "got %lu\n", size );
3178 
3179     create_file( "c:\\testcomponentpath", 21 );
3180 
3181     /* file exists */
3182     path[0] = 0;
3183     size = MAX_PATH;
3184     state = MsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3185     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3186     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3187     ok( size == 20, "got %lu\n", size );
3188 
3189     RegDeleteValueA( key_comp, prod_squashed );
3190     RegDeleteKeyExA( key_prod, "", access & KEY_WOW64_64KEY, 0 );
3191     RegDeleteKeyExA( key_comp, "", access & KEY_WOW64_64KEY, 0 );
3192     RegDeleteValueA( key_installprop, "WindowsInstaller" );
3193     RegDeleteKeyExA( key_installprop, "", access & KEY_WOW64_64KEY, 0 );
3194     RegCloseKey( key_prod );
3195     RegCloseKey( key_comp );
3196     RegCloseKey( key_installprop );
3197     DeleteFileA( "c:\\testcomponentpath" );
3198     lstrcpyA( path_key, "Software\\Classes\\Installer\\Products\\" );
3199     lstrcatA( path_key, prod_squashed );
3200 
3201     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_prod, NULL );
3202     if (res == ERROR_ACCESS_DENIED)
3203     {
3204         skip( "insufficient rights\n" );
3205         LocalFree( usersid );
3206         return;
3207     }
3208     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3209 
3210     /* local classes product key exists */
3211     size = MAX_PATH;
3212     state = MsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3213     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3214     todo_wine ok(!size, "got %lu\n", size);
3215 
3216     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3217     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Components\\" );
3218     lstrcatA( path_key, comp_squashed );
3219 
3220     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE,  path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3221     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3222 
3223     /* local user component key exists */
3224     size = MAX_PATH;
3225     state = MsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3226     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3227     todo_wine ok(!size, "got %lu\n", size);
3228 
3229     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3230     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3231 
3232     /* product value exists */
3233     path[0] = 0;
3234     size = MAX_PATH;
3235     state = MsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3236     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3237     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3238     ok( size == 20, "got %lu\n", size );
3239 
3240     create_file( "c:\\testcomponentpath", 21 );
3241 
3242     /* file exists */
3243     path[0] = 0;
3244     size = MAX_PATH;
3245     state = MsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3246     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3247     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3248     ok( size == 20, "got %lu\n", size );
3249 
3250     RegDeleteValueA( key_comp, prod_squashed );
3251     RegDeleteKeyExA( key_prod, "", access & KEY_WOW64_64KEY, 0 );
3252     RegDeleteKeyExA( key_comp, "", access & KEY_WOW64_64KEY, 0 );
3253     RegCloseKey( key_prod );
3254     RegCloseKey( key_comp );
3255     DeleteFileA( "c:\\testcomponentpath" );
3256     LocalFree( usersid );
3257 }
3258 
test_MsiProvideComponent(void)3259 static void test_MsiProvideComponent(void)
3260 {
3261     INSTALLSTATE state;
3262     char buf[0x100];
3263     WCHAR bufW[0x100];
3264     DWORD len, len2;
3265     UINT r;
3266 
3267     if (!is_process_elevated())
3268     {
3269         skip("process is limited\n");
3270         return;
3271     }
3272 
3273     create_test_files();
3274     create_file("msitest\\sourcedir.txt", 1000);
3275     create_database(msifile, sd_tables, ARRAY_SIZE(sd_tables));
3276 
3277     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3278 
3279     buf[0] = 0;
3280     len = sizeof(buf);
3281     r = MsiProvideComponentA("{90120000-0070-0000-0000-4000000FF1CE}",
3282                              "{17961602-C4E2-482E-800A-DF6E627549CF}",
3283                              "ProductFiles", INSTALLMODE_NODETECTION, buf, &len);
3284     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
3285 
3286     r = MsiInstallProductA(msifile, NULL);
3287     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3288 
3289     state = MsiQueryFeatureStateA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir");
3290     ok(state == INSTALLSTATE_LOCAL, "got %d\n", state);
3291 
3292     buf[0] = 0;
3293     len = sizeof(buf);
3294     r = MsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir",
3295                              "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
3296                              INSTALLMODE_NODETECTION, buf, &len);
3297     ok(r == ERROR_SUCCESS, "got %u\n", r);
3298     ok(buf[0], "empty path\n");
3299     ok(len == lstrlenA(buf), "got %lu\n", len);
3300 
3301     len2 = 0;
3302     r = MsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir",
3303                              "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
3304                              INSTALLMODE_NODETECTION, NULL, &len2);
3305     ok(r == ERROR_SUCCESS, "got %u\n", r);
3306     ok(len2 == len, "got %lu\n", len2);
3307 
3308     len2 = 0;
3309     r = MsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir",
3310                              "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
3311                              INSTALLMODE_NODETECTION, buf, &len2);
3312     ok(r == ERROR_MORE_DATA, "got %u\n", r);
3313     ok(len2 == len, "got %lu\n", len2);
3314 
3315     /* wide version */
3316 
3317     bufW[0] = 0;
3318     len = sizeof(buf);
3319     r = MsiProvideComponentW(L"{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", L"sourcedir",
3320                              L"{DD422F92-3ED8-49B5-A0B7-F266F98357DF}", INSTALLMODE_NODETECTION, bufW, &len);
3321     ok(r == ERROR_SUCCESS, "got %u\n", r);
3322     ok(bufW[0], "empty path\n");
3323     ok(len == lstrlenW(bufW), "got %lu\n", len);
3324 
3325     len2 = 0;
3326     r = MsiProvideComponentW(L"{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", L"sourcedir",
3327                              L"{DD422F92-3ED8-49B5-A0B7-F266F98357DF}", INSTALLMODE_NODETECTION, NULL, &len2);
3328     ok(r == ERROR_SUCCESS, "got %u\n", r);
3329     ok(len2 == len, "got %lu\n", len2);
3330 
3331     len2 = 0;
3332     r = MsiProvideComponentW(L"{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", L"sourcedir",
3333                              L"{DD422F92-3ED8-49B5-A0B7-F266F98357DF}", INSTALLMODE_NODETECTION, bufW, &len2);
3334     ok(r == ERROR_MORE_DATA, "got %u\n", r);
3335     ok(len2 == len, "got %lu\n", len2);
3336 
3337     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3338     ok(r == ERROR_SUCCESS, "got %u\n", r);
3339 
3340     DeleteFileA("msitest\\sourcedir.txt");
3341     delete_test_files();
3342     DeleteFileA(msifile);
3343 }
3344 
test_MsiProvideQualifiedComponentEx(void)3345 static void test_MsiProvideQualifiedComponentEx(void)
3346 {
3347     UINT r;
3348     INSTALLSTATE state;
3349     char comp[39], comp_squashed[33], comp2[39], comp2_base85[21], comp2_squashed[33];
3350     char prod[39], prod_base85[21], prod_squashed[33];
3351     char desc[MAX_PATH], buf[MAX_PATH], keypath[MAX_PATH], path[MAX_PATH];
3352     DWORD len = sizeof(buf);
3353     REGSAM access = KEY_ALL_ACCESS;
3354     HKEY hkey, hkey2, hkey3, hkey4, hkey5;
3355     LONG res;
3356 
3357     if (!is_process_elevated())
3358     {
3359         skip( "process is limited\n" );
3360         return;
3361     }
3362 
3363     create_test_guid( comp, comp_squashed );
3364     compose_base85_guid( comp2, comp2_base85, comp2_squashed );
3365     compose_base85_guid( prod, prod_base85, prod_squashed );
3366 
3367     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3368     ok( r == ERROR_UNKNOWN_COMPONENT, "got %u\n", r );
3369 
3370     lstrcpyA( keypath, "Software\\Classes\\Installer\\Components\\" );
3371     lstrcatA( keypath, comp_squashed );
3372 
3373     if (is_wow64) access |= KEY_WOW64_64KEY;
3374     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey, NULL );
3375     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3376 
3377     lstrcpyA( desc, prod_base85 );
3378     memcpy( desc + lstrlenA(desc), "feature<\0", sizeof("feature<\0") );
3379     res = RegSetValueExA( hkey, "qualifier", 0, REG_MULTI_SZ, (const BYTE *)desc,
3380                           lstrlenA(prod_base85) + sizeof("feature<\0") );
3381     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3382 
3383     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3384     ok( r == ERROR_UNKNOWN_PRODUCT, "got %u\n", r );
3385 
3386     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, NULL, 0, 0, buf, &len );
3387     ok( r == ERROR_UNKNOWN_PRODUCT, "got %u\n", r );
3388 
3389     state = MsiQueryProductStateA( prod );
3390     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3391 
3392     lstrcpyA( keypath, "Software\\Classes\\Installer\\Products\\" );
3393     lstrcatA( keypath, prod_squashed );
3394 
3395     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey2, NULL );
3396     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3397 
3398     state = MsiQueryProductStateA( prod );
3399     ok( state == INSTALLSTATE_ADVERTISED, "got %d\n", state );
3400 
3401     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3402     todo_wine ok( r == ERROR_UNKNOWN_FEATURE, "got %u\n", r );
3403 
3404     lstrcpyA( keypath, "Software\\Classes\\Installer\\Features\\" );
3405     lstrcatA( keypath, prod_squashed );
3406 
3407     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey3, NULL );
3408     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3409 
3410     state = MsiQueryFeatureStateA( prod, "feature" );
3411     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3412 
3413     res = RegSetValueExA( hkey3, "feature", 0, REG_SZ, (const BYTE *)"", 1 );
3414     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3415 
3416     state = MsiQueryFeatureStateA( prod, "feature" );
3417     ok( state == INSTALLSTATE_ADVERTISED, "got %d\n", state );
3418 
3419     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3420     ok( r == ERROR_FILE_NOT_FOUND, "got %u\n", r );
3421 
3422     len = sizeof(buf);
3423     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, NULL, 0, 0, buf, &len );
3424     ok( r == ERROR_FILE_NOT_FOUND, "got %u\n", r );
3425 
3426     lstrcpyA( keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\" );
3427     lstrcatA( keypath, prod_squashed );
3428     lstrcatA( keypath, "\\Features" );
3429 
3430     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey4, NULL );
3431     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3432 
3433     res = RegSetValueExA( hkey4, "feature", 0, REG_SZ, (const BYTE *)comp2_base85, sizeof(comp2_base85) );
3434     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3435 
3436     state = MsiQueryFeatureStateA( prod, "feature" );
3437     ok( state == INSTALLSTATE_ADVERTISED, "got %d\n", state );
3438 
3439     lstrcpyA( keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\" );
3440     lstrcatA( keypath, comp2_squashed );
3441 
3442     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey5, NULL );
3443     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3444 
3445     res = RegSetValueExA( hkey5, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\nosuchfile", sizeof("c:\\nosuchfile") );
3446     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3447 
3448     state = MsiQueryFeatureStateA( prod, "feature" );
3449     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3450 
3451     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3452     ok( r == ERROR_FILE_NOT_FOUND, "got %u\n", r );
3453 
3454     GetCurrentDirectoryA( MAX_PATH, path );
3455     lstrcatA( path, "\\msitest" );
3456     CreateDirectoryA( path, NULL );
3457     lstrcatA( path, "\\test.txt" );
3458     create_file_data( path, "test", 100 );
3459 
3460     res = RegSetValueExA( hkey5, prod_squashed, 0, REG_SZ, (const BYTE *)path, lstrlenA(path) + 1 );
3461     ok( res == ERROR_SUCCESS, "got %ld\n", res );
3462 
3463     buf[0] = 0;
3464     len = sizeof(buf);
3465     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3466     ok( r == ERROR_SUCCESS, "got %u\n", r );
3467     ok( len == lstrlenA(path), "got %lu\n", len );
3468     ok( !lstrcmpA( path, buf ), "got '%s'\n", buf );
3469 
3470     DeleteFileA( "msitest\\text.txt" );
3471     RemoveDirectoryA( "msitest" );
3472 
3473     RegDeleteKeyExA( hkey5, "", access & KEY_WOW64_64KEY, 0 );
3474     RegCloseKey( hkey5 );
3475     RegDeleteKeyExA( hkey4, "", access & KEY_WOW64_64KEY, 0 );
3476     RegCloseKey( hkey4 );
3477     RegDeleteKeyExA( hkey3, "", access & KEY_WOW64_64KEY, 0 );
3478     RegCloseKey( hkey3 );
3479     RegDeleteKeyExA( hkey2, "", access & KEY_WOW64_64KEY, 0 );
3480     RegCloseKey( hkey2 );
3481     RegDeleteKeyExA( hkey, "", access & KEY_WOW64_64KEY, 0 );
3482     RegCloseKey( hkey );
3483 }
3484 
test_MsiGetProductCode(void)3485 static void test_MsiGetProductCode(void)
3486 {
3487     HKEY compkey, prodkey;
3488     CHAR prodcode[MAX_PATH];
3489     CHAR prod_squashed[MAX_PATH];
3490     CHAR prodcode2[MAX_PATH];
3491     CHAR prod2_squashed[MAX_PATH];
3492     CHAR component[MAX_PATH];
3493     CHAR comp_base85[MAX_PATH];
3494     CHAR comp_squashed[MAX_PATH];
3495     CHAR keypath[MAX_PATH];
3496     CHAR product[MAX_PATH];
3497     LPSTR usersid;
3498     LONG res;
3499     UINT r;
3500     REGSAM access = KEY_ALL_ACCESS;
3501 
3502     create_test_guid(prodcode, prod_squashed);
3503     create_test_guid(prodcode2, prod2_squashed);
3504     compose_base85_guid(component, comp_base85, comp_squashed);
3505     usersid = get_user_sid();
3506 
3507     if (is_wow64)
3508         access |= KEY_WOW64_64KEY;
3509 
3510     /* szComponent is NULL */
3511     lstrcpyA(product, "prod");
3512     r = MsiGetProductCodeA(NULL, product);
3513     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3514     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3515 
3516     /* szComponent is empty */
3517     lstrcpyA(product, "prod");
3518     r = MsiGetProductCodeA("", product);
3519     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3520     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3521 
3522     /* garbage szComponent */
3523     lstrcpyA(product, "prod");
3524     r = MsiGetProductCodeA("garbage", product);
3525     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3526     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3527 
3528     /* guid without brackets */
3529     lstrcpyA(product, "prod");
3530     r = MsiGetProductCodeA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", product);
3531     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3532     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3533 
3534     /* guid with brackets */
3535     lstrcpyA(product, "prod");
3536     r = MsiGetProductCodeA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", product);
3537     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3538     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3539 
3540     /* same length as guid, but random */
3541     lstrcpyA(product, "prod");
3542     r = MsiGetProductCodeA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", product);
3543     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3544     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3545 
3546     /* all params correct, szComponent not published */
3547     lstrcpyA(product, "prod");
3548     r = MsiGetProductCodeA(component, product);
3549     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3550     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3551 
3552     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3553     lstrcatA(keypath, "Installer\\UserData\\");
3554     lstrcatA(keypath, usersid);
3555     lstrcatA(keypath, "\\Components\\");
3556     lstrcatA(keypath, comp_squashed);
3557 
3558     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3559     if (res == ERROR_ACCESS_DENIED)
3560     {
3561         skip("Not enough rights to perform tests\n");
3562         LocalFree(usersid);
3563         return;
3564     }
3565     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3566 
3567     /* user unmanaged component key exists */
3568     lstrcpyA(product, "prod");
3569     r = MsiGetProductCodeA(component, product);
3570     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3571     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3572 
3573     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3574     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3575 
3576     /* product value exists */
3577     lstrcpyA(product, "prod");
3578     r = MsiGetProductCodeA(component, product);
3579     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3580     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3581 
3582     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
3583     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3584 
3585     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3586     lstrcatA(keypath, "Installer\\Managed\\");
3587     lstrcatA(keypath, usersid);
3588     lstrcatA(keypath, "\\Installer\\Products\\");
3589     lstrcatA(keypath, prod_squashed);
3590 
3591     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3592     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3593 
3594     /* user managed product key of first product exists */
3595     lstrcpyA(product, "prod");
3596     r = MsiGetProductCodeA(component, product);
3597     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3598     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3599 
3600     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
3601     RegCloseKey(prodkey);
3602 
3603     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
3604     lstrcatA(keypath, prod_squashed);
3605 
3606     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
3607     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3608 
3609     /* user unmanaged product key exists */
3610     lstrcpyA(product, "prod");
3611     r = MsiGetProductCodeA(component, product);
3612     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3613     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3614 
3615     RegDeleteKeyA(prodkey, "");
3616     RegCloseKey(prodkey);
3617 
3618     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
3619     lstrcatA(keypath, prod_squashed);
3620 
3621     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3622     if (res == ERROR_ACCESS_DENIED)
3623     {
3624         skip( "insufficient rights\n" );
3625         LocalFree( usersid );
3626         return;
3627     }
3628     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3629 
3630     /* local classes product key exists */
3631     lstrcpyA(product, "prod");
3632     r = MsiGetProductCodeA(component, product);
3633     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3634     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3635 
3636     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
3637     RegCloseKey(prodkey);
3638 
3639     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3640     lstrcatA(keypath, "Installer\\Managed\\");
3641     lstrcatA(keypath, usersid);
3642     lstrcatA(keypath, "\\Installer\\Products\\");
3643     lstrcatA(keypath, prod2_squashed);
3644 
3645     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3646     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3647 
3648     /* user managed product key of second product exists */
3649     lstrcpyA(product, "prod");
3650     r = MsiGetProductCodeA(component, product);
3651     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3652     ok(!lstrcmpA(product, prodcode2), "Expected %s, got %s\n", prodcode2, product);
3653 
3654     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
3655     RegCloseKey(prodkey);
3656     RegDeleteValueA(compkey, prod_squashed);
3657     RegDeleteValueA(compkey, prod2_squashed);
3658     RegDeleteKeyExA(compkey, "", access & KEY_WOW64_64KEY, 0);
3659     RegCloseKey(compkey);
3660 
3661     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3662     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
3663     lstrcatA(keypath, comp_squashed);
3664 
3665     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3666     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3667 
3668     /* local user component key exists */
3669     lstrcpyA(product, "prod");
3670     r = MsiGetProductCodeA(component, product);
3671     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3672     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
3673 
3674     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3675     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3676 
3677     /* product value exists */
3678     lstrcpyA(product, "prod");
3679     r = MsiGetProductCodeA(component, product);
3680     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3681     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3682 
3683     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
3684     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3685 
3686     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3687     lstrcatA(keypath, "Installer\\Managed\\");
3688     lstrcatA(keypath, usersid);
3689     lstrcatA(keypath, "\\Installer\\Products\\");
3690     lstrcatA(keypath, prod_squashed);
3691 
3692     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3693     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3694 
3695     /* user managed product key of first product exists */
3696     lstrcpyA(product, "prod");
3697     r = MsiGetProductCodeA(component, product);
3698     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3699     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3700 
3701     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
3702     RegCloseKey(prodkey);
3703 
3704     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
3705     lstrcatA(keypath, prod_squashed);
3706 
3707     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
3708     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3709 
3710     /* user unmanaged product key exists */
3711     lstrcpyA(product, "prod");
3712     r = MsiGetProductCodeA(component, product);
3713     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3714     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3715 
3716     RegDeleteKeyA(prodkey, "");
3717     RegCloseKey(prodkey);
3718 
3719     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
3720     lstrcatA(keypath, prod_squashed);
3721 
3722     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3723     if (res == ERROR_ACCESS_DENIED)
3724     {
3725         skip( "insufficient rights\n" );
3726         LocalFree( usersid );
3727         return;
3728     }
3729     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3730 
3731     /* local classes product key exists */
3732     lstrcpyA(product, "prod");
3733     r = MsiGetProductCodeA(component, product);
3734     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3735     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3736 
3737     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
3738     RegCloseKey(prodkey);
3739 
3740     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3741     lstrcatA(keypath, "Installer\\Managed\\");
3742     lstrcatA(keypath, usersid);
3743     lstrcatA(keypath, "\\Installer\\Products\\");
3744     lstrcatA(keypath, prod2_squashed);
3745 
3746     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3747     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3748 
3749     /* user managed product key of second product exists */
3750     lstrcpyA(product, "prod");
3751     r = MsiGetProductCodeA(component, product);
3752     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3753     ok(!lstrcmpA(product, prodcode2), "Expected %s, got %s\n", prodcode2, product);
3754 
3755     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
3756     RegCloseKey(prodkey);
3757     RegDeleteValueA(compkey, prod_squashed);
3758     RegDeleteValueA(compkey, prod2_squashed);
3759     RegDeleteKeyExA(compkey, "", access & KEY_WOW64_64KEY, 0);
3760     RegCloseKey(compkey);
3761     LocalFree(usersid);
3762 }
3763 
test_MsiEnumClients(void)3764 static void test_MsiEnumClients(void)
3765 {
3766     HKEY compkey;
3767     CHAR prodcode[MAX_PATH];
3768     CHAR prod_squashed[MAX_PATH];
3769     CHAR prodcode2[MAX_PATH];
3770     CHAR prod2_squashed[MAX_PATH];
3771     CHAR component[MAX_PATH];
3772     CHAR comp_base85[MAX_PATH];
3773     CHAR comp_squashed[MAX_PATH];
3774     CHAR product[MAX_PATH];
3775     CHAR keypath[MAX_PATH];
3776     LPSTR usersid;
3777     LONG res;
3778     UINT r;
3779     REGSAM access = KEY_ALL_ACCESS;
3780 
3781     create_test_guid(prodcode, prod_squashed);
3782     create_test_guid(prodcode2, prod2_squashed);
3783     compose_base85_guid(component, comp_base85, comp_squashed);
3784     usersid = get_user_sid();
3785 
3786     if (is_wow64)
3787         access |= KEY_WOW64_64KEY;
3788 
3789     /* NULL szComponent */
3790     product[0] = '\0';
3791     r = MsiEnumClientsA(NULL, 0, product);
3792     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3793     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3794 
3795     /* empty szComponent */
3796     product[0] = '\0';
3797     r = MsiEnumClientsA("", 0, product);
3798     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3799     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3800 
3801     /* NULL lpProductBuf */
3802     r = MsiEnumClientsA(component, 0, NULL);
3803     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3804 
3805     /* all params correct, component missing */
3806     product[0] = '\0';
3807     r = MsiEnumClientsA(component, 0, product);
3808     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3809     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3810 
3811     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3812     lstrcatA(keypath, "Installer\\UserData\\");
3813     lstrcatA(keypath, usersid);
3814     lstrcatA(keypath, "\\Components\\");
3815     lstrcatA(keypath, comp_squashed);
3816 
3817     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3818     if (res == ERROR_ACCESS_DENIED)
3819     {
3820         skip("Not enough rights to perform tests\n");
3821         LocalFree(usersid);
3822         return;
3823     }
3824     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3825 
3826     /* user unmanaged component key exists */
3827     product[0] = '\0';
3828     r = MsiEnumClientsA(component, 0, product);
3829     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3830     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3831 
3832     /* index > 0, no products exist */
3833     product[0] = '\0';
3834     r = MsiEnumClientsA(component, 1, product);
3835     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3836     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3837 
3838     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3839     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3840 
3841     /* product value exists */
3842     r = MsiEnumClientsA(component, 0, product);
3843     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3844     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3845 
3846     /* try index 0 again */
3847     product[0] = '\0';
3848     r = MsiEnumClientsA(component, 0, product);
3849     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3850     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3851 
3852     /* try index 1, second product value does not exist */
3853     product[0] = '\0';
3854     r = MsiEnumClientsA(component, 1, product);
3855     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3856     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3857 
3858     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
3859     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3860 
3861     /* try index 1, second product value does exist */
3862     product[0] = '\0';
3863     r = MsiEnumClientsA(component, 1, product);
3864     todo_wine
3865     {
3866         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3867         ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3868     }
3869 
3870     /* start the enumeration over */
3871     product[0] = '\0';
3872     r = MsiEnumClientsA(component, 0, product);
3873     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3874     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
3875        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
3876 
3877     /* correctly query second product */
3878     product[0] = '\0';
3879     r = MsiEnumClientsA(component, 1, product);
3880     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3881     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
3882        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
3883 
3884     RegDeleteValueA(compkey, prod_squashed);
3885     RegDeleteValueA(compkey, prod2_squashed);
3886     RegDeleteKeyExA(compkey, "", access & KEY_WOW64_64KEY, 0);
3887     RegCloseKey(compkey);
3888 
3889     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3890     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
3891     lstrcatA(keypath, comp_squashed);
3892 
3893     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3894     if (res == ERROR_ACCESS_DENIED)
3895     {
3896         skip("Not enough rights to perform tests\n");
3897         LocalFree(usersid);
3898         return;
3899     }
3900     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3901 
3902     /* user local component key exists */
3903     product[0] = '\0';
3904     r = MsiEnumClientsA(component, 0, product);
3905     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3906     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3907 
3908     /* index > 0, no products exist */
3909     product[0] = '\0';
3910     r = MsiEnumClientsA(component, 1, product);
3911     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3912     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3913 
3914     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3915     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3916 
3917     /* product value exists */
3918     product[0] = '\0';
3919     r = MsiEnumClientsA(component, 0, product);
3920     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3921     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3922 
3923     /* try index 0 again */
3924     product[0] = '\0';
3925     r = MsiEnumClientsA(component, 0, product);
3926     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3927 
3928     /* try index 1, second product value does not exist */
3929     product[0] = '\0';
3930     r = MsiEnumClientsA(component, 1, product);
3931     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3932     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3933 
3934     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
3935     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3936 
3937     /* try index 1, second product value does exist */
3938     product[0] = '\0';
3939     r = MsiEnumClientsA(component, 1, product);
3940     todo_wine
3941     {
3942         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3943         ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3944     }
3945 
3946     /* start the enumeration over */
3947     product[0] = '\0';
3948     r = MsiEnumClientsA(component, 0, product);
3949     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3950     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
3951        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
3952 
3953     /* correctly query second product */
3954     product[0] = '\0';
3955     r = MsiEnumClientsA(component, 1, product);
3956     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3957     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
3958        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
3959 
3960     RegDeleteValueA(compkey, prod_squashed);
3961     RegDeleteValueA(compkey, prod2_squashed);
3962     RegDeleteKeyExA(compkey, "", access & KEY_WOW64_64KEY, 0);
3963     RegCloseKey(compkey);
3964     LocalFree(usersid);
3965 }
3966 
get_version_info(LPSTR path,LPSTR * vercheck,LPDWORD verchecksz,LPSTR * langcheck,LPDWORD langchecksz)3967 static void get_version_info(LPSTR path, LPSTR *vercheck, LPDWORD verchecksz,
3968                              LPSTR *langcheck, LPDWORD langchecksz)
3969 {
3970     LPSTR version;
3971     VS_FIXEDFILEINFO *ffi;
3972     DWORD size = GetFileVersionInfoSizeA(path, NULL);
3973     UINT len;
3974     USHORT *lang;
3975 
3976     version = malloc(size);
3977     GetFileVersionInfoA(path, 0, size, version);
3978 
3979     VerQueryValueA(version, "\\", (LPVOID *)&ffi, &len);
3980     *vercheck = malloc(MAX_PATH);
3981     sprintf(*vercheck, "%d.%d.%d.%d", HIWORD(ffi->dwFileVersionMS),
3982             LOWORD(ffi->dwFileVersionMS), HIWORD(ffi->dwFileVersionLS),
3983             LOWORD(ffi->dwFileVersionLS));
3984     *verchecksz = lstrlenA(*vercheck);
3985 
3986     VerQueryValueA(version, "\\VarFileInfo\\Translation", (void **)&lang, &len);
3987     *langcheck = malloc(MAX_PATH);
3988     sprintf(*langcheck, "%d", *lang);
3989     *langchecksz = lstrlenA(*langcheck);
3990 
3991     free(version);
3992 }
3993 
test_MsiGetFileVersion(void)3994 static void test_MsiGetFileVersion(void)
3995 {
3996     UINT r;
3997     DWORD versz, langsz;
3998     char version[MAX_PATH];
3999     char lang[MAX_PATH];
4000     char path[MAX_PATH];
4001     LPSTR vercheck, langcheck;
4002     DWORD verchecksz, langchecksz;
4003 
4004     /* NULL szFilePath */
4005     r = MsiGetFileVersionA(NULL, NULL, NULL, NULL, NULL);
4006     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4007 
4008     versz = MAX_PATH;
4009     langsz = MAX_PATH;
4010     lstrcpyA(version, "version");
4011     lstrcpyA(lang, "lang");
4012     r = MsiGetFileVersionA(NULL, version, &versz, lang, &langsz);
4013     ok(r == ERROR_INVALID_PARAMETER,
4014        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4015     ok(!lstrcmpA(version, "version"),
4016        "Expected version to be unchanged, got %s\n", version);
4017     ok(versz == MAX_PATH, "got %lu\n", versz);
4018     ok(!lstrcmpA(lang, "lang"),
4019        "Expected lang to be unchanged, got %s\n", lang);
4020     ok(langsz == MAX_PATH, "got %lu\n", langsz);
4021 
4022     /* empty szFilePath */
4023     r = MsiGetFileVersionA("", NULL, NULL, NULL, NULL);
4024     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4025 
4026     versz = MAX_PATH;
4027     langsz = MAX_PATH;
4028     lstrcpyA(version, "version");
4029     lstrcpyA(lang, "lang");
4030     r = MsiGetFileVersionA("", version, &versz, lang, &langsz);
4031     ok(r == ERROR_FILE_NOT_FOUND,
4032        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4033     ok(!lstrcmpA(version, "version"),
4034        "Expected version to be unchanged, got %s\n", version);
4035     ok(versz == MAX_PATH, "got %lu\n", versz);
4036     ok(!lstrcmpA(lang, "lang"),
4037        "Expected lang to be unchanged, got %s\n", lang);
4038     ok(langsz == MAX_PATH, "got %lu\n", langsz);
4039 
4040     /* nonexistent szFilePath */
4041     versz = MAX_PATH;
4042     langsz = MAX_PATH;
4043     lstrcpyA(version, "version");
4044     lstrcpyA(lang, "lang");
4045     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
4046     ok(r == ERROR_FILE_NOT_FOUND,
4047        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4048     ok(!lstrcmpA(version, "version"),
4049        "Expected version to be unchanged, got %s\n", version);
4050     ok(versz == MAX_PATH, "got %lu\n", versz);
4051     ok(!lstrcmpA(lang, "lang"),
4052        "Expected lang to be unchanged, got %s\n", lang);
4053     ok(langsz == MAX_PATH, "got %lu\n", langsz);
4054 
4055     /* nonexistent szFilePath, valid lpVersionBuf, NULL pcchVersionBuf */
4056     versz = MAX_PATH;
4057     langsz = MAX_PATH;
4058     lstrcpyA(version, "version");
4059     lstrcpyA(lang, "lang");
4060     r = MsiGetFileVersionA("nonexistent", version, NULL, lang, &langsz);
4061     ok(r == ERROR_INVALID_PARAMETER,
4062        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4063     ok(!lstrcmpA(version, "version"),
4064        "Expected version to be unchanged, got %s\n", version);
4065     ok(versz == MAX_PATH, "got %lu\n", versz);
4066     ok(!lstrcmpA(lang, "lang"),
4067        "Expected lang to be unchanged, got %s\n", lang);
4068     ok(langsz == MAX_PATH, "got %lu\n", langsz);
4069 
4070     /* nonexistent szFilePath, valid lpLangBuf, NULL pcchLangBuf */
4071     versz = MAX_PATH;
4072     langsz = MAX_PATH;
4073     lstrcpyA(version, "version");
4074     lstrcpyA(lang, "lang");
4075     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, NULL);
4076     ok(r == ERROR_INVALID_PARAMETER,
4077        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4078     ok(!lstrcmpA(version, "version"),
4079        "Expected version to be unchanged, got %s\n", version);
4080     ok(versz == MAX_PATH, "got %lu\n", versz);
4081     ok(!lstrcmpA(lang, "lang"),
4082        "Expected lang to be unchanged, got %s\n", lang);
4083     ok(langsz == MAX_PATH, "got %lu\n", langsz);
4084 
4085     /* nonexistent szFilePath, valid lpVersionBuf, pcchVersionBuf is zero */
4086     versz = 0;
4087     langsz = MAX_PATH;
4088     lstrcpyA(version, "version");
4089     lstrcpyA(lang, "lang");
4090     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
4091     ok(r == ERROR_FILE_NOT_FOUND,
4092        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4093     ok(!lstrcmpA(version, "version"),
4094        "Expected version to be unchanged, got %s\n", version);
4095     ok(versz == 0, "Expected 0, got %lu\n", versz);
4096     ok(!lstrcmpA(lang, "lang"),
4097        "Expected lang to be unchanged, got %s\n", lang);
4098     ok(langsz == MAX_PATH, "got %lu\n", langsz);
4099 
4100     /* nonexistent szFilePath, valid lpLangBuf, pcchLangBuf is zero */
4101     versz = MAX_PATH;
4102     langsz = 0;
4103     lstrcpyA(version, "version");
4104     lstrcpyA(lang, "lang");
4105     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
4106     ok(r == ERROR_FILE_NOT_FOUND,
4107        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4108     ok(!lstrcmpA(version, "version"),
4109        "Expected version to be unchanged, got %s\n", version);
4110     ok(versz == MAX_PATH, "got %lu\n", versz);
4111     ok(!lstrcmpA(lang, "lang"),
4112        "Expected lang to be unchanged, got %s\n", lang);
4113     ok(langsz == 0, "Expected 0, got %lu\n", langsz);
4114 
4115     /* nonexistent szFilePath, rest NULL */
4116     r = MsiGetFileVersionA("nonexistent", NULL, NULL, NULL, NULL);
4117     ok(r == ERROR_FILE_NOT_FOUND,
4118        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4119 
4120     create_file("ver.txt", 20);
4121 
4122     /* file exists, no version information */
4123     r = MsiGetFileVersionA("ver.txt", NULL, NULL, NULL, NULL);
4124     ok(r == ERROR_FILE_INVALID, "Expected ERROR_FILE_INVALID, got %d\n", r);
4125 
4126     versz = MAX_PATH;
4127     langsz = MAX_PATH;
4128     lstrcpyA(version, "version");
4129     lstrcpyA(lang, "lang");
4130     r = MsiGetFileVersionA("ver.txt", version, &versz, lang, &langsz);
4131     ok(versz == MAX_PATH, "got %lu\n", versz);
4132     ok(!lstrcmpA(version, "version"),
4133        "Expected version to be unchanged, got %s\n", version);
4134     ok(langsz == MAX_PATH, "got %lu\n", langsz);
4135     ok(!lstrcmpA(lang, "lang"),
4136        "Expected lang to be unchanged, got %s\n", lang);
4137     ok(r == ERROR_FILE_INVALID,
4138        "Expected ERROR_FILE_INVALID, got %d\n", r);
4139 
4140     DeleteFileA("ver.txt");
4141 
4142     /* relative path, has version information */
4143     versz = MAX_PATH;
4144     langsz = MAX_PATH;
4145     lstrcpyA(version, "version");
4146     lstrcpyA(lang, "lang");
4147     r = MsiGetFileVersionA("kernel32.dll", version, &versz, lang, &langsz);
4148     todo_wine
4149     {
4150         ok(r == ERROR_FILE_NOT_FOUND,
4151            "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4152         ok(!lstrcmpA(version, "version"),
4153            "Expected version to be unchanged, got %s\n", version);
4154         ok(versz == MAX_PATH, "got %lu\n", versz);
4155         ok(!lstrcmpA(lang, "lang"),
4156            "Expected lang to be unchanged, got %s\n", lang);
4157         ok(langsz == MAX_PATH, "got %lu\n", langsz);
4158     }
4159 
4160     GetSystemDirectoryA(path, MAX_PATH);
4161     lstrcatA(path, "\\kernel32.dll");
4162 
4163     get_version_info(path, &vercheck, &verchecksz, &langcheck, &langchecksz);
4164 
4165     /* absolute path, has version information */
4166     versz = MAX_PATH;
4167     langsz = MAX_PATH;
4168     lstrcpyA(version, "version");
4169     lstrcpyA(lang, "lang");
4170     r = MsiGetFileVersionA(path, version, &versz, lang, &langsz);
4171     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4172     ok(versz == verchecksz, "Expected %lu, got %lu\n", verchecksz, versz);
4173     ok(strstr(lang, langcheck) != NULL, "Expected \"%s\" in \"%s\"\n", langcheck, lang);
4174     ok(!lstrcmpA(version, vercheck),
4175         "Expected %s, got %s\n", vercheck, version);
4176 
4177     /* only check version */
4178     versz = MAX_PATH;
4179     lstrcpyA(version, "version");
4180     r = MsiGetFileVersionA(path, version, &versz, NULL, NULL);
4181     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4182     ok(versz == verchecksz, "Expected %lu, got %lu\n", verchecksz, versz);
4183     ok(!lstrcmpA(version, vercheck), "Expected %s, got %s\n", vercheck, version);
4184 
4185     /* only check language */
4186     langsz = MAX_PATH;
4187     lstrcpyA(lang, "lang");
4188     r = MsiGetFileVersionA(path, NULL, NULL, lang, &langsz);
4189     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4190     ok(strstr(lang, langcheck) != NULL, "Expected \"%s\" in \"%s\"\n", langcheck, lang);
4191 
4192     /* check neither version nor language */
4193     r = MsiGetFileVersionA(path, NULL, NULL, NULL, NULL);
4194     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4195 
4196     /* get pcchVersionBuf */
4197     versz = MAX_PATH;
4198     r = MsiGetFileVersionA(path, NULL, &versz, NULL, NULL);
4199     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4200     ok(versz == verchecksz, "Expected %lu, got %lu\n", verchecksz, versz);
4201 
4202     /* get pcchLangBuf */
4203     langsz = MAX_PATH;
4204     r = MsiGetFileVersionA(path, NULL, NULL, NULL, &langsz);
4205     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4206     ok(langsz >= langchecksz, "Expected %lu >= %lu\n", langsz, langchecksz);
4207 
4208     /* pcchVersionBuf not big enough */
4209     versz = 5;
4210     lstrcpyA(version, "version");
4211     r = MsiGetFileVersionA(path, version, &versz, NULL, NULL);
4212     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4213     ok(!strncmp(version, vercheck, 4),
4214        "Expected first 4 characters of \"%s\", got \"%s\"\n", vercheck, version);
4215     ok(versz == verchecksz, "Expected %lu, got %lu\n", verchecksz, versz);
4216 
4217     /* pcchLangBuf not big enough */
4218     langsz = 4;
4219     lstrcpyA(lang, "lang");
4220     r = MsiGetFileVersionA(path, NULL, NULL, lang, &langsz);
4221     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4222     ok(lstrcmpA(lang, "lang"), "lang not set\n");
4223     ok(langsz >= langchecksz, "Expected %lu >= %lu\n", langsz, langchecksz);
4224 
4225     /* pcchVersionBuf big enough, pcchLangBuf not big enough */
4226     versz = MAX_PATH;
4227     langsz = 0;
4228     lstrcpyA(version, "version");
4229     r = MsiGetFileVersionA(path, version, &versz, NULL, &langsz);
4230     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4231     ok(versz == verchecksz, "Expected %lu, got %lu\n", verchecksz, versz);
4232     ok(!lstrcmpA(version, vercheck), "Expected \"%s\", got \"%s\"\n", vercheck, version);
4233     ok(langsz >= langchecksz && langsz < MAX_PATH, "Expected %lu >= %lu\n", langsz, langchecksz);
4234 
4235     /* pcchVersionBuf not big enough, pcchLangBuf big enough */
4236     versz = 5;
4237     langsz = MAX_PATH;
4238     lstrcpyA(lang, "lang");
4239     r = MsiGetFileVersionA(path, NULL, &versz, lang, &langsz);
4240     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4241     ok(versz == verchecksz, "Expected %lu, got %lu\n", verchecksz, versz);
4242     ok(langsz >= langchecksz && langsz < MAX_PATH, "Expected %lu >= %lu\n", langsz, langchecksz);
4243     ok(strstr(lang, langcheck) != NULL, "expected %s in %s\n", langcheck, lang);
4244 
4245     /* NULL pcchVersionBuf and pcchLangBuf */
4246     r = MsiGetFileVersionA(path, version, NULL, lang, NULL);
4247     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4248 
4249     /* All NULL except szFilePath */
4250     r = MsiGetFileVersionA(path, NULL, NULL, NULL, NULL);
4251     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4252 
4253     free(vercheck);
4254     free(langcheck);
4255 }
4256 
test_MsiGetProductInfo(void)4257 static void test_MsiGetProductInfo(void)
4258 {
4259     UINT r;
4260     LONG res;
4261     HKEY propkey, source;
4262     HKEY prodkey, localkey;
4263     CHAR prodcode[MAX_PATH];
4264     CHAR prod_squashed[MAX_PATH];
4265     CHAR packcode[MAX_PATH];
4266     CHAR pack_squashed[MAX_PATH];
4267     CHAR buf[MAX_PATH];
4268     CHAR keypath[MAX_PATH];
4269     LPSTR usersid;
4270     DWORD sz, val = 42;
4271     REGSAM access = KEY_ALL_ACCESS;
4272 
4273     create_test_guid(prodcode, prod_squashed);
4274     create_test_guid(packcode, pack_squashed);
4275     usersid = get_user_sid();
4276 
4277     if (is_wow64)
4278         access |= KEY_WOW64_64KEY;
4279 
4280     /* NULL szProduct */
4281     sz = MAX_PATH;
4282     lstrcpyA(buf, "apple");
4283     r = MsiGetProductInfoA(NULL, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4284     ok(r == ERROR_INVALID_PARAMETER,
4285        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4286     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4287     ok(sz == MAX_PATH, "got %lu\n", sz);
4288 
4289     /* empty szProduct */
4290     sz = MAX_PATH;
4291     lstrcpyA(buf, "apple");
4292     r = MsiGetProductInfoA("", INSTALLPROPERTY_HELPLINKA, buf, &sz);
4293     ok(r == ERROR_INVALID_PARAMETER,
4294        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4295     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4296     ok(sz == MAX_PATH, "got %lu\n", sz);
4297 
4298     /* garbage szProduct */
4299     sz = MAX_PATH;
4300     lstrcpyA(buf, "apple");
4301     r = MsiGetProductInfoA("garbage", INSTALLPROPERTY_HELPLINKA, buf, &sz);
4302     ok(r == ERROR_INVALID_PARAMETER,
4303        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4304     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4305     ok(sz == MAX_PATH, "got %lu\n", sz);
4306 
4307     /* guid without brackets */
4308     sz = MAX_PATH;
4309     lstrcpyA(buf, "apple");
4310     r = MsiGetProductInfoA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
4311                            INSTALLPROPERTY_HELPLINKA, buf, &sz);
4312     ok(r == ERROR_INVALID_PARAMETER,
4313        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4314     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4315     ok(sz == MAX_PATH, "got %lu\n", sz);
4316 
4317     /* guid with brackets */
4318     sz = MAX_PATH;
4319     lstrcpyA(buf, "apple");
4320     r = MsiGetProductInfoA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
4321                            INSTALLPROPERTY_HELPLINKA, buf, &sz);
4322     ok(r == ERROR_UNKNOWN_PRODUCT,
4323        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4324     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4325     ok(sz == MAX_PATH, "got %lu\n", sz);
4326 
4327     /* same length as guid, but random */
4328     sz = MAX_PATH;
4329     lstrcpyA(buf, "apple");
4330     r = MsiGetProductInfoA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
4331                            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, "got %lu\n", sz);
4336 
4337     /* not installed, NULL szAttribute */
4338     sz = MAX_PATH;
4339     lstrcpyA(buf, "apple");
4340     r = MsiGetProductInfoA(prodcode, NULL, buf, &sz);
4341     ok(r == ERROR_INVALID_PARAMETER,
4342        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4343     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4344     ok(sz == MAX_PATH, "got %lu\n", sz);
4345 
4346     /* not installed, NULL lpValueBuf */
4347     sz = MAX_PATH;
4348     lstrcpyA(buf, "apple");
4349     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, &sz);
4350     ok(r == ERROR_UNKNOWN_PRODUCT,
4351        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4352     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4353     ok(sz == MAX_PATH, "got %lu\n", sz);
4354 
4355     /* not installed, NULL pcchValueBuf */
4356     sz = MAX_PATH;
4357     lstrcpyA(buf, "apple");
4358     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, NULL);
4359     ok(r == ERROR_INVALID_PARAMETER,
4360        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4361     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4362     ok(sz == MAX_PATH, "got %lu\n", sz);
4363 
4364     /* created guid cannot possibly be an installed product code */
4365     sz = MAX_PATH;
4366     lstrcpyA(buf, "apple");
4367     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4368     ok(r == ERROR_UNKNOWN_PRODUCT,
4369        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4370     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4371     ok(sz == MAX_PATH, "got %lu\n", sz);
4372 
4373     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
4374     lstrcatA(keypath, usersid);
4375     lstrcatA(keypath, "\\Installer\\Products\\");
4376     lstrcatA(keypath, prod_squashed);
4377 
4378     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4379     if (res == ERROR_ACCESS_DENIED)
4380     {
4381         skip("Not enough rights to perform tests\n");
4382         LocalFree(usersid);
4383         return;
4384     }
4385     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4386 
4387     /* managed product code exists */
4388     sz = MAX_PATH;
4389     lstrcpyA(buf, "apple");
4390     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4391     ok(r == ERROR_UNKNOWN_PROPERTY,
4392        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4393     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4394     ok(sz == MAX_PATH, "got %lu\n", sz);
4395 
4396     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
4397     RegCloseKey(prodkey);
4398 
4399     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
4400     lstrcatA(keypath, usersid);
4401     lstrcatA(keypath, "\\Products\\");
4402     lstrcatA(keypath, prod_squashed);
4403 
4404     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
4405     if (res == ERROR_ACCESS_DENIED)
4406     {
4407         skip("Not enough rights to perform tests\n");
4408         LocalFree(usersid);
4409         return;
4410     }
4411     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4412 
4413     /* local user product code exists */
4414     sz = MAX_PATH;
4415     lstrcpyA(buf, "apple");
4416     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4417     ok(r == ERROR_UNKNOWN_PRODUCT,
4418        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4419     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4420     ok(sz == MAX_PATH, "got %lu\n", sz);
4421 
4422     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
4423     lstrcatA(keypath, usersid);
4424     lstrcatA(keypath, "\\Installer\\Products\\");
4425     lstrcatA(keypath, prod_squashed);
4426 
4427     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4428     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4429 
4430     /* both local and managed product code exist */
4431     sz = MAX_PATH;
4432     lstrcpyA(buf, "apple");
4433     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4434     ok(r == ERROR_UNKNOWN_PROPERTY,
4435        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4436     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4437     ok(sz == MAX_PATH, "%lu\n", sz);
4438 
4439     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
4440     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4441 
4442     /* InstallProperties key exists */
4443     sz = MAX_PATH;
4444     lstrcpyA(buf, "apple");
4445     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4446     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4447     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4448     ok(sz == 0, "Expected 0, got %lu\n", sz);
4449 
4450     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
4451     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4452 
4453     /* HelpLink value exists */
4454     sz = MAX_PATH;
4455     lstrcpyA(buf, "apple");
4456     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4457     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4458     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
4459     ok(sz == 4, "Expected 4, got %lu\n", sz);
4460 
4461     /* pcchBuf is NULL */
4462     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, NULL);
4463     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4464 
4465     /* lpValueBuf is NULL */
4466     sz = MAX_PATH;
4467     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, &sz);
4468     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4469     ok(sz == 4, "Expected 4, got %lu\n", sz);
4470 
4471     /* lpValueBuf is NULL, pcchValueBuf is too small */
4472     sz = 2;
4473     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, &sz);
4474     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4475     ok(sz == 4, "Expected 4, got %lu\n", sz);
4476 
4477     /* lpValueBuf is non-NULL, pcchValueBuf is too small */
4478     sz = 2;
4479     lstrcpyA(buf, "apple");
4480     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4481     ok(!lstrcmpA(buf, "apple"), "Expected buf to remain unchanged, got \"%s\"\n", buf);
4482     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4483     ok(sz == 4, "Expected 4, got %lu\n", sz);
4484 
4485     /* lpValueBuf is non-NULL, pcchValueBuf is exactly 4 */
4486     sz = 4;
4487     lstrcpyA(buf, "apple");
4488     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4489     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4490     ok(!lstrcmpA(buf, "apple"),
4491        "Expected buf to remain unchanged, got \"%s\"\n", buf);
4492     ok(sz == 4, "Expected 4, got %lu\n", sz);
4493 
4494     res = RegSetValueExA(propkey, "IMadeThis", 0, REG_SZ, (LPBYTE)"random", 7);
4495     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4496 
4497     /* random property not supported by MSI, value exists */
4498     sz = MAX_PATH;
4499     lstrcpyA(buf, "apple");
4500     r = MsiGetProductInfoA(prodcode, "IMadeThis", buf, &sz);
4501     ok(r == ERROR_UNKNOWN_PROPERTY,
4502        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4503     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4504     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
4505 
4506     RegDeleteValueA(propkey, "IMadeThis");
4507     RegDeleteValueA(propkey, "HelpLink");
4508     RegDeleteKeyExA(propkey, "", access & KEY_WOW64_64KEY, 0);
4509     RegDeleteKeyExA(localkey, "", access & KEY_WOW64_64KEY, 0);
4510     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
4511     RegCloseKey(propkey);
4512     RegCloseKey(localkey);
4513     RegCloseKey(prodkey);
4514 
4515     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
4516     lstrcatA(keypath, prod_squashed);
4517 
4518     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
4519     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4520 
4521     /* user product key exists */
4522     sz = MAX_PATH;
4523     lstrcpyA(buf, "apple");
4524     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4525     ok(r == ERROR_UNKNOWN_PROPERTY,
4526        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4527     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4528     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
4529 
4530     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
4531     lstrcatA(keypath, usersid);
4532     lstrcatA(keypath, "\\Products\\");
4533     lstrcatA(keypath, prod_squashed);
4534 
4535     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
4536     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4537 
4538     /* local user product key exists */
4539     sz = MAX_PATH;
4540     lstrcpyA(buf, "apple");
4541     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4542     ok(r == ERROR_UNKNOWN_PROPERTY,
4543        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4544     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4545     ok(sz == MAX_PATH, "got %lu\n", sz);
4546 
4547     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
4548     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4549 
4550     /* InstallProperties key exists */
4551     sz = MAX_PATH;
4552     lstrcpyA(buf, "apple");
4553     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4554     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4555     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4556     ok(sz == 0, "Expected 0, got %lu\n", sz);
4557 
4558     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
4559     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4560 
4561     /* HelpLink value exists */
4562     sz = MAX_PATH;
4563     lstrcpyA(buf, "apple");
4564     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4565     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4566     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
4567     ok(sz == 4, "Expected 4, got %lu\n", sz);
4568 
4569     RegDeleteValueA(propkey, "HelpLink");
4570     RegDeleteKeyExA(propkey, "", access & KEY_WOW64_64KEY, 0);
4571     RegDeleteKeyExA(localkey, "", access & KEY_WOW64_64KEY, 0);
4572     RegDeleteKeyA(prodkey, "");
4573     RegCloseKey(propkey);
4574     RegCloseKey(localkey);
4575     RegCloseKey(prodkey);
4576 
4577     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
4578     lstrcatA(keypath, prod_squashed);
4579 
4580     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4581     if (res == ERROR_ACCESS_DENIED)
4582     {
4583         skip( "insufficient rights\n" );
4584         LocalFree( usersid );
4585         return;
4586     }
4587     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4588 
4589     /* classes product key exists */
4590     sz = MAX_PATH;
4591     lstrcpyA(buf, "apple");
4592     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4593     ok(r == ERROR_UNKNOWN_PROPERTY,
4594        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4595     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4596     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
4597 
4598     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
4599     lstrcatA(keypath, usersid);
4600     lstrcatA(keypath, "\\Products\\");
4601     lstrcatA(keypath, prod_squashed);
4602 
4603     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
4604     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4605 
4606     /* local user product key exists */
4607     sz = MAX_PATH;
4608     lstrcpyA(buf, "apple");
4609     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4610     ok(r == ERROR_UNKNOWN_PROPERTY,
4611        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4612     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4613     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
4614 
4615     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
4616     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4617 
4618     /* InstallProperties key exists */
4619     sz = MAX_PATH;
4620     lstrcpyA(buf, "apple");
4621     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4622     ok(r == ERROR_UNKNOWN_PROPERTY,
4623        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4624     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4625     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
4626 
4627     RegDeleteKeyExA(propkey, "", access & KEY_WOW64_64KEY, 0);
4628     RegDeleteKeyExA(localkey, "", access & KEY_WOW64_64KEY, 0);
4629     RegCloseKey(propkey);
4630     RegCloseKey(localkey);
4631 
4632     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
4633     lstrcatA(keypath, "S-1-5-18\\\\Products\\");
4634     lstrcatA(keypath, prod_squashed);
4635 
4636     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
4637     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4638 
4639     /* Local System product key exists */
4640     sz = MAX_PATH;
4641     lstrcpyA(buf, "apple");
4642     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4643     ok(r == ERROR_UNKNOWN_PROPERTY,
4644         "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4645     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4646     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
4647 
4648     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
4649     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4650 
4651     /* InstallProperties key exists */
4652     sz = MAX_PATH;
4653     lstrcpyA(buf, "apple");
4654     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4655     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4656     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4657     ok(sz == 0, "Expected 0, got %lu\n", sz);
4658 
4659     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
4660     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4661 
4662     /* HelpLink value exists */
4663     sz = MAX_PATH;
4664     lstrcpyA(buf, "apple");
4665     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4666     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4667     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
4668     ok(sz == 4, "Expected 4, got %lu\n", sz);
4669 
4670     res = RegSetValueExA(propkey, "HelpLink", 0, REG_DWORD,
4671                          (const BYTE *)&val, sizeof(DWORD));
4672     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4673 
4674     /* HelpLink type is REG_DWORD */
4675     sz = MAX_PATH;
4676     lstrcpyA(buf, "apple");
4677     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4678     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4679     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4680     ok(sz == 2, "Expected 2, got %lu\n", sz);
4681 
4682     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
4683     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4684 
4685     /* DisplayName value exists */
4686     sz = MAX_PATH;
4687     lstrcpyA(buf, "apple");
4688     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
4689     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4690     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
4691     ok(sz == 4, "Expected 4, got %lu\n", sz);
4692 
4693     res = RegSetValueExA(propkey, "DisplayName", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
4694     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4695 
4696     /* DisplayName type is REG_DWORD */
4697     sz = MAX_PATH;
4698     lstrcpyA(buf, "apple");
4699     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
4700     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4701     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4702     ok(sz == 2, "Expected 2, got %lu\n", sz);
4703 
4704     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"1.1.1", 6);
4705     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4706 
4707     /* DisplayVersion value exists */
4708     sz = MAX_PATH;
4709     lstrcpyA(buf, "apple");
4710     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
4711     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4712     ok(!lstrcmpA(buf, "1.1.1"), "Expected \"1.1.1\", got \"%s\"\n", buf);
4713     ok(sz == 5, "Expected 5, got %lu\n", sz);
4714 
4715     res = RegSetValueExA(propkey, "DisplayVersion", 0,
4716                          REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
4717     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4718 
4719     /* DisplayVersion type is REG_DWORD */
4720     sz = MAX_PATH;
4721     lstrcpyA(buf, "apple");
4722     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
4723     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4724     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4725     ok(sz == 2, "Expected 2, got %lu\n", sz);
4726 
4727     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"tele", 5);
4728     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4729 
4730     /* HelpTelephone value exists */
4731     sz = MAX_PATH;
4732     lstrcpyA(buf, "apple");
4733     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
4734     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4735     ok(!lstrcmpA(buf, "tele"), "Expected \"tele\", got \"%s\"\n", buf);
4736     ok(sz == 4, "Expected 4, got %lu\n", sz);
4737 
4738     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_DWORD,
4739                          (const BYTE *)&val, sizeof(DWORD));
4740     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4741 
4742     /* HelpTelephone type is REG_DWORD */
4743     sz = MAX_PATH;
4744     lstrcpyA(buf, "apple");
4745     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
4746     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4747     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4748     ok(sz == 2, "Expected 2, got %lu\n", sz);
4749 
4750     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
4751     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4752 
4753     /* InstallLocation value exists */
4754     sz = MAX_PATH;
4755     lstrcpyA(buf, "apple");
4756     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
4757     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4758     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
4759     ok(sz == 3, "Expected 3, got %lu\n", sz);
4760 
4761     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_DWORD,
4762                          (const BYTE *)&val, sizeof(DWORD));
4763     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4764 
4765     /* InstallLocation type is REG_DWORD */
4766     sz = MAX_PATH;
4767     lstrcpyA(buf, "apple");
4768     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
4769     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4770     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4771     ok(sz == 2, "Expected 2, got %lu\n", sz);
4772 
4773     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
4774     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4775 
4776     /* InstallSource value exists */
4777     sz = MAX_PATH;
4778     lstrcpyA(buf, "apple");
4779     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
4780     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4781     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
4782     ok(sz == 6, "Expected 6, got %lu\n", sz);
4783 
4784     res = RegSetValueExA(propkey, "InstallSource", 0, REG_DWORD,
4785                          (const BYTE *)&val, sizeof(DWORD));
4786     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4787 
4788     /* InstallSource type is REG_DWORD */
4789     sz = MAX_PATH;
4790     lstrcpyA(buf, "apple");
4791     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
4792     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4793     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4794     ok(sz == 2, "Expected 2, got %lu\n", sz);
4795 
4796     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
4797     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4798 
4799     /* InstallDate value exists */
4800     sz = MAX_PATH;
4801     lstrcpyA(buf, "apple");
4802     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
4803     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4804     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
4805     ok(sz == 4, "Expected 4, got %lu\n", sz);
4806 
4807     res = RegSetValueExA(propkey, "InstallDate", 0, REG_DWORD,
4808                          (const BYTE *)&val, sizeof(DWORD));
4809     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4810 
4811     /* InstallDate type is REG_DWORD */
4812     sz = MAX_PATH;
4813     lstrcpyA(buf, "apple");
4814     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
4815     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4816     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4817     ok(sz == 2, "Expected 2, got %lu\n", sz);
4818 
4819     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
4820     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4821 
4822     /* Publisher value exists */
4823     sz = MAX_PATH;
4824     lstrcpyA(buf, "apple");
4825     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PUBLISHERA, buf, &sz);
4826     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4827     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
4828     ok(sz == 3, "Expected 3, got %lu\n", sz);
4829 
4830     res = RegSetValueExA(propkey, "Publisher", 0, REG_DWORD,
4831                          (const BYTE *)&val, sizeof(DWORD));
4832     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4833 
4834     /* Publisher type is REG_DWORD */
4835     sz = MAX_PATH;
4836     lstrcpyA(buf, "apple");
4837     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PUBLISHERA, buf, &sz);
4838     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4839     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4840     ok(sz == 2, "Expected 2, got %lu\n", sz);
4841 
4842     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"pack", 5);
4843     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4844 
4845     /* LocalPackage value exists */
4846     sz = MAX_PATH;
4847     lstrcpyA(buf, "apple");
4848     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
4849     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4850     ok(!lstrcmpA(buf, "pack"), "Expected \"pack\", got \"%s\"\n", buf);
4851     ok(sz == 4, "Expected 4, got %lu\n", sz);
4852 
4853     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_DWORD,
4854                          (const BYTE *)&val, sizeof(DWORD));
4855     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4856 
4857     /* LocalPackage type is REG_DWORD */
4858     sz = MAX_PATH;
4859     lstrcpyA(buf, "apple");
4860     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
4861     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4862     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4863     ok(sz == 2, "Expected 2, got %lu\n", sz);
4864 
4865     res = RegSetValueExA(propkey, "UrlInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
4866     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4867 
4868     /* UrlInfoAbout value exists */
4869     sz = MAX_PATH;
4870     lstrcpyA(buf, "apple");
4871     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
4872     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4873     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
4874     ok(sz == 5, "Expected 5, got %lu\n", sz);
4875 
4876     res = RegSetValueExA(propkey, "UrlInfoAbout", 0, REG_DWORD,
4877                          (const BYTE *)&val, sizeof(DWORD));
4878     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4879 
4880     /* UrlInfoAbout type is REG_DWORD */
4881     sz = MAX_PATH;
4882     lstrcpyA(buf, "apple");
4883     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
4884     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4885     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4886     ok(sz == 2, "Expected 2, got %lu\n", sz);
4887 
4888     res = RegSetValueExA(propkey, "UrlUpdateInfo", 0, REG_SZ, (LPBYTE)"info", 5);
4889     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4890 
4891     /* UrlUpdateInfo value exists */
4892     sz = MAX_PATH;
4893     lstrcpyA(buf, "apple");
4894     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
4895     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4896     ok(!lstrcmpA(buf, "info"), "Expected \"info\", got \"%s\"\n", buf);
4897     ok(sz == 4, "Expected 4, got %lu\n", sz);
4898 
4899     res = RegSetValueExA(propkey, "UrlUpdateInfo", 0, REG_DWORD,
4900                          (const BYTE *)&val, sizeof(DWORD));
4901     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4902 
4903     /* UrlUpdateInfo type is REG_DWORD */
4904     sz = MAX_PATH;
4905     lstrcpyA(buf, "apple");
4906     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
4907     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4908     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4909     ok(sz == 2, "Expected 2, got %lu\n", sz);
4910 
4911     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"1", 2);
4912     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4913 
4914     /* VersionMinor value exists */
4915     sz = MAX_PATH;
4916     lstrcpyA(buf, "apple");
4917     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
4918     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4919     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
4920     ok(sz == 1, "Expected 1, got %lu\n", sz);
4921 
4922     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_DWORD,
4923                          (const BYTE *)&val, sizeof(DWORD));
4924     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4925 
4926     /* VersionMinor type is REG_DWORD */
4927     sz = MAX_PATH;
4928     lstrcpyA(buf, "apple");
4929     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
4930     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4931     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4932     ok(sz == 2, "Expected 2, got %lu\n", sz);
4933 
4934     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"1", 2);
4935     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4936 
4937     /* VersionMajor value exists */
4938     sz = MAX_PATH;
4939     lstrcpyA(buf, "apple");
4940     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
4941     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4942     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
4943     ok(sz == 1, "Expected 1, got %lu\n", sz);
4944 
4945     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_DWORD,
4946                          (const BYTE *)&val, sizeof(DWORD));
4947     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4948 
4949     /* VersionMajor type is REG_DWORD */
4950     sz = MAX_PATH;
4951     lstrcpyA(buf, "apple");
4952     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
4953     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4954     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4955     ok(sz == 2, "Expected 2, got %lu\n", sz);
4956 
4957     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
4958     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4959 
4960     /* ProductID value exists */
4961     sz = MAX_PATH;
4962     lstrcpyA(buf, "apple");
4963     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
4964     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4965     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
4966     ok(sz == 2, "Expected 2, got %lu\n", sz);
4967 
4968     res = RegSetValueExA(propkey, "ProductID", 0, REG_DWORD,
4969                          (const BYTE *)&val, sizeof(DWORD));
4970     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4971 
4972     /* ProductID type is REG_DWORD */
4973     sz = MAX_PATH;
4974     lstrcpyA(buf, "apple");
4975     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
4976     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4977     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4978     ok(sz == 2, "Expected 2, got %lu\n", sz);
4979 
4980     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
4981     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4982 
4983     /* RegCompany value exists */
4984     sz = MAX_PATH;
4985     lstrcpyA(buf, "apple");
4986     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
4987     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4988     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
4989     ok(sz == 4, "Expected 4, got %lu\n", sz);
4990 
4991     res = RegSetValueExA(propkey, "RegCompany", 0, REG_DWORD,
4992                          (const BYTE *)&val, sizeof(DWORD));
4993     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4994 
4995     /* RegCompany type is REG_DWORD */
4996     sz = MAX_PATH;
4997     lstrcpyA(buf, "apple");
4998     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
4999     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5000     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5001     ok(sz == 2, "Expected 2, got %lu\n", sz);
5002 
5003     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"own", 4);
5004     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5005 
5006     /* RegOwner value exists */
5007     sz = MAX_PATH;
5008     lstrcpyA(buf, "apple");
5009     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGOWNERA, buf, &sz);
5010     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5011     ok(!lstrcmpA(buf, "own"), "Expected \"own\", got \"%s\"\n", buf);
5012     ok(sz == 3, "Expected 3, got %lu\n", sz);
5013 
5014     res = RegSetValueExA(propkey, "RegOwner", 0, REG_DWORD,
5015                          (const BYTE *)&val, sizeof(DWORD));
5016     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5017 
5018     /* RegOwner type is REG_DWORD */
5019     sz = MAX_PATH;
5020     lstrcpyA(buf, "apple");
5021     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGOWNERA, buf, &sz);
5022     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5023     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5024     ok(sz == 2, "Expected 2, got %lu\n", sz);
5025 
5026     res = RegSetValueExA(propkey, "InstanceType", 0, REG_SZ, (LPBYTE)"type", 5);
5027     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5028 
5029     /* InstanceType value exists */
5030     sz = MAX_PATH;
5031     lstrcpyA(buf, "apple");
5032     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5033     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5034     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5035     ok(sz == 0, "Expected 0, got %lu\n", sz);
5036 
5037     res = RegSetValueExA(propkey, "InstanceType", 0, REG_DWORD,
5038                          (const BYTE *)&val, sizeof(DWORD));
5039     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5040 
5041     /* InstanceType type is REG_DWORD */
5042     sz = MAX_PATH;
5043     lstrcpyA(buf, "apple");
5044     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5045     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5046     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5047     ok(sz == 0, "Expected 0, got %lu\n", sz);
5048 
5049     res = RegSetValueExA(prodkey, "InstanceType", 0, REG_SZ, (LPBYTE)"type", 5);
5050     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5051 
5052     /* InstanceType value exists */
5053     sz = MAX_PATH;
5054     lstrcpyA(buf, "apple");
5055     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5056     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5057     ok(!lstrcmpA(buf, "type"), "Expected \"type\", got \"%s\"\n", buf);
5058     ok(sz == 4, "Expected 4, got %lu\n", sz);
5059 
5060     res = RegSetValueExA(prodkey, "InstanceType", 0, REG_DWORD,
5061                          (const BYTE *)&val, sizeof(DWORD));
5062     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5063 
5064     /* InstanceType type is REG_DWORD */
5065     sz = MAX_PATH;
5066     lstrcpyA(buf, "apple");
5067     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5068     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5069     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5070     ok(sz == 2, "Expected 2, got %lu\n", sz);
5071 
5072     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"tforms", 7);
5073     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5074 
5075     /* Transforms value exists */
5076     sz = MAX_PATH;
5077     lstrcpyA(buf, "apple");
5078     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5079     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5080     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5081     ok(sz == 0, "Expected 0, got %lu\n", sz);
5082 
5083     res = RegSetValueExA(propkey, "Transforms", 0, REG_DWORD,
5084                          (const BYTE *)&val, sizeof(DWORD));
5085     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5086 
5087     /* Transforms type is REG_DWORD */
5088     sz = MAX_PATH;
5089     lstrcpyA(buf, "apple");
5090     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5091     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5092     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5093     ok(sz == 0, "Expected 0, got %lu\n", sz);
5094 
5095     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"tforms", 7);
5096     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5097 
5098     /* Transforms value exists */
5099     sz = MAX_PATH;
5100     lstrcpyA(buf, "apple");
5101     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5102     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5103     ok(!lstrcmpA(buf, "tforms"), "Expected \"tforms\", got \"%s\"\n", buf);
5104     ok(sz == 6, "Expected 6, got %lu\n", sz);
5105 
5106     res = RegSetValueExA(prodkey, "Transforms", 0, REG_DWORD,
5107                          (const BYTE *)&val, sizeof(DWORD));
5108     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5109 
5110     /* Transforms type is REG_DWORD */
5111     sz = MAX_PATH;
5112     lstrcpyA(buf, "apple");
5113     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5114     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5115     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5116     ok(sz == 2, "Expected 2, got %lu\n", sz);
5117 
5118     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
5119     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5120 
5121     /* Language value exists */
5122     sz = MAX_PATH;
5123     lstrcpyA(buf, "apple");
5124     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5125     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5126     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5127     ok(sz == 0, "Expected 0, got %lu\n", sz);
5128 
5129     res = RegSetValueExA(propkey, "Language", 0, REG_DWORD,
5130                          (const BYTE *)&val, sizeof(DWORD));
5131     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5132 
5133     /* Language type is REG_DWORD */
5134     sz = MAX_PATH;
5135     lstrcpyA(buf, "apple");
5136     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5137     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5138     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5139     ok(sz == 0, "Expected 0, got %lu\n", sz);
5140 
5141     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
5142     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5143 
5144     /* Language value exists */
5145     sz = MAX_PATH;
5146     lstrcpyA(buf, "apple");
5147     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5148     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5149     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
5150     ok(sz == 4, "Expected 4, got %lu\n", sz);
5151 
5152     res = RegSetValueExA(prodkey, "Language", 0, REG_DWORD,
5153                          (const BYTE *)&val, sizeof(DWORD));
5154     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5155 
5156     /* Language type is REG_DWORD */
5157     sz = MAX_PATH;
5158     lstrcpyA(buf, "apple");
5159     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5160     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5161     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5162     ok(sz == 2, "Expected 2, got %lu\n", sz);
5163 
5164     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
5165     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5166 
5167     /* ProductName value exists */
5168     sz = MAX_PATH;
5169     lstrcpyA(buf, "apple");
5170     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5171     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5172     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5173     ok(sz == 0, "Expected 0, got %lu\n", sz);
5174 
5175     res = RegSetValueExA(propkey, "ProductName", 0, REG_DWORD,
5176                          (const BYTE *)&val, sizeof(DWORD));
5177     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5178 
5179     /* ProductName type is REG_DWORD */
5180     sz = MAX_PATH;
5181     lstrcpyA(buf, "apple");
5182     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5183     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5184     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5185     ok(sz == 0, "Expected 0, got %lu\n", sz);
5186 
5187     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
5188     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5189 
5190     /* ProductName value exists */
5191     sz = MAX_PATH;
5192     lstrcpyA(buf, "apple");
5193     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5194     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5195     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
5196     ok(sz == 4, "Expected 4, got %lu\n", sz);
5197 
5198     res = RegSetValueExA(prodkey, "ProductName", 0, REG_DWORD,
5199                          (const BYTE *)&val, sizeof(DWORD));
5200     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5201 
5202     /* ProductName type is REG_DWORD */
5203     sz = MAX_PATH;
5204     lstrcpyA(buf, "apple");
5205     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5206     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5207     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5208     ok(sz == 2, "Expected 2, got %lu\n", sz);
5209 
5210     res = RegSetValueExA(propkey, "Assignment", 0, REG_SZ, (LPBYTE)"at", 3);
5211     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5212 
5213     /* Assignment value exists */
5214     sz = MAX_PATH;
5215     lstrcpyA(buf, "apple");
5216     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5217     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5218     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5219     ok(sz == 0, "Expected 0, got %lu\n", sz);
5220 
5221     res = RegSetValueExA(propkey, "Assignment", 0, REG_DWORD,
5222                          (const BYTE *)&val, sizeof(DWORD));
5223     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5224 
5225     /* Assignment type is REG_DWORD */
5226     sz = MAX_PATH;
5227     lstrcpyA(buf, "apple");
5228     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5229     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5230     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5231     ok(sz == 0, "Expected 0, got %lu\n", sz);
5232 
5233     res = RegSetValueExA(prodkey, "Assignment", 0, REG_SZ, (LPBYTE)"at", 3);
5234     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5235 
5236     /* Assignment value exists */
5237     sz = MAX_PATH;
5238     lstrcpyA(buf, "apple");
5239     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5240     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5241     ok(!lstrcmpA(buf, "at"), "Expected \"at\", got \"%s\"\n", buf);
5242     ok(sz == 2, "Expected 2, got %lu\n", sz);
5243 
5244     res = RegSetValueExA(prodkey, "Assignment", 0, REG_DWORD,
5245                          (const BYTE *)&val, sizeof(DWORD));
5246     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5247 
5248     /* Assignment type is REG_DWORD */
5249     sz = MAX_PATH;
5250     lstrcpyA(buf, "apple");
5251     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5252     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5253     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5254     ok(sz == 2, "Expected 2, got %lu\n", sz);
5255 
5256     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
5257     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5258 
5259     /* PackageCode value exists */
5260     sz = MAX_PATH;
5261     lstrcpyA(buf, "apple");
5262     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5263     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5264     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5265     ok(sz == 0, "Expected 0, got %lu\n", sz);
5266 
5267     res = RegSetValueExA(propkey, "PackageCode", 0, REG_DWORD,
5268                          (const BYTE *)&val, sizeof(DWORD));
5269     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5270 
5271     /* PackageCode type is REG_DWORD */
5272     sz = MAX_PATH;
5273     lstrcpyA(buf, "apple");
5274     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5275     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5276     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5277     ok(sz == 0, "Expected 0, got %lu\n", sz);
5278 
5279     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
5280     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5281 
5282     /* PackageCode value exists */
5283     sz = MAX_PATH;
5284     lstrcpyA(buf, "apple");
5285     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5286     ok(r == ERROR_BAD_CONFIGURATION,
5287        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
5288     ok(!lstrcmpA(buf, "code"), "Expected \"code\", got \"%s\"\n", buf);
5289     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5290 
5291     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_DWORD,
5292                          (const BYTE *)&val, sizeof(DWORD));
5293     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5294 
5295     /* PackageCode type is REG_DWORD */
5296     sz = MAX_PATH;
5297     lstrcpyA(buf, "apple");
5298     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5299     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5300     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5301     ok(sz == 2, "Expected 2, got %lu\n", sz);
5302 
5303     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)pack_squashed, 33);
5304     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5305 
5306     /* PackageCode value exists */
5307     sz = MAX_PATH;
5308     lstrcpyA(buf, "apple");
5309     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5310     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5311     ok(!lstrcmpA(buf, packcode), "Expected \"%s\", got \"%s\"\n", packcode, buf);
5312     ok(sz == 38, "Expected 38, got %lu\n", sz);
5313 
5314     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
5315     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5316 
5317     /* Version value exists */
5318     sz = MAX_PATH;
5319     lstrcpyA(buf, "apple");
5320     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5321     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5322     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5323     ok(sz == 0, "Expected 0, got %lu\n", sz);
5324 
5325     res = RegSetValueExA(propkey, "Version", 0, REG_DWORD,
5326                          (const BYTE *)&val, sizeof(DWORD));
5327     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5328 
5329     /* Version type is REG_DWORD */
5330     sz = MAX_PATH;
5331     lstrcpyA(buf, "apple");
5332     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5333     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5334     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5335     ok(sz == 0, "Expected 0, got %lu\n", sz);
5336 
5337     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
5338     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5339 
5340     /* Version value exists */
5341     sz = MAX_PATH;
5342     lstrcpyA(buf, "apple");
5343     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5344     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5345     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
5346     ok(sz == 3, "Expected 3, got %lu\n", sz);
5347 
5348     res = RegSetValueExA(prodkey, "Version", 0, REG_DWORD,
5349                          (const BYTE *)&val, sizeof(DWORD));
5350     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5351 
5352     /* Version type is REG_DWORD */
5353     sz = MAX_PATH;
5354     lstrcpyA(buf, "apple");
5355     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5356     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5357     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5358     ok(sz == 2, "Expected 2, got %lu\n", sz);
5359 
5360     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"ico", 4);
5361     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5362 
5363     /* ProductIcon value exists */
5364     sz = MAX_PATH;
5365     lstrcpyA(buf, "apple");
5366     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5367     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5368     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5369     ok(sz == 0, "Expected 0, got %lu\n", sz);
5370 
5371     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_DWORD,
5372                          (const BYTE *)&val, sizeof(DWORD));
5373     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5374 
5375     /* ProductIcon type is REG_DWORD */
5376     sz = MAX_PATH;
5377     lstrcpyA(buf, "apple");
5378     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5379     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5380     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5381     ok(sz == 0, "Expected 0, got %lu\n", sz);
5382 
5383     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"ico", 4);
5384     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5385 
5386     /* ProductIcon value exists */
5387     sz = MAX_PATH;
5388     lstrcpyA(buf, "apple");
5389     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5390     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5391     ok(!lstrcmpA(buf, "ico"), "Expected \"ico\", got \"%s\"\n", buf);
5392     ok(sz == 3, "Expected 3, got %lu\n", sz);
5393 
5394     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_DWORD,
5395                          (const BYTE *)&val, sizeof(DWORD));
5396     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5397 
5398     /* ProductIcon type is REG_DWORD */
5399     sz = MAX_PATH;
5400     lstrcpyA(buf, "apple");
5401     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5402     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5403     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5404     ok(sz == 2, "Expected 2, got %lu\n", sz);
5405 
5406     /* SourceList key does not exist */
5407     sz = MAX_PATH;
5408     lstrcpyA(buf, "apple");
5409     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5410     ok(r == ERROR_UNKNOWN_PRODUCT,
5411        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5412     ok(!lstrcmpA(buf, "apple"),
5413        "Expected buf to be unchanged, got \"%s\"\n", buf);
5414     ok(sz == MAX_PATH, "Expected sz to be unchanged, got %lu\n", sz);
5415 
5416     res = RegCreateKeyExA(prodkey, "SourceList", 0, NULL, 0, access, NULL, &source, NULL);
5417     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5418 
5419     /* SourceList key exists, but PackageName val does not exist */
5420     sz = MAX_PATH;
5421     lstrcpyA(buf, "apple");
5422     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5423     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5424     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5425     ok(sz == 0, "Expected 0, got %lu\n", sz);
5426 
5427     res = RegSetValueExA(source, "PackageName", 0, REG_SZ, (LPBYTE)"packname", 9);
5428     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5429 
5430     /* PackageName val exists */
5431     sz = MAX_PATH;
5432     lstrcpyA(buf, "apple");
5433     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5434     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5435     ok(!lstrcmpA(buf, "packname"), "Expected \"packname\", got \"%s\"\n", buf);
5436     ok(sz == 8, "Expected 8, got %lu\n", sz);
5437 
5438     res = RegSetValueExA(source, "PackageName", 0, REG_DWORD,
5439                          (const BYTE *)&val, sizeof(DWORD));
5440     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5441 
5442     /* PackageName type is REG_DWORD */
5443     sz = MAX_PATH;
5444     lstrcpyA(buf, "apple");
5445     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5446     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5447     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5448     ok(sz == 2, "Expected 2, got %lu\n", sz);
5449 
5450     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
5451     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5452 
5453     /* Authorized value exists */
5454     sz = MAX_PATH;
5455     lstrcpyA(buf, "apple");
5456     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5457     if (r != ERROR_UNKNOWN_PROPERTY)
5458     {
5459         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5460         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5461         ok(sz == 0, "Expected 0, got %lu\n", sz);
5462     }
5463 
5464     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_DWORD,
5465                          (const BYTE *)&val, sizeof(DWORD));
5466     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5467 
5468     /* AuthorizedLUAApp type is REG_DWORD */
5469     sz = MAX_PATH;
5470     lstrcpyA(buf, "apple");
5471     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5472     if (r != ERROR_UNKNOWN_PROPERTY)
5473     {
5474         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5475         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5476         ok(sz == 0, "Expected 0, got %lu\n", sz);
5477     }
5478 
5479     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
5480     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5481 
5482     /* Authorized value exists */
5483     sz = MAX_PATH;
5484     lstrcpyA(buf, "apple");
5485     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5486     if (r != ERROR_UNKNOWN_PROPERTY)
5487     {
5488         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5489         ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
5490         ok(sz == 4, "Expected 4, got %lu\n", sz);
5491     }
5492 
5493     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_DWORD,
5494                          (const BYTE *)&val, sizeof(DWORD));
5495     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5496 
5497     /* AuthorizedLUAApp type is REG_DWORD */
5498     sz = MAX_PATH;
5499     lstrcpyA(buf, "apple");
5500     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5501     if (r != ERROR_UNKNOWN_PROPERTY)
5502     {
5503         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5504         ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5505         ok(sz == 2, "Expected 2, got %lu\n", sz);
5506     }
5507 
5508     RegDeleteValueA(propkey, "HelpLink");
5509     RegDeleteValueA(propkey, "DisplayName");
5510     RegDeleteValueA(propkey, "DisplayVersion");
5511     RegDeleteValueA(propkey, "HelpTelephone");
5512     RegDeleteValueA(propkey, "InstallLocation");
5513     RegDeleteValueA(propkey, "InstallSource");
5514     RegDeleteValueA(propkey, "InstallDate");
5515     RegDeleteValueA(propkey, "Publisher");
5516     RegDeleteValueA(propkey, "LocalPackage");
5517     RegDeleteValueA(propkey, "UrlInfoAbout");
5518     RegDeleteValueA(propkey, "UrlUpdateInfo");
5519     RegDeleteValueA(propkey, "VersionMinor");
5520     RegDeleteValueA(propkey, "VersionMajor");
5521     RegDeleteValueA(propkey, "ProductID");
5522     RegDeleteValueA(propkey, "RegCompany");
5523     RegDeleteValueA(propkey, "RegOwner");
5524     RegDeleteValueA(propkey, "InstanceType");
5525     RegDeleteValueA(propkey, "Transforms");
5526     RegDeleteValueA(propkey, "Language");
5527     RegDeleteValueA(propkey, "ProductName");
5528     RegDeleteValueA(propkey, "Assignment");
5529     RegDeleteValueA(propkey, "PackageCode");
5530     RegDeleteValueA(propkey, "Version");
5531     RegDeleteValueA(propkey, "ProductIcon");
5532     RegDeleteValueA(propkey, "AuthorizedLUAApp");
5533     RegDeleteKeyExA(propkey, "", access & KEY_WOW64_64KEY, 0);
5534     RegDeleteKeyExA(localkey, "", access & KEY_WOW64_64KEY, 0);
5535     RegDeleteValueA(prodkey, "InstanceType");
5536     RegDeleteValueA(prodkey, "Transforms");
5537     RegDeleteValueA(prodkey, "Language");
5538     RegDeleteValueA(prodkey, "ProductName");
5539     RegDeleteValueA(prodkey, "Assignment");
5540     RegDeleteValueA(prodkey, "PackageCode");
5541     RegDeleteValueA(prodkey, "Version");
5542     RegDeleteValueA(prodkey, "ProductIcon");
5543     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
5544     RegDeleteValueA(source, "PackageName");
5545     RegDeleteKeyExA(source, "", access & KEY_WOW64_64KEY, 0);
5546     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
5547     RegCloseKey(propkey);
5548     RegCloseKey(localkey);
5549     RegCloseKey(source);
5550     RegCloseKey(prodkey);
5551     LocalFree(usersid);
5552 }
5553 
test_MsiGetProductInfoEx(void)5554 static void test_MsiGetProductInfoEx(void)
5555 {
5556     UINT r;
5557     LONG res;
5558     HKEY propkey, userkey;
5559     HKEY prodkey, localkey;
5560     CHAR prodcode[MAX_PATH];
5561     CHAR prod_squashed[MAX_PATH];
5562     CHAR packcode[MAX_PATH];
5563     CHAR pack_squashed[MAX_PATH];
5564     CHAR buf[MAX_PATH];
5565     CHAR keypath[MAX_PATH];
5566     LPSTR usersid;
5567     DWORD sz;
5568     REGSAM access = KEY_ALL_ACCESS;
5569 
5570     create_test_guid(prodcode, prod_squashed);
5571     create_test_guid(packcode, pack_squashed);
5572     usersid = get_user_sid();
5573 
5574     if (is_wow64)
5575         access |= KEY_WOW64_64KEY;
5576 
5577     /* NULL szProductCode */
5578     sz = MAX_PATH;
5579     lstrcpyA(buf, "apple");
5580     r = MsiGetProductInfoExA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
5581                              INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5582     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5583     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5584     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5585 
5586     /* empty szProductCode */
5587     sz = MAX_PATH;
5588     lstrcpyA(buf, "apple");
5589     r = MsiGetProductInfoExA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
5590                              INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5591     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5592     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5593     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5594 
5595     /* garbage szProductCode */
5596     sz = MAX_PATH;
5597     lstrcpyA(buf, "apple");
5598     r = MsiGetProductInfoExA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
5599                              INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5600     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5601     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5602     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5603 
5604     /* guid without brackets */
5605     sz = MAX_PATH;
5606     lstrcpyA(buf, "apple");
5607     r = MsiGetProductInfoExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", usersid,
5608                              MSIINSTALLCONTEXT_USERUNMANAGED,
5609                              INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5610     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5611     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5612     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5613 
5614     /* guid with brackets */
5615     sz = MAX_PATH;
5616     lstrcpyA(buf, "apple");
5617     r = MsiGetProductInfoExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", usersid,
5618                              MSIINSTALLCONTEXT_USERUNMANAGED,
5619                              INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5620     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5621     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5622     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5623 
5624     /* szValue is non-NULL while pcchValue is NULL */
5625     lstrcpyA(buf, "apple");
5626     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
5627                              INSTALLPROPERTY_PRODUCTSTATEA, buf, NULL);
5628     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5629     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5630 
5631     /* dwContext is out of range */
5632     sz = MAX_PATH;
5633     lstrcpyA(buf, "apple");
5634     r = MsiGetProductInfoExA(prodcode, usersid, 42, INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5635     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5636     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5637     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5638 
5639     /* szProperty is NULL */
5640     sz = MAX_PATH;
5641     lstrcpyA(buf, "apple");
5642     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, NULL, buf, &sz);
5643     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5644     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5645     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5646 
5647     /* szProperty is empty */
5648     sz = MAX_PATH;
5649     lstrcpyA(buf, "apple");
5650     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, "", buf, &sz);
5651     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5652     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5653     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5654 
5655     /* szProperty is not a valid property */
5656     sz = MAX_PATH;
5657     lstrcpyA(buf, "apple");
5658     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, "notvalid", buf, &sz);
5659     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5660     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5661     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5662 
5663     /* same length as guid, but random */
5664     sz = MAX_PATH;
5665     lstrcpyA(buf, "apple");
5666     r = MsiGetProductInfoExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
5667                              INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
5668     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5669     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5670     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5671 
5672     /* MSIINSTALLCONTEXT_USERUNMANAGED */
5673 
5674     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
5675     lstrcatA(keypath, usersid);
5676     lstrcatA(keypath, "\\Products\\");
5677     lstrcatA(keypath, prod_squashed);
5678 
5679     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
5680     if (res == ERROR_ACCESS_DENIED)
5681     {
5682         skip("Not enough rights to perform tests\n");
5683         LocalFree(usersid);
5684         return;
5685     }
5686     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5687 
5688     /* local user product key exists */
5689     sz = MAX_PATH;
5690     lstrcpyA(buf, "apple");
5691     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_PRODUCTSTATEA,
5692                              buf, &sz);
5693     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5694     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5695     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5696 
5697     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
5698     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5699 
5700     /* InstallProperties key exists */
5701     sz = MAX_PATH;
5702     lstrcpyA(buf, "apple");
5703     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_PRODUCTSTATEA,
5704                              buf, &sz);
5705     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5706     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5707     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5708 
5709     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
5710     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5711 
5712     /* LocalPackage value exists */
5713     sz = MAX_PATH;
5714     lstrcpyA(buf, "apple");
5715     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_PRODUCTSTATEA,
5716                              buf, &sz);
5717     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5718     ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
5719     ok(sz == 1, "Expected 1, got %lu\n", sz);
5720 
5721     RegDeleteValueA(propkey, "LocalPackage");
5722 
5723     /* LocalPackage value must exist */
5724     sz = MAX_PATH;
5725     lstrcpyA(buf, "apple");
5726     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5727     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5728     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5729     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5730 
5731     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
5732     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5733 
5734     /* LocalPackage exists, but HelpLink does not exist */
5735     sz = MAX_PATH;
5736     lstrcpyA(buf, "apple");
5737     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5738     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5739     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5740     ok(sz == 0, "Expected 0, got %lu\n", sz);
5741 
5742     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
5743     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5744 
5745     /* HelpLink value exists */
5746     sz = MAX_PATH;
5747     lstrcpyA(buf, "apple");
5748     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5749     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5750     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
5751     ok(sz == 4, "Expected 4, got %lu\n", sz);
5752 
5753     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
5754     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5755 
5756     /* HelpTelephone value exists */
5757     sz = MAX_PATH;
5758     lstrcpyA(buf, "apple");
5759     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_HELPTELEPHONEA,
5760                              buf, &sz);
5761     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5762     ok(!lstrcmpA(buf, "phone"), "Expected \"phone\", got \"%s\"\n", buf);
5763     ok(sz == 5, "Expected 5, got %lu\n", sz);
5764 
5765     /* szValue and pcchValue are NULL */
5766     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_HELPTELEPHONEA,
5767                              NULL, NULL);
5768     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5769 
5770     /* pcchValue is exactly 5 */
5771     sz = 5;
5772     lstrcpyA(buf, "apple");
5773     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_HELPTELEPHONEA,
5774                              buf, &sz);
5775     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
5776     ok(sz == 10, "Expected 10, got %lu\n", sz);
5777 
5778     /* szValue is NULL, pcchValue is exactly 5 */
5779     sz = 5;
5780     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_HELPTELEPHONEA,
5781                              NULL, &sz);
5782     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5783     ok(sz == 10, "Expected 10, got %lu\n", sz);
5784 
5785     /* szValue is NULL, pcchValue is MAX_PATH */
5786     sz = MAX_PATH;
5787     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_HELPTELEPHONEA,
5788                              NULL, &sz);
5789     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5790     ok(sz == 10, "Expected 10, got %lu\n", sz);
5791 
5792     /* pcchValue is exactly 0 */
5793     sz = 0;
5794     lstrcpyA(buf, "apple");
5795     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_HELPTELEPHONEA,
5796                              buf, &sz);
5797     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
5798     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
5799     ok(sz == 10, "Expected 10, got %lu\n", sz);
5800 
5801     res = RegSetValueExA(propkey, "notvalid", 0, REG_SZ, (LPBYTE)"invalid", 8);
5802     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5803 
5804     /* szProperty is not a valid property */
5805     sz = MAX_PATH;
5806     lstrcpyA(buf, "apple");
5807     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, "notvalid", buf, &sz);
5808     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5809     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5810     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5811 
5812     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
5813     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5814 
5815     /* InstallDate value exists */
5816     sz = MAX_PATH;
5817     lstrcpyA(buf, "apple");
5818     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_INSTALLDATEA,
5819                              buf, &sz);
5820     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5821     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
5822     ok(sz == 4, "Expected 4, got %lu\n", sz);
5823 
5824     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
5825     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5826 
5827     /* DisplayName value exists */
5828     sz = MAX_PATH;
5829     lstrcpyA(buf, "apple");
5830     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA,
5831                              buf, &sz);
5832     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5833     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
5834     ok(sz == 4, "Expected 4, got %lu\n", sz);
5835 
5836     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
5837     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5838 
5839     /* InstallLocation value exists */
5840     sz = MAX_PATH;
5841     lstrcpyA(buf, "apple");
5842     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_INSTALLLOCATIONA,
5843                              buf, &sz);
5844     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5845     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
5846     ok(sz == 3, "Expected 3, got %lu\n", sz);
5847 
5848     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
5849     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5850 
5851     /* InstallSource value exists */
5852     sz = MAX_PATH;
5853     lstrcpyA(buf, "apple");
5854     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_INSTALLSOURCEA,
5855                              buf, &sz);
5856     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5857     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
5858     ok(sz == 6, "Expected 6, got %lu\n", sz);
5859 
5860     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
5861     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5862 
5863     /* LocalPackage value exists */
5864     sz = MAX_PATH;
5865     lstrcpyA(buf, "apple");
5866     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
5867                              buf, &sz);
5868     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5869     ok(!lstrcmpA(buf, "local"), "Expected \"local\", got \"%s\"\n", buf);
5870     ok(sz == 5, "Expected 5, got %lu\n", sz);
5871 
5872     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
5873     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5874 
5875     /* Publisher value exists */
5876     sz = MAX_PATH;
5877     lstrcpyA(buf, "apple");
5878     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_PUBLISHERA,
5879                              buf, &sz);
5880     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5881     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
5882     ok(sz == 3, "Expected 3, got %lu\n", sz);
5883 
5884     res = RegSetValueExA(propkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
5885     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5886 
5887     /* URLInfoAbout value exists */
5888     sz = MAX_PATH;
5889     lstrcpyA(buf, "apple");
5890     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_URLINFOABOUTA,
5891                              buf, &sz);
5892     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5893     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
5894     ok(sz == 5, "Expected 5, got %lu\n", sz);
5895 
5896     res = RegSetValueExA(propkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
5897     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5898 
5899     /* URLUpdateInfo value exists */
5900     sz = MAX_PATH;
5901     lstrcpyA(buf, "apple");
5902     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_URLUPDATEINFOA,
5903                              buf, &sz);
5904     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5905     ok(!lstrcmpA(buf, "update"), "Expected \"update\", got \"%s\"\n", buf);
5906     ok(sz == 6, "Expected 6, got %lu\n", sz);
5907 
5908     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
5909     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5910 
5911     /* VersionMinor value exists */
5912     sz = MAX_PATH;
5913     lstrcpyA(buf, "apple");
5914     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_VERSIONMINORA,
5915                              buf, &sz);
5916     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5917     ok(!lstrcmpA(buf, "2"), "Expected \"2\", got \"%s\"\n", buf);
5918     ok(sz == 1, "Expected 1, got %lu\n", sz);
5919 
5920     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
5921     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5922 
5923     /* VersionMajor value exists */
5924     sz = MAX_PATH;
5925     lstrcpyA(buf, "apple");
5926     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_VERSIONMAJORA,
5927                              buf, &sz);
5928     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5929     ok(!lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
5930     ok(sz == 1, "Expected 1, got %lu\n", sz);
5931 
5932     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
5933     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5934 
5935     /* DisplayVersion value exists */
5936     sz = MAX_PATH;
5937     lstrcpyA(buf, "apple");
5938     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_VERSIONSTRINGA,
5939                              buf, &sz);
5940     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5941     ok(!lstrcmpA(buf, "3.2.1"), "Expected \"3.2.1\", got \"%s\"\n", buf);
5942     ok(sz == 5, "Expected 5, got %lu\n", sz);
5943 
5944     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
5945     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5946 
5947     /* ProductID value exists */
5948     sz = MAX_PATH;
5949     lstrcpyA(buf, "apple");
5950     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_PRODUCTIDA,
5951                              buf, &sz);
5952     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5953     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
5954     ok(sz == 2, "Expected 2, got %lu\n", sz);
5955 
5956     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
5957     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5958 
5959     /* RegCompany value exists */
5960     sz = MAX_PATH;
5961     lstrcpyA(buf, "apple");
5962     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_REGCOMPANYA,
5963                              buf, &sz);
5964     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5965     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
5966     ok(sz == 4, "Expected 4, got %lu\n", sz);
5967 
5968     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
5969     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5970 
5971     /* RegOwner value exists */
5972     sz = MAX_PATH;
5973     lstrcpyA(buf, "apple");
5974     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_REGOWNERA,
5975                              buf, &sz);
5976     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5977     ok(!lstrcmpA(buf, "owner"), "Expected \"owner\", got \"%s\"\n", buf);
5978     ok(sz == 5, "Expected 5, got %lu\n", sz);
5979 
5980     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
5981     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5982 
5983     /* Transforms value exists */
5984     sz = MAX_PATH;
5985     lstrcpyA(buf, "apple");
5986     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_TRANSFORMSA,
5987                              buf, &sz);
5988     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5989     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5990     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
5991 
5992     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
5993     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
5994 
5995     /* Language value exists */
5996     sz = MAX_PATH;
5997     lstrcpyA(buf, "apple");
5998     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_LANGUAGEA,
5999                              buf, &sz);
6000     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6001     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6002     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6003 
6004     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
6005     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6006 
6007     /* ProductName value exists */
6008     sz = MAX_PATH;
6009     lstrcpyA(buf, "apple");
6010     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_PRODUCTNAMEA,
6011                              buf, &sz);
6012     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6013     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6014     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6015 
6016     res = RegSetValueExA(propkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
6017     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6018 
6019     /* FIXME */
6020 
6021     /* AssignmentType value exists */
6022     sz = MAX_PATH;
6023     lstrcpyA(buf, "apple");
6024     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_ASSIGNMENTTYPEA,
6025                              buf, &sz);
6026     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6027     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6028     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6029 
6030     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
6031     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6032 
6033     /* PackageCode value exists */
6034     sz = MAX_PATH;
6035     lstrcpyA(buf, "apple");
6036     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_PACKAGECODEA,
6037                              buf, &sz);
6038     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6039     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6040     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6041 
6042     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
6043     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6044 
6045     /* Version value exists */
6046     sz = MAX_PATH;
6047     lstrcpyA(buf, "apple");
6048     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_VERSIONA,
6049                              buf, &sz);
6050     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6051     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6052     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6053 
6054     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
6055     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6056 
6057     /* ProductIcon value exists */
6058     sz = MAX_PATH;
6059     lstrcpyA(buf, "apple");
6060     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_PRODUCTICONA,
6061                              buf, &sz);
6062     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6063     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6064     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6065 
6066     res = RegSetValueExA(propkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
6067     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6068 
6069     /* PackageName value exists */
6070     sz = MAX_PATH;
6071     lstrcpyA(buf, "apple");
6072     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_PACKAGENAMEA,
6073                              buf, &sz);
6074     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6075     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6076     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6077 
6078     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
6079     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6080 
6081     /* AuthorizedLUAApp value exists */
6082     sz = MAX_PATH;
6083     lstrcpyA(buf, "apple");
6084     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_AUTHORIZED_LUA_APPA,
6085                              buf, &sz);
6086     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6087     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6088     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6089 
6090     RegDeleteValueA(propkey, "AuthorizedLUAApp");
6091     RegDeleteValueA(propkey, "PackageName");
6092     RegDeleteValueA(propkey, "ProductIcon");
6093     RegDeleteValueA(propkey, "Version");
6094     RegDeleteValueA(propkey, "PackageCode");
6095     RegDeleteValueA(propkey, "AssignmentType");
6096     RegDeleteValueA(propkey, "ProductName");
6097     RegDeleteValueA(propkey, "Language");
6098     RegDeleteValueA(propkey, "Transforms");
6099     RegDeleteValueA(propkey, "RegOwner");
6100     RegDeleteValueA(propkey, "RegCompany");
6101     RegDeleteValueA(propkey, "ProductID");
6102     RegDeleteValueA(propkey, "DisplayVersion");
6103     RegDeleteValueA(propkey, "VersionMajor");
6104     RegDeleteValueA(propkey, "VersionMinor");
6105     RegDeleteValueA(propkey, "URLUpdateInfo");
6106     RegDeleteValueA(propkey, "URLInfoAbout");
6107     RegDeleteValueA(propkey, "Publisher");
6108     RegDeleteValueA(propkey, "LocalPackage");
6109     RegDeleteValueA(propkey, "InstallSource");
6110     RegDeleteValueA(propkey, "InstallLocation");
6111     RegDeleteValueA(propkey, "DisplayName");
6112     RegDeleteValueA(propkey, "InstallDate");
6113     RegDeleteValueA(propkey, "HelpTelephone");
6114     RegDeleteValueA(propkey, "HelpLink");
6115     RegDeleteValueA(propkey, "LocalPackage");
6116     RegDeleteKeyA(propkey, "");
6117     RegCloseKey(propkey);
6118     RegDeleteKeyA(localkey, "");
6119     RegCloseKey(localkey);
6120 
6121     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
6122     lstrcatA(keypath, usersid);
6123     lstrcatA(keypath, "\\Installer\\Products\\");
6124     lstrcatA(keypath, prod_squashed);
6125 
6126     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
6127     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6128 
6129     /* user product key exists */
6130     sz = MAX_PATH;
6131     lstrcpyA(buf, "apple");
6132     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_PRODUCTSTATEA,
6133                              buf, &sz);
6134     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6135     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6136     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6137 
6138     RegDeleteKeyA(userkey, "");
6139     RegCloseKey(userkey);
6140 
6141     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
6142     lstrcatA(keypath, prod_squashed);
6143 
6144     res = RegCreateKeyExA(HKEY_CURRENT_USER, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
6145     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6146 
6147     sz = MAX_PATH;
6148     lstrcpyA(buf, "apple");
6149     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_PRODUCTSTATEA,
6150                              buf, &sz);
6151     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6152     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
6153     ok(sz == 1, "Expected 1, got %lu\n", sz);
6154 
6155     res = RegSetValueExA(prodkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
6156     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6157 
6158     /* HelpLink value exists */
6159     sz = MAX_PATH;
6160     lstrcpyA(buf, "apple");
6161     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_HELPLINKA,
6162                              buf, &sz);
6163     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6164     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6165     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6166 
6167     res = RegSetValueExA(prodkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
6168     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6169 
6170     /* HelpTelephone value exists */
6171     sz = MAX_PATH;
6172     lstrcpyA(buf, "apple");
6173     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_HELPTELEPHONEA,
6174                              buf, &sz);
6175     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6176     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6177     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6178 
6179     res = RegSetValueExA(prodkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
6180     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6181 
6182     /* InstallDate value exists */
6183     sz = MAX_PATH;
6184     lstrcpyA(buf, "apple");
6185     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_INSTALLDATEA,
6186                              buf, &sz);
6187     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6188     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6189     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6190 
6191     res = RegSetValueExA(prodkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
6192     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6193 
6194     /* DisplayName value exists */
6195     sz = MAX_PATH;
6196     lstrcpyA(buf, "apple");
6197     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA,
6198                              buf, &sz);
6199     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6200     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6201     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6202 
6203     res = RegSetValueExA(prodkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
6204     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6205 
6206     /* InstallLocation value exists */
6207     sz = MAX_PATH;
6208     lstrcpyA(buf, "apple");
6209     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_INSTALLLOCATIONA,
6210                              buf, &sz);
6211     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6212     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6213     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6214 
6215     res = RegSetValueExA(prodkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
6216     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6217 
6218     /* InstallSource value exists */
6219     sz = MAX_PATH;
6220     lstrcpyA(buf, "apple");
6221     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_INSTALLSOURCEA,
6222                              buf, &sz);
6223     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6224     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6225     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6226 
6227     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6228     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6229 
6230     /* LocalPackage value exists */
6231     sz = MAX_PATH;
6232     lstrcpyA(buf, "apple");
6233     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
6234                              buf, &sz);
6235     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6236     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6237     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6238 
6239     res = RegSetValueExA(prodkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
6240     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6241 
6242     /* Publisher value exists */
6243     sz = MAX_PATH;
6244     lstrcpyA(buf, "apple");
6245     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_PUBLISHERA,
6246                              buf, &sz);
6247     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6248     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6249     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6250 
6251     res = RegSetValueExA(prodkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
6252     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6253 
6254     /* URLInfoAbout value exists */
6255     sz = MAX_PATH;
6256     lstrcpyA(buf, "apple");
6257     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_URLINFOABOUTA,
6258                              buf, &sz);
6259     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6260     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6261     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6262 
6263     res = RegSetValueExA(prodkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
6264     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6265 
6266     /* URLUpdateInfo value exists */
6267     sz = MAX_PATH;
6268     lstrcpyA(buf, "apple");
6269     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_URLUPDATEINFOA,
6270                              buf, &sz);
6271     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6272     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6273     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6274 
6275     res = RegSetValueExA(prodkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
6276     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6277 
6278     /* VersionMinor value exists */
6279     sz = MAX_PATH;
6280     lstrcpyA(buf, "apple");
6281     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_VERSIONMINORA,
6282                              buf, &sz);
6283     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6284     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6285     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6286 
6287     res = RegSetValueExA(prodkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
6288     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6289 
6290     /* VersionMajor value exists */
6291     sz = MAX_PATH;
6292     lstrcpyA(buf, "apple");
6293     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_VERSIONMAJORA,
6294                              buf, &sz);
6295     ok(r == ERROR_UNKNOWN_PROPERTY, "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 %lu\n", sz);
6298 
6299     res = RegSetValueExA(prodkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
6300     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6301 
6302     /* DisplayVersion value exists */
6303     sz = MAX_PATH;
6304     lstrcpyA(buf, "apple");
6305     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_VERSIONSTRINGA,
6306                              buf, &sz);
6307     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6308     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6309     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6310 
6311     res = RegSetValueExA(prodkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
6312     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6313 
6314     /* ProductID value exists */
6315     sz = MAX_PATH;
6316     lstrcpyA(buf, "apple");
6317     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_PRODUCTIDA,
6318                              buf, &sz);
6319     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6320     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6321     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6322 
6323     res = RegSetValueExA(prodkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
6324     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6325 
6326     /* RegCompany value exists */
6327     sz = MAX_PATH;
6328     lstrcpyA(buf, "apple");
6329     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_REGCOMPANYA,
6330                              buf, &sz);
6331     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6332     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6333     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6334 
6335     res = RegSetValueExA(prodkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
6336     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6337 
6338     /* RegOwner value exists */
6339     sz = MAX_PATH;
6340     lstrcpyA(buf, "apple");
6341     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_REGOWNERA,
6342                              buf, &sz);
6343     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6344     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6345     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6346 
6347     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
6348     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6349 
6350     /* Transforms value exists */
6351     sz = MAX_PATH;
6352     lstrcpyA(buf, "apple");
6353     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_TRANSFORMSA,
6354                              buf, &sz);
6355     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6356     ok(!lstrcmpA(buf, "trans"), "Expected \"trans\", got \"%s\"\n", buf);
6357     ok(sz == 5, "Expected 5, got %lu\n", sz);
6358 
6359     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
6360     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6361 
6362     /* Language value exists */
6363     sz = MAX_PATH;
6364     lstrcpyA(buf, "apple");
6365     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_LANGUAGEA,
6366                              buf, &sz);
6367     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6368     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
6369     ok(sz == 4, "Expected 4, got %lu\n", sz);
6370 
6371     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
6372     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6373 
6374     /* ProductName value exists */
6375     sz = MAX_PATH;
6376     lstrcpyA(buf, "apple");
6377     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_PRODUCTNAMEA,
6378                              buf, &sz);
6379     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6380     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
6381     ok(sz == 4, "Expected 4, got %lu\n", sz);
6382 
6383     res = RegSetValueExA(prodkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
6384     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6385 
6386     /* FIXME */
6387 
6388     /* AssignmentType value exists */
6389     sz = MAX_PATH;
6390     lstrcpyA(buf, "apple");
6391     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_ASSIGNMENTTYPEA,
6392                              buf, &sz);
6393     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6394     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
6395     ok(sz == 0, "Expected 0, got %lu\n", sz);
6396 
6397     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
6398     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6399 
6400     /* FIXME */
6401 
6402     /* PackageCode value exists */
6403     sz = MAX_PATH;
6404     lstrcpyA(buf, "apple");
6405     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_PACKAGECODEA,
6406                              buf, &sz);
6407     todo_wine
6408     {
6409         ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
6410         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6411         ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6412     }
6413 
6414     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
6415     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6416 
6417     /* Version value exists */
6418     sz = MAX_PATH;
6419     lstrcpyA(buf, "apple");
6420     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_VERSIONA,
6421                              buf, &sz);
6422     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6423     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
6424     ok(sz == 3, "Expected 3, got %lu\n", sz);
6425 
6426     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
6427     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6428 
6429     /* ProductIcon value exists */
6430     sz = MAX_PATH;
6431     lstrcpyA(buf, "apple");
6432     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_PRODUCTICONA,
6433                              buf, &sz);
6434     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6435     ok(!lstrcmpA(buf, "icon"), "Expected \"icon\", got \"%s\"\n", buf);
6436     ok(sz == 4, "Expected 4, got %lu\n", sz);
6437 
6438     res = RegSetValueExA(prodkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
6439     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6440 
6441     /* PackageName value exists */
6442     sz = MAX_PATH;
6443     lstrcpyA(buf, "apple");
6444     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_PACKAGENAMEA,
6445                              buf, &sz);
6446     todo_wine
6447     {
6448         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6449         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6450         ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6451     }
6452 
6453     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
6454     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6455 
6456     /* AuthorizedLUAApp value exists */
6457     sz = MAX_PATH;
6458     lstrcpyA(buf, "apple");
6459     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_AUTHORIZED_LUA_APPA,
6460                              buf, &sz);
6461     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6462     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
6463     ok(sz == 4, "Expected 4, got %lu\n", sz);
6464 
6465     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
6466     RegDeleteValueA(prodkey, "PackageName");
6467     RegDeleteValueA(prodkey, "ProductIcon");
6468     RegDeleteValueA(prodkey, "Version");
6469     RegDeleteValueA(prodkey, "PackageCode");
6470     RegDeleteValueA(prodkey, "AssignmentType");
6471     RegDeleteValueA(prodkey, "ProductName");
6472     RegDeleteValueA(prodkey, "Language");
6473     RegDeleteValueA(prodkey, "Transforms");
6474     RegDeleteValueA(prodkey, "RegOwner");
6475     RegDeleteValueA(prodkey, "RegCompany");
6476     RegDeleteValueA(prodkey, "ProductID");
6477     RegDeleteValueA(prodkey, "DisplayVersion");
6478     RegDeleteValueA(prodkey, "VersionMajor");
6479     RegDeleteValueA(prodkey, "VersionMinor");
6480     RegDeleteValueA(prodkey, "URLUpdateInfo");
6481     RegDeleteValueA(prodkey, "URLInfoAbout");
6482     RegDeleteValueA(prodkey, "Publisher");
6483     RegDeleteValueA(prodkey, "LocalPackage");
6484     RegDeleteValueA(prodkey, "InstallSource");
6485     RegDeleteValueA(prodkey, "InstallLocation");
6486     RegDeleteValueA(prodkey, "DisplayName");
6487     RegDeleteValueA(prodkey, "InstallDate");
6488     RegDeleteValueA(prodkey, "HelpTelephone");
6489     RegDeleteValueA(prodkey, "HelpLink");
6490     RegDeleteValueA(prodkey, "LocalPackage");
6491     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
6492     RegCloseKey(prodkey);
6493 
6494     /* MSIINSTALLCONTEXT_USERMANAGED */
6495 
6496     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
6497     lstrcatA(keypath, usersid);
6498     lstrcatA(keypath, "\\Products\\");
6499     lstrcatA(keypath, prod_squashed);
6500 
6501     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
6502     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6503 
6504     /* local user product key exists */
6505     sz = MAX_PATH;
6506     lstrcpyA(buf, "apple");
6507     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_PRODUCTSTATEA,
6508                              buf, &sz);
6509     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6510     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6511     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6512 
6513     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
6514     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6515 
6516     /* InstallProperties key exists */
6517     sz = MAX_PATH;
6518     lstrcpyA(buf, "apple");
6519     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_PRODUCTSTATEA,
6520                              buf, &sz);
6521     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6522     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6523     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6524 
6525     res = RegSetValueExA(propkey, "ManagedLocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6526     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6527 
6528     /* ManagedLocalPackage value exists */
6529     sz = MAX_PATH;
6530     lstrcpyA(buf, "apple");
6531     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_PRODUCTSTATEA,
6532                              buf, &sz);
6533     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6534     ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
6535     ok(sz == 1, "Expected 1, got %lu\n", sz);
6536 
6537     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
6538     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6539 
6540     /* HelpLink value exists */
6541     sz = MAX_PATH;
6542     lstrcpyA(buf, "apple");
6543     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_HELPLINKA,
6544                              buf, &sz);
6545     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6546     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
6547     ok(sz == 4, "Expected 4, got %lu\n", sz);
6548 
6549     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
6550     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6551 
6552     /* HelpTelephone value exists */
6553     sz = MAX_PATH;
6554     lstrcpyA(buf, "apple");
6555     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_HELPTELEPHONEA,
6556                              buf, &sz);
6557     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6558     ok(!lstrcmpA(buf, "phone"), "Expected \"phone\", got \"%s\"\n", buf);
6559     ok(sz == 5, "Expected 5, got %lu\n", sz);
6560 
6561     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
6562     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6563 
6564     /* InstallDate value exists */
6565     sz = MAX_PATH;
6566     lstrcpyA(buf, "apple");
6567     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_INSTALLDATEA,
6568                              buf, &sz);
6569     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6570     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
6571     ok(sz == 4, "Expected 4, got %lu\n", sz);
6572 
6573     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
6574     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6575 
6576     /* DisplayName value exists */
6577     sz = MAX_PATH;
6578     lstrcpyA(buf, "apple");
6579     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA,
6580                              buf, &sz);
6581     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6582     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
6583     ok(sz == 4, "Expected 4, got %lu\n", sz);
6584 
6585     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
6586     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6587 
6588     /* InstallLocation value exists */
6589     sz = MAX_PATH;
6590     lstrcpyA(buf, "apple");
6591     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_INSTALLLOCATIONA,
6592                              buf, &sz);
6593     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6594     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
6595     ok(sz == 3, "Expected 3, got %lu\n", sz);
6596 
6597     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
6598     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6599 
6600     /* InstallSource value exists */
6601     sz = MAX_PATH;
6602     lstrcpyA(buf, "apple");
6603     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_INSTALLSOURCEA,
6604                              buf, &sz);
6605     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6606     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
6607     ok(sz == 6, "Expected 6, got %lu\n", sz);
6608 
6609     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6610     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6611 
6612     /* LocalPackage value exists */
6613     sz = MAX_PATH;
6614     lstrcpyA(buf, "apple");
6615     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
6616                              buf, &sz);
6617     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6618     ok(!lstrcmpA(buf, "local"), "Expected \"local\", got \"%s\"\n", buf);
6619     ok(sz == 5, "Expected 5, got %lu\n", sz);
6620 
6621     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
6622     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6623 
6624     /* Publisher value exists */
6625     sz = MAX_PATH;
6626     lstrcpyA(buf, "apple");
6627     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_PUBLISHERA,
6628                              buf, &sz);
6629     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6630     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
6631     ok(sz == 3, "Expected 3, got %lu\n", sz);
6632 
6633     res = RegSetValueExA(propkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
6634     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6635 
6636     /* URLInfoAbout value exists */
6637     sz = MAX_PATH;
6638     lstrcpyA(buf, "apple");
6639     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_URLINFOABOUTA,
6640                              buf, &sz);
6641     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6642     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
6643     ok(sz == 5, "Expected 5, got %lu\n", sz);
6644 
6645     res = RegSetValueExA(propkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
6646     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6647 
6648     /* URLUpdateInfo value exists */
6649     sz = MAX_PATH;
6650     lstrcpyA(buf, "apple");
6651     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_URLUPDATEINFOA,
6652                              buf, &sz);
6653     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6654     ok(!lstrcmpA(buf, "update"), "Expected \"update\", got \"%s\"\n", buf);
6655     ok(sz == 6, "Expected 6, got %lu\n", sz);
6656 
6657     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
6658     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6659 
6660     /* VersionMinor value exists */
6661     sz = MAX_PATH;
6662     lstrcpyA(buf, "apple");
6663     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_VERSIONMINORA,
6664                              buf, &sz);
6665     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6666     ok(!lstrcmpA(buf, "2"), "Expected \"2\", got \"%s\"\n", buf);
6667     ok(sz == 1, "Expected 1, got %lu\n", sz);
6668 
6669     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
6670     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6671 
6672     /* VersionMajor value exists */
6673     sz = MAX_PATH;
6674     lstrcpyA(buf, "apple");
6675     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_VERSIONMAJORA,
6676                              buf, &sz);
6677     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6678     ok(!lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
6679     ok(sz == 1, "Expected 1, got %lu\n", sz);
6680 
6681     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
6682     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6683 
6684     /* DisplayVersion value exists */
6685     sz = MAX_PATH;
6686     lstrcpyA(buf, "apple");
6687     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_VERSIONSTRINGA,
6688                              buf, &sz);
6689     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6690     ok(!lstrcmpA(buf, "3.2.1"), "Expected \"3.2.1\", got \"%s\"\n", buf);
6691     ok(sz == 5, "Expected 5, got %lu\n", sz);
6692 
6693     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
6694     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6695 
6696     /* ProductID value exists */
6697     sz = MAX_PATH;
6698     lstrcpyA(buf, "apple");
6699     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_PRODUCTIDA,
6700                              buf, &sz);
6701     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6702     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
6703     ok(sz == 2, "Expected 2, got %lu\n", sz);
6704 
6705     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
6706     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6707 
6708     /* RegCompany value exists */
6709     sz = MAX_PATH;
6710     lstrcpyA(buf, "apple");
6711     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_REGCOMPANYA,
6712                              buf, &sz);
6713     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6714     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
6715     ok(sz == 4, "Expected 4, got %lu\n", sz);
6716 
6717     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
6718     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6719 
6720     /* RegOwner value exists */
6721     sz = MAX_PATH;
6722     lstrcpyA(buf, "apple");
6723     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_REGOWNERA,
6724                              buf, &sz);
6725     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6726     ok(!lstrcmpA(buf, "owner"), "Expected \"owner\", got \"%s\"\n", buf);
6727     ok(sz == 5, "Expected 5, got %lu\n", sz);
6728 
6729     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
6730     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6731 
6732     /* Transforms value exists */
6733     sz = MAX_PATH;
6734     lstrcpyA(buf, "apple");
6735     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_TRANSFORMSA,
6736                              buf, &sz);
6737     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6738     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6739     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6740 
6741     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
6742     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6743 
6744     /* Language value exists */
6745     sz = MAX_PATH;
6746     lstrcpyA(buf, "apple");
6747     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_LANGUAGEA,
6748                              buf, &sz);
6749     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6750     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6751     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6752 
6753     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
6754     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6755 
6756     /* ProductName value exists */
6757     sz = MAX_PATH;
6758     lstrcpyA(buf, "apple");
6759     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_PRODUCTNAMEA,
6760                              buf, &sz);
6761     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6762     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6763     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6764 
6765     res = RegSetValueExA(propkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
6766     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6767 
6768     /* FIXME */
6769 
6770     /* AssignmentType value exists */
6771     sz = MAX_PATH;
6772     lstrcpyA(buf, "apple");
6773     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_ASSIGNMENTTYPEA,
6774                              buf, &sz);
6775     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6776     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6777     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6778 
6779     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
6780     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6781 
6782     /* PackageCode value exists */
6783     sz = MAX_PATH;
6784     lstrcpyA(buf, "apple");
6785     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_PACKAGECODEA,
6786                              buf, &sz);
6787     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6788     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6789     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6790 
6791     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
6792     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6793 
6794     /* Version value exists */
6795     sz = MAX_PATH;
6796     lstrcpyA(buf, "apple");
6797     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_VERSIONA,
6798                              buf, &sz);
6799     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6800     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6801     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6802 
6803     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
6804     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6805 
6806     /* ProductIcon value exists */
6807     sz = MAX_PATH;
6808     lstrcpyA(buf, "apple");
6809     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_PRODUCTICONA,
6810                              buf, &sz);
6811     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6812     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6813     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6814 
6815     res = RegSetValueExA(propkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
6816     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6817 
6818     /* PackageName value exists */
6819     sz = MAX_PATH;
6820     lstrcpyA(buf, "apple");
6821     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_PACKAGENAMEA,
6822                              buf, &sz);
6823     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6824     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6825     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6826 
6827     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
6828     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6829 
6830     /* AuthorizedLUAApp value exists */
6831     sz = MAX_PATH;
6832     lstrcpyA(buf, "apple");
6833     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_AUTHORIZED_LUA_APPA,
6834                              buf, &sz);
6835     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6836     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6837     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6838 
6839     RegDeleteValueA(propkey, "AuthorizedLUAApp");
6840     RegDeleteValueA(propkey, "PackageName");
6841     RegDeleteValueA(propkey, "ProductIcon");
6842     RegDeleteValueA(propkey, "Version");
6843     RegDeleteValueA(propkey, "PackageCode");
6844     RegDeleteValueA(propkey, "AssignmentType");
6845     RegDeleteValueA(propkey, "ProductName");
6846     RegDeleteValueA(propkey, "Language");
6847     RegDeleteValueA(propkey, "Transforms");
6848     RegDeleteValueA(propkey, "RegOwner");
6849     RegDeleteValueA(propkey, "RegCompany");
6850     RegDeleteValueA(propkey, "ProductID");
6851     RegDeleteValueA(propkey, "DisplayVersion");
6852     RegDeleteValueA(propkey, "VersionMajor");
6853     RegDeleteValueA(propkey, "VersionMinor");
6854     RegDeleteValueA(propkey, "URLUpdateInfo");
6855     RegDeleteValueA(propkey, "URLInfoAbout");
6856     RegDeleteValueA(propkey, "Publisher");
6857     RegDeleteValueA(propkey, "LocalPackage");
6858     RegDeleteValueA(propkey, "InstallSource");
6859     RegDeleteValueA(propkey, "InstallLocation");
6860     RegDeleteValueA(propkey, "DisplayName");
6861     RegDeleteValueA(propkey, "InstallDate");
6862     RegDeleteValueA(propkey, "HelpTelephone");
6863     RegDeleteValueA(propkey, "HelpLink");
6864     RegDeleteValueA(propkey, "ManagedLocalPackage");
6865     RegDeleteKeyExA(propkey, "", access & KEY_WOW64_64KEY, 0);
6866     RegCloseKey(propkey);
6867     RegDeleteKeyExA(localkey, "", access & KEY_WOW64_64KEY, 0);
6868     RegCloseKey(localkey);
6869 
6870     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
6871     lstrcatA(keypath, usersid);
6872     lstrcatA(keypath, "\\Installer\\Products\\");
6873     lstrcatA(keypath, prod_squashed);
6874 
6875     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
6876     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6877 
6878     /* user product key exists */
6879     sz = MAX_PATH;
6880     lstrcpyA(buf, "apple");
6881     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_PRODUCTSTATEA,
6882                              buf, &sz);
6883     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6884     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
6885     ok(sz == 1, "Expected 1, got %lu\n", sz);
6886 
6887     RegDeleteKeyExA(userkey, "", access & KEY_WOW64_64KEY, 0);
6888     RegCloseKey(userkey);
6889 
6890     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
6891     lstrcatA(keypath, prod_squashed);
6892 
6893     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
6894     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6895 
6896     /* current user product key exists */
6897     sz = MAX_PATH;
6898     lstrcpyA(buf, "apple");
6899     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_PRODUCTSTATEA,
6900                              buf, &sz);
6901     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6902     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6903     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6904 
6905     res = RegSetValueExA(prodkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
6906     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6907 
6908     /* HelpLink value exists, user product key does not exist */
6909     sz = MAX_PATH;
6910     lstrcpyA(buf, "apple");
6911     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_HELPLINKA,
6912                              buf, &sz);
6913     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6914     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6915     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6916 
6917     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
6918     lstrcatA(keypath, usersid);
6919     lstrcatA(keypath, "\\Installer\\Products\\");
6920     lstrcatA(keypath, prod_squashed);
6921 
6922     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
6923     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6924 
6925     res = RegSetValueExA(userkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
6926     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6927 
6928     /* HelpLink value exists, user product key does exist */
6929     sz = MAX_PATH;
6930     lstrcpyA(buf, "apple");
6931     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_HELPLINKA,
6932                              buf, &sz);
6933     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, 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 %lu\n", sz);
6936 
6937     res = RegSetValueExA(userkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
6938     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6939 
6940     /* HelpTelephone value exists */
6941     sz = MAX_PATH;
6942     lstrcpyA(buf, "apple");
6943     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_HELPTELEPHONEA,
6944                              buf, &sz);
6945     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6946     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6947     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6948 
6949     res = RegSetValueExA(userkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
6950     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6951 
6952     /* InstallDate value exists */
6953     sz = MAX_PATH;
6954     lstrcpyA(buf, "apple");
6955     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_INSTALLDATEA,
6956                              buf, &sz);
6957     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6958     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6959     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6960 
6961     res = RegSetValueExA(userkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
6962     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6963 
6964     /* DisplayName value exists */
6965     sz = MAX_PATH;
6966     lstrcpyA(buf, "apple");
6967     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA,
6968                              buf, &sz);
6969     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6970     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6971     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6972 
6973     res = RegSetValueExA(userkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
6974     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6975 
6976     /* InstallLocation value exists */
6977     sz = MAX_PATH;
6978     lstrcpyA(buf, "apple");
6979     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_INSTALLLOCATIONA,
6980                              buf, &sz);
6981     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6982     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6983     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6984 
6985     res = RegSetValueExA(userkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
6986     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6987 
6988     /* InstallSource value exists */
6989     sz = MAX_PATH;
6990     lstrcpyA(buf, "apple");
6991     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_INSTALLSOURCEA,
6992                              buf, &sz);
6993     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6994     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6995     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
6996 
6997     res = RegSetValueExA(userkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6998     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
6999 
7000     /* LocalPackage value exists */
7001     sz = MAX_PATH;
7002     lstrcpyA(buf, "apple");
7003     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
7004                              buf, &sz);
7005     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, 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 %lu\n", sz);
7008 
7009     res = RegSetValueExA(userkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
7010     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7011 
7012     /* Publisher value exists */
7013     sz = MAX_PATH;
7014     lstrcpyA(buf, "apple");
7015     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_PUBLISHERA,
7016                              buf, &sz);
7017     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7018     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7019     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7020 
7021     res = RegSetValueExA(userkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
7022     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7023 
7024     /* URLInfoAbout value exists */
7025     sz = MAX_PATH;
7026     lstrcpyA(buf, "apple");
7027     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_URLINFOABOUTA,
7028                              buf, &sz);
7029     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7030     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7031     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7032 
7033     res = RegSetValueExA(userkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
7034     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7035 
7036     /* URLUpdateInfo value exists */
7037     sz = MAX_PATH;
7038     lstrcpyA(buf, "apple");
7039     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_URLUPDATEINFOA,
7040                              buf, &sz);
7041     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7042     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7043     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7044 
7045     res = RegSetValueExA(userkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
7046     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7047 
7048     /* VersionMinor value exists */
7049     sz = MAX_PATH;
7050     lstrcpyA(buf, "apple");
7051     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_VERSIONMINORA,
7052                              buf, &sz);
7053     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7054     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7055     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7056 
7057     res = RegSetValueExA(userkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
7058     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7059 
7060     /* VersionMajor value exists */
7061     sz = MAX_PATH;
7062     lstrcpyA(buf, "apple");
7063     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_VERSIONMAJORA,
7064                              buf, &sz);
7065     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7066     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7067     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7068 
7069     res = RegSetValueExA(userkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
7070     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7071 
7072     /* DisplayVersion value exists */
7073     sz = MAX_PATH;
7074     lstrcpyA(buf, "apple");
7075     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_VERSIONSTRINGA,
7076                              buf, &sz);
7077     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7078     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7079     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7080 
7081     res = RegSetValueExA(userkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
7082     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7083 
7084     /* ProductID value exists */
7085     sz = MAX_PATH;
7086     lstrcpyA(buf, "apple");
7087     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_PRODUCTIDA,
7088                              buf, &sz);
7089     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7090     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7091     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7092 
7093     res = RegSetValueExA(userkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
7094     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7095 
7096     /* RegCompany value exists */
7097     sz = MAX_PATH;
7098     lstrcpyA(buf, "apple");
7099     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_REGCOMPANYA,
7100                              buf, &sz);
7101     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7102     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7103     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7104 
7105     res = RegSetValueExA(userkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
7106     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7107 
7108     /* RegOwner value exists */
7109     sz = MAX_PATH;
7110     lstrcpyA(buf, "apple");
7111     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_REGOWNERA,
7112                              buf, &sz);
7113     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7114     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7115     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7116 
7117     res = RegSetValueExA(userkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
7118     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7119 
7120     /* Transforms value exists */
7121     sz = MAX_PATH;
7122     lstrcpyA(buf, "apple");
7123     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_TRANSFORMSA,
7124                              buf, &sz);
7125     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7126     ok(!lstrcmpA(buf, "trans"), "Expected \"trans\", got \"%s\"\n", buf);
7127     ok(sz == 5, "Expected 5, got %lu\n", sz);
7128 
7129     res = RegSetValueExA(userkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
7130     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7131 
7132     /* Language value exists */
7133     sz = MAX_PATH;
7134     lstrcpyA(buf, "apple");
7135     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_LANGUAGEA,
7136                              buf, &sz);
7137     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7138     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
7139     ok(sz == 4, "Expected 4, got %lu\n", sz);
7140 
7141     res = RegSetValueExA(userkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
7142     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7143 
7144     /* ProductName value exists */
7145     sz = MAX_PATH;
7146     lstrcpyA(buf, "apple");
7147     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_PRODUCTNAMEA,
7148                              buf, &sz);
7149     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7150     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
7151     ok(sz == 4, "Expected 4, got %lu\n", sz);
7152 
7153     res = RegSetValueExA(userkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
7154     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7155 
7156     /* FIXME */
7157 
7158     /* AssignmentType value exists */
7159     sz = MAX_PATH;
7160     lstrcpyA(buf, "apple");
7161     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_ASSIGNMENTTYPEA,
7162                              buf, &sz);
7163     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7164     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7165     ok(sz == 0, "Expected 0, got %lu\n", sz);
7166 
7167     res = RegSetValueExA(userkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
7168     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7169 
7170     /* FIXME */
7171 
7172     /* PackageCode value exists */
7173     sz = MAX_PATH;
7174     lstrcpyA(buf, "apple");
7175     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_PACKAGECODEA,
7176                              buf, &sz);
7177     todo_wine
7178     {
7179         ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
7180         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7181         ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7182     }
7183 
7184     res = RegSetValueExA(userkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
7185     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7186 
7187     /* Version value exists */
7188     sz = MAX_PATH;
7189     lstrcpyA(buf, "apple");
7190     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_VERSIONA,
7191                              buf, &sz);
7192     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7193     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
7194     ok(sz == 3, "Expected 3, got %lu\n", sz);
7195 
7196     res = RegSetValueExA(userkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
7197     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7198 
7199     /* ProductIcon value exists */
7200     sz = MAX_PATH;
7201     lstrcpyA(buf, "apple");
7202     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_PRODUCTICONA,
7203                              buf, &sz);
7204     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7205     ok(!lstrcmpA(buf, "icon"), "Expected \"icon\", got \"%s\"\n", buf);
7206     ok(sz == 4, "Expected 4, got %lu\n", sz);
7207 
7208     res = RegSetValueExA(userkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
7209     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7210 
7211     /* PackageName value exists */
7212     sz = MAX_PATH;
7213     lstrcpyA(buf, "apple");
7214     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_PACKAGENAMEA,
7215                              buf, &sz);
7216     todo_wine
7217     {
7218         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7219         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7220         ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7221     }
7222 
7223     res = RegSetValueExA(userkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
7224     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7225 
7226     /* AuthorizedLUAApp value exists */
7227     sz = MAX_PATH;
7228     lstrcpyA(buf, "apple");
7229     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_AUTHORIZED_LUA_APPA,
7230                              buf, &sz);
7231     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7232     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
7233     ok(sz == 4, "Expected 4, got %lu\n", sz);
7234 
7235     RegDeleteValueA(userkey, "AuthorizedLUAApp");
7236     RegDeleteValueA(userkey, "PackageName");
7237     RegDeleteValueA(userkey, "ProductIcon");
7238     RegDeleteValueA(userkey, "Version");
7239     RegDeleteValueA(userkey, "PackageCode");
7240     RegDeleteValueA(userkey, "AssignmentType");
7241     RegDeleteValueA(userkey, "ProductName");
7242     RegDeleteValueA(userkey, "Language");
7243     RegDeleteValueA(userkey, "Transforms");
7244     RegDeleteValueA(userkey, "RegOwner");
7245     RegDeleteValueA(userkey, "RegCompany");
7246     RegDeleteValueA(userkey, "ProductID");
7247     RegDeleteValueA(userkey, "DisplayVersion");
7248     RegDeleteValueA(userkey, "VersionMajor");
7249     RegDeleteValueA(userkey, "VersionMinor");
7250     RegDeleteValueA(userkey, "URLUpdateInfo");
7251     RegDeleteValueA(userkey, "URLInfoAbout");
7252     RegDeleteValueA(userkey, "Publisher");
7253     RegDeleteValueA(userkey, "LocalPackage");
7254     RegDeleteValueA(userkey, "InstallSource");
7255     RegDeleteValueA(userkey, "InstallLocation");
7256     RegDeleteValueA(userkey, "DisplayName");
7257     RegDeleteValueA(userkey, "InstallDate");
7258     RegDeleteValueA(userkey, "HelpTelephone");
7259     RegDeleteValueA(userkey, "HelpLink");
7260     RegDeleteKeyExA(userkey, "", access & KEY_WOW64_64KEY, 0);
7261     RegCloseKey(userkey);
7262     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
7263     RegCloseKey(prodkey);
7264 
7265     /* MSIINSTALLCONTEXT_MACHINE */
7266 
7267     /* szUserSid is non-NULL */
7268     sz = MAX_PATH;
7269     lstrcpyA(buf, "apple");
7270     r = MsiGetProductInfoExA(prodcode, usersid, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7271     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
7272     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7273     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7274 
7275     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\");
7276     lstrcatA(keypath, prod_squashed);
7277 
7278     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
7279     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7280 
7281     /* local system product key exists */
7282     sz = MAX_PATH;
7283     lstrcpyA(buf, "apple");
7284     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7285     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7286     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7287     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7288 
7289     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
7290     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7291 
7292     /* InstallProperties key exists */
7293     sz = MAX_PATH;
7294     lstrcpyA(buf, "apple");
7295     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7296     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7297     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7298     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7299 
7300     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
7301     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7302 
7303     /* LocalPackage value exists */
7304     sz = MAX_PATH;
7305     lstrcpyA(buf, "apple");
7306     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7307     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7308     ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
7309     ok(sz == 1, "Expected 1, got %lu\n", sz);
7310 
7311     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
7312     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7313 
7314     /* HelpLink value exists */
7315     sz = MAX_PATH;
7316     lstrcpyA(buf, "apple");
7317     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_HELPLINKA, buf, &sz);
7318     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7319     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
7320     ok(sz == 4, "Expected 4, got %lu\n", sz);
7321 
7322     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
7323     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7324 
7325     /* HelpTelephone value exists */
7326     sz = MAX_PATH;
7327     lstrcpyA(buf, "apple");
7328     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
7329     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7330     ok(!lstrcmpA(buf, "phone"), "Expected \"phone\", got \"%s\"\n", buf);
7331     ok(sz == 5, "Expected 5, got %lu\n", sz);
7332 
7333     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
7334     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7335 
7336     /* InstallDate value exists */
7337     sz = MAX_PATH;
7338     lstrcpyA(buf, "apple");
7339     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
7340     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7341     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
7342     ok(sz == 4, "Expected 4, got %lu\n", sz);
7343 
7344     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
7345     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7346 
7347     /* DisplayName value exists */
7348     sz = MAX_PATH;
7349     lstrcpyA(buf, "apple");
7350     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA,
7351                              buf, &sz);
7352     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7353     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
7354     ok(sz == 4, "Expected 4, got %lu\n", sz);
7355 
7356     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
7357     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7358 
7359     /* InstallLocation value exists */
7360     sz = MAX_PATH;
7361     lstrcpyA(buf, "apple");
7362     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
7363     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7364     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
7365     ok(sz == 3, "Expected 3, got %lu\n", sz);
7366 
7367     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
7368     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7369 
7370     /* InstallSource value exists */
7371     sz = MAX_PATH;
7372     lstrcpyA(buf, "apple");
7373     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
7374     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7375     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
7376     ok(sz == 6, "Expected 6, got %lu\n", sz);
7377 
7378     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
7379     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7380 
7381     /* LocalPackage value exists */
7382     sz = MAX_PATH;
7383     lstrcpyA(buf, "apple");
7384     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
7385     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7386     ok(!lstrcmpA(buf, "local"), "Expected \"local\", got \"%s\"\n", buf);
7387     ok(sz == 5, "Expected 5, got %lu\n", sz);
7388 
7389     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
7390     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7391 
7392     /* Publisher value exists */
7393     sz = MAX_PATH;
7394     lstrcpyA(buf, "apple");
7395     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_PUBLISHERA, buf, &sz);
7396     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7397     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
7398     ok(sz == 3, "Expected 3, got %lu\n", sz);
7399 
7400     res = RegSetValueExA(propkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
7401     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7402 
7403     /* URLInfoAbout value exists */
7404     sz = MAX_PATH;
7405     lstrcpyA(buf, "apple");
7406     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
7407     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7408     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
7409     ok(sz == 5, "Expected 5, got %lu\n", sz);
7410 
7411     res = RegSetValueExA(propkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
7412     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7413 
7414     /* URLUpdateInfo value exists */
7415     sz = MAX_PATH;
7416     lstrcpyA(buf, "apple");
7417     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
7418     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7419     ok(!lstrcmpA(buf, "update"), "Expected \"update\", got \"%s\"\n", buf);
7420     ok(sz == 6, "Expected 6, got %lu\n", sz);
7421 
7422     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
7423     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7424 
7425     /* VersionMinor value exists */
7426     sz = MAX_PATH;
7427     lstrcpyA(buf, "apple");
7428     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
7429     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7430     ok(!lstrcmpA(buf, "2"), "Expected \"2\", got \"%s\"\n", buf);
7431     ok(sz == 1, "Expected 1, got %lu\n", sz);
7432 
7433     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
7434     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7435 
7436     /* VersionMajor value exists */
7437     sz = MAX_PATH;
7438     lstrcpyA(buf, "apple");
7439     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
7440     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7441     ok(!lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
7442     ok(sz == 1, "Expected 1, got %lu\n", sz);
7443 
7444     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
7445     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7446 
7447     /* DisplayVersion value exists */
7448     sz = MAX_PATH;
7449     lstrcpyA(buf, "apple");
7450     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
7451     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7452     ok(!lstrcmpA(buf, "3.2.1"), "Expected \"3.2.1\", got \"%s\"\n", buf);
7453     ok(sz == 5, "Expected 5, got %lu\n", sz);
7454 
7455     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
7456     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7457 
7458     /* ProductID value exists */
7459     sz = MAX_PATH;
7460     lstrcpyA(buf, "apple");
7461     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
7462     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7463     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
7464     ok(sz == 2, "Expected 2, got %lu\n", sz);
7465 
7466     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
7467     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7468 
7469     /* RegCompany value exists */
7470     sz = MAX_PATH;
7471     lstrcpyA(buf, "apple");
7472     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
7473     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7474     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
7475     ok(sz == 4, "Expected 4, got %lu\n", sz);
7476 
7477     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
7478     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7479 
7480     /* RegOwner value exists */
7481     sz = MAX_PATH;
7482     lstrcpyA(buf, "apple");
7483     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_REGOWNERA, buf, &sz);
7484     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7485     ok(!lstrcmpA(buf, "owner"), "Expected \"owner\", got \"%s\"\n", buf);
7486     ok(sz == 5, "Expected 5, got %lu\n", sz);
7487 
7488     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
7489     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7490 
7491     /* Transforms value exists */
7492     sz = MAX_PATH;
7493     lstrcpyA(buf, "apple");
7494     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
7495     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7496     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7497     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7498 
7499     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
7500     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7501 
7502     /* Language value exists */
7503     sz = MAX_PATH;
7504     lstrcpyA(buf, "apple");
7505     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
7506     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7507     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7508     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7509 
7510     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
7511     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7512 
7513     /* ProductName value exists */
7514     sz = MAX_PATH;
7515     lstrcpyA(buf, "apple");
7516     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
7517     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7518     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7519     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7520 
7521     res = RegSetValueExA(propkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
7522     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7523 
7524     /* FIXME */
7525 
7526     /* AssignmentType value exists */
7527     sz = MAX_PATH;
7528     lstrcpyA(buf, "apple");
7529     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
7530     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7531     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7532     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7533 
7534     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
7535     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7536 
7537     /* PackageCode value exists */
7538     sz = MAX_PATH;
7539     lstrcpyA(buf, "apple");
7540     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
7541     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7542     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7543     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7544 
7545     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
7546     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7547 
7548     /* Version value exists */
7549     sz = MAX_PATH;
7550     lstrcpyA(buf, "apple");
7551     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_VERSIONA, buf, &sz);
7552     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7553     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7554     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7555 
7556     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
7557     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7558 
7559     /* ProductIcon value exists */
7560     sz = MAX_PATH;
7561     lstrcpyA(buf, "apple");
7562     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
7563     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7564     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7565     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7566 
7567     res = RegSetValueExA(propkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
7568     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7569 
7570     /* PackageName value exists */
7571     sz = MAX_PATH;
7572     lstrcpyA(buf, "apple");
7573     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
7574     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7575     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7576     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7577 
7578     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
7579     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7580 
7581     /* AuthorizedLUAApp value exists */
7582     sz = MAX_PATH;
7583     lstrcpyA(buf, "apple");
7584     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
7585     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7586     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7587     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7588 
7589     RegDeleteValueA(propkey, "AuthorizedLUAApp");
7590     RegDeleteValueA(propkey, "PackageName");
7591     RegDeleteValueA(propkey, "ProductIcon");
7592     RegDeleteValueA(propkey, "Version");
7593     RegDeleteValueA(propkey, "PackageCode");
7594     RegDeleteValueA(propkey, "AssignmentType");
7595     RegDeleteValueA(propkey, "ProductName");
7596     RegDeleteValueA(propkey, "Language");
7597     RegDeleteValueA(propkey, "Transforms");
7598     RegDeleteValueA(propkey, "RegOwner");
7599     RegDeleteValueA(propkey, "RegCompany");
7600     RegDeleteValueA(propkey, "ProductID");
7601     RegDeleteValueA(propkey, "DisplayVersion");
7602     RegDeleteValueA(propkey, "VersionMajor");
7603     RegDeleteValueA(propkey, "VersionMinor");
7604     RegDeleteValueA(propkey, "URLUpdateInfo");
7605     RegDeleteValueA(propkey, "URLInfoAbout");
7606     RegDeleteValueA(propkey, "Publisher");
7607     RegDeleteValueA(propkey, "LocalPackage");
7608     RegDeleteValueA(propkey, "InstallSource");
7609     RegDeleteValueA(propkey, "InstallLocation");
7610     RegDeleteValueA(propkey, "DisplayName");
7611     RegDeleteValueA(propkey, "InstallDate");
7612     RegDeleteValueA(propkey, "HelpTelephone");
7613     RegDeleteValueA(propkey, "HelpLink");
7614     RegDeleteValueA(propkey, "LocalPackage");
7615     RegDeleteKeyExA(propkey, "", access & KEY_WOW64_64KEY, 0);
7616     RegCloseKey(propkey);
7617     RegDeleteKeyExA(localkey, "", access & KEY_WOW64_64KEY, 0);
7618     RegCloseKey(localkey);
7619 
7620     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
7621     lstrcatA(keypath, prod_squashed);
7622 
7623     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
7624     if (res == ERROR_ACCESS_DENIED)
7625     {
7626         skip( "insufficient rights\n" );
7627         LocalFree( usersid );
7628         return;
7629     }
7630     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7631 
7632     /* local classes product key exists */
7633     sz = MAX_PATH;
7634     lstrcpyA(buf, "apple");
7635     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7636     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7637     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
7638     ok(sz == 1, "Expected 1, got %lu\n", sz);
7639 
7640     res = RegSetValueExA(prodkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
7641     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7642 
7643     /* HelpLink value exists */
7644     sz = MAX_PATH;
7645     lstrcpyA(buf, "apple");
7646     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_HELPLINKA, buf, &sz);
7647     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7648     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7649     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7650 
7651     res = RegSetValueExA(prodkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
7652     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7653 
7654     /* HelpTelephone value exists */
7655     sz = MAX_PATH;
7656     lstrcpyA(buf, "apple");
7657     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
7658     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7659     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7660     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7661 
7662     res = RegSetValueExA(prodkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
7663     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7664 
7665     /* InstallDate value exists */
7666     sz = MAX_PATH;
7667     lstrcpyA(buf, "apple");
7668     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
7669     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7670     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7671     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7672 
7673     res = RegSetValueExA(prodkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
7674     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7675 
7676     /* DisplayName value exists */
7677     sz = MAX_PATH;
7678     lstrcpyA(buf, "apple");
7679     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA,
7680                              buf, &sz);
7681     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7682     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7683     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7684 
7685     res = RegSetValueExA(prodkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
7686     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7687 
7688     /* InstallLocation value exists */
7689     sz = MAX_PATH;
7690     lstrcpyA(buf, "apple");
7691     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
7692     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7693     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7694     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7695 
7696     res = RegSetValueExA(prodkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
7697     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7698 
7699     /* InstallSource value exists */
7700     sz = MAX_PATH;
7701     lstrcpyA(buf, "apple");
7702     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
7703     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7704     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7705     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7706 
7707     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
7708     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7709 
7710     /* LocalPackage value exists */
7711     sz = MAX_PATH;
7712     lstrcpyA(buf, "apple");
7713     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
7714     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7715     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7716     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7717 
7718     res = RegSetValueExA(prodkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
7719     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7720 
7721     /* Publisher value exists */
7722     sz = MAX_PATH;
7723     lstrcpyA(buf, "apple");
7724     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_PUBLISHERA, buf, &sz);
7725     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7726     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7727     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7728 
7729     res = RegSetValueExA(prodkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
7730     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7731 
7732     /* URLInfoAbout value exists */
7733     sz = MAX_PATH;
7734     lstrcpyA(buf, "apple");
7735     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
7736     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7737     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7738     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7739 
7740     res = RegSetValueExA(prodkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
7741     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7742 
7743     /* URLUpdateInfo value exists */
7744     sz = MAX_PATH;
7745     lstrcpyA(buf, "apple");
7746     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
7747     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7748     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7749     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7750 
7751     res = RegSetValueExA(prodkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
7752     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7753 
7754     /* VersionMinor value exists */
7755     sz = MAX_PATH;
7756     lstrcpyA(buf, "apple");
7757     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
7758     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7759     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7760     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7761 
7762     res = RegSetValueExA(prodkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
7763     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7764 
7765     /* VersionMajor value exists */
7766     sz = MAX_PATH;
7767     lstrcpyA(buf, "apple");
7768     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
7769     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7770     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7771     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7772 
7773     res = RegSetValueExA(prodkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
7774     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7775 
7776     /* DisplayVersion value exists */
7777     sz = MAX_PATH;
7778     lstrcpyA(buf, "apple");
7779     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
7780     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7781     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7782     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7783 
7784     res = RegSetValueExA(prodkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
7785     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7786 
7787     /* ProductID value exists */
7788     sz = MAX_PATH;
7789     lstrcpyA(buf, "apple");
7790     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
7791     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7792     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7793     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7794 
7795     res = RegSetValueExA(prodkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
7796     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7797 
7798     /* RegCompany value exists */
7799     sz = MAX_PATH;
7800     lstrcpyA(buf, "apple");
7801     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
7802     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7803     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7804     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7805 
7806     res = RegSetValueExA(prodkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
7807     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7808 
7809     /* RegOwner value exists */
7810     sz = MAX_PATH;
7811     lstrcpyA(buf, "apple");
7812     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_REGOWNERA, buf, &sz);
7813     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7814     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7815     ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7816 
7817     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
7818     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7819 
7820     /* Transforms value exists */
7821     sz = MAX_PATH;
7822     lstrcpyA(buf, "apple");
7823     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
7824     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7825     ok(!lstrcmpA(buf, "trans"), "Expected \"trans\", got \"%s\"\n", buf);
7826     ok(sz == 5, "Expected 5, got %lu\n", sz);
7827 
7828     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
7829     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7830 
7831     /* Language value exists */
7832     sz = MAX_PATH;
7833     lstrcpyA(buf, "apple");
7834     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
7835     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7836     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
7837     ok(sz == 4, "Expected 4, got %lu\n", sz);
7838 
7839     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
7840     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7841 
7842     /* ProductName value exists */
7843     sz = MAX_PATH;
7844     lstrcpyA(buf, "apple");
7845     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
7846     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7847     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
7848     ok(sz == 4, "Expected 4, got %lu\n", sz);
7849 
7850     res = RegSetValueExA(prodkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
7851     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7852 
7853     /* FIXME */
7854 
7855     /* AssignmentType value exists */
7856     sz = MAX_PATH;
7857     lstrcpyA(buf, "apple");
7858     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
7859     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7860     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7861     ok(sz == 0, "Expected 0, got %lu\n", sz);
7862 
7863     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
7864     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7865 
7866     /* FIXME */
7867 
7868     /* PackageCode value exists */
7869     sz = MAX_PATH;
7870     lstrcpyA(buf, "apple");
7871     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
7872     todo_wine
7873     {
7874         ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
7875         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7876         ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7877     }
7878 
7879     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
7880     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7881 
7882     /* Version value exists */
7883     sz = MAX_PATH;
7884     lstrcpyA(buf, "apple");
7885     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_VERSIONA, buf, &sz);
7886     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7887     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
7888     ok(sz == 3, "Expected 3, got %lu\n", sz);
7889 
7890     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
7891     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7892 
7893     /* ProductIcon value exists */
7894     sz = MAX_PATH;
7895     lstrcpyA(buf, "apple");
7896     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
7897     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7898     ok(!lstrcmpA(buf, "icon"), "Expected \"icon\", got \"%s\"\n", buf);
7899     ok(sz == 4, "Expected 4, got %lu\n", sz);
7900 
7901     res = RegSetValueExA(prodkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
7902     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7903 
7904     /* PackageName value exists */
7905     sz = MAX_PATH;
7906     lstrcpyA(buf, "apple");
7907     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
7908     todo_wine
7909     {
7910         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7911         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7912         ok(sz == MAX_PATH, "Expected MAX_PATH, got %lu\n", sz);
7913     }
7914 
7915     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
7916     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7917 
7918     /* AuthorizedLUAApp value exists */
7919     sz = MAX_PATH;
7920     lstrcpyA(buf, "apple");
7921     r = MsiGetProductInfoExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_AUTHORIZED_LUA_APPA,
7922                              buf, &sz);
7923     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7924     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
7925     ok(sz == 4, "Expected 4, got %lu\n", sz);
7926 
7927     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
7928     RegDeleteValueA(prodkey, "PackageName");
7929     RegDeleteValueA(prodkey, "ProductIcon");
7930     RegDeleteValueA(prodkey, "Version");
7931     RegDeleteValueA(prodkey, "PackageCode");
7932     RegDeleteValueA(prodkey, "AssignmentType");
7933     RegDeleteValueA(prodkey, "ProductName");
7934     RegDeleteValueA(prodkey, "Language");
7935     RegDeleteValueA(prodkey, "Transforms");
7936     RegDeleteValueA(prodkey, "RegOwner");
7937     RegDeleteValueA(prodkey, "RegCompany");
7938     RegDeleteValueA(prodkey, "ProductID");
7939     RegDeleteValueA(prodkey, "DisplayVersion");
7940     RegDeleteValueA(prodkey, "VersionMajor");
7941     RegDeleteValueA(prodkey, "VersionMinor");
7942     RegDeleteValueA(prodkey, "URLUpdateInfo");
7943     RegDeleteValueA(prodkey, "URLInfoAbout");
7944     RegDeleteValueA(prodkey, "Publisher");
7945     RegDeleteValueA(prodkey, "LocalPackage");
7946     RegDeleteValueA(prodkey, "InstallSource");
7947     RegDeleteValueA(prodkey, "InstallLocation");
7948     RegDeleteValueA(prodkey, "DisplayName");
7949     RegDeleteValueA(prodkey, "InstallDate");
7950     RegDeleteValueA(prodkey, "HelpTelephone");
7951     RegDeleteValueA(prodkey, "HelpLink");
7952     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
7953     RegCloseKey(prodkey);
7954     LocalFree(usersid);
7955 }
7956 
7957 #define INIT_USERINFO() \
7958     lstrcpyA(user, "apple"); \
7959     lstrcpyA(org, "orange"); \
7960     lstrcpyA(serial, "banana"); \
7961     usersz = orgsz = serialsz = MAX_PATH;
7962 
test_MsiGetUserInfo(void)7963 static void test_MsiGetUserInfo(void)
7964 {
7965     USERINFOSTATE state;
7966     CHAR user[MAX_PATH];
7967     CHAR org[MAX_PATH];
7968     CHAR serial[MAX_PATH];
7969     DWORD usersz, orgsz, serialsz;
7970     CHAR keypath[MAX_PATH * 2];
7971     CHAR prodcode[MAX_PATH];
7972     CHAR prod_squashed[MAX_PATH];
7973     HKEY prodkey, userprod, props;
7974     LPSTR usersid;
7975     LONG res;
7976     REGSAM access = KEY_ALL_ACCESS;
7977 
7978     create_test_guid(prodcode, prod_squashed);
7979     usersid = get_user_sid();
7980 
7981     if (is_wow64)
7982         access |= KEY_WOW64_64KEY;
7983 
7984     /* NULL szProduct */
7985     INIT_USERINFO();
7986     state = MsiGetUserInfoA(NULL, user, &usersz, org, &orgsz, serial, &serialsz);
7987     ok(state == USERINFOSTATE_INVALIDARG,
7988        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
7989     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
7990     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
7991     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7992     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
7993     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
7994     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
7995 
7996     /* empty szProductCode */
7997     INIT_USERINFO();
7998     state = MsiGetUserInfoA("", user, &usersz, org, &orgsz, serial, &serialsz);
7999     ok(state == USERINFOSTATE_INVALIDARG,
8000        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8001     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8002     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8003     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8004     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8005     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8006     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8007 
8008     /* garbage szProductCode */
8009     INIT_USERINFO();
8010     state = MsiGetUserInfoA("garbage", user, &usersz, org, &orgsz, serial, &serialsz);
8011     ok(state == USERINFOSTATE_INVALIDARG,
8012        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8013     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8014     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8015     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8016     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8017     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8018     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8019 
8020     /* guid without brackets */
8021     INIT_USERINFO();
8022     state = MsiGetUserInfoA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
8023                             user, &usersz, org, &orgsz, serial, &serialsz);
8024     ok(state == USERINFOSTATE_INVALIDARG,
8025        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8026     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8027     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8028     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8029     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8030     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8031     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8032 
8033     /* guid with brackets */
8034     INIT_USERINFO();
8035     state = MsiGetUserInfoA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
8036                             user, &usersz, org, &orgsz, serial, &serialsz);
8037     ok(state == USERINFOSTATE_UNKNOWN,
8038        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8039     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8040     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8041     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8042     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8043     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8044     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8045 
8046     /* NULL lpUserNameBuf */
8047     INIT_USERINFO();
8048     state = MsiGetUserInfoA(prodcode, NULL, &usersz, org, &orgsz, serial, &serialsz);
8049     ok(state == USERINFOSTATE_UNKNOWN,
8050        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8051     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8052     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8053     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8054     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8055     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8056 
8057     /* NULL pcchUserNameBuf */
8058     INIT_USERINFO();
8059     state = MsiGetUserInfoA(prodcode, user, NULL, org, &orgsz, serial, &serialsz);
8060     ok(state == USERINFOSTATE_INVALIDARG,
8061        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8062     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8063     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8064     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8065     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8066     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8067 
8068     /* both lpUserNameBuf and pcchUserNameBuf NULL */
8069     INIT_USERINFO();
8070     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
8071     ok(state == USERINFOSTATE_UNKNOWN,
8072        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8073     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8074     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8075     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8076     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8077 
8078     /* NULL lpOrgNameBuf */
8079     INIT_USERINFO();
8080     state = MsiGetUserInfoA(prodcode, user, &usersz, NULL, &orgsz, serial, &serialsz);
8081     ok(state == USERINFOSTATE_UNKNOWN,
8082        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8083     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8084     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8085     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8086     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8087     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8088 
8089     /* NULL pcchOrgNameBuf */
8090     INIT_USERINFO();
8091     state = MsiGetUserInfoA(prodcode, user, &usersz, org, NULL, serial, &serialsz);
8092     ok(state == USERINFOSTATE_INVALIDARG,
8093        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8094     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8095     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8096     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8097     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8098     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8099 
8100     /* both lpOrgNameBuf and pcchOrgNameBuf NULL */
8101     INIT_USERINFO();
8102     state = MsiGetUserInfoA(prodcode, user, &usersz, NULL, NULL, serial, &serialsz);
8103     ok(state == USERINFOSTATE_UNKNOWN,
8104        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8105     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8106     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8107     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8108     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8109 
8110     /* NULL lpSerialBuf */
8111     INIT_USERINFO();
8112     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, NULL, &serialsz);
8113     ok(state == USERINFOSTATE_UNKNOWN,
8114        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8115     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8116     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8117     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8118     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8119     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8120 
8121     /* NULL pcchSerialBuf */
8122     INIT_USERINFO();
8123     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, NULL);
8124     ok(state == USERINFOSTATE_INVALIDARG,
8125        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8126     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8127     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8128     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8129     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8130     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8131 
8132     /* both lpSerialBuf and pcchSerialBuf NULL */
8133     INIT_USERINFO();
8134     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, NULL, NULL);
8135     ok(state == USERINFOSTATE_UNKNOWN,
8136        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8137     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8138     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8139     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8140     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8141 
8142     /* MSIINSTALLCONTEXT_USERMANAGED */
8143 
8144     /* create local system product key */
8145     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
8146     lstrcatA(keypath, usersid);
8147     lstrcatA(keypath, "\\Installer\\Products\\");
8148     lstrcatA(keypath, prod_squashed);
8149 
8150     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8151     if (res == ERROR_ACCESS_DENIED)
8152     {
8153         skip("Not enough rights to perform tests\n");
8154         LocalFree(usersid);
8155         return;
8156     }
8157     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8158 
8159     /* managed product key exists */
8160     INIT_USERINFO();
8161     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8162     ok(state == USERINFOSTATE_ABSENT,
8163        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8164     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8165     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8166     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8167     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8168     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8169     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8170 
8171     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8172     lstrcatA(keypath, "Installer\\UserData\\");
8173     lstrcatA(keypath, usersid);
8174     lstrcatA(keypath, "\\Products\\");
8175     lstrcatA(keypath, prod_squashed);
8176 
8177     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL);
8178     if (res == ERROR_ACCESS_DENIED)
8179     {
8180         skip("Not enough rights to perform tests\n");
8181         LocalFree(usersid);
8182         return;
8183     }
8184     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8185 
8186     res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8187     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8188 
8189     /* InstallProperties key exists */
8190     INIT_USERINFO();
8191     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8192     ok(state == USERINFOSTATE_ABSENT,
8193        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8194     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8195     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8196     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8197     ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", usersz);
8198     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8199     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8200 
8201     /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */
8202     INIT_USERINFO();
8203     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
8204     ok(state == USERINFOSTATE_ABSENT,
8205        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8206     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
8207     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8208     ok(orgsz == 0, "Expected 0, got %lu\n", orgsz);
8209     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", serialsz);
8210 
8211     /* RegOwner, RegCompany don't exist, out params are NULL */
8212     INIT_USERINFO();
8213     state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz);
8214     ok(state == USERINFOSTATE_ABSENT,
8215        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8216     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8217     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", serialsz);
8218 
8219     res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
8220     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8221 
8222     /* RegOwner value exists */
8223     INIT_USERINFO();
8224     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8225     ok(state == USERINFOSTATE_ABSENT,
8226        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8227     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8228     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
8229     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8230     ok(usersz == 5, "Expected 5, got %lu\n", usersz);
8231     ok(orgsz == 0, "Expected 0, got %lu\n", orgsz);
8232     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", serialsz);
8233 
8234     res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8);
8235     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8236 
8237     /* RegCompany value exists */
8238     INIT_USERINFO();
8239     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8240     ok(state == USERINFOSTATE_ABSENT,
8241        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8242     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8243     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8244     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8245     ok(usersz == 5, "Expected 5, got %lu\n", usersz);
8246     ok(orgsz == 7, "Expected 7, got %lu\n", orgsz);
8247     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", serialsz);
8248 
8249     res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3);
8250     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8251 
8252     /* ProductID value exists */
8253     INIT_USERINFO();
8254     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8255     ok(state == USERINFOSTATE_PRESENT,
8256        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
8257     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8258     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8259     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
8260     ok(usersz == 5, "Expected 5, got %lu\n", usersz);
8261     ok(orgsz == 7, "Expected 7, got %lu\n", orgsz);
8262     ok(serialsz == 2, "Expected 2, got %lu\n", serialsz);
8263 
8264     /* pcchUserNameBuf is too small */
8265     INIT_USERINFO();
8266     usersz = 0;
8267     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8268     ok(state == USERINFOSTATE_MOREDATA,
8269        "Expected USERINFOSTATE_MOREDATA, got %d\n", state);
8270     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8271     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8272     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8273     ok(usersz == 5, "Expected 5, got %lu\n", usersz);
8274     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8275     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8276 
8277     /* pcchUserNameBuf has no room for NULL terminator */
8278     INIT_USERINFO();
8279     usersz = 5;
8280     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8281     ok(state == USERINFOSTATE_MOREDATA,
8282        "Expected USERINFOSTATE_MOREDATA, got %d\n", state);
8283     todo_wine
8284     {
8285         ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8286     }
8287     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8288     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8289     ok(usersz == 5, "Expected 5, got %lu\n", usersz);
8290     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8291     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8292 
8293     /* pcchUserNameBuf is too small, lpUserNameBuf is NULL */
8294     INIT_USERINFO();
8295     usersz = 0;
8296     state = MsiGetUserInfoA(prodcode, NULL, &usersz, org, &orgsz, serial, &serialsz);
8297     ok(state == USERINFOSTATE_PRESENT,
8298        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
8299     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8300     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8301     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
8302     ok(usersz == 5, "Expected 5, got %lu\n", usersz);
8303     ok(orgsz == 7, "Expected 7, got %lu\n", orgsz);
8304     ok(serialsz == 2, "Expected 2, got %lu\n", serialsz);
8305 
8306     RegDeleteValueA(props, "ProductID");
8307     RegDeleteValueA(props, "RegCompany");
8308     RegDeleteValueA(props, "RegOwner");
8309     RegDeleteKeyExA(props, "", access & KEY_WOW64_64KEY, 0);
8310     RegCloseKey(props);
8311     RegDeleteKeyExA(userprod, "", access & KEY_WOW64_64KEY, 0);
8312     RegCloseKey(userprod);
8313     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
8314     RegCloseKey(prodkey);
8315 
8316     /* MSIINSTALLCONTEXT_USERUNMANAGED */
8317 
8318     /* create local system product key */
8319     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
8320     lstrcatA(keypath, prod_squashed);
8321 
8322     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
8323     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8324 
8325     /* product key exists */
8326     INIT_USERINFO();
8327     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8328     ok(state == USERINFOSTATE_ABSENT,
8329        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8330     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8331     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8332     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8333     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8334     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8335     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8336 
8337     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8338     lstrcatA(keypath, "Installer\\UserData\\");
8339     lstrcatA(keypath, usersid);
8340     lstrcatA(keypath, "\\Products\\");
8341     lstrcatA(keypath, prod_squashed);
8342 
8343     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL);
8344     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8345 
8346     res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8347     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8348 
8349     /* InstallProperties key exists */
8350     INIT_USERINFO();
8351     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8352     ok(state == USERINFOSTATE_ABSENT,
8353        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8354     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8355     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8356     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8357     ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", usersz);
8358     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8359     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8360 
8361     /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */
8362     INIT_USERINFO();
8363     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
8364     ok(state == USERINFOSTATE_ABSENT,
8365        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8366     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
8367     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8368     ok(orgsz == 0, "Expected 0, got %lu\n", orgsz);
8369     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", serialsz);
8370 
8371     /* RegOwner, RegCompany don't exist, out params are NULL */
8372     INIT_USERINFO();
8373     state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz);
8374     ok(state == USERINFOSTATE_ABSENT,
8375        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8376     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8377     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", serialsz);
8378 
8379     res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
8380     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8381 
8382     /* RegOwner value exists */
8383     INIT_USERINFO();
8384     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8385     ok(state == USERINFOSTATE_ABSENT,
8386        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8387     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8388     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
8389     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8390     ok(usersz == 5, "Expected 5, got %lu\n", usersz);
8391     ok(orgsz == 0, "Expected 0, got %lu\n", orgsz);
8392     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", serialsz);
8393 
8394     res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8);
8395     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8396 
8397     /* RegCompany value exists */
8398     INIT_USERINFO();
8399     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8400     ok(state == USERINFOSTATE_ABSENT,
8401        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8402     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8403     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8404     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8405     ok(usersz == 5, "Expected 5, got %lu\n", usersz);
8406     ok(orgsz == 7, "Expected 7, got %lu\n", orgsz);
8407     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", serialsz);
8408 
8409     res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3);
8410     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8411 
8412     /* ProductID value exists */
8413     INIT_USERINFO();
8414     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8415     ok(state == USERINFOSTATE_PRESENT,
8416        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
8417     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8418     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8419     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
8420     ok(usersz == 5, "Expected 5, got %lu\n", usersz);
8421     ok(orgsz == 7, "Expected 7, got %lu\n", orgsz);
8422     ok(serialsz == 2, "Expected 2, got %lu\n", serialsz);
8423 
8424     RegDeleteValueA(props, "ProductID");
8425     RegDeleteValueA(props, "RegCompany");
8426     RegDeleteValueA(props, "RegOwner");
8427     RegDeleteKeyExA(props, "", access & KEY_WOW64_64KEY, 0);
8428     RegCloseKey(props);
8429     RegDeleteKeyExA(userprod, "", access & KEY_WOW64_64KEY, 0);
8430     RegCloseKey(userprod);
8431     RegDeleteKeyA(prodkey, "");
8432     RegCloseKey(prodkey);
8433 
8434     /* MSIINSTALLCONTEXT_MACHINE */
8435 
8436     /* create local system product key */
8437     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
8438     lstrcatA(keypath, prod_squashed);
8439 
8440     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8441     if (res == ERROR_ACCESS_DENIED)
8442     {
8443         skip( "insufficient rights\n" );
8444         LocalFree( usersid );
8445         return;
8446     }
8447     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8448 
8449     /* product key exists */
8450     INIT_USERINFO();
8451     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8452     ok(state == USERINFOSTATE_ABSENT,
8453        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8454     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8455     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8456     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8457     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %lu\n", usersz);
8458     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8459     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8460 
8461     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8462     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18");
8463     lstrcatA(keypath, "\\Products\\");
8464     lstrcatA(keypath, prod_squashed);
8465 
8466     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL);
8467     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8468 
8469     res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8470     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8471 
8472     /* InstallProperties key exists */
8473     INIT_USERINFO();
8474     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8475     ok(state == USERINFOSTATE_ABSENT,
8476        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8477     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8478     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8479     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8480     ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", usersz);
8481     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", orgsz);
8482     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %lu\n", serialsz);
8483 
8484     /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */
8485     INIT_USERINFO();
8486     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
8487     ok(state == USERINFOSTATE_ABSENT,
8488        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8489     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
8490     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8491     ok(orgsz == 0, "Expected 0, got %lu\n", orgsz);
8492     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", serialsz);
8493 
8494     /* RegOwner, RegCompany don't exist, out params are NULL */
8495     INIT_USERINFO();
8496     state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz);
8497     ok(state == USERINFOSTATE_ABSENT,
8498        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8499     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8500     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", serialsz);
8501 
8502     res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
8503     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8504 
8505     /* RegOwner value exists */
8506     INIT_USERINFO();
8507     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8508     ok(state == USERINFOSTATE_ABSENT,
8509        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8510     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8511     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
8512     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8513     ok(usersz == 5, "Expected 5, got %lu\n", usersz);
8514     ok(orgsz == 0, "Expected 0, got %lu\n", orgsz);
8515     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", serialsz);
8516 
8517     res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8);
8518     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8519 
8520     /* RegCompany value exists */
8521     INIT_USERINFO();
8522     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8523     ok(state == USERINFOSTATE_ABSENT,
8524        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8525     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8526     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8527     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8528     ok(usersz == 5, "Expected 5, got %lu\n", usersz);
8529     ok(orgsz == 7, "Expected 7, got %lu\n", orgsz);
8530     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %lu\n", serialsz);
8531 
8532     res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3);
8533     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8534 
8535     /* ProductID value exists */
8536     INIT_USERINFO();
8537     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8538     ok(state == USERINFOSTATE_PRESENT,
8539        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
8540     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8541     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8542     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
8543     ok(usersz == 5, "Expected 5, got %lu\n", usersz);
8544     ok(orgsz == 7, "Expected 7, got %lu\n", orgsz);
8545     ok(serialsz == 2, "Expected 2, got %lu\n", serialsz);
8546 
8547     RegDeleteValueA(props, "ProductID");
8548     RegDeleteValueA(props, "RegCompany");
8549     RegDeleteValueA(props, "RegOwner");
8550     RegDeleteKeyExA(props, "", access & KEY_WOW64_64KEY, 0);
8551     RegCloseKey(props);
8552     RegDeleteKeyExA(userprod, "", access & KEY_WOW64_64KEY, 0);
8553     RegCloseKey(userprod);
8554     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
8555     RegCloseKey(prodkey);
8556     LocalFree(usersid);
8557 }
8558 
test_MsiOpenProduct(void)8559 static void test_MsiOpenProduct(void)
8560 {
8561     MSIHANDLE hprod, hdb;
8562     CHAR val[MAX_PATH];
8563     CHAR path[MAX_PATH];
8564     CHAR keypath[MAX_PATH*2];
8565     CHAR prodcode[MAX_PATH];
8566     CHAR prod_squashed[MAX_PATH];
8567     HKEY prodkey, userkey, props;
8568     LPSTR usersid;
8569     DWORD size;
8570     LONG res;
8571     UINT r;
8572     REGSAM access = KEY_ALL_ACCESS;
8573 
8574     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
8575 
8576     GetCurrentDirectoryA(MAX_PATH, path);
8577     lstrcatA(path, "\\");
8578 
8579     create_test_guid(prodcode, prod_squashed);
8580     usersid = get_user_sid();
8581 
8582     if (is_wow64)
8583         access |= KEY_WOW64_64KEY;
8584 
8585     hdb = create_package_db(prodcode);
8586     MsiCloseHandle(hdb);
8587 
8588     /* NULL szProduct */
8589     hprod = 0xdeadbeef;
8590     r = MsiOpenProductA(NULL, &hprod);
8591     ok(r == ERROR_INVALID_PARAMETER,
8592        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8593     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8594 
8595     /* empty szProduct */
8596     hprod = 0xdeadbeef;
8597     r = MsiOpenProductA("", &hprod);
8598     ok(r == ERROR_INVALID_PARAMETER,
8599        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8600     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8601 
8602     /* garbage szProduct */
8603     hprod = 0xdeadbeef;
8604     r = MsiOpenProductA("garbage", &hprod);
8605     ok(r == ERROR_INVALID_PARAMETER,
8606        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8607     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8608 
8609     /* guid without brackets */
8610     hprod = 0xdeadbeef;
8611     r = MsiOpenProductA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", &hprod);
8612     ok(r == ERROR_INVALID_PARAMETER,
8613        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8614     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8615 
8616     /* guid with brackets */
8617     hprod = 0xdeadbeef;
8618     r = MsiOpenProductA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", &hprod);
8619     ok(r == ERROR_UNKNOWN_PRODUCT,
8620        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8621     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8622 
8623     /* same length as guid, but random */
8624     hprod = 0xdeadbeef;
8625     r = MsiOpenProductA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", &hprod);
8626     ok(r == ERROR_INVALID_PARAMETER,
8627        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8628     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8629 
8630     /* hProduct is NULL */
8631     hprod = 0xdeadbeef;
8632     r = MsiOpenProductA(prodcode, NULL);
8633     ok(r == ERROR_INVALID_PARAMETER,
8634        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8635     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8636 
8637     /* MSIINSTALLCONTEXT_USERMANAGED */
8638 
8639     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8640     lstrcatA(keypath, "Installer\\Managed\\");
8641     lstrcatA(keypath, usersid);
8642     lstrcatA(keypath, "\\Installer\\Products\\");
8643     lstrcatA(keypath, prod_squashed);
8644 
8645     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8646     if (res == ERROR_ACCESS_DENIED)
8647     {
8648         skip("Not enough rights to perform tests\n");
8649         LocalFree(usersid);
8650         return;
8651     }
8652     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8653 
8654     /* managed product key exists */
8655     hprod = 0xdeadbeef;
8656     r = MsiOpenProductA(prodcode, &hprod);
8657     ok(r == ERROR_UNKNOWN_PRODUCT,
8658        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8659     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8660 
8661     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8662     lstrcatA(keypath, "Installer\\UserData\\");
8663     lstrcatA(keypath, usersid);
8664     lstrcatA(keypath, "\\Products\\");
8665     lstrcatA(keypath, prod_squashed);
8666 
8667     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
8668     if (res == ERROR_ACCESS_DENIED)
8669     {
8670         skip("Not enough rights to perform tests\n");
8671         LocalFree(usersid);
8672         return;
8673     }
8674     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8675 
8676     /* user product key exists */
8677     hprod = 0xdeadbeef;
8678     r = MsiOpenProductA(prodcode, &hprod);
8679     ok(r == ERROR_UNKNOWN_PRODUCT,
8680        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8681     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8682 
8683     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8684     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8685 
8686     /* InstallProperties key exists */
8687     hprod = 0xdeadbeef;
8688     r = MsiOpenProductA(prodcode, &hprod);
8689     ok(r == ERROR_UNKNOWN_PRODUCT,
8690        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8691     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8692 
8693     lstrcpyA(val, path);
8694     lstrcatA(val, "\\winetest.msi");
8695     res = RegSetValueExA(props, "ManagedLocalPackage", 0, REG_SZ,
8696                          (const BYTE *)val, lstrlenA(val) + 1);
8697     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8698 
8699     /* ManagedLocalPackage value exists */
8700     hprod = 0xdeadbeef;
8701     r = MsiOpenProductA(prodcode, &hprod);
8702     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8703     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
8704 
8705     size = MAX_PATH;
8706     r = MsiGetPropertyA(hprod, "ProductCode", val, &size);
8707     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8708     ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val);
8709     ok(size == lstrlenA(prodcode), "Expected %d, got %lu\n", lstrlenA(prodcode), size);
8710 
8711     MsiCloseHandle(hprod);
8712 
8713     RegDeleteValueA(props, "ManagedLocalPackage");
8714     RegDeleteKeyExA(props, "", access & KEY_WOW64_64KEY, 0);
8715     RegCloseKey(props);
8716     RegDeleteKeyExA(userkey, "", access & KEY_WOW64_64KEY, 0);
8717     RegCloseKey(userkey);
8718     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
8719     RegCloseKey(prodkey);
8720 
8721     /* MSIINSTALLCONTEXT_USERUNMANAGED */
8722 
8723     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
8724     lstrcatA(keypath, prod_squashed);
8725 
8726     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
8727     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8728 
8729     /* unmanaged product key exists */
8730     hprod = 0xdeadbeef;
8731     r = MsiOpenProductA(prodcode, &hprod);
8732     ok(r == ERROR_UNKNOWN_PRODUCT,
8733        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8734     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8735 
8736     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8737     lstrcatA(keypath, "Installer\\UserData\\");
8738     lstrcatA(keypath, usersid);
8739     lstrcatA(keypath, "\\Products\\");
8740     lstrcatA(keypath, prod_squashed);
8741 
8742     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
8743     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8744 
8745     /* user product key exists */
8746     hprod = 0xdeadbeef;
8747     r = MsiOpenProductA(prodcode, &hprod);
8748     ok(r == ERROR_UNKNOWN_PRODUCT,
8749        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8750     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8751 
8752     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8753     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8754 
8755     /* InstallProperties key exists */
8756     hprod = 0xdeadbeef;
8757     r = MsiOpenProductA(prodcode, &hprod);
8758     ok(r == ERROR_UNKNOWN_PRODUCT,
8759        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8760     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8761 
8762     lstrcpyA(val, path);
8763     lstrcatA(val, "\\winetest.msi");
8764     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
8765                          (const BYTE *)val, lstrlenA(val) + 1);
8766     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8767 
8768     /* LocalPackage value exists */
8769     hprod = 0xdeadbeef;
8770     r = MsiOpenProductA(prodcode, &hprod);
8771     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8772     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
8773 
8774     size = MAX_PATH;
8775     r = MsiGetPropertyA(hprod, "ProductCode", val, &size);
8776     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8777     ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val);
8778     ok(size == lstrlenA(prodcode), "Expected %d, got %lu\n", lstrlenA(prodcode), size);
8779 
8780     MsiCloseHandle(hprod);
8781 
8782     RegDeleteValueA(props, "LocalPackage");
8783     RegDeleteKeyExA(props, "", access & KEY_WOW64_64KEY, 0);
8784     RegCloseKey(props);
8785     RegDeleteKeyExA(userkey, "", access & KEY_WOW64_64KEY, 0);
8786     RegCloseKey(userkey);
8787     RegDeleteKeyA(prodkey, "");
8788     RegCloseKey(prodkey);
8789 
8790     /* MSIINSTALLCONTEXT_MACHINE */
8791 
8792     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
8793     lstrcatA(keypath, prod_squashed);
8794 
8795     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8796     if (res == ERROR_ACCESS_DENIED)
8797     {
8798         skip( "insufficient rights\n" );
8799         LocalFree( usersid );
8800         return;
8801     }
8802     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8803 
8804     /* managed product key exists */
8805     hprod = 0xdeadbeef;
8806     r = MsiOpenProductA(prodcode, &hprod);
8807     ok(r == ERROR_UNKNOWN_PRODUCT,
8808        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8809     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8810 
8811     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8812     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
8813     lstrcatA(keypath, prod_squashed);
8814 
8815     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
8816     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8817 
8818     /* user product key exists */
8819     hprod = 0xdeadbeef;
8820     r = MsiOpenProductA(prodcode, &hprod);
8821     ok(r == ERROR_UNKNOWN_PRODUCT,
8822        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8823     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8824 
8825     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8826     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8827 
8828     /* InstallProperties key exists */
8829     hprod = 0xdeadbeef;
8830     r = MsiOpenProductA(prodcode, &hprod);
8831     ok(r == ERROR_UNKNOWN_PRODUCT,
8832        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8833     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8834 
8835     lstrcpyA(val, path);
8836     lstrcatA(val, "\\winetest.msi");
8837     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
8838                          (const BYTE *)val, lstrlenA(val) + 1);
8839     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8840 
8841     /* LocalPackage value exists */
8842     hprod = 0xdeadbeef;
8843     r = MsiOpenProductA(prodcode, &hprod);
8844     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8845     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
8846 
8847     size = MAX_PATH;
8848     r = MsiGetPropertyA(hprod, "ProductCode", val, &size);
8849     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8850     ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val);
8851     ok(size == lstrlenA(prodcode), "Expected %d, got %lu\n", lstrlenA(prodcode), size);
8852 
8853     MsiCloseHandle(hprod);
8854 
8855     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
8856                          (const BYTE *)"winetest.msi", 13);
8857     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8858 
8859     lstrcpyA(val, path);
8860     lstrcatA(val, "\\winetest.msi");
8861     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
8862                          (const BYTE *)val, lstrlenA(val) + 1);
8863     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8864 
8865     DeleteFileA(msifile);
8866 
8867     /* local package does not exist */
8868     hprod = 0xdeadbeef;
8869     r = MsiOpenProductA(prodcode, &hprod);
8870     ok(r == ERROR_UNKNOWN_PRODUCT,
8871        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8872     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8873 
8874     RegDeleteValueA(props, "LocalPackage");
8875     RegDeleteKeyExA(props, "", access & KEY_WOW64_64KEY, 0);
8876     RegCloseKey(props);
8877     RegDeleteKeyExA(userkey, "", access & KEY_WOW64_64KEY, 0);
8878     RegCloseKey(userkey);
8879     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
8880     RegCloseKey(prodkey);
8881 
8882     DeleteFileA(msifile);
8883     LocalFree(usersid);
8884 }
8885 
test_MsiEnumPatchesEx_usermanaged(LPCSTR usersid,LPCSTR expectedsid)8886 static void test_MsiEnumPatchesEx_usermanaged(LPCSTR usersid, LPCSTR expectedsid)
8887 {
8888     MSIINSTALLCONTEXT context;
8889     CHAR keypath[MAX_PATH], patch[MAX_PATH];
8890     CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
8891     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
8892     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
8893     HKEY prodkey, patches, udprod, udpatch, hpatch;
8894     DWORD size, data;
8895     LONG res;
8896     UINT r;
8897     REGSAM access = KEY_ALL_ACCESS;
8898 
8899     create_test_guid(prodcode, prod_squashed);
8900     create_test_guid(patch, patch_squashed);
8901 
8902     if (is_wow64)
8903         access |= KEY_WOW64_64KEY;
8904 
8905     /* MSIPATCHSTATE_APPLIED */
8906 
8907     lstrcpyA(patchcode, "apple");
8908     lstrcpyA(targetprod, "banana");
8909     context = 0xdeadbeef;
8910     lstrcpyA(targetsid, "kiwi");
8911     size = MAX_PATH;
8912     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8913                           MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
8914                           &context, targetsid, &size);
8915     if (r == ERROR_ACCESS_DENIED)
8916     {
8917         skip("Not enough rights to perform tests\n");
8918         return;
8919     }
8920     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8921     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
8922     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
8923     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
8924     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
8925     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
8926 
8927     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
8928     lstrcatA(keypath, expectedsid);
8929     lstrcatA(keypath, "\\Installer\\Products\\");
8930     lstrcatA(keypath, prod_squashed);
8931 
8932     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8933     if (res == ERROR_ACCESS_DENIED)
8934     {
8935         skip("Not enough rights to perform tests\n");
8936         return;
8937     }
8938     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8939 
8940     /* managed product key exists */
8941     lstrcpyA(patchcode, "apple");
8942     lstrcpyA(targetprod, "banana");
8943     context = 0xdeadbeef;
8944     lstrcpyA(targetsid, "kiwi");
8945     size = MAX_PATH;
8946     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_APPLIED,
8947                           0, patchcode, targetprod, &context, targetsid, &size);
8948     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8949     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
8950     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
8951     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
8952     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
8953     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
8954 
8955     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
8956     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8957 
8958     /* patches key exists */
8959     lstrcpyA(patchcode, "apple");
8960     lstrcpyA(targetprod, "banana");
8961     context = 0xdeadbeef;
8962     lstrcpyA(targetsid, "kiwi");
8963     size = MAX_PATH;
8964     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_APPLIED,
8965                           0, patchcode, targetprod, &context, targetsid, &size);
8966     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8967     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
8968     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
8969     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
8970     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
8971     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
8972 
8973     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
8974                          (const BYTE *)patch_squashed,
8975                          lstrlenA(patch_squashed) + 1);
8976     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8977 
8978     /* Patches value exists, is not REG_MULTI_SZ */
8979     lstrcpyA(patchcode, "apple");
8980     lstrcpyA(targetprod, "banana");
8981     context = 0xdeadbeef;
8982     lstrcpyA(targetsid, "kiwi");
8983     size = MAX_PATH;
8984     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_APPLIED,
8985                           0, patchcode, targetprod, &context, targetsid, &size);
8986     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
8987     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
8988     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
8989     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
8990     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
8991     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
8992 
8993     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
8994                          (const BYTE *)"a\0b\0c\0\0", 7);
8995     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8996 
8997     /* Patches value exists, is not a squashed guid */
8998     lstrcpyA(patchcode, "apple");
8999     lstrcpyA(targetprod, "banana");
9000     context = 0xdeadbeef;
9001     lstrcpyA(targetsid, "kiwi");
9002     size = MAX_PATH;
9003     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_APPLIED,
9004                           0, patchcode, targetprod, &context, targetsid, &size);
9005     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9006     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9007     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9008     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9009     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9010     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9011 
9012     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
9013     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
9014                          (const BYTE *)patch_squashed,
9015                          lstrlenA(patch_squashed) + 2);
9016     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9017 
9018     /* Patches value exists */
9019     lstrcpyA(patchcode, "apple");
9020     lstrcpyA(targetprod, "banana");
9021     context = 0xdeadbeef;
9022     lstrcpyA(targetsid, "kiwi");
9023     size = MAX_PATH;
9024     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_APPLIED,
9025                           0, patchcode, targetprod, &context, targetsid, &size);
9026     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9027     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9028     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9029     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9030     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9031     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9032 
9033     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
9034                          (const BYTE *)"whatever", 9);
9035     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9036 
9037     /* patch squashed value exists */
9038     lstrcpyA(patchcode, "apple");
9039     lstrcpyA(targetprod, "banana");
9040     context = 0xdeadbeef;
9041     lstrcpyA(targetsid, "kiwi");
9042     size = MAX_PATH;
9043     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_APPLIED,
9044                           0, patchcode, targetprod, &context, targetsid, &size);
9045     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9046     ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9047     ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9048     ok(context == MSIINSTALLCONTEXT_USERMANAGED, "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9049     ok(!lstrcmpA(targetsid, expectedsid), "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9050     ok(size == lstrlenA(expectedsid), "Expected %d, got %lu\n", lstrlenA(expectedsid), size);
9051 
9052     /* increase the index */
9053     lstrcpyA(patchcode, "apple");
9054     lstrcpyA(targetprod, "banana");
9055     context = 0xdeadbeef;
9056     lstrcpyA(targetsid, "kiwi");
9057     size = MAX_PATH;
9058     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_APPLIED,
9059                           1, patchcode, targetprod, &context, targetsid, &size);
9060     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9061     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9062     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9063     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9064     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9065     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9066 
9067     /* increase again */
9068     lstrcpyA(patchcode, "apple");
9069     lstrcpyA(targetprod, "banana");
9070     context = 0xdeadbeef;
9071     lstrcpyA(targetsid, "kiwi");
9072     size = MAX_PATH;
9073     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_APPLIED,
9074                           2, patchcode, targetprod, &context, targetsid, &size);
9075     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9076     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9077     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9078     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9079     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9080     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9081 
9082     /* szPatchCode is NULL */
9083     lstrcpyA(targetprod, "banana");
9084     context = 0xdeadbeef;
9085     lstrcpyA(targetsid, "kiwi");
9086     size = MAX_PATH;
9087     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_APPLIED,
9088                           0, NULL, targetprod, &context, targetsid, &size);
9089     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9090     ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9091     ok(context == MSIINSTALLCONTEXT_USERMANAGED, "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9092     ok(!lstrcmpA(targetsid, expectedsid), "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9093     ok(size == lstrlenA(expectedsid), "Expected %d, got %lu\n", lstrlenA(expectedsid), size);
9094 
9095     /* szTargetProductCode is NULL */
9096     lstrcpyA(patchcode, "apple");
9097     context = 0xdeadbeef;
9098     lstrcpyA(targetsid, "kiwi");
9099     size = MAX_PATH;
9100     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_APPLIED,
9101                           0, patchcode, NULL, &context, targetsid, &size);
9102     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9103     ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9104     ok(context == MSIINSTALLCONTEXT_USERMANAGED, "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9105     ok(!lstrcmpA(targetsid, expectedsid), "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9106     ok(size == lstrlenA(expectedsid), "Expected %d, got %lu\n", lstrlenA(expectedsid), size);
9107 
9108     /* pdwTargetProductContext is NULL */
9109     lstrcpyA(patchcode, "apple");
9110     lstrcpyA(targetprod, "banana");
9111     lstrcpyA(targetsid, "kiwi");
9112     size = MAX_PATH;
9113     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_APPLIED,
9114                           0, patchcode, targetprod, NULL, targetsid, &size);
9115     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9116     ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9117     ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9118     ok(!lstrcmpA(targetsid, expectedsid), "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9119     ok(size == lstrlenA(expectedsid), "Expected %d, got %lu\n", lstrlenA(expectedsid), size);
9120 
9121     /* szTargetUserSid is NULL */
9122     lstrcpyA(patchcode, "apple");
9123     lstrcpyA(targetprod, "banana");
9124     context = 0xdeadbeef;
9125     size = MAX_PATH;
9126     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_APPLIED,
9127                           0, patchcode, targetprod, &context, NULL, &size);
9128     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9129     ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9130     ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9131     ok(context == MSIINSTALLCONTEXT_USERMANAGED, "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9132     ok(size == lstrlenA(expectedsid) * sizeof(WCHAR), "Expected %d*sizeof(WCHAR), got %lu\n", lstrlenA(expectedsid), size);
9133 
9134     /* pcchTargetUserSid is exactly the length of szTargetUserSid */
9135     lstrcpyA(patchcode, "apple");
9136     lstrcpyA(targetprod, "banana");
9137     context = 0xdeadbeef;
9138     lstrcpyA(targetsid, "kiwi");
9139     size = lstrlenA(expectedsid);
9140     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_APPLIED,
9141                           0, patchcode, targetprod, &context, targetsid, &size);
9142     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
9143     ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9144     ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9145     ok(context == MSIINSTALLCONTEXT_USERMANAGED, "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9146     ok(!strncmp(targetsid, expectedsid, lstrlenA(expectedsid) - 1), "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9147     ok(size == lstrlenA(expectedsid) * sizeof(WCHAR), "Expected %d*sizeof(WCHAR), got %lu\n", lstrlenA(expectedsid), size);
9148 
9149     /* pcchTargetUserSid has enough room for NULL terminator */
9150     lstrcpyA(patchcode, "apple");
9151     lstrcpyA(targetprod, "banana");
9152     context = 0xdeadbeef;
9153     lstrcpyA(targetsid, "kiwi");
9154     size = lstrlenA(expectedsid) + 1;
9155     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_APPLIED,
9156                           0, patchcode, targetprod, &context, targetsid, &size);
9157     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9158     ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9159     ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9160     ok(context == MSIINSTALLCONTEXT_USERMANAGED, "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9161     ok(!lstrcmpA(targetsid, expectedsid), "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9162     ok(size == lstrlenA(expectedsid), "Expected %d, got %lu\n", lstrlenA(expectedsid), size);
9163 
9164     /* both szTargetuserSid and pcchTargetUserSid are NULL */
9165     lstrcpyA(patchcode, "apple");
9166     lstrcpyA(targetprod, "banana");
9167     context = 0xdeadbeef;
9168     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_APPLIED,
9169                           0, patchcode, targetprod, &context, NULL, NULL);
9170     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9171     ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9172     ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9173     ok(context == MSIINSTALLCONTEXT_USERMANAGED, "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9174 
9175     /* MSIPATCHSTATE_SUPERSEDED */
9176 
9177     lstrcpyA(patchcode, "apple");
9178     lstrcpyA(targetprod, "banana");
9179     context = 0xdeadbeef;
9180     lstrcpyA(targetsid, "kiwi");
9181     size = MAX_PATH;
9182     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_SUPERSEDED,
9183                           0, patchcode, targetprod, &context, targetsid, &size);
9184     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9185     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9186     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9187     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9188     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9189     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9190 
9191     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
9192     lstrcatA(keypath, expectedsid);
9193     lstrcatA(keypath, "\\Products\\");
9194     lstrcatA(keypath, prod_squashed);
9195 
9196     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
9197     if (res == ERROR_ACCESS_DENIED)
9198     {
9199         skip("Not enough rights to perform tests\n");
9200         return;
9201     }
9202     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9203 
9204     /* UserData product key exists */
9205     lstrcpyA(patchcode, "apple");
9206     lstrcpyA(targetprod, "banana");
9207     context = 0xdeadbeef;
9208     lstrcpyA(targetsid, "kiwi");
9209     size = MAX_PATH;
9210     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_SUPERSEDED,
9211                           0, patchcode, targetprod, &context, targetsid, &size);
9212     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9213     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9214     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9215     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9216     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9217     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9218 
9219     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
9220     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9221 
9222     /* UserData patches key exists */
9223     lstrcpyA(patchcode, "apple");
9224     lstrcpyA(targetprod, "banana");
9225     context = 0xdeadbeef;
9226     lstrcpyA(targetsid, "kiwi");
9227     size = MAX_PATH;
9228     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_SUPERSEDED,
9229                           0, patchcode, targetprod, &context, targetsid, &size);
9230     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9231     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9232     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9233     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9234     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9235     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9236 
9237     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
9238     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9239 
9240     /* specific UserData patch key exists */
9241     lstrcpyA(patchcode, "apple");
9242     lstrcpyA(targetprod, "banana");
9243     context = 0xdeadbeef;
9244     lstrcpyA(targetsid, "kiwi");
9245     size = MAX_PATH;
9246     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_SUPERSEDED,
9247                           0, patchcode, targetprod, &context, targetsid, &size);
9248     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9249     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9250     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9251     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9252     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9253     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9254 
9255     data = MSIPATCHSTATE_SUPERSEDED;
9256     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
9257                          (const BYTE *)&data, sizeof(DWORD));
9258     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9259 
9260     /* State value exists */
9261     lstrcpyA(patchcode, "apple");
9262     lstrcpyA(targetprod, "banana");
9263     context = 0xdeadbeef;
9264     lstrcpyA(targetsid, "kiwi");
9265     size = MAX_PATH;
9266     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_SUPERSEDED,
9267                           0, patchcode, targetprod, &context, targetsid, &size);
9268     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9269     ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9270     ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9271     ok(context == MSIINSTALLCONTEXT_USERMANAGED, "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9272     ok(!lstrcmpA(targetsid, expectedsid), "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9273     ok(size == lstrlenA(expectedsid), "Expected %d, got %lu\n", lstrlenA(expectedsid), size);
9274 
9275     /* MSIPATCHSTATE_OBSOLETED */
9276 
9277     lstrcpyA(patchcode, "apple");
9278     lstrcpyA(targetprod, "banana");
9279     context = 0xdeadbeef;
9280     lstrcpyA(targetsid, "kiwi");
9281     size = MAX_PATH;
9282     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_OBSOLETED,
9283                           0, patchcode, targetprod, &context, targetsid, &size);
9284     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9285     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9286     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9287     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9288     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9289     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9290 
9291     data = MSIPATCHSTATE_OBSOLETED;
9292     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
9293                          (const BYTE *)&data, sizeof(DWORD));
9294     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9295 
9296     /* State value is obsoleted */
9297     lstrcpyA(patchcode, "apple");
9298     lstrcpyA(targetprod, "banana");
9299     context = 0xdeadbeef;
9300     lstrcpyA(targetsid, "kiwi");
9301     size = MAX_PATH;
9302     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_OBSOLETED,
9303                           0, patchcode, targetprod, &context, targetsid, &size);
9304     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9305     ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9306     ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9307     ok(context == MSIINSTALLCONTEXT_USERMANAGED, "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9308     ok(!lstrcmpA(targetsid, expectedsid), "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9309     ok(size == lstrlenA(expectedsid), "Expected %d, got %lu\n", lstrlenA(expectedsid), size);
9310 
9311     /* MSIPATCHSTATE_REGISTERED */
9312     /* FIXME */
9313 
9314     /* MSIPATCHSTATE_ALL */
9315 
9316     /* 1st */
9317     lstrcpyA(patchcode, "apple");
9318     lstrcpyA(targetprod, "banana");
9319     context = 0xdeadbeef;
9320     lstrcpyA(targetsid, "kiwi");
9321     size = MAX_PATH;
9322     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_ALL,
9323                           0, patchcode, targetprod, &context, targetsid, &size);
9324     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9325     ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9326     ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9327     ok(context == MSIINSTALLCONTEXT_USERMANAGED, "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9328     ok(!lstrcmpA(targetsid, expectedsid), "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9329     ok(size == lstrlenA(expectedsid), "Expected %d, got %lu\n", lstrlenA(expectedsid), size);
9330 
9331     /* same patch in multiple places, only one is enumerated */
9332     lstrcpyA(patchcode, "apple");
9333     lstrcpyA(targetprod, "banana");
9334     context = 0xdeadbeef;
9335     lstrcpyA(targetsid, "kiwi");
9336     size = MAX_PATH;
9337     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_ALL,
9338                           1, patchcode, targetprod, &context, targetsid, &size);
9339     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9340     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9341     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9342     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9343     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9344     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9345 
9346     RegDeleteValueA(hpatch, "State");
9347     RegDeleteKeyExA(hpatch, "", access & KEY_WOW64_64KEY, 0);
9348     RegCloseKey(hpatch);
9349     RegDeleteKeyExA(udpatch, "", access & KEY_WOW64_64KEY, 0);
9350     RegCloseKey(udpatch);
9351     RegDeleteKeyExA(udprod, "", access & KEY_WOW64_64KEY, 0);
9352     RegCloseKey(udprod);
9353     RegDeleteValueA(patches, "Patches");
9354     RegDeleteKeyExA(patches, "", access & KEY_WOW64_64KEY, 0);
9355     RegCloseKey(patches);
9356     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
9357     RegCloseKey(prodkey);
9358 }
9359 
test_MsiEnumPatchesEx_userunmanaged(LPCSTR usersid,LPCSTR expectedsid)9360 static void test_MsiEnumPatchesEx_userunmanaged(LPCSTR usersid, LPCSTR expectedsid)
9361 {
9362     MSIINSTALLCONTEXT context;
9363     CHAR keypath[MAX_PATH], patch[MAX_PATH];
9364     CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
9365     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
9366     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
9367     HKEY prodkey, patches, udprod, udpatch;
9368     HKEY userkey, hpatch;
9369     DWORD size, data;
9370     LONG res;
9371     UINT r;
9372     REGSAM access = KEY_ALL_ACCESS;
9373 
9374     create_test_guid(prodcode, prod_squashed);
9375     create_test_guid(patch, patch_squashed);
9376 
9377     if (is_wow64)
9378         access |= KEY_WOW64_64KEY;
9379 
9380     /* MSIPATCHSTATE_APPLIED */
9381 
9382     lstrcpyA(patchcode, "apple");
9383     lstrcpyA(targetprod, "banana");
9384     context = 0xdeadbeef;
9385     lstrcpyA(targetsid, "kiwi");
9386     size = MAX_PATH;
9387     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_APPLIED,
9388                           0, patchcode, targetprod, &context, targetsid, &size);
9389     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9390     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9391     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9392     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9393     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9394     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9395 
9396     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
9397     lstrcatA(keypath, prod_squashed);
9398 
9399     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
9400     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9401 
9402     /* current user product key exists */
9403     lstrcpyA(patchcode, "apple");
9404     lstrcpyA(targetprod, "banana");
9405     context = 0xdeadbeef;
9406     lstrcpyA(targetsid, "kiwi");
9407     size = MAX_PATH;
9408     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_APPLIED,
9409                           0, patchcode, targetprod, &context, targetsid, &size);
9410     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9411     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9412     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9413     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9414     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9415     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9416 
9417     res = RegCreateKeyA(prodkey, "Patches", &patches);
9418     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9419 
9420     /* Patches key exists */
9421     lstrcpyA(patchcode, "apple");
9422     lstrcpyA(targetprod, "banana");
9423     context = 0xdeadbeef;
9424     lstrcpyA(targetsid, "kiwi");
9425     size = MAX_PATH;
9426     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_APPLIED,
9427                           0, patchcode, targetprod, &context, targetsid, &size);
9428     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9429     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9430     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9431     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9432     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9433     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9434 
9435     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
9436                          (const BYTE *)patch_squashed,
9437                          lstrlenA(patch_squashed) + 1);
9438     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9439 
9440     /* Patches value exists, is not REG_MULTI_SZ */
9441     lstrcpyA(patchcode, "apple");
9442     lstrcpyA(targetprod, "banana");
9443     context = 0xdeadbeef;
9444     lstrcpyA(targetsid, "kiwi");
9445     size = MAX_PATH;
9446     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_APPLIED,
9447                           0, patchcode, targetprod, &context, targetsid, &size);
9448     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9449     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9450     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9451     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9452     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9453     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9454 
9455     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
9456                          (const BYTE *)"a\0b\0c\0\0", 7);
9457     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9458 
9459     /* Patches value exists, is not a squashed guid */
9460     lstrcpyA(patchcode, "apple");
9461     lstrcpyA(targetprod, "banana");
9462     context = 0xdeadbeef;
9463     lstrcpyA(targetsid, "kiwi");
9464     size = MAX_PATH;
9465     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_APPLIED,
9466                           0, patchcode, targetprod, &context, targetsid, &size);
9467     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9468     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9469     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9470     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9471     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9472     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9473 
9474     patch_squashed[lstrlenA(patch_squashed) + 1] = 0;
9475     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
9476                          (const BYTE *)patch_squashed,
9477                          lstrlenA(patch_squashed) + 2);
9478     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9479 
9480     /* Patches value exists */
9481     lstrcpyA(patchcode, "apple");
9482     lstrcpyA(targetprod, "banana");
9483     context = 0xdeadbeef;
9484     lstrcpyA(targetsid, "kiwi");
9485     size = MAX_PATH;
9486     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_APPLIED,
9487                           0, patchcode, targetprod, &context, targetsid, &size);
9488     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9489     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9490     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9491     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9492     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9493     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9494 
9495     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
9496                          (const BYTE *)"whatever", 9);
9497     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9498 
9499     /* patch code value exists */
9500     lstrcpyA(patchcode, "apple");
9501     lstrcpyA(targetprod, "banana");
9502     context = 0xdeadbeef;
9503     lstrcpyA(targetsid, "kiwi");
9504     size = MAX_PATH;
9505     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_APPLIED,
9506                           0, patchcode, targetprod, &context, targetsid, &size);
9507     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9508     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9509     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9510     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9511     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9512     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9513 
9514     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
9515     lstrcatA(keypath, expectedsid);
9516     lstrcatA(keypath, "\\Patches\\");
9517     lstrcatA(keypath, patch_squashed);
9518 
9519     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
9520     if (res == ERROR_ACCESS_DENIED)
9521     {
9522         skip("Not enough rights to perform tests\n");
9523         goto error;
9524     }
9525     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9526 
9527     /* userdata patch key exists */
9528     lstrcpyA(patchcode, "apple");
9529     lstrcpyA(targetprod, "banana");
9530     context = 0xdeadbeef;
9531     lstrcpyA(targetsid, "kiwi");
9532     size = MAX_PATH;
9533     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_APPLIED,
9534                           0, patchcode, targetprod, &context, targetsid, &size);
9535     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9536     ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9537     ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9538     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED, "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
9539     ok(!lstrcmpA(targetsid, expectedsid), "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9540     ok(size == lstrlenA(expectedsid), "Expected %d, got %lu\n", lstrlenA(expectedsid), size);
9541 
9542     /* MSIPATCHSTATE_SUPERSEDED */
9543 
9544     lstrcpyA(patchcode, "apple");
9545     lstrcpyA(targetprod, "banana");
9546     context = 0xdeadbeef;
9547     lstrcpyA(targetsid, "kiwi");
9548     size = MAX_PATH;
9549     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_SUPERSEDED,
9550                           0, patchcode, targetprod, &context, targetsid, &size);
9551     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9552     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9553     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9554     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9555     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9556     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9557 
9558     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
9559     lstrcatA(keypath, expectedsid);
9560     lstrcatA(keypath, "\\Products\\");
9561     lstrcatA(keypath, prod_squashed);
9562 
9563     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
9564     if (res == ERROR_ACCESS_DENIED)
9565     {
9566         skip("Not enough rights to perform tests\n");
9567         goto error;
9568     }
9569     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9570 
9571     /* UserData product key exists */
9572     lstrcpyA(patchcode, "apple");
9573     lstrcpyA(targetprod, "banana");
9574     context = 0xdeadbeef;
9575     lstrcpyA(targetsid, "kiwi");
9576     size = MAX_PATH;
9577     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_SUPERSEDED,
9578                           0, patchcode, targetprod, &context, targetsid, &size);
9579     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9580     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9581     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9582     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9583     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9584     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9585 
9586     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
9587     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9588 
9589     /* UserData patches key exists */
9590     lstrcpyA(patchcode, "apple");
9591     lstrcpyA(targetprod, "banana");
9592     context = 0xdeadbeef;
9593     lstrcpyA(targetsid, "kiwi");
9594     size = MAX_PATH;
9595     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_SUPERSEDED,
9596                           0, patchcode, targetprod, &context, targetsid, &size);
9597     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9598     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9599     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9600     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9601     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9602     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9603 
9604     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
9605     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9606 
9607     /* specific UserData patch key exists */
9608     lstrcpyA(patchcode, "apple");
9609     lstrcpyA(targetprod, "banana");
9610     context = 0xdeadbeef;
9611     lstrcpyA(targetsid, "kiwi");
9612     size = MAX_PATH;
9613     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_SUPERSEDED,
9614                           0, patchcode, targetprod, &context, targetsid, &size);
9615     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9616     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9617     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9618     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9619     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9620     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9621 
9622     data = MSIPATCHSTATE_SUPERSEDED;
9623     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
9624                          (const BYTE *)&data, sizeof(DWORD));
9625     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9626 
9627     /* State value exists */
9628     lstrcpyA(patchcode, "apple");
9629     lstrcpyA(targetprod, "banana");
9630     context = 0xdeadbeef;
9631     lstrcpyA(targetsid, "kiwi");
9632     size = MAX_PATH;
9633     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_SUPERSEDED,
9634                           0, patchcode, targetprod, &context, targetsid, &size);
9635     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9636     ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9637     ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9638     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED, "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
9639     ok(!lstrcmpA(targetsid, expectedsid), "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9640     ok(size == lstrlenA(expectedsid), "Expected %d, got %lu\n", lstrlenA(expectedsid), size);
9641 
9642     /* MSIPATCHSTATE_OBSOLETED */
9643 
9644     lstrcpyA(patchcode, "apple");
9645     lstrcpyA(targetprod, "banana");
9646     context = 0xdeadbeef;
9647     lstrcpyA(targetsid, "kiwi");
9648     size = MAX_PATH;
9649     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_OBSOLETED,
9650                           0, patchcode, targetprod, &context, targetsid, &size);
9651     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9652     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9653     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9654     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9655     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9656     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9657 
9658     data = MSIPATCHSTATE_OBSOLETED;
9659     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
9660                          (const BYTE *)&data, sizeof(DWORD));
9661     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9662 
9663     /* State value is obsoleted */
9664     lstrcpyA(patchcode, "apple");
9665     lstrcpyA(targetprod, "banana");
9666     context = 0xdeadbeef;
9667     lstrcpyA(targetsid, "kiwi");
9668     size = MAX_PATH;
9669     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_OBSOLETED,
9670                           0, patchcode, targetprod, &context, targetsid, &size);
9671     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9672     ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9673     ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9674     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED, "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
9675     ok(!lstrcmpA(targetsid, expectedsid), "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9676     ok(size == lstrlenA(expectedsid), "Expected %d, got %lu\n", lstrlenA(expectedsid), size);
9677 
9678     /* MSIPATCHSTATE_REGISTERED */
9679     /* FIXME */
9680 
9681     /* MSIPATCHSTATE_ALL */
9682 
9683     /* 1st */
9684     lstrcpyA(patchcode, "apple");
9685     lstrcpyA(targetprod, "banana");
9686     context = 0xdeadbeef;
9687     lstrcpyA(targetsid, "kiwi");
9688     size = MAX_PATH;
9689     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
9690                           0, patchcode, targetprod, &context, targetsid, &size);
9691     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9692     ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9693     ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9694     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED, "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
9695     ok(!lstrcmpA(targetsid, expectedsid), "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9696     ok(size == lstrlenA(expectedsid), "Expected %d, got %lu\n", lstrlenA(expectedsid), size);
9697 
9698     /* same patch in multiple places, only one is enumerated */
9699     lstrcpyA(patchcode, "apple");
9700     lstrcpyA(targetprod, "banana");
9701     context = 0xdeadbeef;
9702     lstrcpyA(targetsid, "kiwi");
9703     size = MAX_PATH;
9704     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
9705                           1, patchcode, targetprod, &context, targetsid, &size);
9706     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9707     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9708     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9709     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9710     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9711     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9712 
9713     RegDeleteValueA(hpatch, "State");
9714     RegDeleteKeyExA(hpatch, "", access & KEY_WOW64_64KEY, 0);
9715     RegCloseKey(hpatch);
9716     RegDeleteKeyExA(udpatch, "", access & KEY_WOW64_64KEY, 0);
9717     RegCloseKey(udpatch);
9718     RegDeleteKeyExA(udprod, "", access & KEY_WOW64_64KEY, 0);
9719     RegCloseKey(udprod);
9720     RegDeleteKeyExA(userkey, "", access & KEY_WOW64_64KEY, 0);
9721     RegCloseKey(userkey);
9722     RegDeleteValueA(patches, patch_squashed);
9723     RegDeleteValueA(patches, "Patches");
9724 
9725 error:
9726     RegDeleteKeyA(patches, "");
9727     RegCloseKey(patches);
9728     RegDeleteKeyA(prodkey, "");
9729     RegCloseKey(prodkey);
9730 }
9731 
test_MsiEnumPatchesEx_machine(void)9732 static void test_MsiEnumPatchesEx_machine(void)
9733 {
9734     CHAR keypath[MAX_PATH], patch[MAX_PATH];
9735     CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
9736     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
9737     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
9738     HKEY prodkey, patches, udprod, udpatch;
9739     HKEY hpatch;
9740     MSIINSTALLCONTEXT context;
9741     DWORD size, data;
9742     LONG res;
9743     UINT r;
9744     REGSAM access = KEY_ALL_ACCESS;
9745 
9746     create_test_guid(prodcode, prod_squashed);
9747     create_test_guid(patch, patch_squashed);
9748 
9749     if (is_wow64)
9750         access |= KEY_WOW64_64KEY;
9751 
9752     /* MSIPATCHSTATE_APPLIED */
9753 
9754     lstrcpyA(patchcode, "apple");
9755     lstrcpyA(targetprod, "banana");
9756     context = 0xdeadbeef;
9757     lstrcpyA(targetsid, "kiwi");
9758     size = MAX_PATH;
9759     r = MsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSIPATCHSTATE_APPLIED,
9760                           0, patchcode, targetprod, &context, targetsid, &size);
9761     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9762     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9763     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9764     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9765     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9766     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9767 
9768     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
9769     lstrcatA(keypath, prod_squashed);
9770 
9771     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
9772     if (res == ERROR_ACCESS_DENIED)
9773     {
9774         skip("Not enough rights to perform tests\n");
9775         return;
9776     }
9777     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9778 
9779     /* local product key exists */
9780     lstrcpyA(patchcode, "apple");
9781     lstrcpyA(targetprod, "banana");
9782     context = 0xdeadbeef;
9783     lstrcpyA(targetsid, "kiwi");
9784     size = MAX_PATH;
9785     r = MsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSIPATCHSTATE_APPLIED,
9786                          0, patchcode, targetprod, &context, targetsid, &size);
9787     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9788     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9789     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9790     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9791     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9792     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9793 
9794     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
9795     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9796 
9797     /* Patches key exists */
9798     lstrcpyA(patchcode, "apple");
9799     lstrcpyA(targetprod, "banana");
9800     context = 0xdeadbeef;
9801     lstrcpyA(targetsid, "kiwi");
9802     size = MAX_PATH;
9803     r = MsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSIPATCHSTATE_APPLIED,
9804                           0, patchcode, targetprod, &context, targetsid, &size);
9805     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9806     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9807     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9808     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9809     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9810     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9811 
9812     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
9813                          (const BYTE *)patch_squashed,
9814                          lstrlenA(patch_squashed) + 1);
9815     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9816 
9817     /* Patches value exists, is not REG_MULTI_SZ */
9818     lstrcpyA(patchcode, "apple");
9819     lstrcpyA(targetprod, "banana");
9820     context = 0xdeadbeef;
9821     lstrcpyA(targetsid, "kiwi");
9822     size = MAX_PATH;
9823     r = MsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSIPATCHSTATE_APPLIED,
9824                           0, patchcode, targetprod, &context, targetsid, &size);
9825     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9826     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9827     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9828     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9829     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9830     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9831 
9832     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
9833                          (const BYTE *)"a\0b\0c\0\0", 7);
9834     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9835 
9836     /* Patches value exists, is not a squashed guid */
9837     lstrcpyA(patchcode, "apple");
9838     lstrcpyA(targetprod, "banana");
9839     context = 0xdeadbeef;
9840     lstrcpyA(targetsid, "kiwi");
9841     size = MAX_PATH;
9842     r = MsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSIPATCHSTATE_APPLIED,
9843                           0, patchcode, targetprod, &context, targetsid, &size);
9844     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9845     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9846     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9847     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9848     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9849     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9850 
9851     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
9852     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
9853                          (const BYTE *)patch_squashed,
9854                          lstrlenA(patch_squashed) + 2);
9855     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9856 
9857     /* Patches value exists */
9858     lstrcpyA(patchcode, "apple");
9859     lstrcpyA(targetprod, "banana");
9860     context = 0xdeadbeef;
9861     lstrcpyA(targetsid, "kiwi");
9862     size = MAX_PATH;
9863     r = MsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSIPATCHSTATE_APPLIED,
9864                           0, patchcode, targetprod, &context, targetsid, &size);
9865     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9866     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9867     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9868     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9869     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9870     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9871 
9872     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
9873                          (const BYTE *)"whatever", 9);
9874     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9875 
9876     /* patch code value exists */
9877     lstrcpyA(patchcode, "apple");
9878     lstrcpyA(targetprod, "banana");
9879     context = 0xdeadbeef;
9880     lstrcpyA(targetsid, "kiwi");
9881     size = MAX_PATH;
9882     r = MsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSIPATCHSTATE_APPLIED,
9883                           0, patchcode, targetprod, &context, targetsid, &size);
9884     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9885     ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9886     ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9887     ok(context == MSIINSTALLCONTEXT_MACHINE, "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
9888     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
9889     ok(size == 0, "Expected 0, got %lu\n", size);
9890 
9891     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9892     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
9893     lstrcatA(keypath, prod_squashed);
9894 
9895     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
9896     if (res == ERROR_ACCESS_DENIED)
9897     {
9898         skip("Not enough rights to perform tests\n");
9899         goto done;
9900     }
9901     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9902 
9903     /* local UserData product key exists */
9904     lstrcpyA(patchcode, "apple");
9905     lstrcpyA(targetprod, "banana");
9906     context = 0xdeadbeef;
9907     lstrcpyA(targetsid, "kiwi");
9908     size = MAX_PATH;
9909     r = MsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSIPATCHSTATE_APPLIED,
9910                           0, patchcode, targetprod, &context, targetsid, &size);
9911     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9912     ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9913     ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9914     ok(context == MSIINSTALLCONTEXT_MACHINE, "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
9915     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
9916     ok(size == 0, "Expected 0, got %lu\n", size);
9917 
9918     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
9919     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9920 
9921     /* local UserData Patches key exists */
9922     lstrcpyA(patchcode, "apple");
9923     lstrcpyA(targetprod, "banana");
9924     context = 0xdeadbeef;
9925     lstrcpyA(targetsid, "kiwi");
9926     size = MAX_PATH;
9927     r = MsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSIPATCHSTATE_APPLIED,
9928                           0, patchcode, targetprod, &context, targetsid, &size);
9929     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9930     ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9931     ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9932     ok(context == MSIINSTALLCONTEXT_MACHINE, "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
9933     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
9934     ok(size == 0, "Expected 0, got %lu\n", size);
9935 
9936     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
9937     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9938 
9939     /* local UserData Product patch key exists */
9940     lstrcpyA(patchcode, "apple");
9941     lstrcpyA(targetprod, "banana");
9942     context = 0xdeadbeef;
9943     lstrcpyA(targetsid, "kiwi");
9944     size = MAX_PATH;
9945     r = MsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSIPATCHSTATE_APPLIED,
9946                           0, patchcode, targetprod, &context, targetsid, &size);
9947     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9948     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9949     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9950     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9951     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9952     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9953 
9954     data = MSIPATCHSTATE_APPLIED;
9955     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
9956                          (const BYTE *)&data, sizeof(DWORD));
9957     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9958 
9959     /* State value exists */
9960     lstrcpyA(patchcode, "apple");
9961     lstrcpyA(targetprod, "banana");
9962     context = 0xdeadbeef;
9963     lstrcpyA(targetsid, "kiwi");
9964     size = MAX_PATH;
9965     r = MsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSIPATCHSTATE_APPLIED,
9966                           0, patchcode, targetprod, &context, targetsid, &size);
9967     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9968     ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9969     ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9970     ok(context == MSIINSTALLCONTEXT_MACHINE, "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
9971     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
9972     ok(size == 0, "Expected 0, got %lu\n", size);
9973 
9974     /* MSIPATCHSTATE_SUPERSEDED */
9975 
9976     lstrcpyA(patchcode, "apple");
9977     lstrcpyA(targetprod, "banana");
9978     context = 0xdeadbeef;
9979     lstrcpyA(targetsid, "kiwi");
9980     size = MAX_PATH;
9981     r = MsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSIPATCHSTATE_SUPERSEDED,
9982                           0, patchcode, targetprod, &context, targetsid, &size);
9983     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9984     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9985     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9986     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9987     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9988     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9989 
9990     data = MSIPATCHSTATE_SUPERSEDED;
9991     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
9992                          (const BYTE *)&data, sizeof(DWORD));
9993     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9994 
9995     /* State value is MSIPATCHSTATE_SUPERSEDED */
9996     lstrcpyA(patchcode, "apple");
9997     lstrcpyA(targetprod, "banana");
9998     context = 0xdeadbeef;
9999     lstrcpyA(targetsid, "kiwi");
10000     size = MAX_PATH;
10001     r = MsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSIPATCHSTATE_SUPERSEDED,
10002                           0, patchcode, targetprod, &context, targetsid, &size);
10003     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10004     ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10005     ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10006     ok(context == MSIINSTALLCONTEXT_MACHINE, "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10007     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
10008     ok(size == 0, "Expected 0, got %lu\n", size);
10009 
10010     /* MSIPATCHSTATE_OBSOLETED */
10011 
10012     lstrcpyA(patchcode, "apple");
10013     lstrcpyA(targetprod, "banana");
10014     context = 0xdeadbeef;
10015     lstrcpyA(targetsid, "kiwi");
10016     size = MAX_PATH;
10017     r = MsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSIPATCHSTATE_OBSOLETED,
10018                           0, patchcode, targetprod, &context, targetsid, &size);
10019     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10020     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10021     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10022     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10023     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10024     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10025 
10026     data = MSIPATCHSTATE_OBSOLETED;
10027     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10028                          (const BYTE *)&data, sizeof(DWORD));
10029     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10030 
10031     /* State value is obsoleted */
10032     lstrcpyA(patchcode, "apple");
10033     lstrcpyA(targetprod, "banana");
10034     context = 0xdeadbeef;
10035     lstrcpyA(targetsid, "kiwi");
10036     size = MAX_PATH;
10037     r = MsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSIPATCHSTATE_OBSOLETED,
10038                           0, patchcode, targetprod, &context, targetsid, &size);
10039     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10040     ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10041     ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10042     ok(context == MSIINSTALLCONTEXT_MACHINE, "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10043     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
10044     ok(size == 0, "Expected 0, got %lu\n", size);
10045 
10046     /* MSIPATCHSTATE_REGISTERED */
10047     /* FIXME */
10048 
10049     /* MSIPATCHSTATE_ALL */
10050 
10051     /* 1st */
10052     lstrcpyA(patchcode, "apple");
10053     lstrcpyA(targetprod, "banana");
10054     context = 0xdeadbeef;
10055     lstrcpyA(targetsid, "kiwi");
10056     size = MAX_PATH;
10057     r = MsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSIPATCHSTATE_ALL,
10058                           0, patchcode, targetprod, &context, targetsid, &size);
10059     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10060     ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10061     ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10062     ok(context == MSIINSTALLCONTEXT_MACHINE, "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10063     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
10064     ok(size == 0, "Expected 0, got %lu\n", size);
10065 
10066     /* same patch in multiple places, only one is enumerated */
10067     lstrcpyA(patchcode, "apple");
10068     lstrcpyA(targetprod, "banana");
10069     context = 0xdeadbeef;
10070     lstrcpyA(targetsid, "kiwi");
10071     size = MAX_PATH;
10072     r = MsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, MSIPATCHSTATE_ALL,
10073                           1, patchcode, targetprod, &context, targetsid, &size);
10074     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10075     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10076     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10077     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10078     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10079     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10080 
10081     RegDeleteKeyExA(hpatch, "", access & KEY_WOW64_64KEY, 0);
10082     RegDeleteValueA(hpatch, "State");
10083     RegCloseKey(hpatch);
10084     RegDeleteKeyExA(udpatch, "", access & KEY_WOW64_64KEY, 0);
10085     RegCloseKey(udpatch);
10086     RegDeleteKeyExA(udprod, "", access & KEY_WOW64_64KEY, 0);
10087     RegCloseKey(udprod);
10088 
10089 done:
10090     RegDeleteValueA(patches, patch_squashed);
10091     RegDeleteValueA(patches, "Patches");
10092     RegDeleteKeyExA(patches, "", access & KEY_WOW64_64KEY, 0);
10093     RegCloseKey(patches);
10094     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
10095     RegCloseKey(prodkey);
10096 }
10097 
test_MsiEnumPatchesEx(void)10098 static void test_MsiEnumPatchesEx(void)
10099 {
10100     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
10101     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
10102     CHAR patchcode[MAX_PATH];
10103     MSIINSTALLCONTEXT context;
10104     LPSTR usersid;
10105     DWORD size;
10106     UINT r;
10107 
10108     create_test_guid(prodcode, prod_squashed);
10109     usersid = get_user_sid();
10110 
10111     /* empty szProductCode */
10112     lstrcpyA(patchcode, "apple");
10113     lstrcpyA(targetprod, "banana");
10114     context = 0xdeadbeef;
10115     lstrcpyA(targetsid, "kiwi");
10116     size = MAX_PATH;
10117     r = MsiEnumPatchesExA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
10118                           0, patchcode, targetprod, &context, targetsid, &size);
10119     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10120     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10121     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10122     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10123     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10124     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10125 
10126     /* garbage szProductCode */
10127     lstrcpyA(patchcode, "apple");
10128     lstrcpyA(targetprod, "banana");
10129     context = 0xdeadbeef;
10130     lstrcpyA(targetsid, "kiwi");
10131     size = MAX_PATH;
10132     r = MsiEnumPatchesExA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
10133                           0, patchcode, targetprod, &context, targetsid, &size);
10134     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10135     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10136     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10137     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10138     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10139     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10140 
10141     /* guid without brackets */
10142     lstrcpyA(patchcode, "apple");
10143     lstrcpyA(targetprod, "banana");
10144     context = 0xdeadbeef;
10145     lstrcpyA(targetsid, "kiwi");
10146     size = MAX_PATH;
10147     r = MsiEnumPatchesExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10148                           MSIPATCHSTATE_ALL, 0, patchcode, targetprod, &context, targetsid, &size);
10149     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10150     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10151     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10152     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10153     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10154     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10155 
10156     /* guid with brackets */
10157     lstrcpyA(patchcode, "apple");
10158     lstrcpyA(targetprod, "banana");
10159     context = 0xdeadbeef;
10160     lstrcpyA(targetsid, "kiwi");
10161     size = MAX_PATH;
10162     r = MsiEnumPatchesExA("{6700E8CF-95AB-4D9C-BC2C-15840DDA7A5D}", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10163                           MSIPATCHSTATE_ALL, 0, patchcode, targetprod, &context, targetsid, &size);
10164     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10165     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10166     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10167     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10168     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10169     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10170 
10171     /* szUserSid is S-1-5-18 */
10172     lstrcpyA(patchcode, "apple");
10173     lstrcpyA(targetprod, "banana");
10174     context = 0xdeadbeef;
10175     lstrcpyA(targetsid, "kiwi");
10176     size = MAX_PATH;
10177     r = MsiEnumPatchesExA(prodcode, "S-1-5-18", MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
10178                           0, patchcode, targetprod, &context, targetsid, &size);
10179     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10180     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10181     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10182     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10183     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10184     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10185 
10186     /* dwContext is MSIINSTALLCONTEXT_MACHINE, but szUserSid is non-NULL */
10187     lstrcpyA(patchcode, "apple");
10188     lstrcpyA(targetprod, "banana");
10189     context = 0xdeadbeef;
10190     lstrcpyA(targetsid, "kiwi");
10191     size = MAX_PATH;
10192     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_MACHINE, MSIPATCHSTATE_ALL,
10193                           0, patchcode, targetprod, &context, targetsid, &size);
10194     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10195     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10196     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10197     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10198     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10199     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10200 
10201     /* dwContext is out of bounds */
10202     lstrcpyA(patchcode, "apple");
10203     lstrcpyA(targetprod, "banana");
10204     context = 0xdeadbeef;
10205     lstrcpyA(targetsid, "kiwi");
10206     size = MAX_PATH;
10207     r = MsiEnumPatchesExA(prodcode, usersid, 0, MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
10208                           &context, targetsid, &size);
10209     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10210     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10211     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10212     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10213     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10214     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10215 
10216     /* dwContext is out of bounds */
10217     lstrcpyA(patchcode, "apple");
10218     lstrcpyA(targetprod, "banana");
10219     context = 0xdeadbeef;
10220     lstrcpyA(targetsid, "kiwi");
10221     size = MAX_PATH;
10222     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_ALL + 1, MSIPATCHSTATE_ALL, 0, patchcode,
10223                           targetprod, &context, targetsid, &size);
10224     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10225     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10226     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10227     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10228     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10229     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10230 
10231     /* dwFilter is out of bounds */
10232     lstrcpyA(patchcode, "apple");
10233     lstrcpyA(targetprod, "banana");
10234     context = 0xdeadbeef;
10235     lstrcpyA(targetsid, "kiwi");
10236     size = MAX_PATH;
10237     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_INVALID,
10238                           0, patchcode, targetprod, &context, targetsid, &size);
10239     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10240     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10241     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10242     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10243     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10244     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10245 
10246     /* dwFilter is out of bounds */
10247     lstrcpyA(patchcode, "apple");
10248     lstrcpyA(targetprod, "banana");
10249     context = 0xdeadbeef;
10250     lstrcpyA(targetsid, "kiwi");
10251     size = MAX_PATH;
10252     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL + 1,
10253                           0, patchcode, targetprod, &context, targetsid, &size);
10254     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10255     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10256     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10257     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10258     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10259     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10260 
10261     /* pcchTargetUserSid is NULL while szTargetUserSid is non-NULL */
10262     lstrcpyA(patchcode, "apple");
10263     lstrcpyA(targetprod, "banana");
10264     context = 0xdeadbeef;
10265     lstrcpyA(targetsid, "kiwi");
10266     r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
10267                           0, patchcode, targetprod, &context, targetsid, NULL);
10268     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10269     ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10270     ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10271     ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10272     ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10273 
10274     test_MsiEnumPatchesEx_usermanaged(usersid, usersid);
10275     test_MsiEnumPatchesEx_usermanaged(NULL, usersid);
10276     test_MsiEnumPatchesEx_usermanaged("S-1-2-34", "S-1-2-34");
10277     test_MsiEnumPatchesEx_userunmanaged(usersid, usersid);
10278     test_MsiEnumPatchesEx_userunmanaged(NULL, usersid);
10279     /* FIXME: Successfully test userunmanaged with a different user */
10280     test_MsiEnumPatchesEx_machine();
10281     LocalFree(usersid);
10282 }
10283 
test_MsiEnumPatches(void)10284 static void test_MsiEnumPatches(void)
10285 {
10286     CHAR keypath[MAX_PATH], patch[MAX_PATH];
10287     CHAR patchcode[MAX_PATH], patch_squashed[MAX_PATH];
10288     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
10289     CHAR transforms[MAX_PATH];
10290     WCHAR patchW[MAX_PATH], prodcodeW[MAX_PATH], transformsW[MAX_PATH];
10291     HKEY prodkey, patches, udprod;
10292     HKEY userkey, hpatch, udpatch;
10293     DWORD size, data;
10294     LPSTR usersid;
10295     LONG res;
10296     UINT r;
10297     REGSAM access = KEY_ALL_ACCESS;
10298 
10299     create_test_guid(prodcode, prod_squashed);
10300     create_test_guid(patchcode, patch_squashed);
10301     usersid = get_user_sid();
10302 
10303     if (is_wow64)
10304         access |= KEY_WOW64_64KEY;
10305 
10306     /* NULL szProduct */
10307     size = MAX_PATH;
10308     lstrcpyA(patch, "apple");
10309     lstrcpyA(transforms, "banana");
10310     r = MsiEnumPatchesA(NULL, 0, patch, transforms, &size);
10311     ok(r == ERROR_INVALID_PARAMETER,
10312        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10313     ok(!lstrcmpA(patch, "apple"),
10314        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10315     ok(!lstrcmpA(transforms, "banana"),
10316        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10317     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10318 
10319     /* empty szProduct */
10320     size = MAX_PATH;
10321     lstrcpyA(patch, "apple");
10322     lstrcpyA(transforms, "banana");
10323     r = MsiEnumPatchesA("", 0, patch, transforms, &size);
10324     ok(r == ERROR_INVALID_PARAMETER,
10325        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10326     ok(!lstrcmpA(patch, "apple"),
10327        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10328     ok(!lstrcmpA(transforms, "banana"),
10329        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10330     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10331 
10332     /* garbage szProduct */
10333     size = MAX_PATH;
10334     lstrcpyA(patch, "apple");
10335     lstrcpyA(transforms, "banana");
10336     r = MsiEnumPatchesA("garbage", 0, patch, transforms, &size);
10337     ok(r == ERROR_INVALID_PARAMETER,
10338        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10339     ok(!lstrcmpA(patch, "apple"),
10340        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10341     ok(!lstrcmpA(transforms, "banana"),
10342        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10343     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10344 
10345     /* guid without brackets */
10346     size = MAX_PATH;
10347     lstrcpyA(patch, "apple");
10348     lstrcpyA(transforms, "banana");
10349     r = MsiEnumPatchesA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", 0, patch,
10350                         transforms, &size);
10351     ok(r == ERROR_INVALID_PARAMETER,
10352        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10353     ok(!lstrcmpA(patch, "apple"),
10354        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10355     ok(!lstrcmpA(transforms, "banana"),
10356        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10357     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10358 
10359     /* guid with brackets */
10360     size = MAX_PATH;
10361     lstrcpyA(patch, "apple");
10362     lstrcpyA(transforms, "banana");
10363     r = MsiEnumPatchesA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", 0, patch,
10364                         transforms, &size);
10365     ok(r == ERROR_UNKNOWN_PRODUCT,
10366        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
10367     ok(!lstrcmpA(patch, "apple"),
10368        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10369     ok(!lstrcmpA(transforms, "banana"),
10370        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10371     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10372 
10373     /* same length as guid, but random */
10374     size = MAX_PATH;
10375     lstrcpyA(patch, "apple");
10376     lstrcpyA(transforms, "banana");
10377     r = MsiEnumPatchesA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", 0, patch,
10378                         transforms, &size);
10379     ok(r == ERROR_INVALID_PARAMETER,
10380        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10381     ok(!lstrcmpA(patch, "apple"),
10382        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10383     ok(!lstrcmpA(transforms, "banana"),
10384        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10385     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10386 
10387     /* MSIINSTALLCONTEXT_USERMANAGED */
10388 
10389     size = MAX_PATH;
10390     lstrcpyA(patch, "apple");
10391     lstrcpyA(transforms, "banana");
10392     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10393     ok(r == ERROR_UNKNOWN_PRODUCT,
10394        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
10395     ok(!lstrcmpA(patch, "apple"),
10396        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10397     ok(!lstrcmpA(transforms, "banana"),
10398        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10399     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10400 
10401     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
10402     lstrcatA(keypath, usersid);
10403     lstrcatA(keypath, "\\Installer\\Products\\");
10404     lstrcatA(keypath, prod_squashed);
10405 
10406     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
10407     if (res == ERROR_ACCESS_DENIED)
10408     {
10409         skip("Not enough rights to perform tests\n");
10410         LocalFree(usersid);
10411         return;
10412     }
10413     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10414 
10415     /* managed product key exists */
10416     size = MAX_PATH;
10417     lstrcpyA(patch, "apple");
10418     lstrcpyA(transforms, "banana");
10419     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10420     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10421     ok(!lstrcmpA(patch, "apple"),
10422        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10423     ok(!lstrcmpA(transforms, "banana"),
10424        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10425     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10426 
10427     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
10428     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10429 
10430     /* patches key exists */
10431     size = MAX_PATH;
10432     lstrcpyA(patch, "apple");
10433     lstrcpyA(transforms, "banana");
10434     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10435     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10436     ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10437     ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10438     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10439 
10440     res = RegSetValueExA(patches, "Patches", 0, REG_SZ, (const BYTE *)patch_squashed, lstrlenA(patch_squashed) + 1);
10441     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10442 
10443     /* Patches value exists, is not REG_MULTI_SZ */
10444     size = MAX_PATH;
10445     lstrcpyA(patch, "apple");
10446     lstrcpyA(transforms, "banana");
10447     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10448     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10449     ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10450     ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10451     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10452 
10453     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ, (const BYTE *)"a\0b\0c\0\0", 7);
10454     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10455 
10456     /* Patches value exists, is not a squashed guid */
10457     size = MAX_PATH;
10458     lstrcpyA(patch, "apple");
10459     lstrcpyA(transforms, "banana");
10460     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10461     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10462     ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10463     ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10464     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10465 
10466     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
10467     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ, (const BYTE *)patch_squashed, lstrlenA(patch_squashed) + 2);
10468     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10469 
10470     /* Patches value exists */
10471     size = MAX_PATH;
10472     lstrcpyA(patch, "apple");
10473     lstrcpyA(transforms, "banana");
10474     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10475     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10476     ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10477     ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10478     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10479 
10480     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ, (const BYTE *)"whatever", 9);
10481     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10482 
10483     /* patch squashed value exists */
10484     size = MAX_PATH;
10485     lstrcpyA(patch, "apple");
10486     lstrcpyA(transforms, "banana");
10487     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10488     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10489     ok(!lstrcmpA(patch, patchcode), "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10490     ok(!lstrcmpA(transforms, "whatever"), "Expected \"whatever\", got \"%s\"\n", transforms);
10491     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %lu\n", size);
10492 
10493     /* lpPatchBuf is NULL */
10494     size = MAX_PATH;
10495     lstrcpyA(transforms, "banana");
10496     r = MsiEnumPatchesA(prodcode, 0, NULL, transforms, &size);
10497     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10498     ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10499     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10500 
10501     /* lpTransformsBuf is NULL, pcchTransformsBuf is not */
10502     size = MAX_PATH;
10503     lstrcpyA(patch, "apple");
10504     r = MsiEnumPatchesA(prodcode, 0, patch, NULL, &size);
10505     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10506     ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10507     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10508 
10509     /* pcchTransformsBuf is NULL, lpTransformsBuf is not */
10510     lstrcpyA(patch, "apple");
10511     lstrcpyA(transforms, "banana");
10512     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, NULL);
10513     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10514     ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10515     ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10516 
10517     /* pcchTransformsBuf is too small */
10518     size = 6;
10519     lstrcpyA(patch, "apple");
10520     lstrcpyA(transforms, "banana");
10521     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10522     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
10523     ok(!lstrcmpA(patch, patchcode), "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10524     ok(!lstrcmpA(transforms, "whate"), "Expected \"whate\", got \"%s\"\n", transforms);
10525     ok(size == 8 || size == 16, "Expected 8 or 16, got %lu\n", size);
10526 
10527     /* increase the index */
10528     size = MAX_PATH;
10529     lstrcpyA(patch, "apple");
10530     lstrcpyA(transforms, "banana");
10531     r = MsiEnumPatchesA(prodcode, 1, patch, transforms, &size);
10532     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10533     ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10534     ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10535     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10536 
10537     /* increase again */
10538     size = MAX_PATH;
10539     lstrcpyA(patch, "apple");
10540     lstrcpyA(transforms, "banana");
10541     r = MsiEnumPatchesA(prodcode, 2, patch, transforms, &size);
10542     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10543     ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10544     ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10545     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10546 
10547     RegDeleteValueA(patches, "Patches");
10548     RegDeleteKeyExA(patches, "", access & KEY_WOW64_64KEY, 0);
10549     RegCloseKey(patches);
10550     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
10551     RegCloseKey(prodkey);
10552 
10553     /* MSIINSTALLCONTEXT_USERUNMANAGED */
10554 
10555     size = MAX_PATH;
10556     lstrcpyA(patch, "apple");
10557     lstrcpyA(transforms, "banana");
10558     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10559     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
10560     ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10561     ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10562     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10563 
10564     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
10565     lstrcatA(keypath, prod_squashed);
10566 
10567     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
10568     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10569 
10570     /* current user product key exists */
10571     size = MAX_PATH;
10572     lstrcpyA(patch, "apple");
10573     lstrcpyA(transforms, "banana");
10574     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10575     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10576     ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10577     ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10578     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10579 
10580     res = RegCreateKeyA(prodkey, "Patches", &patches);
10581     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10582 
10583     /* Patches key exists */
10584     size = MAX_PATH;
10585     lstrcpyA(patch, "apple");
10586     lstrcpyA(transforms, "banana");
10587     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10588     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10589     ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10590     ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10591     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10592 
10593     res = RegSetValueExA(patches, "Patches", 0, REG_SZ, (const BYTE *)patch_squashed, lstrlenA(patch_squashed) + 1);
10594     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10595 
10596     /* Patches value exists, is not REG_MULTI_SZ */
10597     size = MAX_PATH;
10598     lstrcpyA(patch, "apple");
10599     lstrcpyA(transforms, "banana");
10600     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10601     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10602     ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10603     ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10604     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10605 
10606     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ, (const BYTE *)"a\0b\0c\0\0", 7);
10607     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10608 
10609     /* Patches value exists, is not a squashed guid */
10610     size = MAX_PATH;
10611     lstrcpyA(patch, "apple");
10612     lstrcpyA(transforms, "banana");
10613     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10614     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10615     ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10616     ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10617     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10618 
10619     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
10620     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ, (const BYTE *)patch_squashed, lstrlenA(patch_squashed) + 2);
10621     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10622 
10623     /* Patches value exists */
10624     size = MAX_PATH;
10625     lstrcpyA(patch, "apple");
10626     lstrcpyA(transforms, "banana");
10627     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10628     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10629     ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10630     ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10631     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10632 
10633     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ, (const BYTE *)"whatever", 9);
10634     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10635 
10636     /* patch code value exists */
10637     size = MAX_PATH;
10638     lstrcpyA(patch, "apple");
10639     lstrcpyA(transforms, "banana");
10640     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10641     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10642     ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10643     ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10644     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10645 
10646     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
10647     lstrcatA(keypath, usersid);
10648     lstrcatA(keypath, "\\Patches\\");
10649     lstrcatA(keypath, patch_squashed);
10650 
10651     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
10652     if (res == ERROR_ACCESS_DENIED)
10653     {
10654         skip("Not enough rights to perform tests\n");
10655         LocalFree(usersid);
10656         return;
10657     }
10658     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10659 
10660     /* userdata patch key exists */
10661     size = MAX_PATH;
10662     lstrcpyA(patch, "apple");
10663     lstrcpyA(transforms, "banana");
10664     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10665     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10666     ok(!lstrcmpA(patch, patchcode), "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10667     ok(!lstrcmpA(transforms, "whatever"), "Expected \"whatever\", got \"%s\"\n", transforms);
10668     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %lu\n", size);
10669 
10670     RegDeleteKeyExA(userkey, "", access & KEY_WOW64_64KEY, 0);
10671     RegCloseKey(userkey);
10672     RegDeleteValueA(patches, patch_squashed);
10673     RegDeleteValueA(patches, "Patches");
10674     RegDeleteKeyA(patches, "");
10675     RegCloseKey(patches);
10676     RegDeleteKeyA(prodkey, "");
10677     RegCloseKey(prodkey);
10678 
10679     /* MSIINSTALLCONTEXT_MACHINE */
10680 
10681     size = MAX_PATH;
10682     lstrcpyA(patch, "apple");
10683     lstrcpyA(transforms, "banana");
10684     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10685     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
10686     ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10687     ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10688     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10689 
10690     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
10691     lstrcatA(keypath, prod_squashed);
10692 
10693     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
10694     if (res == ERROR_ACCESS_DENIED)
10695     {
10696         skip("Not enough rights to perform tests\n");
10697         LocalFree(usersid);
10698         return;
10699     }
10700     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10701 
10702     /* local product key exists */
10703     size = MAX_PATH;
10704     lstrcpyA(patch, "apple");
10705     lstrcpyA(transforms, "banana");
10706     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10707     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10708     ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10709     ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10710     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10711 
10712     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
10713     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10714 
10715     /* Patches key exists */
10716     size = MAX_PATH;
10717     lstrcpyA(patch, "apple");
10718     lstrcpyA(transforms, "banana");
10719     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10720     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10721     ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10722     ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10723     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10724 
10725     res = RegSetValueExA(patches, "Patches", 0, REG_SZ, (const BYTE *)patch_squashed, lstrlenA(patch_squashed) + 1);
10726     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10727 
10728     /* Patches value exists, is not REG_MULTI_SZ */
10729     size = MAX_PATH;
10730     lstrcpyA(patch, "apple");
10731     lstrcpyA(transforms, "banana");
10732     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10733     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10734     ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10735     ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10736     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10737 
10738     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ, (const BYTE *)"a\0b\0c\0\0", 7);
10739     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10740 
10741     /* Patches value exists, is not a squashed guid */
10742     size = MAX_PATH;
10743     lstrcpyA(patch, "apple");
10744     lstrcpyA(transforms, "banana");
10745     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10746     ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10747     ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10748     ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10749     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10750 
10751     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
10752     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ, (const BYTE *)patch_squashed, lstrlenA(patch_squashed) + 2);
10753     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10754 
10755     /* Patches value exists */
10756     size = MAX_PATH;
10757     lstrcpyA(patch, "apple");
10758     lstrcpyA(transforms, "banana");
10759     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10760     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10761     ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10762     ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10763     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10764 
10765     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ, (const BYTE *)"whatever", 9);
10766     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10767 
10768     /* patch code value exists */
10769     size = MAX_PATH;
10770     lstrcpyA(patch, "apple");
10771     lstrcpyA(transforms, "banana");
10772     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10773     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10774     ok(!lstrcmpA(patch, patchcode), "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10775     ok(!lstrcmpA(transforms, "whatever"), "Expected \"whatever\", got \"%s\"\n", transforms);
10776     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %lu\n", size);
10777 
10778     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
10779     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
10780     lstrcatA(keypath, prod_squashed);
10781 
10782     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
10783     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10784 
10785     /* local UserData product key exists */
10786     size = MAX_PATH;
10787     lstrcpyA(patch, "apple");
10788     lstrcpyA(transforms, "banana");
10789     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10790     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10791     ok(!lstrcmpA(patch, patchcode), "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10792     ok(!lstrcmpA(transforms, "whatever"), "Expected \"whatever\", got \"%s\"\n", transforms);
10793     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %lu\n", size);
10794 
10795     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
10796     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10797 
10798     /* local UserData Patches key exists */
10799     size = MAX_PATH;
10800     lstrcpyA(patch, "apple");
10801     lstrcpyA(transforms, "banana");
10802     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10803     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10804     ok(!lstrcmpA(patch, patchcode), "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10805     ok(!lstrcmpA(transforms, "whatever"), "Expected \"whatever\", got \"%s\"\n", transforms);
10806     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %lu\n", size);
10807 
10808     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
10809     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10810 
10811     /* local UserData Product patch key exists */
10812     size = MAX_PATH;
10813     lstrcpyA(patch, "apple");
10814     lstrcpyA(transforms, "banana");
10815     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10816     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10817     ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10818     ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10819     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10820 
10821     data = MSIPATCHSTATE_APPLIED;
10822     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
10823     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10824 
10825     /* State value exists */
10826     size = MAX_PATH;
10827     lstrcpyA(patch, "apple");
10828     lstrcpyA(transforms, "banana");
10829     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10830     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10831     ok(!lstrcmpA(patch, patchcode), "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10832     ok(!lstrcmpA(transforms, "whatever"), "Expected \"whatever\", got \"%s\"\n", transforms);
10833     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %lu\n", size);
10834 
10835     /* now duplicate some of the tests for the W version */
10836 
10837     /* pcchTransformsBuf is too small */
10838     size = 6;
10839     MultiByteToWideChar( CP_ACP, 0, prodcode, -1, prodcodeW, MAX_PATH );
10840     MultiByteToWideChar( CP_ACP, 0, "apple", -1, patchW, MAX_PATH );
10841     MultiByteToWideChar( CP_ACP, 0, "banana", -1, transformsW, MAX_PATH );
10842     r = MsiEnumPatchesW(prodcodeW, 0, patchW, transformsW, &size);
10843     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
10844     WideCharToMultiByte( CP_ACP, 0, patchW, -1, patch, MAX_PATH, NULL, NULL );
10845     WideCharToMultiByte( CP_ACP, 0, transformsW, -1, transforms, MAX_PATH, NULL, NULL );
10846     ok(!lstrcmpA(patch, patchcode), "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10847     ok(!lstrcmpA(transforms, "whate"), "Expected \"whate\", got \"%s\"\n", transforms);
10848     ok(size == 8, "Expected 8, got %lu\n", size);
10849 
10850     /* patch code value exists */
10851     size = MAX_PATH;
10852     MultiByteToWideChar( CP_ACP, 0, "apple", -1, patchW, MAX_PATH );
10853     MultiByteToWideChar( CP_ACP, 0, "banana", -1, transformsW, MAX_PATH );
10854     r = MsiEnumPatchesW(prodcodeW, 0, patchW, transformsW, &size);
10855     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10856     WideCharToMultiByte( CP_ACP, 0, patchW, -1, patch, MAX_PATH, NULL, NULL );
10857     WideCharToMultiByte( CP_ACP, 0, transformsW, -1, transforms, MAX_PATH, NULL, NULL );
10858     ok(!lstrcmpA(patch, patchcode), "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10859     ok(!lstrcmpA(transforms, "whatever"), "Expected \"whatever\", got \"%s\"\n", transforms);
10860     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %lu\n", size);
10861 
10862     RegDeleteValueA(patches, patch_squashed);
10863     RegDeleteValueA(patches, "Patches");
10864     RegDeleteKeyExA(patches, "", access & KEY_WOW64_64KEY, 0);
10865     RegCloseKey(patches);
10866     RegDeleteValueA(hpatch, "State");
10867     RegDeleteKeyExA(hpatch, "", access & KEY_WOW64_64KEY, 0);
10868     RegCloseKey(hpatch);
10869     RegDeleteKeyExA(udpatch, "", access & KEY_WOW64_64KEY, 0);
10870     RegCloseKey(udpatch);
10871     RegDeleteKeyExA(udprod, "", access & KEY_WOW64_64KEY, 0);
10872     RegCloseKey(udprod);
10873     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
10874     RegCloseKey(prodkey);
10875     LocalFree(usersid);
10876 }
10877 
test_MsiGetPatchInfoEx(void)10878 static void test_MsiGetPatchInfoEx(void)
10879 {
10880     CHAR keypath[MAX_PATH], val[MAX_PATH];
10881     CHAR patchcode[MAX_PATH], patch_squashed[MAX_PATH];
10882     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
10883     HKEY prodkey, patches, udprod, props;
10884     HKEY hpatch, udpatch, prodpatches;
10885     LPSTR usersid;
10886     DWORD size;
10887     LONG res;
10888     UINT r;
10889     REGSAM access = KEY_ALL_ACCESS;
10890 
10891     create_test_guid(prodcode, prod_squashed);
10892     create_test_guid(patchcode, patch_squashed);
10893     usersid = get_user_sid();
10894 
10895     if (is_wow64)
10896         access |= KEY_WOW64_64KEY;
10897 
10898     /* NULL szPatchCode */
10899     lstrcpyA(val, "apple");
10900     size = MAX_PATH;
10901     r = MsiGetPatchInfoExA(NULL, prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
10902                            val, &size);
10903     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10904     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
10905     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10906 
10907     /* empty szPatchCode */
10908     size = MAX_PATH;
10909     lstrcpyA(val, "apple");
10910     r = MsiGetPatchInfoExA("", prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
10911                            val, &size);
10912     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10913     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
10914     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10915 
10916     /* garbage szPatchCode */
10917     size = MAX_PATH;
10918     lstrcpyA(val, "apple");
10919     r = MsiGetPatchInfoExA("garbage", prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
10920                            val, &size);
10921     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10922     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
10923     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10924 
10925     /* guid without brackets */
10926     size = MAX_PATH;
10927     lstrcpyA(val, "apple");
10928     r = MsiGetPatchInfoExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED,
10929                            INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
10930     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10931     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
10932     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10933 
10934     /* guid with brackets */
10935     size = MAX_PATH;
10936     lstrcpyA(val, "apple");
10937     r = MsiGetPatchInfoExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED,
10938                            INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
10939     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
10940     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
10941     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10942 
10943     /* same length as guid, but random */
10944     size = MAX_PATH;
10945     lstrcpyA(val, "apple");
10946     r = MsiGetPatchInfoExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED,
10947                            INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
10948     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10949     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
10950     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10951 
10952     /* NULL szProductCode */
10953     lstrcpyA(val, "apple");
10954     size = MAX_PATH;
10955     r = MsiGetPatchInfoExA(patchcode, NULL, NULL, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
10956                            val, &size);
10957     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10958     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
10959     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10960 
10961     /* empty szProductCode */
10962     size = MAX_PATH;
10963     lstrcpyA(val, "apple");
10964     r = MsiGetPatchInfoExA(patchcode, "", NULL, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
10965                            val, &size);
10966     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10967     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
10968     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10969 
10970     /* garbage szProductCode */
10971     size = MAX_PATH;
10972     lstrcpyA(val, "apple");
10973     r = MsiGetPatchInfoExA(patchcode, "garbage", NULL, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
10974                            val, &size);
10975     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10976     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
10977     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10978 
10979     /* guid without brackets */
10980     size = MAX_PATH;
10981     lstrcpyA(val, "apple");
10982     r = MsiGetPatchInfoExA(patchcode, "6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", NULL, MSIINSTALLCONTEXT_USERMANAGED,
10983                            INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
10984     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10985     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
10986     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10987 
10988     /* guid with brackets */
10989     size = MAX_PATH;
10990     lstrcpyA(val, "apple");
10991     r = MsiGetPatchInfoExA(patchcode, "{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", NULL, MSIINSTALLCONTEXT_USERMANAGED,
10992                            INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
10993     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
10994     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
10995     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10996 
10997     /* same length as guid, but random */
10998     size = MAX_PATH;
10999     lstrcpyA(val, "apple");
11000     r = MsiGetPatchInfoExA(patchcode, "A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", NULL, MSIINSTALLCONTEXT_USERMANAGED,
11001                            INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11002     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11003     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11004     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11005 
11006     /* szUserSid cannot be S-1-5-18 for MSIINSTALLCONTEXT_USERMANAGED */
11007     size = MAX_PATH;
11008     lstrcpyA(val, "apple");
11009     r = MsiGetPatchInfoExA(patchcode, prodcode, "S-1-5-18", MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
11010                            val, &size);
11011     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11012     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11013     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11014 
11015     /* szUserSid cannot be S-1-5-18 for MSIINSTALLCONTEXT_USERUNMANAGED */
11016     size = MAX_PATH;
11017     lstrcpyA(val, "apple");
11018     r = MsiGetPatchInfoExA(patchcode, prodcode, "S-1-5-18", MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
11019                            val, &size);
11020     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11021     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11022     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11023 
11024     /* szUserSid cannot be S-1-5-18 for MSIINSTALLCONTEXT_MACHINE */
11025     size = MAX_PATH;
11026     lstrcpyA(val, "apple");
11027     r = MsiGetPatchInfoExA(patchcode, prodcode, "S-1-5-18", MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_LOCALPACKAGEA,
11028                            val, &size);
11029     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11030     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11031     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11032 
11033     /* szUserSid must be NULL for MSIINSTALLCONTEXT_MACHINE */
11034     size = MAX_PATH;
11035     lstrcpyA(val, "apple");
11036     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_LOCALPACKAGEA,
11037                            val, &size);
11038     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11039     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11040     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11041 
11042     /* dwContext is out of range */
11043     size = MAX_PATH;
11044     lstrcpyA(val, "apple");
11045     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_NONE, INSTALLPROPERTY_LOCALPACKAGEA,
11046                            val, &size);
11047     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11048     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11049     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11050 
11051     /* dwContext is out of range */
11052     size = MAX_PATH;
11053     lstrcpyA(val, "apple");
11054     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_ALL, INSTALLPROPERTY_LOCALPACKAGEA,
11055                            val, &size);
11056     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11057     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11058     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11059 
11060     /* dwContext is invalid */
11061     size = MAX_PATH;
11062     lstrcpyA(val, "apple");
11063     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, 3, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11064     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11065     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11066     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11067 
11068     /* MSIINSTALLCONTEXT_USERMANAGED */
11069 
11070     size = MAX_PATH;
11071     lstrcpyA(val, "apple");
11072     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
11073                            val, &size);
11074     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11075     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11076     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11077 
11078     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
11079     lstrcatA(keypath, usersid);
11080     lstrcatA(keypath, "\\Products\\");
11081     lstrcatA(keypath, prod_squashed);
11082 
11083     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
11084     if (res == ERROR_ACCESS_DENIED)
11085     {
11086         skip("Not enough rights to perform tests\n");
11087         LocalFree(usersid);
11088         return;
11089     }
11090     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11091 
11092     /* local UserData product key exists */
11093     size = MAX_PATH;
11094     lstrcpyA(val, "apple");
11095     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
11096                            val, &size);
11097     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11098     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11099     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11100 
11101     res = RegCreateKeyExA(udprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
11102     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11103 
11104     /* InstallProperties key exists */
11105     size = MAX_PATH;
11106     lstrcpyA(val, "apple");
11107     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
11108                            val, &size);
11109     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11110     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11111     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11112 
11113     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
11114     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11115 
11116     /* Patches key exists */
11117     size = MAX_PATH;
11118     lstrcpyA(val, "apple");
11119     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
11120                            val, &size);
11121     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCHA, got %d\n", r);
11122     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11123     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11124 
11125     res = RegCreateKeyExA(patches, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
11126     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11127 
11128     /* Patches key exists */
11129     size = MAX_PATH;
11130     lstrcpyA(val, "apple");
11131     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
11132                            val, &size);
11133     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11134     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11135     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11136 
11137     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
11138     lstrcatA(keypath, usersid);
11139     lstrcatA(keypath, "\\Installer\\Products\\");
11140     lstrcatA(keypath, prod_squashed);
11141 
11142     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
11143     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11144 
11145     /* managed product key exists */
11146     size = MAX_PATH;
11147     lstrcpyA(val, "apple");
11148     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
11149                            val, &size);
11150     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11151     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11152     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11153 
11154     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &prodpatches, NULL);
11155     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11156 
11157     /* Patches key exists */
11158     size = MAX_PATH;
11159     lstrcpyA(val, "apple");
11160     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
11161                            val, &size);
11162     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11163     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11164     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11165 
11166     res = RegSetValueExA(prodpatches, patch_squashed, 0, REG_SZ, (const BYTE *)"transforms", 11);
11167     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11168 
11169     /* specific patch value exists */
11170     size = MAX_PATH;
11171     lstrcpyA(val, "apple");
11172     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
11173                            val, &size);
11174     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11175     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11176     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11177 
11178     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
11179     lstrcatA(keypath, usersid);
11180     lstrcatA(keypath, "\\Patches\\");
11181     lstrcatA(keypath, patch_squashed);
11182 
11183     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udpatch, NULL);
11184     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11185 
11186     /* UserData Patches key exists */
11187     size = MAX_PATH;
11188     lstrcpyA(val, "apple");
11189     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
11190                            val, &size);
11191     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11192     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
11193     ok(size == 0, "Expected 0, got %lu\n", size);
11194 
11195     res = RegSetValueExA(udpatch, "ManagedLocalPackage", 0, REG_SZ, (const BYTE *)"pack", 5);
11196     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11197 
11198     /* ManagedLocalPatch value exists */
11199     size = MAX_PATH;
11200     lstrcpyA(val, "apple");
11201     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
11202                            val, &size);
11203     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11204     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
11205     ok(size == 4, "Expected 4, got %lu\n", size);
11206 
11207     size = MAX_PATH;
11208     lstrcpyA(val, "apple");
11209     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_TRANSFORMSA,
11210                            val, &size);
11211     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11212     ok(!lstrcmpA(val, "transforms"), "Expected \"transforms\", got \"%s\"\n", val);
11213     ok(size == 10, "Expected 10, got %lu\n", size);
11214 
11215     res = RegSetValueExA(hpatch, "Installed", 0, REG_SZ, (const BYTE *)"mydate", 7);
11216     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11217 
11218     /* Installed value exists */
11219     size = MAX_PATH;
11220     lstrcpyA(val, "apple");
11221     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_INSTALLDATEA,
11222                            val, &size);
11223     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11224     ok(!lstrcmpA(val, "mydate"), "Expected \"mydate\", got \"%s\"\n", val);
11225     ok(size == 6, "Expected 6, got %lu\n", size);
11226 
11227     res = RegSetValueExA(hpatch, "Uninstallable", 0, REG_SZ, (const BYTE *)"yes", 4);
11228     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11229 
11230     /* Uninstallable value exists */
11231     size = MAX_PATH;
11232     lstrcpyA(val, "apple");
11233     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_UNINSTALLABLEA,
11234                            val, &size);
11235     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11236     ok(!lstrcmpA(val, "yes"), "Expected \"yes\", got \"%s\"\n", val);
11237     ok(size == 3, "Expected 3, got %lu\n", size);
11238 
11239     res = RegSetValueExA(hpatch, "State", 0, REG_SZ, (const BYTE *)"good", 5);
11240     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11241 
11242     /* State value exists */
11243     size = MAX_PATH;
11244     lstrcpyA(val, "apple");
11245     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_PATCHSTATEA,
11246                            val, &size);
11247     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11248     ok(!lstrcmpA(val, "good"), "Expected \"good\", got \"%s\"\n", val);
11249     ok(size == 4, "Expected 4, got %lu\n", size);
11250 
11251     size = 1;
11252     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD, (const BYTE *)&size, sizeof(DWORD));
11253     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11254 
11255     /* State value exists */
11256     size = MAX_PATH;
11257     lstrcpyA(val, "apple");
11258     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_PATCHSTATEA,
11259                            val, &size);
11260     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11261     ok(!lstrcmpA(val, "1"), "Expected \"1\", got \"%s\"\n", val);
11262     ok(size == 1, "Expected 1, got %lu\n", size);
11263 
11264     size = 1;
11265     res = RegSetValueExA(hpatch, "Uninstallable", 0, REG_DWORD, (const BYTE *)&size, sizeof(DWORD));
11266     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11267 
11268     /* Uninstallable value exists */
11269     size = MAX_PATH;
11270     lstrcpyA(val, "apple");
11271     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_UNINSTALLABLEA,
11272                            val, &size);
11273     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11274     ok(!lstrcmpA(val, "1"), "Expected \"1\", got \"%s\"\n", val);
11275     ok(size == 1, "Expected 1, got %lu\n", size);
11276 
11277     res = RegSetValueExA(hpatch, "DisplayName", 0, REG_SZ, (const BYTE *)"display", 8);
11278     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11279 
11280     /* DisplayName value exists */
11281     size = MAX_PATH;
11282     lstrcpyA(val, "apple");
11283     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_DISPLAYNAMEA,
11284                            val, &size);
11285     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11286     ok(!lstrcmpA(val, "display"), "Expected \"display\", got \"%s\"\n", val);
11287     ok(size == 7, "Expected 7, got %lu\n", size);
11288 
11289     res = RegSetValueExA(hpatch, "MoreInfoURL", 0, REG_SZ, (const BYTE *)"moreinfo", 9);
11290     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11291 
11292     /* MoreInfoURL value exists */
11293     size = MAX_PATH;
11294     lstrcpyA(val, "apple");
11295     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_MOREINFOURLA,
11296                            val, &size);
11297     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11298     ok(!lstrcmpA(val, "moreinfo"), "Expected \"moreinfo\", got \"%s\"\n", val);
11299     ok(size == 8, "Expected 8, got %lu\n", size);
11300 
11301     /* szProperty is invalid */
11302     size = MAX_PATH;
11303     lstrcpyA(val, "apple");
11304     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, "IDontExist", val, &size);
11305     ok(r == ERROR_UNKNOWN_PROPERTY, "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
11306     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
11307     ok(size == MAX_PATH, "Expected MAX_PATH, got %lu\n", size);
11308 
11309     /* lpValue is NULL, while pcchValue is non-NULL */
11310     size = MAX_PATH;
11311     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_MOREINFOURLA,
11312                            NULL, &size);
11313     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11314     ok(size == 16, "Expected 16, got %lu\n", size);
11315 
11316     /* pcchValue is NULL, while lpValue is non-NULL */
11317     lstrcpyA(val, "apple");
11318     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_MOREINFOURLA,
11319                            val, NULL);
11320     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11321     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
11322 
11323     /* both lpValue and pcchValue are NULL */
11324     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_MOREINFOURLA,
11325                            NULL, NULL);
11326     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11327 
11328     /* pcchValue doesn't have enough room for NULL terminator */
11329     size = 8;
11330     lstrcpyA(val, "apple");
11331     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_MOREINFOURLA,
11332                            val, &size);
11333     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
11334     ok(!lstrcmpA(val, "moreinf"), "Expected \"moreinf\", got \"%s\"\n", val);
11335     ok(size == 16, "Expected 16, got %lu\n", size);
11336 
11337     /* pcchValue has exactly enough room for NULL terminator */
11338     size = 9;
11339     lstrcpyA(val, "apple");
11340     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_MOREINFOURLA,
11341                            val, &size);
11342     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11343     ok(!lstrcmpA(val, "moreinfo"), "Expected \"moreinfo\", got \"%s\"\n", val);
11344     ok(size == 8, "Expected 8, got %lu\n", size);
11345 
11346     /* pcchValue is too small, lpValue is NULL */
11347     size = 0;
11348     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_MOREINFOURLA,
11349                            NULL, &size);
11350     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11351     ok(size == 16, "Expected 16, got %lu\n", size);
11352 
11353     RegDeleteValueA(prodpatches, patch_squashed);
11354     RegDeleteKeyExA(prodpatches, "", access & KEY_WOW64_64KEY, 0);
11355     RegCloseKey(prodpatches);
11356     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
11357     RegCloseKey(prodkey);
11358 
11359     /* UserData is sufficient for all properties
11360      * except INSTALLPROPERTY_TRANSFORMS
11361      */
11362     size = MAX_PATH;
11363     lstrcpyA(val, "apple");
11364     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
11365                            val, &size);
11366     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11367     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
11368     ok(size == 4, "Expected 4, got %lu\n", size);
11369 
11370     /* UserData is sufficient for all properties
11371      * except INSTALLPROPERTY_TRANSFORMS
11372      */
11373     size = MAX_PATH;
11374     lstrcpyA(val, "apple");
11375     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED, INSTALLPROPERTY_TRANSFORMSA,
11376                            val, &size);
11377     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11378     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
11379     ok(size == MAX_PATH, "Expected MAX_PATH, got %lu\n", size);
11380 
11381     RegDeleteValueA(hpatch, "MoreInfoURL");
11382     RegDeleteValueA(hpatch, "Display");
11383     RegDeleteValueA(hpatch, "State");
11384     RegDeleteValueA(hpatch, "Uninstallable");
11385     RegDeleteValueA(hpatch, "Installed");
11386     RegDeleteValueA(udpatch, "ManagedLocalPackage");
11387     RegDeleteKeyExA(udpatch, "", access & KEY_WOW64_64KEY, 0);
11388     RegCloseKey(udpatch);
11389     RegDeleteKeyExA(hpatch, "", access & KEY_WOW64_64KEY, 0);
11390     RegCloseKey(hpatch);
11391     RegDeleteKeyExA(patches, "", access & KEY_WOW64_64KEY, 0);
11392     RegCloseKey(patches);
11393     RegDeleteKeyExA(props, "", access & KEY_WOW64_64KEY, 0);
11394     RegCloseKey(props);
11395     RegDeleteKeyExA(udprod, "", access & KEY_WOW64_64KEY, 0);
11396     RegCloseKey(udprod);
11397 
11398     /* MSIINSTALLCONTEXT_USERUNMANAGED */
11399 
11400     size = MAX_PATH;
11401     lstrcpyA(val, "apple");
11402     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
11403                            val, &size);
11404     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11405     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11406     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11407 
11408     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
11409     lstrcatA(keypath, usersid);
11410     lstrcatA(keypath, "\\Products\\");
11411     lstrcatA(keypath, prod_squashed);
11412 
11413     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
11414     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11415 
11416     /* local UserData product key exists */
11417     size = MAX_PATH;
11418     lstrcpyA(val, "apple");
11419     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
11420                            val, &size);
11421     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11422     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11423     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11424 
11425     res = RegCreateKeyExA(udprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
11426     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11427 
11428     /* InstallProperties key exists */
11429     size = MAX_PATH;
11430     lstrcpyA(val, "apple");
11431     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
11432                            val, &size);
11433     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11434     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11435     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11436 
11437     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
11438     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11439 
11440     /* Patches key exists */
11441     size = MAX_PATH;
11442     lstrcpyA(val, "apple");
11443     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
11444                            val, &size);
11445     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11446     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11447     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11448 
11449     res = RegCreateKeyExA(patches, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
11450     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11451 
11452     /* Patches key exists */
11453     size = MAX_PATH;
11454     lstrcpyA(val, "apple");
11455     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
11456                            val, &size);
11457     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11458     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11459     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11460 
11461     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
11462     lstrcatA(keypath, prod_squashed);
11463 
11464     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
11465     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11466 
11467     /* current user product key exists */
11468     size = MAX_PATH;
11469     lstrcpyA(val, "apple");
11470     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
11471                            val, &size);
11472     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11473     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11474     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11475 
11476     res = RegCreateKeyA(prodkey, "Patches", &prodpatches);
11477     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11478 
11479     /* Patches key exists */
11480     size = MAX_PATH;
11481     lstrcpyA(val, "apple");
11482     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
11483                            val, &size);
11484     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11485     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11486     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11487 
11488     res = RegSetValueExA(prodpatches, patch_squashed, 0, REG_SZ,
11489                          (const BYTE *)"transforms", 11);
11490     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11491 
11492     /* specific patch value exists */
11493     size = MAX_PATH;
11494     lstrcpyA(val, "apple");
11495     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
11496                            val, &size);
11497     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11498     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11499     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11500 
11501     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
11502     lstrcatA(keypath, usersid);
11503     lstrcatA(keypath, "\\Patches\\");
11504     lstrcatA(keypath, patch_squashed);
11505 
11506     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udpatch, NULL);
11507     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11508 
11509     /* UserData Patches key exists */
11510     size = MAX_PATH;
11511     lstrcpyA(val, "apple");
11512     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
11513                            val, &size);
11514     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11515     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
11516     ok(size == 0, "Expected 0, got %lu\n", size);
11517 
11518     res = RegSetValueExA(udpatch, "LocalPackage", 0, REG_SZ,
11519                          (const BYTE *)"pack", 5);
11520     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11521 
11522     /* LocalPatch value exists */
11523     size = MAX_PATH;
11524     lstrcpyA(val, "apple");
11525     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
11526                            val, &size);
11527     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11528     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
11529     ok(size == 4, "Expected 4, got %lu\n", size);
11530 
11531     size = MAX_PATH;
11532     lstrcpyA(val, "apple");
11533     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_TRANSFORMSA,
11534                            val, &size);
11535     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11536     ok(!lstrcmpA(val, "transforms"), "Expected \"transforms\", got \"%s\"\n", val);
11537     ok(size == 10, "Expected 10, got %lu\n", size);
11538 
11539     RegDeleteValueA(prodpatches, patch_squashed);
11540     RegDeleteKeyExA(prodpatches, "", access & KEY_WOW64_64KEY, 0);
11541     RegCloseKey(prodpatches);
11542     RegDeleteKeyA(prodkey, "");
11543     RegCloseKey(prodkey);
11544 
11545     /* UserData is sufficient for all properties
11546      * except INSTALLPROPERTY_TRANSFORMS
11547      */
11548     size = MAX_PATH;
11549     lstrcpyA(val, "apple");
11550     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_LOCALPACKAGEA,
11551                            val, &size);
11552     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11553     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
11554     ok(size == 4, "Expected 4, got %lu\n", size);
11555 
11556     /* UserData is sufficient for all properties
11557      * except INSTALLPROPERTY_TRANSFORMS
11558      */
11559     size = MAX_PATH;
11560     lstrcpyA(val, "apple");
11561     r = MsiGetPatchInfoExA(patchcode, prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_TRANSFORMSA,
11562                            val, &size);
11563     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11564     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
11565     ok(size == MAX_PATH, "Expected MAX_PATH, got %lu\n", size);
11566 
11567     RegDeleteValueA(udpatch, "LocalPackage");
11568     RegDeleteKeyExA(udpatch, "", access & KEY_WOW64_64KEY, 0);
11569     RegCloseKey(udpatch);
11570     RegDeleteKeyExA(hpatch, "", access & KEY_WOW64_64KEY, 0);
11571     RegCloseKey(hpatch);
11572     RegDeleteKeyExA(patches, "", access & KEY_WOW64_64KEY, 0);
11573     RegCloseKey(patches);
11574     RegDeleteKeyExA(props, "", access & KEY_WOW64_64KEY, 0);
11575     RegCloseKey(props);
11576     RegDeleteKeyExA(udprod, "", access & KEY_WOW64_64KEY, 0);
11577     RegCloseKey(udprod);
11578 
11579     /* MSIINSTALLCONTEXT_MACHINE */
11580 
11581     size = MAX_PATH;
11582     lstrcpyA(val, "apple");
11583     r = MsiGetPatchInfoExA(patchcode, prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_LOCALPACKAGEA,
11584                            val, &size);
11585     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11586     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11587     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11588 
11589     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
11590     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Products\\");
11591     lstrcatA(keypath, prod_squashed);
11592 
11593     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
11594     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11595 
11596     /* local UserData product key exists */
11597     size = MAX_PATH;
11598     lstrcpyA(val, "apple");
11599     r = MsiGetPatchInfoExA(patchcode, prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_LOCALPACKAGEA,
11600                            val, &size);
11601     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11602     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11603     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11604 
11605     res = RegCreateKeyExA(udprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
11606     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11607 
11608     /* InstallProperties key exists */
11609     size = MAX_PATH;
11610     lstrcpyA(val, "apple");
11611     r = MsiGetPatchInfoExA(patchcode, prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_LOCALPACKAGEA,
11612                            val, &size);
11613     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11614     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11615     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11616 
11617     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
11618     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11619 
11620     /* Patches key exists */
11621     size = MAX_PATH;
11622     lstrcpyA(val, "apple");
11623     r = MsiGetPatchInfoExA(patchcode, prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_LOCALPACKAGEA,
11624                            val, &size);
11625     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11626     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11627     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11628 
11629     res = RegCreateKeyExA(patches, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
11630     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11631 
11632     /* Patches key exists */
11633     size = MAX_PATH;
11634     lstrcpyA(val, "apple");
11635     r = MsiGetPatchInfoExA(patchcode, prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_LOCALPACKAGEA,
11636                            val, &size);
11637     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11638     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11639     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11640 
11641     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
11642     lstrcatA(keypath, prod_squashed);
11643 
11644     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
11645     if (res == ERROR_ACCESS_DENIED)
11646     {
11647         skip( "insufficient rights\n" );
11648         LocalFree( usersid );
11649         return;
11650     }
11651     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11652 
11653     /* local product key exists */
11654     size = MAX_PATH;
11655     lstrcpyA(val, "apple");
11656     r = MsiGetPatchInfoExA(patchcode, prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_LOCALPACKAGEA,
11657                            val, &size);
11658     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11659     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11660     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11661 
11662     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &prodpatches, NULL);
11663     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11664 
11665     /* Patches key exists */
11666     size = MAX_PATH;
11667     lstrcpyA(val, "apple");
11668     r = MsiGetPatchInfoExA(patchcode, prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_LOCALPACKAGEA,
11669                            val, &size);
11670     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11671     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11672     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11673 
11674     res = RegSetValueExA(prodpatches, patch_squashed, 0, REG_SZ,
11675                          (const BYTE *)"transforms", 11);
11676     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11677 
11678     /* specific patch value exists */
11679     size = MAX_PATH;
11680     lstrcpyA(val, "apple");
11681     r = MsiGetPatchInfoExA(patchcode, prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_LOCALPACKAGEA,
11682                            val, &size);
11683     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11684     ok(!lstrcmpA(val, "apple"), "Expected val to be unchanged, got \"%s\"\n", val);
11685     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
11686 
11687     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
11688     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Patches\\");
11689     lstrcatA(keypath, patch_squashed);
11690 
11691     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udpatch, NULL);
11692     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11693 
11694     /* UserData Patches key exists */
11695     size = MAX_PATH;
11696     lstrcpyA(val, "apple");
11697     r = MsiGetPatchInfoExA(patchcode, prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_LOCALPACKAGEA,
11698                            val, &size);
11699     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11700     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
11701     ok(size == 0, "Expected 0, got %lu\n", size);
11702 
11703     res = RegSetValueExA(udpatch, "LocalPackage", 0, REG_SZ, (const BYTE *)"pack", 5);
11704     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11705 
11706     /* LocalPatch value exists */
11707     size = MAX_PATH;
11708     lstrcpyA(val, "apple");
11709     r = MsiGetPatchInfoExA(patchcode, prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_LOCALPACKAGEA,
11710                            val, &size);
11711     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11712     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
11713     ok(size == 4, "Expected 4, got %lu\n", size);
11714 
11715     size = MAX_PATH;
11716     lstrcpyA(val, "apple");
11717     r = MsiGetPatchInfoExA(patchcode, prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_TRANSFORMSA,
11718                            val, &size);
11719     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11720     ok(!lstrcmpA(val, "transforms"), "Expected \"transforms\", got \"%s\"\n", val);
11721     ok(size == 10, "Expected 10, got %lu\n", size);
11722 
11723     RegDeleteValueA(prodpatches, patch_squashed);
11724     RegDeleteKeyExA(prodpatches, "", access & KEY_WOW64_64KEY, 0);
11725     RegCloseKey(prodpatches);
11726     RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
11727     RegCloseKey(prodkey);
11728 
11729     /* UserData is sufficient for all properties
11730      * except INSTALLPROPERTY_TRANSFORMS
11731      */
11732     size = MAX_PATH;
11733     lstrcpyA(val, "apple");
11734     r = MsiGetPatchInfoExA(patchcode, prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_LOCALPACKAGEA,
11735                            val, &size);
11736     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11737     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
11738     ok(size == 4, "Expected 4, got %lu\n", size);
11739 
11740     /* UserData is sufficient for all properties
11741      * except INSTALLPROPERTY_TRANSFORMS
11742      */
11743     size = MAX_PATH;
11744     lstrcpyA(val, "apple");
11745     r = MsiGetPatchInfoExA(patchcode, prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_TRANSFORMSA,
11746                            val, &size);
11747     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11748     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
11749     ok(size == MAX_PATH, "Expected MAX_PATH, got %lu\n", size);
11750 
11751     RegDeleteValueA(udpatch, "LocalPackage");
11752     RegDeleteKeyExA(udpatch, "", access & KEY_WOW64_64KEY, 0);
11753     RegCloseKey(udpatch);
11754     RegDeleteKeyExA(hpatch, "", access & KEY_WOW64_64KEY, 0);
11755     RegCloseKey(hpatch);
11756     RegDeleteKeyExA(patches, "", access & KEY_WOW64_64KEY, 0);
11757     RegCloseKey(patches);
11758     RegDeleteKeyExA(props, "", access & KEY_WOW64_64KEY, 0);
11759     RegCloseKey(props);
11760     RegDeleteKeyExA(udprod, "", access & KEY_WOW64_64KEY, 0);
11761     RegCloseKey(udprod);
11762     LocalFree(usersid);
11763 }
11764 
test_MsiGetPatchInfo(void)11765 static void test_MsiGetPatchInfo(void)
11766 {
11767     UINT r;
11768     char prod_code[MAX_PATH], prod_squashed[MAX_PATH], val[MAX_PATH];
11769     char patch_code[MAX_PATH], patch_squashed[MAX_PATH], keypath[MAX_PATH];
11770     WCHAR valW[MAX_PATH], patch_codeW[MAX_PATH];
11771     HKEY hkey_product, hkey_patch, hkey_patches, hkey_udprops, hkey_udproduct;
11772     HKEY hkey_udpatch, hkey_udpatches, hkey_udproductpatches, hkey_udproductpatch;
11773     DWORD size;
11774     LONG res;
11775     REGSAM access = KEY_ALL_ACCESS;
11776 
11777     create_test_guid(patch_code, patch_squashed);
11778     create_test_guid(prod_code, prod_squashed);
11779     MultiByteToWideChar(CP_ACP, 0, patch_code, -1, patch_codeW, MAX_PATH);
11780 
11781     if (is_wow64)
11782         access |= KEY_WOW64_64KEY;
11783 
11784     r = MsiGetPatchInfoA(NULL, NULL, NULL, NULL);
11785     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
11786 
11787     r = MsiGetPatchInfoA(patch_code, NULL, NULL, NULL);
11788     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
11789 
11790     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, NULL, NULL);
11791     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
11792 
11793     size = 0;
11794     r = MsiGetPatchInfoA(patch_code, NULL, NULL, &size);
11795     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
11796 
11797     r = MsiGetPatchInfoA(patch_code, "", NULL, &size);
11798     ok(r == ERROR_UNKNOWN_PROPERTY, "expected ERROR_UNKNOWN_PROPERTY, got %u\n", r);
11799 
11800     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
11801     lstrcatA(keypath, prod_squashed);
11802 
11803     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey_product, NULL);
11804     if (res == ERROR_ACCESS_DENIED)
11805     {
11806         skip("Not enough rights to perform tests\n");
11807         return;
11808     }
11809     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %ld\n", res);
11810 
11811     /* product key exists */
11812     size = MAX_PATH;
11813     lstrcpyA(val, "apple");
11814     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11815     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
11816     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged, got \"%s\"\n", val);
11817     ok(size == MAX_PATH, "expected size to be unchanged got %lu\n", size);
11818 
11819     res = RegCreateKeyExA(hkey_product, "Patches", 0, NULL, 0, access, NULL, &hkey_patches, NULL);
11820     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %ld\n", res);
11821 
11822     /* patches key exists */
11823     size = MAX_PATH;
11824     lstrcpyA(val, "apple");
11825     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11826     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
11827     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
11828     ok(size == MAX_PATH, "expected size to be unchanged got %lu\n", size);
11829 
11830     res = RegCreateKeyExA(hkey_patches, patch_squashed, 0, NULL, 0, access, NULL, &hkey_patch, NULL);
11831     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %ld\n", res);
11832 
11833     /* patch key exists */
11834     size = MAX_PATH;
11835     lstrcpyA(val, "apple");
11836     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11837     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
11838     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
11839     ok(size == MAX_PATH, "expected size to be unchanged got %lu\n", size);
11840 
11841     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
11842     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Products\\");
11843     lstrcatA(keypath, prod_squashed);
11844 
11845     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey_udproduct, NULL);
11846     if (res == ERROR_ACCESS_DENIED)
11847     {
11848         skip("Not enough rights to perform tests\n");
11849         goto done;
11850     }
11851     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %ld\n", res);
11852 
11853     /* UserData product key exists */
11854     size = MAX_PATH;
11855     lstrcpyA(val, "apple");
11856     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11857     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
11858     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
11859     ok(size == MAX_PATH, "expected size to be unchanged got %lu\n", size);
11860 
11861     res = RegCreateKeyExA(hkey_udproduct, "InstallProperties", 0, NULL, 0, access, NULL, &hkey_udprops, NULL);
11862     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %ld\n", res);
11863 
11864     /* InstallProperties key exists */
11865     size = MAX_PATH;
11866     lstrcpyA(val, "apple");
11867     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11868     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
11869     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged, got \"%s\"\n", val);
11870     ok(size == MAX_PATH, "expected size to be unchanged got %lu\n", size);
11871 
11872     res = RegCreateKeyExA(hkey_udproduct, "Patches", 0, NULL, 0, access, NULL, &hkey_udpatches, NULL);
11873     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %ld\n", res);
11874 
11875     /* UserData Patches key exists */
11876     size = MAX_PATH;
11877     lstrcpyA(val, "apple");
11878     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11879     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
11880     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
11881     ok(size == MAX_PATH, "expected size to be unchanged got %lu\n", size);
11882 
11883     res = RegCreateKeyExA(hkey_udproduct, "Patches", 0, NULL, 0, access, NULL, &hkey_udproductpatches, NULL);
11884     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11885 
11886     res = RegCreateKeyExA(hkey_udproductpatches, patch_squashed, 0, NULL, 0, access, NULL, &hkey_udproductpatch, NULL);
11887     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
11888 
11889     /* UserData product patch key exists */
11890     size = MAX_PATH;
11891     lstrcpyA(val, "apple");
11892     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11893     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
11894     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
11895     ok(size == MAX_PATH, "expected size to be unchanged got %lu\n", size);
11896 
11897     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
11898     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Patches\\");
11899     lstrcatA(keypath, patch_squashed);
11900 
11901     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey_udpatch, NULL);
11902     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %ld\n", res);
11903 
11904     res = RegSetValueExA(hkey_udpatch, "LocalPackage", 0, REG_SZ, (const BYTE *)"c:\\test.msp", 12);
11905     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %ld\n", res);
11906 
11907     /* UserData Patch key exists */
11908     size = 0;
11909     lstrcpyA(val, "apple");
11910     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11911     ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", r);
11912     ok(!lstrcmpA(val, "apple"), "expected \"apple\", got \"%s\"\n", val);
11913     ok(size == 11, "expected 11 got %lu\n", size);
11914 
11915     size = MAX_PATH;
11916     lstrcpyA(val, "apple");
11917     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11918     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS got %u\n", r);
11919     ok(!lstrcmpA(val, "c:\\test.msp"), "expected \"c:\\test.msp\", got \"%s\"\n", val);
11920     ok(size == 11, "expected 11 got %lu\n", size);
11921 
11922     size = 0;
11923     valW[0] = 0;
11924     r = MsiGetPatchInfoW(patch_codeW, INSTALLPROPERTY_LOCALPACKAGEW, valW, &size);
11925     ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", r);
11926     ok(!valW[0], "expected 0 got %u\n", valW[0]);
11927     ok(size == 11, "expected 11 got %lu\n", size);
11928 
11929     size = MAX_PATH;
11930     valW[0] = 0;
11931     r = MsiGetPatchInfoW(patch_codeW, INSTALLPROPERTY_LOCALPACKAGEW, valW, &size);
11932     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS got %u\n", r);
11933     ok(valW[0], "expected > 0 got %u\n", valW[0]);
11934     ok(size == 11, "expected 11 got %lu\n", size);
11935 
11936     RegDeleteKeyExA(hkey_udproductpatch, "", access & KEY_WOW64_64KEY, 0);
11937     RegCloseKey(hkey_udproductpatch);
11938     RegDeleteKeyExA(hkey_udproductpatches, "", access & KEY_WOW64_64KEY, 0);
11939     RegCloseKey(hkey_udproductpatches);
11940     RegDeleteKeyExA(hkey_udpatch, "", access & KEY_WOW64_64KEY, 0);
11941     RegCloseKey(hkey_udpatch);
11942     RegDeleteKeyExA(hkey_udpatches, "", access & KEY_WOW64_64KEY, 0);
11943     RegCloseKey(hkey_udpatches);
11944     RegDeleteKeyExA(hkey_udprops, "", access & KEY_WOW64_64KEY, 0);
11945     RegCloseKey(hkey_udprops);
11946     RegDeleteKeyExA(hkey_udproduct, "", access & KEY_WOW64_64KEY, 0);
11947     RegCloseKey(hkey_udproduct);
11948 
11949 done:
11950     RegDeleteKeyExA(hkey_patches, "", access & KEY_WOW64_64KEY, 0);
11951     RegCloseKey(hkey_patches);
11952     RegDeleteKeyExA(hkey_product, "", access & KEY_WOW64_64KEY, 0);
11953     RegCloseKey(hkey_product);
11954     RegDeleteKeyExA(hkey_patch, "", access & KEY_WOW64_64KEY, 0);
11955     RegCloseKey(hkey_patch);
11956 }
11957 
test_MsiEnumProducts(void)11958 static void test_MsiEnumProducts(void)
11959 {
11960     UINT r;
11961     BOOL found1, found2, found3;
11962     DWORD index;
11963     char product1[39], product2[39], product3[39], guid[39];
11964     char product_squashed1[33], product_squashed2[33], product_squashed3[33];
11965     char keypath1[MAX_PATH], keypath2[MAX_PATH], keypath3[MAX_PATH];
11966     char *usersid;
11967     HKEY key1, key2, key3;
11968     REGSAM access = KEY_ALL_ACCESS;
11969 
11970     if (!is_process_elevated())
11971     {
11972         skip( "process is limited\n" );
11973         return;
11974     }
11975 
11976     create_test_guid(product1, product_squashed1);
11977     create_test_guid(product2, product_squashed2);
11978     create_test_guid(product3, product_squashed3);
11979     usersid = get_user_sid();
11980 
11981     if (is_wow64)
11982         access |= KEY_WOW64_64KEY;
11983 
11984     strcpy(keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
11985     strcat(keypath2, usersid);
11986     strcat(keypath2, "\\Installer\\Products\\");
11987     strcat(keypath2, product_squashed2);
11988 
11989     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL);
11990     if (r == ERROR_ACCESS_DENIED)
11991     {
11992         skip("Not enough rights to perform tests\n");
11993         LocalFree(usersid);
11994         return;
11995     }
11996     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11997 
11998     strcpy(keypath1, "Software\\Classes\\Installer\\Products\\");
11999     strcat(keypath1, product_squashed1);
12000 
12001     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL);
12002     if (r == ERROR_ACCESS_DENIED)
12003     {
12004         skip( "insufficient rights\n" );
12005         LocalFree( usersid );
12006         return;
12007     }
12008     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12009 
12010     strcpy(keypath3, "Software\\Microsoft\\Installer\\Products\\");
12011     strcat(keypath3, product_squashed3);
12012 
12013     r = RegCreateKeyA(HKEY_CURRENT_USER, keypath3, &key3);
12014     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12015 
12016     index = 0;
12017     r = MsiEnumProductsA(index, guid);
12018     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
12019 
12020     r = MsiEnumProductsA(index, NULL);
12021     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
12022 
12023     index = 2;
12024     r = MsiEnumProductsA(index, guid);
12025     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
12026 
12027     index = 0;
12028     r = MsiEnumProductsA(index, guid);
12029     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
12030 
12031     found1 = found2 = found3 = FALSE;
12032     while ((r = MsiEnumProductsA(index, guid)) == ERROR_SUCCESS)
12033     {
12034         if (!strcmp(product1, guid)) found1 = TRUE;
12035         if (!strcmp(product2, guid)) found2 = TRUE;
12036         if (!strcmp(product3, guid)) found3 = TRUE;
12037         if (found1 && found2 && found3) break;
12038         index++;
12039     }
12040     ok(found1, "product1 not found\n");
12041     ok(found2, "product2 not found\n");
12042     ros_skip_flaky
12043     ok(found3, "product3 not found\n");
12044 
12045     RegDeleteKeyExA(key1, "", access & KEY_WOW64_64KEY, 0);
12046     RegDeleteKeyExA(key2, "", access & KEY_WOW64_64KEY, 0);
12047     RegDeleteKeyA(key3, "");
12048     RegCloseKey(key1);
12049     RegCloseKey(key2);
12050     RegCloseKey(key3);
12051     LocalFree(usersid);
12052 }
12053 
test_MsiGetFileSignatureInformation(void)12054 static void test_MsiGetFileSignatureInformation(void)
12055 {
12056     HRESULT hr;
12057     const CERT_CONTEXT *cert;
12058     DWORD len;
12059 
12060     hr = MsiGetFileSignatureInformationA( NULL, 0, NULL, NULL, NULL );
12061     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %#lx\n", hr);
12062 
12063     hr = MsiGetFileSignatureInformationA( NULL, 0, NULL, NULL, &len );
12064     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %#lx\n", hr);
12065 
12066     hr = MsiGetFileSignatureInformationA( NULL, 0, &cert, NULL, &len );
12067     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %#lx\n", hr);
12068 
12069     hr = MsiGetFileSignatureInformationA( "", 0, NULL, NULL, NULL );
12070     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %#lx\n", hr);
12071 
12072     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, NULL );
12073     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %#lx\n", hr);
12074 
12075     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, &len );
12076     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %#lx\n", hr);
12077 
12078     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, &cert, NULL, &len );
12079     todo_wine ok(hr == CRYPT_E_FILE_ERROR, "expected CRYPT_E_FILE_ERROR got %#lx\n", hr);
12080 
12081     create_file_data( "signature.bin", "signature", sizeof("signature") );
12082 
12083     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, NULL );
12084     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %#lx\n", hr);
12085 
12086     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, &len );
12087     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %#lx\n", hr);
12088 
12089     cert = (const CERT_CONTEXT *)0xdeadbeef;
12090     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, &cert, NULL, &len );
12091     todo_wine ok(hr == HRESULT_FROM_WIN32(ERROR_FUNCTION_FAILED), "got %#lx\n", hr);
12092     ok(cert == NULL, "got %p\n", cert);
12093 
12094     DeleteFileA( "signature.bin" );
12095 }
12096 
test_MsiEnumProductsEx(void)12097 static void test_MsiEnumProductsEx(void)
12098 {
12099     UINT r;
12100     DWORD len, index;
12101     MSIINSTALLCONTEXT context;
12102     char product0[39], product1[39], product2[39], product3[39], guid[39], sid[128];
12103     char product_squashed1[33], product_squashed2[33], product_squashed3[33];
12104     char keypath1[MAX_PATH], keypath2[MAX_PATH], keypath3[MAX_PATH];
12105     HKEY key1 = NULL, key2 = NULL, key3 = NULL;
12106     REGSAM access = KEY_ALL_ACCESS;
12107     char *usersid = get_user_sid();
12108     BOOL found1, found2, found3;
12109 
12110     create_test_guid( product0, NULL );
12111     create_test_guid( product1, product_squashed1 );
12112     create_test_guid( product2, product_squashed2 );
12113     create_test_guid( product3, product_squashed3 );
12114 
12115     if (is_wow64) access |= KEY_WOW64_64KEY;
12116 
12117     strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\" );
12118     strcat( keypath2, usersid );
12119     strcat( keypath2, "\\Installer\\Products\\" );
12120     strcat( keypath2, product_squashed2 );
12121 
12122     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
12123     if (r == ERROR_ACCESS_DENIED)
12124     {
12125         skip( "insufficient rights\n" );
12126         goto done;
12127     }
12128     ok( r == ERROR_SUCCESS, "got %u\n", r );
12129 
12130     strcpy( keypath1, "Software\\Classes\\Installer\\Products\\" );
12131     strcat( keypath1, product_squashed1 );
12132 
12133     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
12134     if (r == ERROR_ACCESS_DENIED)
12135     {
12136         skip( "insufficient rights\n" );
12137         goto done;
12138     }
12139     ok( r == ERROR_SUCCESS, "got %u\n", r );
12140 
12141     strcpy( keypath3, usersid );
12142     strcat( keypath3, "\\Software\\Microsoft\\Installer\\Products\\" );
12143     strcat( keypath3, product_squashed3 );
12144 
12145     r = RegCreateKeyExA( HKEY_USERS, keypath3, 0, NULL, 0, access, NULL, &key3, NULL );
12146     ok( r == ERROR_SUCCESS, "got %u\n", r );
12147 
12148     r = MsiEnumProductsExA( NULL, NULL, 0, 0, NULL, NULL, NULL, NULL );
12149     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
12150 
12151     len = sizeof(sid);
12152     r = MsiEnumProductsExA( NULL, NULL, 0, 0, NULL, NULL, NULL, &len );
12153     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
12154     ok( len == sizeof(sid), "got %lu\n", len );
12155 
12156     r = MsiEnumProductsExA( NULL, NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, NULL, NULL );
12157     ok( r == ERROR_SUCCESS, "got %u\n", r );
12158 
12159     sid[0] = 0;
12160     len = sizeof(sid);
12161     r = MsiEnumProductsExA( product0, NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, &len );
12162     ok( r == ERROR_NO_MORE_ITEMS, "got %u\n", r );
12163     ok( len == sizeof(sid), "got %lu\n", len );
12164     ok( !sid[0], "got %s\n", sid );
12165 
12166     sid[0] = 0;
12167     len = sizeof(sid);
12168     r = MsiEnumProductsExA( product0, usersid, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, &len );
12169     ok( r == ERROR_NO_MORE_ITEMS, "got %u\n", r );
12170     ok( len == sizeof(sid), "got %lu\n", len );
12171     ok( !sid[0], "got %s\n", sid );
12172 
12173     sid[0] = 0;
12174     len = 0;
12175     r = MsiEnumProductsExA( NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, 0, NULL, NULL, sid, &len );
12176     ok( r == ERROR_MORE_DATA, "got %u\n", r );
12177     ok( len, "length unchanged\n" );
12178     ok( !sid[0], "got %s\n", sid );
12179 
12180     guid[0] = 0;
12181     context = 0xdeadbeef;
12182     sid[0] = 0;
12183     len = sizeof(sid);
12184     r = MsiEnumProductsExA( NULL, NULL, MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
12185     ok( r == ERROR_SUCCESS, "got %u\n", r );
12186     ok( guid[0], "empty guid\n" );
12187     ok( context != 0xdeadbeef, "context unchanged\n" );
12188     ok( !len, "got %lu\n", len );
12189     ok( !sid[0], "got %s\n", sid );
12190 
12191     guid[0] = 0;
12192     context = 0xdeadbeef;
12193     sid[0] = 0;
12194     len = sizeof(sid);
12195     r = MsiEnumProductsExA( NULL, usersid, MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
12196     ok( r == ERROR_SUCCESS, "got %u\n", r );
12197     ok( guid[0], "empty guid\n" );
12198     ok( context != 0xdeadbeef, "context unchanged\n" );
12199     ok( !len, "got %lu\n", len );
12200     ok( !sid[0], "got %s\n", sid );
12201 
12202     guid[0] = 0;
12203     context = 0xdeadbeef;
12204     sid[0] = 0;
12205     len = sizeof(sid);
12206     r = MsiEnumProductsExA( NULL, "S-1-1-0", MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
12207     if (r == ERROR_ACCESS_DENIED)
12208     {
12209         skip( "insufficient rights\n" );
12210         goto done;
12211     }
12212     ok( r == ERROR_SUCCESS, "got %u\n", r );
12213     ok( guid[0], "empty guid\n" );
12214     ok( context != 0xdeadbeef, "context unchanged\n" );
12215     ok( !len, "got %lu\n", len );
12216     ok( !sid[0], "got %s\n", sid );
12217 
12218     index = 0;
12219     guid[0] = 0;
12220     context = 0xdeadbeef;
12221     sid[0] = 0;
12222     len = sizeof(sid);
12223     found1 = found2 = found3 = FALSE;
12224     while (!MsiEnumProductsExA( NULL, "S-1-1-0", MSIINSTALLCONTEXT_ALL, index, guid, &context, sid, &len ))
12225     {
12226         if (!strcmp( product1, guid ))
12227         {
12228             ok( context == MSIINSTALLCONTEXT_MACHINE, "got %u\n", context );
12229             ok( !sid[0], "got \"%s\"\n", sid );
12230             ok( !len, "unexpected length %lu\n", len );
12231             found1 = TRUE;
12232         }
12233         if (!strcmp( product2, guid ))
12234         {
12235             ok( context == MSIINSTALLCONTEXT_USERMANAGED, "got %u\n", context );
12236             ok( sid[0], "empty sid\n" );
12237             ok( len == strlen(sid), "unexpected length %lu\n", len );
12238             found2 = TRUE;
12239         }
12240         if (!strcmp( product3, guid ))
12241         {
12242             ok( context == MSIINSTALLCONTEXT_USERUNMANAGED, "got %u\n", context );
12243             ok( sid[0], "empty sid\n" );
12244             ok( len == strlen(sid), "unexpected length %lu\n", len );
12245             found3 = TRUE;
12246         }
12247         if (found1 && found2 && found3) break;
12248         index++;
12249         guid[0] = 0;
12250         context = 0xdeadbeef;
12251         sid[0] = 0;
12252         len = sizeof(sid);
12253     }
12254     ok(found1, "product1 not found\n");
12255     ok(found2, "product2 not found\n");
12256     ok(found3, "product3 not found\n");
12257 
12258 done:
12259     RegDeleteKeyExA( key1, "", access, 0 );
12260     RegDeleteKeyExA( key2, "", access, 0 );
12261     RegDeleteKeyExA( key3, "", access, 0 );
12262     RegCloseKey( key1 );
12263     RegCloseKey( key2 );
12264     RegCloseKey( key3 );
12265     LocalFree( usersid );
12266 }
12267 
test_MsiEnumComponents(void)12268 static void test_MsiEnumComponents(void)
12269 {
12270     UINT r;
12271     BOOL found1, found2;
12272     DWORD index;
12273     char comp1[39], comp2[39], guid[39];
12274     char comp_squashed1[33], comp_squashed2[33];
12275     char keypath1[MAX_PATH], keypath2[MAX_PATH];
12276     REGSAM access = KEY_ALL_ACCESS;
12277     char *usersid = get_user_sid();
12278     HKEY key1 = NULL, key2 = NULL;
12279 
12280     if (!is_process_elevated())
12281     {
12282         skip("process is limited\n");
12283         return;
12284     }
12285 
12286     create_test_guid( comp1, comp_squashed1 );
12287     create_test_guid( comp2, comp_squashed2 );
12288 
12289     if (is_wow64) access |= KEY_WOW64_64KEY;
12290 
12291     strcpy( keypath1, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
12292     strcat( keypath1, "S-1-5-18\\Components\\" );
12293     strcat( keypath1, comp_squashed1 );
12294 
12295     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
12296     if (r == ERROR_ACCESS_DENIED)
12297     {
12298         skip( "insufficient rights\n" );
12299         goto done;
12300     }
12301     ok( r == ERROR_SUCCESS, "got %u\n", r );
12302 
12303     strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
12304     strcat( keypath2, usersid );
12305     strcat( keypath2, "\\Components\\" );
12306     strcat( keypath2, comp_squashed2 );
12307 
12308     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
12309     if (r == ERROR_ACCESS_DENIED)
12310     {
12311         skip( "insufficient rights\n" );
12312         goto done;
12313     }
12314 
12315     r = MsiEnumComponentsA( 0, NULL );
12316     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
12317 
12318     index = 0;
12319     guid[0] = 0;
12320     found1 = found2 = FALSE;
12321     while (!MsiEnumComponentsA( index, guid ))
12322     {
12323         if (!strcmp( guid, comp1 )) found1 = TRUE;
12324         if (!strcmp( guid, comp2 )) found2 = TRUE;
12325         ok( guid[0], "empty guid\n" );
12326         if (found1 && found2) break;
12327         guid[0] = 0;
12328         index++;
12329     }
12330     ok( found1, "comp1 not found\n" );
12331     ok( found2, "comp2 not found\n" );
12332 
12333 done:
12334     RegDeleteKeyExA( key1, "", access, 0 );
12335     RegDeleteKeyExA( key2, "", access, 0 );
12336     RegCloseKey( key1 );
12337     RegCloseKey( key2 );
12338     LocalFree( usersid );
12339 }
12340 
test_MsiEnumComponentsEx(void)12341 static void test_MsiEnumComponentsEx(void)
12342 {
12343     UINT r;
12344     BOOL found1, found2;
12345     DWORD len, index;
12346     MSIINSTALLCONTEXT context;
12347     char comp1[39], comp2[39], guid[39], sid[128];
12348     char comp_squashed1[33], comp_squashed2[33];
12349     char keypath1[MAX_PATH], keypath2[MAX_PATH];
12350     HKEY key1 = NULL, key2 = NULL;
12351     REGSAM access = KEY_ALL_ACCESS;
12352     char *usersid = get_user_sid();
12353 
12354     if (!is_process_elevated())
12355     {
12356         skip("process is limited\n");
12357         return;
12358     }
12359 
12360     create_test_guid( comp1, comp_squashed1 );
12361     create_test_guid( comp2, comp_squashed2 );
12362 
12363     if (is_wow64) access |= KEY_WOW64_64KEY;
12364 
12365     strcpy( keypath1, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
12366     strcat( keypath1, "S-1-5-18\\Components\\" );
12367     strcat( keypath1, comp_squashed1 );
12368 
12369     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
12370     if (r == ERROR_ACCESS_DENIED)
12371     {
12372         skip( "insufficient rights\n" );
12373         goto done;
12374     }
12375     ok( r == ERROR_SUCCESS, "got %u\n", r );
12376 
12377     strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
12378     strcat( keypath2, usersid );
12379     strcat( keypath2, "\\Components\\" );
12380     strcat( keypath2, comp_squashed2 );
12381 
12382     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
12383     if (r == ERROR_ACCESS_DENIED)
12384     {
12385         skip( "insufficient rights\n" );
12386         goto done;
12387     }
12388     ok( r == ERROR_SUCCESS, "got %u\n", r );
12389     r = RegSetValueExA( key2, comp_squashed2, 0, REG_SZ, (const BYTE *)"c:\\doesnotexist",
12390                         sizeof("c:\\doesnotexist"));
12391     ok( r == ERROR_SUCCESS, "got %u\n", r );
12392 
12393     index = 0;
12394     guid[0] = 0;
12395     context = 0xdeadbeef;
12396     sid[0] = 0;
12397     len = sizeof(sid);
12398     found1 = found2 = FALSE;
12399     while (!MsiEnumComponentsExA( "S-1-1-0", MSIINSTALLCONTEXT_ALL, index, guid, &context, sid, &len ))
12400     {
12401         if (!strcmp( comp1, guid ))
12402         {
12403             ok( context == MSIINSTALLCONTEXT_MACHINE, "got %u\n", context );
12404             ok( !sid[0], "got \"%s\"\n", sid );
12405             ok( !len, "unexpected length %lu\n", len );
12406             found1 = TRUE;
12407             if (found2) break;
12408         }
12409         if (!strcmp( comp2, guid ))
12410         {
12411             ok( context == MSIINSTALLCONTEXT_USERUNMANAGED, "got %u\n", context );
12412             ok( sid[0], "empty sid\n" );
12413             ok( len == strlen(sid), "unexpected length %lu\n", len );
12414             found2 = TRUE;
12415             if (found1) break;
12416         }
12417         index++;
12418         guid[0] = 0;
12419         context = 0xdeadbeef;
12420         sid[0] = 0;
12421         len = sizeof(sid);
12422     }
12423     ok( found1, "comp1 not found\n" );
12424     ok( found2, "comp2 not found\n" );
12425 
12426     r = MsiEnumComponentsExA( NULL, 0, 0, NULL, NULL, NULL, NULL );
12427     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
12428 
12429     r = MsiEnumComponentsExA( NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, NULL );
12430     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
12431 
12432 done:
12433     RegDeleteValueA( key2, comp_squashed2 );
12434     RegDeleteKeyExA( key1, "", access, 0 );
12435     RegDeleteKeyExA( key2, "", access, 0 );
12436     RegCloseKey( key1 );
12437     RegCloseKey( key2 );
12438     LocalFree( usersid );
12439 }
12440 
test_MsiConfigureProductEx(void)12441 static void test_MsiConfigureProductEx(void)
12442 {
12443     UINT r;
12444     LONG res;
12445     DWORD type, size;
12446     HKEY props, source;
12447     CHAR keypath[MAX_PATH * 2], localpackage[MAX_PATH], packagename[MAX_PATH];
12448     REGSAM access = KEY_ALL_ACCESS;
12449 
12450     if (!is_process_elevated())
12451     {
12452         skip("process is limited\n");
12453         return;
12454     }
12455 
12456     CreateDirectoryA("msitest", NULL);
12457     create_file_data("msitest\\hydrogen", "hydrogen", 500);
12458     create_file_data("msitest\\helium", "helium", 500);
12459     create_file_data("msitest\\lithium", "lithium", 500);
12460 
12461     create_database(msifile, mcp_tables, ARRAY_SIZE(mcp_tables));
12462 
12463     if (is_wow64)
12464         access |= KEY_WOW64_64KEY;
12465 
12466     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
12467 
12468     /* NULL szProduct */
12469     r = MsiConfigureProductExA(NULL, INSTALLLEVEL_DEFAULT,
12470                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
12471     ok(r == ERROR_INVALID_PARAMETER,
12472        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12473 
12474     /* empty szProduct */
12475     r = MsiConfigureProductExA("", INSTALLLEVEL_DEFAULT,
12476                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
12477     ok(r == ERROR_INVALID_PARAMETER,
12478        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12479 
12480     /* garbage szProduct */
12481     r = MsiConfigureProductExA("garbage", INSTALLLEVEL_DEFAULT,
12482                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
12483     ok(r == ERROR_INVALID_PARAMETER,
12484        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12485 
12486     /* guid without brackets */
12487     r = MsiConfigureProductExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
12488                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
12489                                "PROPVAR=42");
12490     ok(r == ERROR_INVALID_PARAMETER,
12491        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12492 
12493     /* guid with brackets */
12494     r = MsiConfigureProductExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
12495                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
12496                                "PROPVAR=42");
12497     ok(r == ERROR_UNKNOWN_PRODUCT,
12498        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12499 
12500     /* same length as guid, but random */
12501     r = MsiConfigureProductExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
12502                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
12503                                "PROPVAR=42");
12504     ok(r == ERROR_UNKNOWN_PRODUCT,
12505        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12506 
12507     /* product not installed yet */
12508     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
12509                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
12510                                "PROPVAR=42");
12511     ok(r == ERROR_UNKNOWN_PRODUCT,
12512        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12513 
12514     /* install the product, per-user unmanaged */
12515     r = MsiInstallProductA(msifile, "INSTALLLEVEL=10 PROPVAR=42");
12516     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
12517     {
12518         skip("Not enough rights to perform tests\n");
12519         goto error;
12520     }
12521     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
12522     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
12523     ok(pf_exists("msitest\\helium"), "File not installed\n");
12524     ok(pf_exists("msitest\\lithium"), "File not installed\n");
12525     ok(pf_exists("msitest"), "File not installed\n");
12526 
12527     /* product is installed per-user managed, remove it */
12528     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12529                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
12530                                "PROPVAR=42");
12531     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12532     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
12533     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
12534     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
12535     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
12536 
12537     /* product has been removed */
12538     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12539                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
12540                                "PROPVAR=42");
12541     ok(r == ERROR_UNKNOWN_PRODUCT,
12542        "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
12543 
12544     /* install the product, machine */
12545     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
12546     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
12547     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
12548     ok(pf_exists("msitest\\helium"), "File not installed\n");
12549     ok(pf_exists("msitest\\lithium"), "File not installed\n");
12550     ok(pf_exists("msitest"), "File not installed\n");
12551 
12552     /* product is installed machine, remove it */
12553     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12554                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
12555                                "PROPVAR=42");
12556     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12557     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
12558     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
12559     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
12560     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
12561 
12562     /* product has been removed */
12563     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12564                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
12565                                "PROPVAR=42");
12566     ok(r == ERROR_UNKNOWN_PRODUCT,
12567        "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
12568 
12569     /* install the product, machine */
12570     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
12571     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
12572     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
12573     ok(pf_exists("msitest\\helium"), "File not installed\n");
12574     ok(pf_exists("msitest\\lithium"), "File not installed\n");
12575     ok(pf_exists("msitest"), "File not installed\n");
12576 
12577     DeleteFileA(msifile);
12578 
12579     /* msifile is removed */
12580     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12581                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
12582                                "PROPVAR=42");
12583     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12584     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
12585     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
12586     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
12587     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
12588 
12589     create_database(msifile, mcp_tables, ARRAY_SIZE(mcp_tables));
12590 
12591     /* install the product, machine */
12592     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
12593     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
12594     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
12595     ok(pf_exists("msitest\\helium"), "File not installed\n");
12596     ok(pf_exists("msitest\\lithium"), "File not installed\n");
12597     ok(pf_exists("msitest"), "File not installed\n");
12598 
12599     DeleteFileA(msifile);
12600 
12601     lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
12602     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
12603     lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\InstallProperties");
12604 
12605     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &props);
12606     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12607 
12608     type = REG_SZ;
12609     size = MAX_PATH;
12610     res = RegQueryValueExA(props, "LocalPackage", NULL, &type,
12611                            (LPBYTE)localpackage, &size);
12612     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12613 
12614     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
12615                          (const BYTE *)"C:\\idontexist.msi", 18);
12616     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12617 
12618     /* LocalPackage is used to find the cached msi package */
12619     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12620                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
12621                                "PROPVAR=42");
12622     ok(r == ERROR_INSTALL_SOURCE_ABSENT,
12623        "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
12624     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
12625     ok(pf_exists("msitest\\helium"), "File not installed\n");
12626     ok(pf_exists("msitest\\lithium"), "File not installed\n");
12627     ok(pf_exists("msitest"), "File not installed\n");
12628 
12629     RegCloseKey(props);
12630     create_database(msifile, mcp_tables, ARRAY_SIZE(mcp_tables));
12631 
12632     /* LastUsedSource can be used as a last resort */
12633     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12634                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
12635                                "PROPVAR=42");
12636     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12637     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
12638     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
12639     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
12640     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
12641     DeleteFileA( localpackage );
12642 
12643     /* install the product, machine */
12644     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
12645     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
12646     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
12647     ok(pf_exists("msitest\\helium"), "File not installed\n");
12648     ok(pf_exists("msitest\\lithium"), "File not installed\n");
12649     ok(pf_exists("msitest"), "File not installed\n");
12650 
12651     lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
12652     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
12653     lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\InstallProperties");
12654 
12655     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &props);
12656     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12657 
12658     type = REG_SZ;
12659     size = MAX_PATH;
12660     res = RegQueryValueExA(props, "LocalPackage", NULL, &type,
12661                            (LPBYTE)localpackage, &size);
12662     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12663 
12664     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
12665                          (const BYTE *)"C:\\idontexist.msi", 18);
12666     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12667 
12668     lstrcpyA(keypath, "SOFTWARE\\Classes\\Installer\\Products\\");
12669     lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\SourceList");
12670 
12671     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &source);
12672     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12673 
12674     type = REG_SZ;
12675     size = MAX_PATH;
12676     res = RegQueryValueExA(source, "PackageName", NULL, &type,
12677                            (LPBYTE)packagename, &size);
12678     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12679 
12680     res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
12681                          (const BYTE *)"idontexist.msi", 15);
12682     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12683 
12684     /* SourceList is altered */
12685     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12686                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
12687                                "PROPVAR=42");
12688     ok(r == ERROR_INSTALL_SOURCE_ABSENT,
12689        "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
12690     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
12691     ok(pf_exists("msitest\\helium"), "File not installed\n");
12692     ok(pf_exists("msitest\\lithium"), "File not installed\n");
12693     ok(pf_exists("msitest"), "File not installed\n");
12694 
12695     /* restore PackageName */
12696     res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
12697                          (const BYTE *)packagename, lstrlenA(packagename) + 1);
12698     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12699 
12700     /* restore LocalPackage */
12701     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
12702                          (const BYTE *)localpackage, lstrlenA(localpackage) + 1);
12703     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12704 
12705     /* finally remove the product */
12706     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12707                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
12708                                "PROPVAR=42");
12709     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12710     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
12711     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
12712     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
12713     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
12714 
12715     RegCloseKey(source);
12716     RegCloseKey(props);
12717 
12718 error:
12719     DeleteFileA("msitest\\hydrogen");
12720     DeleteFileA("msitest\\helium");
12721     DeleteFileA("msitest\\lithium");
12722     RemoveDirectoryA("msitest");
12723     DeleteFileA(msifile);
12724 }
12725 
test_MsiSetFeatureAttributes(void)12726 static void test_MsiSetFeatureAttributes(void)
12727 {
12728     UINT r;
12729     DWORD attrs;
12730     char path[MAX_PATH];
12731     MSIHANDLE package;
12732 
12733     if (!is_process_elevated())
12734     {
12735         skip("process is limited\n");
12736         return;
12737     }
12738     create_database( msifile, tables, ARRAY_SIZE( tables ));
12739 
12740     strcpy( path, CURR_DIR );
12741     strcat( path, "\\" );
12742     strcat( path, msifile );
12743 
12744     r = MsiOpenPackageA( path, &package );
12745     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
12746     {
12747         skip("Not enough rights to perform tests\n");
12748         DeleteFileA( msifile );
12749         return;
12750     }
12751     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12752 
12753     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
12754     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %u\n", r);
12755 
12756     r = MsiDoActionA( package, "CostInitialize" );
12757     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12758 
12759     r = MsiSetFeatureAttributesA( 0, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
12760     ok(r == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", r);
12761 
12762     r = MsiSetFeatureAttributesA( package, "", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
12763     ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
12764 
12765     r = MsiSetFeatureAttributesA( package, NULL, INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
12766     ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
12767 
12768     r = MsiSetFeatureAttributesA( package, "One", 0 );
12769     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12770 
12771     attrs = 0xdeadbeef;
12772     r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL );
12773     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12774     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL,
12775        "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %#lx\n", attrs);
12776 
12777     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
12778     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12779 
12780     attrs = 0;
12781     r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL );
12782     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12783     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL,
12784        "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %#lx\n", attrs);
12785 
12786     r = MsiDoActionA( package, "FileCost" );
12787     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12788 
12789     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORSOURCE );
12790     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12791 
12792     attrs = 0;
12793     r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL );
12794     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12795     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORSOURCE,
12796        "expected INSTALLFEATUREATTRIBUTE_FAVORSOURCE, got %#lx\n", attrs);
12797 
12798     r = MsiDoActionA( package, "CostFinalize" );
12799     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12800 
12801     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
12802     ok(r == ERROR_FUNCTION_FAILED, "expected ERROR_FUNCTION_FAILED, got %u\n", r);
12803 
12804     MsiCloseHandle( package );
12805     DeleteFileA( msifile );
12806 }
12807 
test_MsiGetFeatureInfo(void)12808 static void test_MsiGetFeatureInfo(void)
12809 {
12810     UINT r;
12811     MSIHANDLE package;
12812     char title[32], help[32], path[MAX_PATH];
12813     DWORD attrs, title_len, help_len;
12814 
12815     if (!is_process_elevated())
12816     {
12817         skip("process is limited\n");
12818         return;
12819     }
12820     create_database( msifile, tables, ARRAY_SIZE( tables ));
12821 
12822     strcpy( path, CURR_DIR );
12823     strcat( path, "\\" );
12824     strcat( path, msifile );
12825 
12826     r = MsiOpenPackageA( path, &package );
12827     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
12828     {
12829         skip("Not enough rights to perform tests\n");
12830         DeleteFileA( msifile );
12831         return;
12832     }
12833     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
12834 
12835     r = MsiGetFeatureInfoA( 0, NULL, NULL, NULL, NULL, NULL, NULL );
12836     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
12837 
12838     r = MsiGetFeatureInfoA( package, NULL, NULL, NULL, NULL, NULL, NULL );
12839     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
12840 
12841     r = MsiGetFeatureInfoA( package, "", NULL, NULL, NULL, NULL, NULL );
12842     ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
12843 
12844     r = MsiGetFeatureInfoA( package, "One", NULL, NULL, NULL, NULL, NULL );
12845     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12846 
12847     r = MsiGetFeatureInfoA( 0, "One", NULL, NULL, NULL, NULL, NULL );
12848     ok(r == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", r);
12849 
12850     title_len = help_len = 0;
12851     r = MsiGetFeatureInfoA( package, "One", NULL, NULL, &title_len, NULL, &help_len );
12852     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12853     ok(title_len == 3, "expected 3, got %lu\n", title_len);
12854     ok(help_len == 3, "expected 3, got %lu\n", help_len);
12855 
12856     title[0] = help[0] = 0;
12857     title_len = help_len = 0;
12858     r = MsiGetFeatureInfoA( package, "One", NULL, title, &title_len, help, &help_len );
12859     ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %u\n", r);
12860     ok(title_len == 3, "expected 3, got %lu\n", title_len);
12861     ok(help_len == 3, "expected 3, got %lu\n", help_len);
12862 
12863     attrs = 0;
12864     title[0] = help[0] = 0;
12865     title_len = sizeof(title);
12866     help_len = sizeof(help);
12867     r = MsiGetFeatureInfoA( package, "One", &attrs, title, &title_len, help, &help_len );
12868     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12869     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %lu\n", attrs);
12870     ok(title_len == 3, "expected 3, got %lu\n", title_len);
12871     ok(help_len == 3, "expected 3, got %lu\n", help_len);
12872     ok(!strcmp(title, "One"), "expected \"One\", got \"%s\"\n", title);
12873     ok(!strcmp(help, "One"), "expected \"One\", got \"%s\"\n", help);
12874 
12875     attrs = 0;
12876     title[0] = help[0] = 0;
12877     title_len = sizeof(title);
12878     help_len = sizeof(help);
12879     r = MsiGetFeatureInfoA( package, "Two", &attrs, title, &title_len, help, &help_len );
12880     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12881     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %lu\n", attrs);
12882     ok(!title_len, "expected 0, got %lu\n", title_len);
12883     ok(!help_len, "expected 0, got %lu\n", help_len);
12884     ok(!title[0], "expected \"\", got \"%s\"\n", title);
12885     ok(!help[0], "expected \"\", got \"%s\"\n", help);
12886 
12887     MsiCloseHandle( package );
12888     DeleteFileA( msifile );
12889 }
12890 
handler_a(LPVOID context,UINT type,LPCSTR msg)12891 static INT CALLBACK handler_a(LPVOID context, UINT type, LPCSTR msg)
12892 {
12893     return IDOK;
12894 }
12895 
handler_w(LPVOID context,UINT type,LPCWSTR msg)12896 static INT CALLBACK handler_w(LPVOID context, UINT type, LPCWSTR msg)
12897 {
12898     return IDOK;
12899 }
12900 
handler_record(LPVOID context,UINT type,MSIHANDLE record)12901 static INT CALLBACK handler_record(LPVOID context, UINT type, MSIHANDLE record)
12902 {
12903     return IDOK;
12904 }
12905 
test_MsiSetInternalUI(void)12906 static void test_MsiSetInternalUI(void)
12907 {
12908     INSTALLUILEVEL level;
12909 
12910     level = MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
12911     ok(level == INSTALLUILEVEL_DEFAULT, "expected INSTALLUILEVEL_DEFAULT, got %d\n", level);
12912 
12913     level = MsiSetInternalUI(INSTALLUILEVEL_DEFAULT, NULL);
12914     ok(level == INSTALLUILEVEL_FULL, "expected INSTALLUILEVEL_FULL, got %d\n", level);
12915 
12916     level = MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE, NULL);
12917     ok(level == INSTALLUILEVEL_DEFAULT, "expected INSTALLUILEVEL_DEFAULT, got %d\n", level);
12918 
12919     level = MsiSetInternalUI(0xdeadbeef, NULL);
12920     ok(level == INSTALLUILEVEL_NOCHANGE, "expected INSTALLUILEVEL_NOCHANGE, got %d\n", level);
12921 }
12922 
test_MsiSetExternalUI(void)12923 static void test_MsiSetExternalUI(void)
12924 {
12925     INSTALLUI_HANDLERA ret_a;
12926     INSTALLUI_HANDLERW ret_w;
12927     INSTALLUI_HANDLER_RECORD prev;
12928     UINT error;
12929 
12930     ret_a = MsiSetExternalUIA(handler_a, INSTALLLOGMODE_ERROR, NULL);
12931     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
12932 
12933     ret_a = MsiSetExternalUIA(NULL, 0, NULL);
12934     ok(ret_a == handler_a, "expected %p, got %p\n", handler_a, ret_a);
12935 
12936     error = MsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, &prev);
12937     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
12938     ok(prev == NULL, "expected NULL, got %p\n", prev);
12939 
12940     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
12941     error = MsiSetExternalUIRecord(NULL, INSTALLLOGMODE_ERROR, NULL, &prev);
12942     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
12943     ok(prev == handler_record, "expected %p, got %p\n", handler_record, prev);
12944 
12945     ret_w = MsiSetExternalUIW(handler_w, INSTALLLOGMODE_ERROR, NULL);
12946     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
12947 
12948     ret_w = MsiSetExternalUIW(NULL, 0, NULL);
12949     ok(ret_w == handler_w, "expected %p, got %p\n", handler_w, ret_w);
12950 
12951     ret_a = MsiSetExternalUIA(handler_a, INSTALLLOGMODE_ERROR, NULL);
12952     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
12953 
12954     ret_w = MsiSetExternalUIW(handler_w, INSTALLLOGMODE_ERROR, NULL);
12955     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
12956 
12957     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
12958     error = MsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, &prev);
12959     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
12960     ok(prev == NULL, "expected NULL, got %p\n", prev);
12961 
12962     ret_a = MsiSetExternalUIA(NULL, 0, NULL);
12963     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
12964 
12965     ret_w = MsiSetExternalUIW(NULL, 0, NULL);
12966     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
12967 
12968     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
12969     error = MsiSetExternalUIRecord(NULL, 0, NULL, &prev);
12970     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
12971     ok(prev == handler_record, "expected %p, got %p\n", handler_record, prev);
12972 
12973     error = MsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, NULL);
12974     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
12975 
12976     error = MsiSetExternalUIRecord(NULL, 0, NULL, NULL);
12977     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
12978 }
12979 
test_lastusedsource(void)12980 static void test_lastusedsource(void)
12981 {
12982     static const char prodcode[] = "{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}";
12983     char value[MAX_PATH], path[MAX_PATH];
12984     DWORD size;
12985     UINT r;
12986 
12987     CreateDirectoryA("msitest", NULL);
12988     create_file("maximus", 500);
12989     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
12990     DeleteFileA("maximus");
12991 
12992     create_database("msifile0.msi", lus0_tables, ARRAY_SIZE(lus0_tables));
12993     create_database("msifile1.msi", lus1_tables, ARRAY_SIZE(lus1_tables));
12994     create_database("msifile2.msi", lus2_tables, ARRAY_SIZE(lus2_tables));
12995 
12996     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
12997 
12998     /* no cabinet file */
12999 
13000     size = MAX_PATH;
13001     lstrcpyA(value, "aaa");
13002     r = MsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
13003                               MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
13004     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
13005     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
13006 
13007     r = MsiInstallProductA("msifile0.msi", "PUBLISH_PRODUCT=1");
13008     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
13009     {
13010         skip("Not enough rights to perform tests\n");
13011         goto error;
13012     }
13013     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13014 
13015     lstrcpyA(path, CURR_DIR);
13016     lstrcatA(path, "\\");
13017 
13018     size = MAX_PATH;
13019     lstrcpyA(value, "aaa");
13020     r = MsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
13021                               MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
13022     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13023     ok(!lstrcmpA(value, path), "expected \"%s\", got \"%s\"\n", path, value);
13024     ok(size == lstrlenA(path), "expected %d, got %lu\n", lstrlenA(path), size);
13025 
13026     r = MsiInstallProductA("msifile0.msi", "REMOVE=ALL FULL=1");
13027     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13028 
13029     /* separate cabinet file */
13030 
13031     size = MAX_PATH;
13032     lstrcpyA(value, "aaa");
13033     r = MsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
13034                               MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
13035     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
13036     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
13037 
13038     r = MsiInstallProductA("msifile1.msi", "PUBLISH_PRODUCT=1");
13039     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13040 
13041     lstrcpyA(path, CURR_DIR);
13042     lstrcatA(path, "\\");
13043 
13044     size = MAX_PATH;
13045     lstrcpyA(value, "aaa");
13046     r = MsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
13047                               MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
13048     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13049     ok(!lstrcmpA(value, path), "expected \"%s\", got \"%s\"\n", path, value);
13050     ok(size == lstrlenA(path), "expected %d, got %lu\n", lstrlenA(path), size);
13051 
13052     r = MsiInstallProductA("msifile1.msi", "REMOVE=ALL FULL=1");
13053     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13054 
13055     size = MAX_PATH;
13056     lstrcpyA(value, "aaa");
13057     r = MsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
13058                               MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
13059     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
13060     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
13061 
13062     /* embedded cabinet stream */
13063 
13064     add_cabinet_storage("msifile2.msi", "test1.cab");
13065 
13066     r = MsiInstallProductA("msifile2.msi", "PUBLISH_PRODUCT=1");
13067     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13068 
13069     size = MAX_PATH;
13070     lstrcpyA(value, "aaa");
13071     r = MsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
13072                               MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
13073     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13074     ok(!lstrcmpA(value, path), "expected \"%s\", got \"%s\"\n", path, value);
13075     ok(size == lstrlenA(path), "expected %d, got %lu\n", lstrlenA(path), size);
13076 
13077     r = MsiInstallProductA("msifile2.msi", "REMOVE=ALL FULL=1");
13078     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13079 
13080     size = MAX_PATH;
13081     lstrcpyA(value, "aaa");
13082     r = MsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
13083                               MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
13084     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
13085     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
13086 
13087 error:
13088     delete_cab_files();
13089     DeleteFileA("msitest\\maximus");
13090     RemoveDirectoryA("msitest");
13091     DeleteFileA("msifile0.msi");
13092     DeleteFileA("msifile1.msi");
13093     DeleteFileA("msifile2.msi");
13094 }
13095 
test_setpropertyfolder(void)13096 static void test_setpropertyfolder(void)
13097 {
13098     UINT r;
13099 
13100     if (!is_process_elevated())
13101     {
13102         skip("process is limited\n");
13103         return;
13104     }
13105 
13106     CreateDirectoryA("msitest", NULL);
13107     create_file("msitest\\maximus", 500);
13108 
13109     create_database(msifile, spf_tables, ARRAY_SIZE(spf_tables));
13110 
13111     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
13112 
13113     r = MsiInstallProductA(msifile, NULL);
13114     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
13115     {
13116         skip("Not enough rights to perform tests\n");
13117         goto error;
13118     }
13119     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13120     ok(delete_pf("msitest\\added\\added2\\maximus", TRUE), "File not installed\n");
13121     ok(delete_pf("msitest\\added\\added2", FALSE), "Directory not created\n");
13122     ok(delete_pf("msitest\\added", FALSE), "Directory not created\n");
13123     ok(delete_pf("msitest", FALSE), "Directory not created\n");
13124 
13125     CreateDirectoryA("parent", NULL);
13126     CreateDirectoryA("parent\\child", NULL);
13127     create_file("parent\\child\\maximus", 500);
13128 
13129     create_database(msifile, spf2_tables, ARRAY_SIZE(spf2_tables));
13130 
13131     r = MsiInstallProductA(msifile, "TARGETDIR=c:\\");
13132     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13133 
13134     ok(delete_pf("msitest\\maximus", TRUE), "file not installed\n");
13135     ok(delete_pf("msitest", FALSE), "directory not created\n");
13136 
13137     ok(DeleteFileA("c:\\parent\\child\\Shortcut.lnk"), "file not installed\n");
13138     ok(RemoveDirectoryA("c:\\parent\\child"), "directory not created\n");
13139     ok(RemoveDirectoryA("c:\\parent"), "directory not created\n");
13140 
13141     DeleteFileA("parent\\child\\maximus");
13142     RemoveDirectoryA("parent\\child");
13143     RemoveDirectoryA("parent");
13144 
13145 error:
13146     DeleteFileA(msifile);
13147     DeleteFileA("msitest\\maximus");
13148     RemoveDirectoryA("msitest");
13149 }
13150 
test_sourcedir_props(void)13151 static void test_sourcedir_props(void)
13152 {
13153     UINT r;
13154 
13155     if (!is_process_elevated())
13156     {
13157         skip("process is limited\n");
13158         return;
13159     }
13160 
13161     create_test_files();
13162     create_file("msitest\\sourcedir.txt", 1000);
13163     create_database(msifile, sd_tables, ARRAY_SIZE(sd_tables));
13164 
13165     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
13166 
13167     /* full UI, no ResolveSource action */
13168     r = MsiInstallProductA(msifile, NULL);
13169     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13170 
13171     r = MsiInstallProductA(msifile, "REMOVE=ALL");
13172     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13173 
13174     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
13175     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
13176 
13177     /* full UI, ResolveSource action */
13178     r = MsiInstallProductA(msifile, "ResolveSource=1");
13179     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13180 
13181     r = MsiInstallProductA(msifile, "REMOVE=ALL");
13182     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13183 
13184     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
13185     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
13186 
13187     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
13188 
13189     /* no UI, no ResolveSource action */
13190     r = MsiInstallProductA(msifile, NULL);
13191     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13192 
13193     r = MsiInstallProductA(msifile, "REMOVE=ALL");
13194     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13195 
13196     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
13197     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
13198 
13199     /* no UI, ResolveSource action */
13200     r = MsiInstallProductA(msifile, "ResolveSource=1");
13201     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13202 
13203     r = MsiInstallProductA(msifile, "REMOVE=ALL");
13204     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13205 
13206     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
13207     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
13208 
13209     DeleteFileA("msitest\\sourcedir.txt");
13210     delete_test_files();
13211     DeleteFileA(msifile);
13212 }
13213 
test_concurrentinstall(void)13214 static void test_concurrentinstall(void)
13215 {
13216     UINT r;
13217     CHAR path[MAX_PATH];
13218 
13219     if (!is_process_elevated())
13220     {
13221         skip("process is limited\n");
13222         return;
13223     }
13224 
13225     CreateDirectoryA("msitest", NULL);
13226     CreateDirectoryA("msitest\\msitest", NULL);
13227     create_file("msitest\\maximus", 500);
13228     create_file("msitest\\msitest\\augustus", 500);
13229 
13230     create_database(msifile, ci_tables, ARRAY_SIZE(ci_tables));
13231 
13232     lstrcpyA(path, CURR_DIR);
13233     lstrcatA(path, "\\msitest\\concurrent.msi");
13234     create_database(path, ci2_tables, ARRAY_SIZE(ci2_tables));
13235 
13236     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
13237 
13238     r = MsiInstallProductA(msifile, NULL);
13239     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
13240     {
13241         skip("Not enough rights to perform tests\n");
13242         goto error;
13243     }
13244     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13245     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
13246     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
13247     ok(delete_pf("msitest", FALSE), "Directory not created\n");
13248 
13249     r = MsiConfigureProductA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", INSTALLLEVEL_DEFAULT,
13250                              INSTALLSTATE_ABSENT);
13251     ok(r == ERROR_SUCCESS, "got %u\n", r);
13252 
13253     r = MsiConfigureProductA("{FF4AFE9C-6AC2-44F9-A060-9EA6BD16C75E}", INSTALLLEVEL_DEFAULT,
13254                              INSTALLSTATE_ABSENT);
13255     ok(r == ERROR_SUCCESS, "got %u\n", r);
13256 
13257 error:
13258     DeleteFileA(path);
13259     DeleteFileA(msifile);
13260     DeleteFileA("msitest\\msitest\\augustus");
13261     DeleteFileA("msitest\\maximus");
13262     RemoveDirectoryA("msitest\\msitest");
13263     RemoveDirectoryA("msitest");
13264 }
13265 
test_command_line_parsing(void)13266 static void test_command_line_parsing(void)
13267 {
13268     UINT r;
13269     const char *cmd;
13270 
13271     if (!is_process_elevated())
13272     {
13273         skip("process is limited\n");
13274         return;
13275     }
13276 
13277     create_test_files();
13278     create_database(msifile, cl_tables, ARRAY_SIZE(cl_tables));
13279 
13280     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
13281 
13282     cmd = " ";
13283     r = MsiInstallProductA(msifile, cmd);
13284     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13285 
13286     cmd = "=";
13287     r = MsiInstallProductA(msifile, cmd);
13288     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
13289 
13290     cmd = "==";
13291     r = MsiInstallProductA(msifile, cmd);
13292     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
13293 
13294     cmd = "one";
13295     r = MsiInstallProductA(msifile, cmd);
13296     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
13297 
13298     cmd = "=one";
13299     r = MsiInstallProductA(msifile, cmd);
13300     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
13301 
13302     cmd = "P=";
13303     r = MsiInstallProductA(msifile, cmd);
13304     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13305 
13306     cmd = "  P=";
13307     r = MsiInstallProductA(msifile, cmd);
13308     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13309 
13310     cmd = "P=  ";
13311     r = MsiInstallProductA(msifile, cmd);
13312     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13313 
13314     cmd = "P=\"";
13315     r = MsiInstallProductA(msifile, cmd);
13316     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
13317 
13318     cmd = "P=\"\"";
13319     r = MsiInstallProductA(msifile, cmd);
13320     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13321 
13322     cmd = "P=\"\"\"";
13323     r = MsiInstallProductA(msifile, cmd);
13324     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
13325 
13326     cmd = "P=\"\"\"\"";
13327     r = MsiInstallProductA(msifile, cmd);
13328     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13329 
13330     cmd = "P=\" ";
13331     r = MsiInstallProductA(msifile, cmd);
13332     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
13333 
13334     cmd = "P= \"";
13335     r = MsiInstallProductA(msifile, cmd);
13336     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
13337 
13338     cmd = "P= \"\" ";
13339     r = MsiInstallProductA(msifile, cmd);
13340     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13341 
13342     cmd = "P=\"  \"";
13343     r = MsiInstallProductA(msifile, cmd);
13344     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13345 
13346     cmd = "P=one";
13347     r = MsiInstallProductA(msifile, cmd);
13348     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
13349 
13350     cmd = "P= one";
13351     r = MsiInstallProductA(msifile, cmd);
13352     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
13353 
13354     cmd = "P=\"one";
13355     r = MsiInstallProductA(msifile, cmd);
13356     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
13357 
13358     cmd = "P=one\"";
13359     r = MsiInstallProductA(msifile, cmd);
13360     todo_wine ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13361 
13362     cmd = "P=\"one\"";
13363     r = MsiInstallProductA(msifile, cmd);
13364     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
13365 
13366     cmd = "P= \"one\" ";
13367     r = MsiInstallProductA(msifile, cmd);
13368     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
13369 
13370     cmd = "P=\"one\"\"";
13371     r = MsiInstallProductA(msifile, cmd);
13372     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
13373 
13374     cmd = "P=\"\"one\"";
13375     r = MsiInstallProductA(msifile, cmd);
13376     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
13377 
13378     cmd = "P=\"\"one\"\"";
13379     r = MsiInstallProductA(msifile, cmd);
13380     todo_wine ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
13381 
13382     cmd = "P=\"one two\"";
13383     r = MsiInstallProductA(msifile, cmd);
13384     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13385 
13386     cmd = "P=\"\"\"one\"\" two\"";
13387     r = MsiInstallProductA(msifile, cmd);
13388     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13389 
13390     cmd = "P=\"\"\"one\"\" two\" Q=three";
13391     r = MsiInstallProductA(msifile, cmd);
13392     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13393 
13394     cmd = "P=\"\" Q=\"two\"";
13395     r = MsiInstallProductA(msifile, cmd);
13396     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13397 
13398     cmd = "P=\"one\" Q=\"two\"";
13399     r = MsiInstallProductA(msifile, cmd);
13400     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
13401 
13402     cmd = "P=\"one=two\"";
13403     r = MsiInstallProductA(msifile, cmd);
13404     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13405 
13406     cmd = "Q=\"\" P=\"one\"";
13407     r = MsiInstallProductA(msifile, cmd);
13408     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
13409 
13410     cmd = "P=\"\"\"one\"\"\" Q=\"two\"";
13411     r = MsiInstallProductA(msifile, cmd);
13412     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13413 
13414     cmd = "P=\"one \"\"two\"\"\" Q=\"three\"";
13415     r = MsiInstallProductA(msifile, cmd);
13416     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13417 
13418     cmd = "P=\"\"\"one\"\" two\" Q=\"three\"";
13419     r = MsiInstallProductA(msifile, cmd);
13420     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13421 
13422     DeleteFileA(msifile);
13423     delete_test_files();
13424 }
13425 
START_TEST(msi)13426 START_TEST(msi)
13427 {
13428     DWORD len;
13429     char temp_path[MAX_PATH], prev_path[MAX_PATH];
13430 
13431 #ifdef __REACTOS__
13432     if (!winetest_interactive &&
13433         !strcmp(winetest_platform, "windows"))
13434     {
13435         skip("ROSTESTS-180: Skipping msi_winetest:msi because it hangs on WHS-Testbot. Set winetest_interactive to run it anyway.\n");
13436         return;
13437     }
13438 #endif
13439 
13440     if (!is_process_elevated()) restart_as_admin_elevated();
13441 
13442     IsWow64Process(GetCurrentProcess(), &is_wow64);
13443 
13444     GetCurrentDirectoryA(MAX_PATH, prev_path);
13445     GetTempPathA(MAX_PATH, temp_path);
13446     SetCurrentDirectoryA(temp_path);
13447 
13448     lstrcpyA(CURR_DIR, temp_path);
13449     len = lstrlenA(CURR_DIR);
13450 
13451     if(len && (CURR_DIR[len - 1] == '\\'))
13452         CURR_DIR[len - 1] = 0;
13453 
13454     ok(get_system_dirs(), "failed to retrieve system dirs\n");
13455 
13456     test_usefeature();
13457     test_null();
13458     test_getcomponentpath();
13459     test_MsiGetFileHash();
13460     test_MsiSetInternalUI();
13461     test_MsiSetExternalUI();
13462     test_MsiQueryProductState();
13463     test_MsiQueryFeatureState();
13464     test_MsiQueryComponentState();
13465     test_MsiGetComponentPath();
13466     test_MsiGetComponentPathEx();
13467     test_MsiProvideComponent();
13468     test_MsiGetProductCode();
13469     test_MsiEnumClients();
13470     test_MsiGetProductInfo();
13471     test_MsiGetProductInfoEx();
13472     test_MsiGetUserInfo();
13473     test_MsiOpenProduct();
13474     test_MsiEnumPatchesEx();
13475     test_MsiEnumPatches();
13476     test_MsiGetPatchInfoEx();
13477     test_MsiGetPatchInfo();
13478     test_MsiEnumProducts();
13479     test_MsiEnumProductsEx();
13480     test_MsiEnumComponents();
13481     test_MsiEnumComponentsEx();
13482     test_MsiGetFileVersion();
13483     test_MsiGetFileSignatureInformation();
13484     test_MsiConfigureProductEx();
13485     test_MsiSetFeatureAttributes();
13486     test_MsiGetFeatureInfo();
13487     test_lastusedsource();
13488     test_setpropertyfolder();
13489     test_sourcedir_props();
13490     test_concurrentinstall();
13491     test_command_line_parsing();
13492     test_MsiProvideQualifiedComponentEx();
13493 
13494     SetCurrentDirectoryA(prev_path);
13495 }
13496