Release 1.5.29.
[wine] / dlls / msi / tests / msi.c
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
23 #include <stdio.h>
24 #include <windows.h>
25 #include <msi.h>
26 #include <msiquery.h>
27 #include <msidefs.h>
28 #include <sddl.h>
29
30 #include "wine/test.h"
31
32 static BOOL is_wow64;
33 static const char msifile[] = "winetest.msi";
34 static char CURR_DIR[MAX_PATH];
35 static char PROG_FILES_DIR[MAX_PATH];
36 static char PROG_FILES_DIR_NATIVE[MAX_PATH];
37 static char COMMON_FILES_DIR[MAX_PATH];
38 static char WINDOWS_DIR[MAX_PATH];
39
40 static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
41 static BOOL (WINAPI *pOpenProcessToken)( HANDLE, DWORD, PHANDLE );
42 static LONG (WINAPI *pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD);
43 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
44
45 static INSTALLSTATE (WINAPI *pMsiGetComponentPathA)
46     (LPCSTR, LPCSTR, LPSTR, DWORD*);
47 static UINT (WINAPI *pMsiGetFileHashA)
48     (LPCSTR, DWORD, PMSIFILEHASHINFO);
49 static UINT (WINAPI *pMsiGetProductInfoExA)
50     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, LPSTR, LPDWORD);
51 static UINT (WINAPI *pMsiOpenPackageExA)
52     (LPCSTR, DWORD, MSIHANDLE*);
53 static UINT (WINAPI *pMsiOpenPackageExW)
54     (LPCWSTR, DWORD, MSIHANDLE*);
55 static UINT (WINAPI *pMsiEnumPatchesExA)
56     (LPCSTR, LPCSTR, DWORD, DWORD, DWORD, LPSTR, LPSTR,
57     MSIINSTALLCONTEXT*, LPSTR, LPDWORD);
58 static UINT (WINAPI *pMsiQueryComponentStateA)
59     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, INSTALLSTATE*);
60 static INSTALLSTATE (WINAPI *pMsiUseFeatureExA)
61     (LPCSTR, LPCSTR ,DWORD, DWORD);
62 static UINT (WINAPI *pMsiGetPatchInfoExA)
63     (LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, LPSTR, DWORD *);
64 static UINT (WINAPI *pMsiEnumProductsExA)
65     (LPCSTR, LPCSTR, DWORD, DWORD, CHAR[39], MSIINSTALLCONTEXT *, LPSTR, LPDWORD);
66 static UINT (WINAPI *pMsiEnumComponentsExA)
67     (LPCSTR, DWORD, DWORD, CHAR[39], MSIINSTALLCONTEXT *, LPSTR, LPDWORD);
68 static UINT (WINAPI *pMsiSetExternalUIRecord)
69     (INSTALLUI_HANDLER_RECORD, DWORD, LPVOID, PINSTALLUI_HANDLER_RECORD);
70
71 static void init_functionpointers(void)
72 {
73     HMODULE hmsi = GetModuleHandleA("msi.dll");
74     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
75     HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
76
77 #define GET_PROC(dll, func) \
78     p ## func = (void *)GetProcAddress(dll, #func); \
79     if(!p ## func) \
80       trace("GetProcAddress(%s) failed\n", #func);
81
82     GET_PROC(hmsi, MsiGetComponentPathA)
83     GET_PROC(hmsi, MsiGetFileHashA)
84     GET_PROC(hmsi, MsiGetProductInfoExA)
85     GET_PROC(hmsi, MsiOpenPackageExA)
86     GET_PROC(hmsi, MsiOpenPackageExW)
87     GET_PROC(hmsi, MsiEnumPatchesExA)
88     GET_PROC(hmsi, MsiQueryComponentStateA)
89     GET_PROC(hmsi, MsiSetExternalUIRecord)
90     GET_PROC(hmsi, MsiUseFeatureExA)
91     GET_PROC(hmsi, MsiGetPatchInfoExA)
92     GET_PROC(hmsi, MsiEnumProductsExA)
93     GET_PROC(hmsi, MsiEnumComponentsExA)
94
95     GET_PROC(hadvapi32, ConvertSidToStringSidA)
96     GET_PROC(hadvapi32, OpenProcessToken);
97     GET_PROC(hadvapi32, RegDeleteKeyExA)
98     GET_PROC(hkernel32, IsWow64Process)
99
100 #undef GET_PROC
101 }
102
103 static BOOL get_system_dirs(void)
104 {
105     HKEY hkey;
106     DWORD type, size;
107
108     if (RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", &hkey))
109         return FALSE;
110
111     size = MAX_PATH;
112     if (RegQueryValueExA(hkey, "ProgramFilesDir (x86)", 0, &type, (LPBYTE)PROG_FILES_DIR, &size) &&
113         RegQueryValueExA(hkey, "ProgramFilesDir", 0, &type, (LPBYTE)PROG_FILES_DIR, &size))
114     {
115         RegCloseKey(hkey);
116         return FALSE;
117     }
118     size = MAX_PATH;
119     if (RegQueryValueExA(hkey, "CommonFilesDir (x86)", 0, &type, (LPBYTE)COMMON_FILES_DIR, &size) &&
120         RegQueryValueExA(hkey, "CommonFilesDir", 0, &type, (LPBYTE)COMMON_FILES_DIR, &size))
121     {
122         RegCloseKey(hkey);
123         return FALSE;
124     }
125     size = MAX_PATH;
126     if (RegQueryValueExA(hkey, "ProgramFilesDir", 0, &type, (LPBYTE)PROG_FILES_DIR_NATIVE, &size))
127     {
128         RegCloseKey(hkey);
129         return FALSE;
130     }
131     RegCloseKey(hkey);
132     if (!GetWindowsDirectoryA(WINDOWS_DIR, MAX_PATH)) return FALSE;
133     return TRUE;
134 }
135
136 static BOOL file_exists(const char *file)
137 {
138     return GetFileAttributes(file) != INVALID_FILE_ATTRIBUTES;
139 }
140
141 static BOOL pf_exists(const char *file)
142 {
143     char path[MAX_PATH];
144
145     lstrcpyA(path, PROG_FILES_DIR);
146     lstrcatA(path, "\\");
147     lstrcatA(path, file);
148     return file_exists(path);
149 }
150
151 static BOOL delete_pf(const char *rel_path, BOOL is_file)
152 {
153     char path[MAX_PATH];
154
155     lstrcpyA(path, PROG_FILES_DIR);
156     lstrcatA(path, "\\");
157     lstrcatA(path, rel_path);
158
159     if (is_file)
160         return DeleteFileA(path);
161     else
162         return RemoveDirectoryA(path);
163 }
164
165 static BOOL is_process_limited(void)
166 {
167     HANDLE token;
168     TOKEN_ELEVATION_TYPE type = TokenElevationTypeDefault;
169     DWORD size;
170     BOOL ret;
171
172     if (!pOpenProcessToken) return FALSE;
173     if (!pOpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) return FALSE;
174     ret = GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &size);
175     CloseHandle(token);
176     return (ret && type == TokenElevationTypeLimited);
177 }
178
179 /* msi database data */
180
181 static const char directory_dat[] =
182     "Directory\tDirectory_Parent\tDefaultDir\n"
183     "s72\tS72\tl255\n"
184     "Directory\tDirectory\n"
185     "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
186     "ProgramFilesFolder\tTARGETDIR\t.\n"
187     "TARGETDIR\t\tSourceDir";
188
189 static const char component_dat[] =
190     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
191     "s72\tS38\ts72\ti2\tS255\tS72\n"
192     "Component\tComponent\n"
193     "One\t{8F5BAEEF-DD92-40AC-9397-BE3CF9F97C81}\tMSITESTDIR\t2\tNOT REINSTALL\tone.txt\n";
194
195 static const char feature_dat[] =
196     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
197     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
198     "Feature\tFeature\n"
199     "One\t\tOne\tOne\t1\t3\tMSITESTDIR\t0\n"
200     "Two\t\t\t\t2\t1\tTARGETDIR\t0\n";
201
202 static const char feature_comp_dat[] =
203     "Feature_\tComponent_\n"
204     "s38\ts72\n"
205     "FeatureComponents\tFeature_\tComponent_\n"
206     "One\tOne\n";
207
208 static const char file_dat[] =
209     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
210     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
211     "File\tFile\n"
212     "one.txt\tOne\tone.txt\t1000\t\t\t0\t1\n";
213
214 static const char install_exec_seq_dat[] =
215     "Action\tCondition\tSequence\n"
216     "s72\tS255\tI2\n"
217     "InstallExecuteSequence\tAction\n"
218     "ValidateProductID\t\t700\n"
219     "CostInitialize\t\t800\n"
220     "FileCost\t\t900\n"
221     "CostFinalize\t\t1000\n"
222     "InstallValidate\t\t1400\n"
223     "InstallInitialize\t\t1500\n"
224     "ProcessComponents\t\t1600\n"
225     "UnpublishFeatures\t\t1800\n"
226     "RemoveFiles\t\t3500\n"
227     "InstallFiles\t\t4000\n"
228     "RegisterProduct\t\t6100\n"
229     "PublishFeatures\t\t6300\n"
230     "PublishProduct\t\t6400\n"
231     "InstallFinalize\t\t6600";
232
233 static const char media_dat[] =
234     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
235     "i2\ti4\tL64\tS255\tS32\tS72\n"
236     "Media\tDiskId\n"
237     "1\t1\t\t\tDISK1\t\n";
238
239 static const char property_dat[] =
240     "Property\tValue\n"
241     "s72\tl0\n"
242     "Property\tProperty\n"
243     "INSTALLLEVEL\t3\n"
244     "Manufacturer\tWine\n"
245     "ProductCode\t{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}\n"
246     "ProductName\tMSITEST\n"
247     "ProductVersion\t1.1.1\n"
248     "UpgradeCode\t{9574448F-9B86-4E07-B6F6-8D199DA12127}\n"
249     "MSIFASTINSTALL\t1\n";
250
251 static const char mcp_component_dat[] =
252     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
253     "s72\tS38\ts72\ti2\tS255\tS72\n"
254     "Component\tComponent\n"
255     "hydrogen\t{C844BD1E-1907-4C00-8BC9-150BD70DF0A1}\tMSITESTDIR\t2\t\thydrogen\n"
256     "helium\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t2\t\thelium\n"
257     "lithium\t{4AF28FFC-71C7-4307-BDE4-B77C5338F56F}\tMSITESTDIR\t2\tPROPVAR=42\tlithium\n";
258
259 static const char mcp_feature_dat[] =
260     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
261     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
262     "Feature\tFeature\n"
263     "hydroxyl\t\thydroxyl\thydroxyl\t2\t1\tTARGETDIR\t0\n"
264     "heliox\t\theliox\theliox\t2\t5\tTARGETDIR\t0\n"
265     "lithia\t\tlithia\tlithia\t2\t10\tTARGETDIR\t0";
266
267 static const char mcp_feature_comp_dat[] =
268     "Feature_\tComponent_\n"
269     "s38\ts72\n"
270     "FeatureComponents\tFeature_\tComponent_\n"
271     "hydroxyl\thydrogen\n"
272     "heliox\thelium\n"
273     "lithia\tlithium";
274
275 static const CHAR mcp_file_dat[] =
276     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
277     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
278     "File\tFile\n"
279     "hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n"
280     "helium\thelium\thelium\t0\t\t\t8192\t1\n"
281     "lithium\tlithium\tlithium\t0\t\t\t8192\t1";
282
283 typedef struct _msi_table
284 {
285     const CHAR *filename;
286     const CHAR *data;
287     int size;
288 } msi_table;
289
290 #define ADD_TABLE(x) {#x".idt", x##_dat, sizeof(x##_dat)}
291
292 static const msi_table tables[] =
293 {
294     ADD_TABLE(directory),
295     ADD_TABLE(component),
296     ADD_TABLE(feature),
297     ADD_TABLE(feature_comp),
298     ADD_TABLE(file),
299     ADD_TABLE(install_exec_seq),
300     ADD_TABLE(media),
301     ADD_TABLE(property),
302 };
303
304 static const msi_table mcp_tables[] =
305 {
306     ADD_TABLE(directory),
307     ADD_TABLE(mcp_component),
308     ADD_TABLE(mcp_feature),
309     ADD_TABLE(mcp_feature_comp),
310     ADD_TABLE(mcp_file),
311     ADD_TABLE(install_exec_seq),
312     ADD_TABLE(media),
313     ADD_TABLE(property)
314 };
315
316 static void write_file(const CHAR *filename, const char *data, int data_size)
317 {
318     DWORD size;
319
320     HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
321                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
322
323     WriteFile(hf, data, data_size, &size, NULL);
324     CloseHandle(hf);
325 }
326
327 static void write_msi_summary_info(MSIHANDLE db, INT version, INT wordcount, const char *template)
328 {
329     MSIHANDLE summary;
330     UINT r;
331
332     r = MsiGetSummaryInformationA(db, NULL, 5, &summary);
333     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
334
335     r = MsiSummaryInfoSetPropertyA(summary, PID_TEMPLATE, VT_LPSTR, 0, NULL, template);
336     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
337
338     r = MsiSummaryInfoSetPropertyA(summary, PID_REVNUMBER, VT_LPSTR, 0, NULL,
339                                    "{004757CA-5092-49C2-AD20-28E1CE0DF5F2}");
340     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
341
342     r = MsiSummaryInfoSetPropertyA(summary, PID_PAGECOUNT, VT_I4, version, NULL, NULL);
343     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
344
345     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, wordcount, NULL, NULL);
346     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
347
348     r = MsiSummaryInfoSetPropertyA(summary, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
349     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
350
351     /* write the summary changes back to the stream */
352     r = MsiSummaryInfoPersist(summary);
353     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
354
355     MsiCloseHandle(summary);
356 }
357
358 #define create_database(name, tables, num_tables) \
359     create_database_wordcount(name, tables, num_tables, 100, 0, ";1033");
360
361 #define create_database_template(name, tables, num_tables, version, template) \
362     create_database_wordcount(name, tables, num_tables, version, 0, template);
363
364 static void create_database_wordcount(const CHAR *name, const msi_table *tables,
365                                       int num_tables, INT version, INT wordcount,
366                                       const char *template)
367 {
368     MSIHANDLE db;
369     UINT r;
370     int j;
371
372     r = MsiOpenDatabaseA(name, MSIDBOPEN_CREATE, &db);
373     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
374
375     /* import the tables into the database */
376     for (j = 0; j < num_tables; j++)
377     {
378         const msi_table *table = &tables[j];
379
380         write_file(table->filename, table->data, (table->size - 1) * sizeof(char));
381
382         r = MsiDatabaseImportA(db, CURR_DIR, table->filename);
383         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
384
385         DeleteFileA(table->filename);
386     }
387
388     write_msi_summary_info(db, version, wordcount, template);
389
390     r = MsiDatabaseCommit(db);
391     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
392
393     MsiCloseHandle(db);
394 }
395
396 static UINT run_query(MSIHANDLE hdb, const char *query)
397 {
398     MSIHANDLE hview = 0;
399     UINT r;
400
401     r = MsiDatabaseOpenView(hdb, query, &hview);
402     if (r != ERROR_SUCCESS)
403         return r;
404
405     r = MsiViewExecute(hview, 0);
406     if (r == ERROR_SUCCESS)
407         r = MsiViewClose(hview);
408     MsiCloseHandle(hview);
409     return r;
410 }
411
412 static UINT set_summary_info(MSIHANDLE hdb, LPSTR prodcode)
413 {
414     UINT res;
415     MSIHANDLE suminfo;
416
417     /* build summary info */
418     res = MsiGetSummaryInformation(hdb, NULL, 7, &suminfo);
419     ok(res == ERROR_SUCCESS, "Failed to open summaryinfo\n");
420
421     res = MsiSummaryInfoSetProperty(suminfo, 2, VT_LPSTR, 0, NULL,
422                                     "Installation Database");
423     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
424
425     res = MsiSummaryInfoSetProperty(suminfo, 3, VT_LPSTR, 0, NULL,
426                                     "Installation Database");
427     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
428
429     res = MsiSummaryInfoSetProperty(suminfo, 4, VT_LPSTR, 0, NULL,
430                                     "Wine Hackers");
431     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
432
433     res = MsiSummaryInfoSetProperty(suminfo, 7, VT_LPSTR, 0, NULL,
434                                     ";1033");
435     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
436
437     res = MsiSummaryInfoSetProperty(suminfo, PID_REVNUMBER, VT_LPSTR, 0, NULL,
438                                     "{A2078D65-94D6-4205-8DEE-F68D6FD622AA}");
439     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
440
441     res = MsiSummaryInfoSetProperty(suminfo, 14, VT_I4, 100, NULL, NULL);
442     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
443
444     res = MsiSummaryInfoSetProperty(suminfo, 15, VT_I4, 0, NULL, NULL);
445     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
446
447     res = MsiSummaryInfoPersist(suminfo);
448     ok(res == ERROR_SUCCESS, "Failed to make summary info persist\n");
449
450     res = MsiCloseHandle(suminfo);
451     ok(res == ERROR_SUCCESS, "Failed to close suminfo\n");
452
453     return res;
454 }
455
456 static MSIHANDLE create_package_db(LPSTR prodcode)
457 {
458     MSIHANDLE hdb = 0;
459     CHAR query[MAX_PATH];
460     UINT res;
461
462     DeleteFile(msifile);
463
464     /* create an empty database */
465     res = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
466     ok( res == ERROR_SUCCESS , "Failed to create database\n" );
467     if (res != ERROR_SUCCESS)
468         return hdb;
469
470     res = MsiDatabaseCommit(hdb);
471     ok(res == ERROR_SUCCESS, "Failed to commit database\n");
472
473     set_summary_info(hdb, prodcode);
474
475     res = run_query(hdb,
476             "CREATE TABLE `Directory` ( "
477             "`Directory` CHAR(255) NOT NULL, "
478             "`Directory_Parent` CHAR(255), "
479             "`DefaultDir` CHAR(255) NOT NULL "
480             "PRIMARY KEY `Directory`)");
481     ok(res == ERROR_SUCCESS , "Failed to create directory table\n");
482
483     res = run_query(hdb,
484             "CREATE TABLE `Property` ( "
485             "`Property` CHAR(72) NOT NULL, "
486             "`Value` CHAR(255) "
487             "PRIMARY KEY `Property`)");
488     ok(res == ERROR_SUCCESS , "Failed to create directory table\n");
489
490     sprintf(query, "INSERT INTO `Property` "
491             "(`Property`, `Value`) "
492             "VALUES( 'ProductCode', '%s' )", prodcode);
493     res = run_query(hdb, query);
494     ok(res == ERROR_SUCCESS , "Failed\n");
495
496     res = MsiDatabaseCommit(hdb);
497     ok(res == ERROR_SUCCESS, "Failed to commit database\n");
498
499     return hdb;
500 }
501
502 static void test_usefeature(void)
503 {
504     INSTALLSTATE r;
505
506     if (!pMsiUseFeatureExA)
507     {
508         win_skip("MsiUseFeatureExA not implemented\n");
509         return;
510     }
511
512     r = MsiQueryFeatureState(NULL,NULL);
513     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
514
515     r = MsiQueryFeatureState("{9085040-6000-11d3-8cfe-0150048383c9}" ,NULL);
516     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
517
518     r = pMsiUseFeatureExA(NULL,NULL,0,0);
519     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
520
521     r = pMsiUseFeatureExA(NULL, "WORDVIEWFiles", -2, 1 );
522     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
523
524     r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}", 
525                          NULL, -2, 0 );
526     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
527
528     r = pMsiUseFeatureExA("{9085040-6000-11d3-8cfe-0150048383c9}", 
529                          "WORDVIEWFiles", -2, 0 );
530     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
531
532     r = pMsiUseFeatureExA("{0085040-6000-11d3-8cfe-0150048383c9}", 
533                          "WORDVIEWFiles", -2, 0 );
534     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
535
536     r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}", 
537                          "WORDVIEWFiles", -2, 1 );
538     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
539 }
540
541 static LONG delete_key( HKEY key, LPCSTR subkey, REGSAM access )
542 {
543     if (pRegDeleteKeyExA)
544         return pRegDeleteKeyExA( key, subkey, access, 0 );
545     return RegDeleteKeyA( key, subkey );
546 }
547
548 static void test_null(void)
549 {
550     MSIHANDLE hpkg;
551     UINT r;
552     HKEY hkey;
553     DWORD dwType, cbData;
554     LPBYTE lpData = NULL;
555     INSTALLSTATE state;
556     REGSAM access = KEY_ALL_ACCESS;
557
558     if (is_wow64)
559         access |= KEY_WOW64_64KEY;
560
561     r = pMsiOpenPackageExW(NULL, 0, &hpkg);
562     ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
563
564     state = MsiQueryProductStateW(NULL);
565     ok( state == INSTALLSTATE_INVALIDARG, "wrong return\n");
566
567     r = MsiEnumFeaturesW(NULL,0,NULL,NULL);
568     ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
569
570     r = MsiConfigureFeatureW(NULL, NULL, 0);
571     ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
572
573     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", NULL, 0);
574     ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
575
576     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000001}", "foo", 0);
577     ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
578
579     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000002}", "foo", INSTALLSTATE_DEFAULT);
580     ok( r == ERROR_UNKNOWN_PRODUCT, "wrong error %d\n", r);
581
582     /* make sure empty string to MsiGetProductInfo is not a handle to default registry value, saving and restoring the
583      * necessary registry values */
584
585     /* empty product string */
586     r = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", 0, access, &hkey);
587     if (r == ERROR_ACCESS_DENIED)
588     {
589         skip("Not enough rights to perform tests\n");
590         return;
591     }
592     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
593
594     r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
595     ok ( r == ERROR_SUCCESS || r == ERROR_FILE_NOT_FOUND, "wrong error %d\n", r);
596     if ( r == ERROR_SUCCESS )
597     {
598         lpData = HeapAlloc(GetProcessHeap(), 0, cbData);
599         if (!lpData)
600             skip("Out of memory\n");
601         else
602         {
603             r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
604             ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
605         }
606     }
607
608     r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
609     if (r == ERROR_ACCESS_DENIED)
610     {
611         skip("Not enough rights to perform tests\n");
612         HeapFree(GetProcessHeap(), 0, lpData);
613         RegCloseKey(hkey);
614         return;
615     }
616     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
617
618     r = MsiGetProductInfoA("", "", NULL, NULL);
619     ok ( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
620
621     if (lpData)
622     {
623         r = RegSetValueExA(hkey, NULL, 0, dwType, lpData, cbData);
624         ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
625
626         HeapFree(GetProcessHeap(), 0, lpData);
627     }
628     else
629     {
630         r = RegDeleteValueA(hkey, NULL);
631         ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
632     }
633
634     r = RegCloseKey(hkey);
635     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
636
637     /* empty attribute */
638     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}",
639                         0, NULL, 0, access, NULL, &hkey, NULL);
640     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
641
642     r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
643     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
644
645     r = MsiGetProductInfoA("{F1C3AF50-8B56-4A69-A00C-00773FE42F30}", "", NULL, NULL);
646     ok ( r == ERROR_UNKNOWN_PROPERTY, "wrong error %d\n", r);
647
648     r = RegCloseKey(hkey);
649     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
650
651     r = delete_key(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}",
652                    access & KEY_WOW64_64KEY);
653     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
654 }
655
656 static void test_getcomponentpath(void)
657 {
658     INSTALLSTATE r;
659     char buffer[0x100];
660     DWORD sz;
661
662     if(!pMsiGetComponentPathA)
663         return;
664
665     r = pMsiGetComponentPathA( NULL, NULL, NULL, NULL );
666     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
667
668     r = pMsiGetComponentPathA( "bogus", "bogus", NULL, NULL );
669     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
670
671     r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", NULL, NULL );
672     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
673
674     sz = sizeof buffer;
675     buffer[0]=0;
676     r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", buffer, &sz );
677     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
678
679     r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C998E7}",
680         "{00000000-0000-0000-0000-000000000000}", buffer, &sz );
681     ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
682
683     r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
684         "{00000000-0000-0000-0000-00000000}", buffer, &sz );
685     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
686
687     r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
688         "{029E403D-A86A-1D11-5B5B0006799C897E}", buffer, &sz );
689     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
690
691     r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C9987e}",
692                             "{00000000-A68A-11d1-5B5B-0006799C897E}", buffer, &sz );
693     ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
694 }
695
696 static void create_file(LPCSTR name, LPCSTR data, DWORD size)
697 {
698     HANDLE file;
699     DWORD written;
700
701     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
702     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
703     WriteFile(file, data, strlen(data), &written, NULL);
704
705     if (size)
706     {
707         SetFilePointer(file, size, NULL, FILE_BEGIN);
708         SetEndOfFile(file);
709     }
710
711     CloseHandle(file);
712 }
713
714 #define HASHSIZE sizeof(MSIFILEHASHINFO)
715
716 static const struct
717 {
718     LPCSTR data;
719     DWORD size;
720     MSIFILEHASHINFO hash;
721 } hash_data[] =
722 {
723     { "", 0,
724       { HASHSIZE,
725         { 0, 0, 0, 0 },
726       },
727     },
728
729     { "abc", 0,
730       { HASHSIZE,
731         { 0x98500190, 0xb04fd23c, 0x7d3f96d6, 0x727fe128 },
732       },
733     },
734
735     { "C:\\Program Files\\msitest\\caesar\n", 0,
736       { HASHSIZE,
737         { 0x2b566794, 0xfd42181b, 0x2514d6e4, 0x5768b4e2 },
738       },
739     },
740
741     { "C:\\Program Files\\msitest\\caesar\n", 500,
742       { HASHSIZE,
743         { 0x58095058, 0x805efeff, 0x10f3483e, 0x0147d653 },
744       },
745     },
746 };
747
748 static void test_MsiGetFileHash(void)
749 {
750     const char name[] = "msitest.bin";
751     UINT r;
752     MSIFILEHASHINFO hash;
753     DWORD i;
754
755     if (!pMsiGetFileHashA)
756     {
757         win_skip("MsiGetFileHash not implemented\n");
758         return;
759     }
760
761     hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
762
763     /* szFilePath is NULL */
764     r = pMsiGetFileHashA(NULL, 0, &hash);
765     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
766
767     /* szFilePath is empty */
768     r = pMsiGetFileHashA("", 0, &hash);
769     ok(r == ERROR_PATH_NOT_FOUND || r == ERROR_BAD_PATHNAME,
770        "Expected ERROR_PATH_NOT_FOUND or ERROR_BAD_PATHNAME, got %d\n", r);
771
772     /* szFilePath is nonexistent */
773     r = pMsiGetFileHashA(name, 0, &hash);
774     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
775
776     /* dwOptions is non-zero */
777     r = pMsiGetFileHashA(name, 1, &hash);
778     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
779
780     /* pHash.dwFileHashInfoSize is not correct */
781     hash.dwFileHashInfoSize = 0;
782     r = pMsiGetFileHashA(name, 0, &hash);
783     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
784
785     /* pHash is NULL */
786     r = pMsiGetFileHashA(name, 0, NULL);
787     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
788
789     for (i = 0; i < sizeof(hash_data) / sizeof(hash_data[0]); i++)
790     {
791         int ret;
792
793         create_file(name, hash_data[i].data, hash_data[i].size);
794
795         memset(&hash, 0, sizeof(MSIFILEHASHINFO));
796         hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
797
798         r = pMsiGetFileHashA(name, 0, &hash);
799         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
800
801         ret = memcmp(&hash, &hash_data[i].hash, HASHSIZE);
802         ok(!ret, "Hash incorrect\n");
803
804         DeleteFile(name);
805     }
806 }
807
808 /* copied from dlls/msi/registry.c */
809 static BOOL squash_guid(LPCWSTR in, LPWSTR out)
810 {
811     DWORD i,n=1;
812     GUID guid;
813
814     if (FAILED(CLSIDFromString((LPCOLESTR)in, &guid)))
815         return FALSE;
816
817     for(i=0; i<8; i++)
818         out[7-i] = in[n++];
819     n++;
820     for(i=0; i<4; i++)
821         out[11-i] = in[n++];
822     n++;
823     for(i=0; i<4; i++)
824         out[15-i] = in[n++];
825     n++;
826     for(i=0; i<2; i++)
827     {
828         out[17+i*2] = in[n++];
829         out[16+i*2] = in[n++];
830     }
831     n++;
832     for( ; i<8; i++)
833     {
834         out[17+i*2] = in[n++];
835         out[16+i*2] = in[n++];
836     }
837     out[32]=0;
838     return TRUE;
839 }
840
841 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
842 {
843     WCHAR guidW[MAX_PATH];
844     WCHAR squashedW[MAX_PATH];
845     GUID guid;
846     HRESULT hr;
847     int size;
848
849     hr = CoCreateGuid(&guid);
850     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
851
852     size = StringFromGUID2(&guid, guidW, MAX_PATH);
853     ok(size == 39, "Expected 39, got %d\n", hr);
854
855     WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
856     if (squashed)
857     {
858         squash_guid(guidW, squashedW);
859         WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
860     }
861 }
862
863 static char *get_user_sid(void)
864 {
865     HANDLE token;
866     DWORD size = 0;
867     TOKEN_USER *user;
868     char *usersid = NULL;
869
870     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
871     GetTokenInformation(token, TokenUser, NULL, size, &size);
872
873     user = HeapAlloc(GetProcessHeap(), 0, size);
874     GetTokenInformation(token, TokenUser, user, size, &size);
875     pConvertSidToStringSidA(user->User.Sid, &usersid);
876     HeapFree(GetProcessHeap(), 0, user);
877
878     CloseHandle(token);
879     return usersid;
880 }
881
882 static void test_MsiQueryProductState(void)
883 {
884     CHAR prodcode[MAX_PATH];
885     CHAR prod_squashed[MAX_PATH];
886     CHAR keypath[MAX_PATH*2];
887     LPSTR usersid;
888     INSTALLSTATE state;
889     LONG res;
890     HKEY userkey, localkey, props;
891     HKEY prodkey;
892     DWORD data, error;
893     REGSAM access = KEY_ALL_ACCESS;
894
895     create_test_guid(prodcode, prod_squashed);
896     usersid = get_user_sid();
897
898     if (is_wow64)
899         access |= KEY_WOW64_64KEY;
900
901     /* NULL prodcode */
902     SetLastError(0xdeadbeef);
903     state = MsiQueryProductStateA(NULL);
904     error = GetLastError();
905     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
906     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
907
908     /* empty prodcode */
909     SetLastError(0xdeadbeef);
910     state = MsiQueryProductStateA("");
911     error = GetLastError();
912     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
913     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
914
915     /* garbage prodcode */
916     SetLastError(0xdeadbeef);
917     state = MsiQueryProductStateA("garbage");
918     error = GetLastError();
919     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
920     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
921
922     /* guid without brackets */
923     SetLastError(0xdeadbeef);
924     state = MsiQueryProductStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D");
925     error = GetLastError();
926     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
927     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
928
929     /* guid with brackets */
930     SetLastError(0xdeadbeef);
931     state = MsiQueryProductStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}");
932     error = GetLastError();
933     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
934     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
935        "expected ERROR_SUCCESS, got %u\n", error);
936
937     /* same length as guid, but random */
938     SetLastError(0xdeadbeef);
939     state = MsiQueryProductStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93");
940     error = GetLastError();
941     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
942     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
943
944     /* MSIINSTALLCONTEXT_USERUNMANAGED */
945
946     SetLastError(0xdeadbeef);
947     state = MsiQueryProductStateA(prodcode);
948     error = GetLastError();
949     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
950     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
951        "expected ERROR_SUCCESS, got %u\n", error);
952
953     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
954     lstrcatA(keypath, prod_squashed);
955
956     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
957     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
958
959     /* user product key exists */
960     SetLastError(0xdeadbeef);
961     state = MsiQueryProductStateA(prodcode);
962     error = GetLastError();
963     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
964     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
965        "expected ERROR_SUCCESS, got %u\n", error);
966
967     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
968     lstrcatA(keypath, prodcode);
969
970     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
971     if (res == ERROR_ACCESS_DENIED)
972     {
973         skip("Not enough rights to perform tests\n");
974         RegDeleteKeyA(userkey, "");
975         LocalFree(usersid);
976         return;
977     }
978     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
979
980     /* local uninstall key exists */
981     SetLastError(0xdeadbeef);
982     state = MsiQueryProductStateA(prodcode);
983     error = GetLastError();
984     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
985     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
986        "expected ERROR_SUCCESS, got %u\n", error);
987
988     data = 1;
989     res = RegSetValueExA(localkey, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
990     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
991
992     /* WindowsInstaller value exists */
993     SetLastError(0xdeadbeef);
994     state = MsiQueryProductStateA(prodcode);
995     error = GetLastError();
996     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
997     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
998        "expected ERROR_SUCCESS, got %u\n", error);
999
1000     RegDeleteValueA(localkey, "WindowsInstaller");
1001     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1002
1003     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1004     lstrcatA(keypath, usersid);
1005     lstrcatA(keypath, "\\Products\\");
1006     lstrcatA(keypath, prod_squashed);
1007
1008     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1009     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1010
1011     /* local product key exists */
1012     SetLastError(0xdeadbeef);
1013     state = MsiQueryProductStateA(prodcode);
1014     error = GetLastError();
1015     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1016     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1017        "expected ERROR_SUCCESS, got %u\n", error);
1018
1019     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1020     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1021
1022     /* install properties key exists */
1023     SetLastError(0xdeadbeef);
1024     state = MsiQueryProductStateA(prodcode);
1025     error = GetLastError();
1026     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1027     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1028        "expected ERROR_SUCCESS, got %u\n", error);
1029
1030     data = 1;
1031     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1032     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1033
1034     /* WindowsInstaller value exists */
1035     SetLastError(0xdeadbeef);
1036     state = MsiQueryProductStateA(prodcode);
1037     error = GetLastError();
1038     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1039     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1040        "expected ERROR_SUCCESS, got %u\n", error);
1041
1042     data = 2;
1043     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1044     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1045
1046     /* WindowsInstaller value is not 1 */
1047     SetLastError(0xdeadbeef);
1048     state = MsiQueryProductStateA(prodcode);
1049     error = GetLastError();
1050     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1051     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1052        "expected ERROR_SUCCESS, got %u\n", error);
1053
1054     RegDeleteKeyA(userkey, "");
1055
1056     /* user product key does not exist */
1057     SetLastError(0xdeadbeef);
1058     state = MsiQueryProductStateA(prodcode);
1059     error = GetLastError();
1060     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1061     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1062        "expected ERROR_SUCCESS, got %u\n", error);
1063
1064     RegDeleteValueA(props, "WindowsInstaller");
1065     delete_key(props, "", access & KEY_WOW64_64KEY);
1066     RegCloseKey(props);
1067     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1068     RegCloseKey(localkey);
1069     RegDeleteKeyA(userkey, "");
1070     RegCloseKey(userkey);
1071
1072     /* MSIINSTALLCONTEXT_USERMANAGED */
1073
1074     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
1075     lstrcatA(keypath, usersid);
1076     lstrcatA(keypath, "\\Installer\\Products\\");
1077     lstrcatA(keypath, prod_squashed);
1078
1079     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
1080     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1081
1082     state = MsiQueryProductStateA(prodcode);
1083     ok(state == INSTALLSTATE_ADVERTISED,
1084        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1085
1086     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1087     lstrcatA(keypath, usersid);
1088     lstrcatA(keypath, "\\Products\\");
1089     lstrcatA(keypath, prod_squashed);
1090
1091     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1092     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1093
1094     state = MsiQueryProductStateA(prodcode);
1095     ok(state == INSTALLSTATE_ADVERTISED,
1096        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1097
1098     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1099     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1100
1101     state = MsiQueryProductStateA(prodcode);
1102     ok(state == INSTALLSTATE_ADVERTISED,
1103        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1104
1105     data = 1;
1106     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1107     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1108
1109     /* WindowsInstaller value exists */
1110     state = MsiQueryProductStateA(prodcode);
1111     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1112
1113     RegDeleteValueA(props, "WindowsInstaller");
1114     delete_key(props, "", access & KEY_WOW64_64KEY);
1115     RegCloseKey(props);
1116     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1117     RegCloseKey(localkey);
1118     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
1119     RegCloseKey(prodkey);
1120
1121     /* MSIINSTALLCONTEXT_MACHINE */
1122
1123     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
1124     lstrcatA(keypath, prod_squashed);
1125
1126     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
1127     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1128
1129     state = MsiQueryProductStateA(prodcode);
1130     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1131
1132     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1133     lstrcatA(keypath, "S-1-5-18\\Products\\");
1134     lstrcatA(keypath, prod_squashed);
1135
1136     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1137     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1138
1139     state = MsiQueryProductStateA(prodcode);
1140     ok(state == INSTALLSTATE_ADVERTISED,
1141        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1142
1143     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1144     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1145
1146     state = MsiQueryProductStateA(prodcode);
1147     ok(state == INSTALLSTATE_ADVERTISED,
1148        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1149
1150     data = 1;
1151     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1152     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1153
1154     /* WindowsInstaller value exists */
1155     state = MsiQueryProductStateA(prodcode);
1156     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1157
1158     RegDeleteValueA(props, "WindowsInstaller");
1159     delete_key(props, "", access & KEY_WOW64_64KEY);
1160     RegCloseKey(props);
1161     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1162     RegCloseKey(localkey);
1163     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
1164     RegCloseKey(prodkey);
1165
1166     LocalFree(usersid);
1167 }
1168
1169 static const char table_enc85[] =
1170 "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
1171 "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
1172 "yz{}~";
1173
1174 /*
1175  *  Encodes a base85 guid given a GUID pointer
1176  *  Caller should provide a 21 character buffer for the encoded string.
1177  */
1178 static void encode_base85_guid( GUID *guid, LPWSTR str )
1179 {
1180     unsigned int x, *p, i;
1181
1182     p = (unsigned int*) guid;
1183     for( i=0; i<4; i++ )
1184     {
1185         x = p[i];
1186         *str++ = table_enc85[x%85];
1187         x = x/85;
1188         *str++ = table_enc85[x%85];
1189         x = x/85;
1190         *str++ = table_enc85[x%85];
1191         x = x/85;
1192         *str++ = table_enc85[x%85];
1193         x = x/85;
1194         *str++ = table_enc85[x%85];
1195     }
1196     *str = 0;
1197 }
1198
1199 static void compose_base85_guid(LPSTR component, LPSTR comp_base85, LPSTR squashed)
1200 {
1201     WCHAR guidW[MAX_PATH];
1202     WCHAR base85W[MAX_PATH];
1203     WCHAR squashedW[MAX_PATH];
1204     GUID guid;
1205     HRESULT hr;
1206     int size;
1207
1208     hr = CoCreateGuid(&guid);
1209     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
1210
1211     size = StringFromGUID2(&guid, guidW, MAX_PATH);
1212     ok(size == 39, "Expected 39, got %d\n", hr);
1213
1214     WideCharToMultiByte(CP_ACP, 0, guidW, size, component, MAX_PATH, NULL, NULL);
1215     encode_base85_guid(&guid, base85W);
1216     WideCharToMultiByte(CP_ACP, 0, base85W, -1, comp_base85, MAX_PATH, NULL, NULL);
1217     squash_guid(guidW, squashedW);
1218     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
1219 }
1220
1221 static void test_MsiQueryFeatureState(void)
1222 {
1223     HKEY userkey, localkey, compkey, compkey2;
1224     CHAR prodcode[MAX_PATH];
1225     CHAR prod_squashed[MAX_PATH];
1226     CHAR component[MAX_PATH];
1227     CHAR comp_base85[MAX_PATH];
1228     CHAR comp_squashed[MAX_PATH], comp_squashed2[MAX_PATH];
1229     CHAR keypath[MAX_PATH*2];
1230     INSTALLSTATE state;
1231     LPSTR usersid;
1232     LONG res;
1233     REGSAM access = KEY_ALL_ACCESS;
1234     DWORD error;
1235
1236     create_test_guid(prodcode, prod_squashed);
1237     compose_base85_guid(component, comp_base85, comp_squashed);
1238     compose_base85_guid(component, comp_base85 + 20, comp_squashed2);
1239     usersid = get_user_sid();
1240
1241     if (is_wow64)
1242         access |= KEY_WOW64_64KEY;
1243
1244     /* NULL prodcode */
1245     SetLastError(0xdeadbeef);
1246     state = MsiQueryFeatureStateA(NULL, "feature");
1247     error = GetLastError();
1248     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1249     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1250
1251     /* empty prodcode */
1252     SetLastError(0xdeadbeef);
1253     state = MsiQueryFeatureStateA("", "feature");
1254     error = GetLastError();
1255     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1256     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1257
1258     /* garbage prodcode */
1259     SetLastError(0xdeadbeef);
1260     state = MsiQueryFeatureStateA("garbage", "feature");
1261     error = GetLastError();
1262     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1263     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1264
1265     /* guid without brackets */
1266     SetLastError(0xdeadbeef);
1267     state = MsiQueryFeatureStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", "feature");
1268     error = GetLastError();
1269     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1270     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1271
1272     /* guid with brackets */
1273     SetLastError(0xdeadbeef);
1274     state = MsiQueryFeatureStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", "feature");
1275     error = GetLastError();
1276     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1277     ok(error == ERROR_SUCCESS || broken(error == ERROR_ALREADY_EXISTS) /* win2k */,
1278        "expected ERROR_SUCCESS, got %u\n", error);
1279
1280     /* same length as guid, but random */
1281     SetLastError(0xdeadbeef);
1282     state = MsiQueryFeatureStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", "feature");
1283     error = GetLastError();
1284     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1285     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1286
1287     /* NULL szFeature */
1288     SetLastError(0xdeadbeef);
1289     state = MsiQueryFeatureStateA(prodcode, NULL);
1290     error = GetLastError();
1291     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1292     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1293
1294     /* empty szFeature */
1295     SetLastError(0xdeadbeef);
1296     state = MsiQueryFeatureStateA(prodcode, "");
1297     error = GetLastError();
1298     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1299     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1300        "expected ERROR_SUCCESS, got %u\n", error);
1301
1302     /* feature key does not exist yet */
1303     SetLastError(0xdeadbeef);
1304     state = MsiQueryFeatureStateA(prodcode, "feature");
1305     error = GetLastError();
1306     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1307     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1308        "expected ERROR_SUCCESS, got %u\n", error);
1309
1310     /* MSIINSTALLCONTEXT_USERUNMANAGED */
1311
1312     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Features\\");
1313     lstrcatA(keypath, prod_squashed);
1314
1315     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
1316     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1317
1318     /* feature key exists */
1319     SetLastError(0xdeadbeef);
1320     state = MsiQueryFeatureStateA(prodcode, "feature");
1321     error = GetLastError();
1322     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1323     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1324        "expected ERROR_SUCCESS, got %u\n", error);
1325
1326     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 2);
1327     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1328
1329     /* feature value exists */
1330     SetLastError(0xdeadbeef);
1331     state = MsiQueryFeatureStateA(prodcode, "feature");
1332     error = GetLastError();
1333     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1334     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1335        "expected ERROR_SUCCESS, got %u\n", error);
1336
1337     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1338     lstrcatA(keypath, usersid);
1339     lstrcatA(keypath, "\\Products\\");
1340     lstrcatA(keypath, prod_squashed);
1341     lstrcatA(keypath, "\\Features");
1342
1343     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1344     if (res == ERROR_ACCESS_DENIED)
1345     {
1346         skip("Not enough rights to perform tests\n");
1347         RegDeleteKeyA(userkey, "");
1348         RegCloseKey(userkey);
1349         LocalFree(usersid);
1350         return;
1351     }
1352     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1353
1354     /* userdata features key exists */
1355     SetLastError(0xdeadbeef);
1356     state = MsiQueryFeatureStateA(prodcode, "feature");
1357     error = GetLastError();
1358     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1359     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1360        "expected ERROR_SUCCESS, got %u\n", error);
1361
1362     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
1363     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1364
1365     SetLastError(0xdeadbeef);
1366     state = MsiQueryFeatureStateA(prodcode, "feature");
1367     error = GetLastError();
1368     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
1369     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1370        "expected ERROR_SUCCESS, got %u\n", error);
1371
1372     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
1373     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1374
1375     SetLastError(0xdeadbeef);
1376     state = MsiQueryFeatureStateA(prodcode, "feature");
1377     error = GetLastError();
1378     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1379     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1380        "expected ERROR_SUCCESS, got %u\n", error);
1381
1382     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
1383     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1384
1385     SetLastError(0xdeadbeef);
1386     state = MsiQueryFeatureStateA(prodcode, "feature");
1387     error = GetLastError();
1388     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1389     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1390        "expected ERROR_SUCCESS, got %u\n", error);
1391
1392     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
1393     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1394
1395     SetLastError(0xdeadbeef);
1396     state = MsiQueryFeatureStateA(prodcode, "feature");
1397     error = GetLastError();
1398     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1399     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1400        "expected ERROR_SUCCESS, got %u\n", error);
1401
1402     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1403     lstrcatA(keypath, usersid);
1404     lstrcatA(keypath, "\\Components\\");
1405     lstrcatA(keypath, comp_squashed);
1406
1407     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
1408     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1409
1410     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1411     lstrcatA(keypath, usersid);
1412     lstrcatA(keypath, "\\Components\\");
1413     lstrcatA(keypath, comp_squashed2);
1414
1415     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
1416     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1417
1418     SetLastError(0xdeadbeef);
1419     state = MsiQueryFeatureStateA(prodcode, "feature");
1420     error = GetLastError();
1421     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1422     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1423        "expected ERROR_SUCCESS, got %u\n", error);
1424
1425     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
1426     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1427
1428     SetLastError(0xdeadbeef);
1429     state = MsiQueryFeatureStateA(prodcode, "feature");
1430     error = GetLastError();
1431     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1432     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1433        "expected ERROR_SUCCESS, got %u\n", error);
1434
1435     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
1436     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1437
1438     SetLastError(0xdeadbeef);
1439     state = MsiQueryFeatureStateA(prodcode, "feature");
1440     error = GetLastError();
1441     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1442     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1443        "expected ERROR_SUCCESS, got %u\n", error);
1444
1445     res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
1446     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1447
1448     /* INSTALLSTATE_LOCAL */
1449     SetLastError(0xdeadbeef);
1450     state = MsiQueryFeatureStateA(prodcode, "feature");
1451     error = GetLastError();
1452     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1453     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1454        "expected ERROR_SUCCESS, got %u\n", error);
1455
1456     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01\\", 4);
1457     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1458
1459     /* INSTALLSTATE_SOURCE */
1460     SetLastError(0xdeadbeef);
1461     state = MsiQueryFeatureStateA(prodcode, "feature");
1462     error = GetLastError();
1463     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
1464     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1465        "expected ERROR_SUCCESS, got %u\n", error);
1466
1467     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
1468     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1469
1470     /* bad INSTALLSTATE_SOURCE */
1471     SetLastError(0xdeadbeef);
1472     state = MsiQueryFeatureStateA(prodcode, "feature");
1473     error = GetLastError();
1474     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1475     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1476        "expected ERROR_SUCCESS, got %u\n", error);
1477
1478     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01a", 4);
1479     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1480
1481     /* INSTALLSTATE_SOURCE */
1482     SetLastError(0xdeadbeef);
1483     state = MsiQueryFeatureStateA(prodcode, "feature");
1484     error = GetLastError();
1485     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
1486     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1487        "expected ERROR_SUCCESS, got %u\n", error);
1488
1489     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
1490     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1491
1492     /* bad INSTALLSTATE_SOURCE */
1493     SetLastError(0xdeadbeef);
1494     state = MsiQueryFeatureStateA(prodcode, "feature");
1495     error = GetLastError();
1496     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1497     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1498        "expected ERROR_SUCCESS, got %u\n", error);
1499
1500     RegDeleteValueA(compkey, prod_squashed);
1501     RegDeleteValueA(compkey2, prod_squashed);
1502     delete_key(compkey, "", access & KEY_WOW64_64KEY);
1503     delete_key(compkey2, "", access & KEY_WOW64_64KEY);
1504     RegDeleteValueA(localkey, "feature");
1505     RegDeleteValueA(userkey, "feature");
1506     RegDeleteKeyA(userkey, "");
1507     RegCloseKey(compkey);
1508     RegCloseKey(compkey2);
1509     RegCloseKey(localkey);
1510     RegCloseKey(userkey);
1511
1512     /* MSIINSTALLCONTEXT_USERMANAGED */
1513
1514     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
1515     lstrcatA(keypath, usersid);
1516     lstrcatA(keypath, "\\Installer\\Features\\");
1517     lstrcatA(keypath, prod_squashed);
1518
1519     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
1520     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1521
1522     /* feature key exists */
1523     state = MsiQueryFeatureStateA(prodcode, "feature");
1524     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1525
1526     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 1);
1527     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1528
1529     /* feature value exists */
1530     state = MsiQueryFeatureStateA(prodcode, "feature");
1531     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1532
1533     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1534     lstrcatA(keypath, usersid);
1535     lstrcatA(keypath, "\\Products\\");
1536     lstrcatA(keypath, prod_squashed);
1537     lstrcatA(keypath, "\\Features");
1538
1539     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1540     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1541
1542     /* userdata features key exists */
1543     state = MsiQueryFeatureStateA(prodcode, "feature");
1544     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1545
1546     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
1547     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1548
1549     state = MsiQueryFeatureStateA(prodcode, "feature");
1550     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
1551
1552     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
1553     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1554
1555     state = MsiQueryFeatureStateA(prodcode, "feature");
1556     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1557
1558     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
1559     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1560
1561     state = MsiQueryFeatureStateA(prodcode, "feature");
1562     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1563
1564     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
1565     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1566
1567     state = MsiQueryFeatureStateA(prodcode, "feature");
1568     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1569
1570     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1571     lstrcatA(keypath, usersid);
1572     lstrcatA(keypath, "\\Components\\");
1573     lstrcatA(keypath, comp_squashed);
1574
1575     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
1576     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1577
1578     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1579     lstrcatA(keypath, usersid);
1580     lstrcatA(keypath, "\\Components\\");
1581     lstrcatA(keypath, comp_squashed2);
1582
1583     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
1584     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1585
1586     state = MsiQueryFeatureStateA(prodcode, "feature");
1587     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1588
1589     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
1590     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1591
1592     state = MsiQueryFeatureStateA(prodcode, "feature");
1593     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1594
1595     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
1596     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1597
1598     state = MsiQueryFeatureStateA(prodcode, "feature");
1599     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1600
1601     res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
1602     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1603
1604     state = MsiQueryFeatureStateA(prodcode, "feature");
1605     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1606
1607     RegDeleteValueA(compkey, prod_squashed);
1608     RegDeleteValueA(compkey2, prod_squashed);
1609     delete_key(compkey, "", access & KEY_WOW64_64KEY);
1610     delete_key(compkey2, "", access & KEY_WOW64_64KEY);
1611     RegDeleteValueA(localkey, "feature");
1612     RegDeleteValueA(userkey, "feature");
1613     delete_key(userkey, "", access & KEY_WOW64_64KEY);
1614     RegCloseKey(compkey);
1615     RegCloseKey(compkey2);
1616     RegCloseKey(localkey);
1617     RegCloseKey(userkey);
1618
1619     /* MSIINSTALLCONTEXT_MACHINE */
1620
1621     lstrcpyA(keypath, "Software\\Classes\\Installer\\Features\\");
1622     lstrcatA(keypath, prod_squashed);
1623
1624     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
1625     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1626
1627     /* feature key exists */
1628     state = MsiQueryFeatureStateA(prodcode, "feature");
1629     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1630
1631     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 1);
1632     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1633
1634     /* feature value exists */
1635     state = MsiQueryFeatureStateA(prodcode, "feature");
1636     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1637
1638     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1639     lstrcatA(keypath, "S-1-5-18\\Products\\");
1640     lstrcatA(keypath, prod_squashed);
1641     lstrcatA(keypath, "\\Features");
1642
1643     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1644     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1645
1646     /* userdata features key exists */
1647     state = MsiQueryFeatureStateA(prodcode, "feature");
1648     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1649
1650     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
1651     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1652
1653     state = MsiQueryFeatureStateA(prodcode, "feature");
1654     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
1655
1656     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
1657     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1658
1659     state = MsiQueryFeatureStateA(prodcode, "feature");
1660     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1661
1662     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
1663     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1664
1665     state = MsiQueryFeatureStateA(prodcode, "feature");
1666     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1667
1668     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
1669     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1670
1671     state = MsiQueryFeatureStateA(prodcode, "feature");
1672     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1673
1674     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1675     lstrcatA(keypath, "S-1-5-18\\Components\\");
1676     lstrcatA(keypath, comp_squashed);
1677
1678     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
1679     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1680
1681     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1682     lstrcatA(keypath, "S-1-5-18\\Components\\");
1683     lstrcatA(keypath, comp_squashed2);
1684
1685     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
1686     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1687
1688     state = MsiQueryFeatureStateA(prodcode, "feature");
1689     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1690
1691     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
1692     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1693
1694     state = MsiQueryFeatureStateA(prodcode, "feature");
1695     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1696
1697     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
1698     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1699
1700     state = MsiQueryFeatureStateA(prodcode, "feature");
1701     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1702
1703     res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
1704     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1705
1706     state = MsiQueryFeatureStateA(prodcode, "feature");
1707     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1708
1709     RegDeleteValueA(compkey, prod_squashed);
1710     RegDeleteValueA(compkey2, prod_squashed);
1711     delete_key(compkey, "", access & KEY_WOW64_64KEY);
1712     delete_key(compkey2, "", access & KEY_WOW64_64KEY);
1713     RegDeleteValueA(localkey, "feature");
1714     RegDeleteValueA(userkey, "feature");
1715     delete_key(userkey, "", access & KEY_WOW64_64KEY);
1716     RegCloseKey(compkey);
1717     RegCloseKey(compkey2);
1718     RegCloseKey(localkey);
1719     RegCloseKey(userkey);
1720     LocalFree(usersid);
1721 }
1722
1723 static void test_MsiQueryComponentState(void)
1724 {
1725     HKEY compkey, prodkey;
1726     CHAR prodcode[MAX_PATH];
1727     CHAR prod_squashed[MAX_PATH];
1728     CHAR component[MAX_PATH];
1729     CHAR comp_base85[MAX_PATH];
1730     CHAR comp_squashed[MAX_PATH];
1731     CHAR keypath[MAX_PATH];
1732     INSTALLSTATE state;
1733     LPSTR usersid;
1734     LONG res;
1735     UINT r;
1736     REGSAM access = KEY_ALL_ACCESS;
1737     DWORD error;
1738
1739     static const INSTALLSTATE MAGIC_ERROR = 0xdeadbeef;
1740
1741     if (!pMsiQueryComponentStateA)
1742     {
1743         win_skip("MsiQueryComponentStateA not implemented\n");
1744         return;
1745     }
1746
1747     create_test_guid(prodcode, prod_squashed);
1748     compose_base85_guid(component, comp_base85, comp_squashed);
1749     usersid = get_user_sid();
1750
1751     if (is_wow64)
1752         access |= KEY_WOW64_64KEY;
1753
1754     /* NULL szProductCode */
1755     state = MAGIC_ERROR;
1756     SetLastError(0xdeadbeef);
1757     r = pMsiQueryComponentStateA(NULL, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
1758     error = GetLastError();
1759     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1760     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
1761     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1762
1763     /* empty szProductCode */
1764     state = MAGIC_ERROR;
1765     SetLastError(0xdeadbeef);
1766     r = pMsiQueryComponentStateA("", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
1767     error = GetLastError();
1768     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1769     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
1770     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1771
1772     /* random szProductCode */
1773     state = MAGIC_ERROR;
1774     SetLastError(0xdeadbeef);
1775     r = pMsiQueryComponentStateA("random", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
1776     error = GetLastError();
1777     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1778     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
1779     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1780
1781     /* GUID-length szProductCode */
1782     state = MAGIC_ERROR;
1783     SetLastError(0xdeadbeef);
1784     r = pMsiQueryComponentStateA("DJANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KDE", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
1785     error = GetLastError();
1786     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1787     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
1788     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1789
1790     /* GUID-length with brackets */
1791     state = MAGIC_ERROR;
1792     SetLastError(0xdeadbeef);
1793     r = pMsiQueryComponentStateA("{JANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KD}", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
1794     error = GetLastError();
1795     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1796     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
1797     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1798
1799     /* actual GUID */
1800     state = MAGIC_ERROR;
1801     SetLastError(0xdeadbeef);
1802     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
1803     error = GetLastError();
1804     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1805     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
1806     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1807
1808     state = MAGIC_ERROR;
1809     SetLastError(0xdeadbeef);
1810     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
1811     error = GetLastError();
1812     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1813     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
1814     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1815
1816     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
1817     lstrcatA(keypath, prod_squashed);
1818
1819     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
1820     if (res == ERROR_ACCESS_DENIED)
1821     {
1822         skip("Not enough rights to perform tests\n");
1823         LocalFree(usersid);
1824         return;
1825     }
1826     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1827
1828     state = MAGIC_ERROR;
1829     SetLastError(0xdeadbeef);
1830     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
1831     error = GetLastError();
1832     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
1833     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1834     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1835
1836     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
1837     RegCloseKey(prodkey);
1838
1839     /* create local system product key */
1840     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\");
1841     lstrcatA(keypath, prod_squashed);
1842     lstrcatA(keypath, "\\InstallProperties");
1843
1844     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
1845     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1846
1847     /* local system product key exists */
1848     state = MAGIC_ERROR;
1849     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
1850     error = GetLastError();
1851     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1852     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
1853     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1854
1855     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
1856     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1857
1858     /* LocalPackage value exists */
1859     state = MAGIC_ERROR;
1860     SetLastError(0xdeadbeef);
1861     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
1862     error = GetLastError();
1863     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
1864     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1865     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1866
1867     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\");
1868     lstrcatA(keypath, comp_squashed);
1869
1870     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
1871     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1872
1873     /* component key exists */
1874     state = MAGIC_ERROR;
1875     SetLastError(0xdeadbeef);
1876     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
1877     error = GetLastError();
1878     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
1879     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1880     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1881
1882     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
1883     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1884
1885     /* component\product exists */
1886     state = MAGIC_ERROR;
1887     SetLastError(0xdeadbeef);
1888     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
1889     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1890     error = GetLastError();
1891     ok(state == INSTALLSTATE_NOTUSED || state == INSTALLSTATE_LOCAL,
1892        "Expected INSTALLSTATE_NOTUSED or INSTALLSTATE_LOCAL, got %d\n", state);
1893     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1894
1895     /* NULL component, product exists */
1896     state = MAGIC_ERROR;
1897     SetLastError(0xdeadbeef);
1898     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, NULL, &state);
1899     error = GetLastError();
1900     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1901     ok(state == MAGIC_ERROR, "Expected state not changed, got %d\n", state);
1902     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1903
1904     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
1905     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1906
1907     /* INSTALLSTATE_LOCAL */
1908     state = MAGIC_ERROR;
1909     SetLastError(0xdeadbeef);
1910     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
1911     error = GetLastError();
1912     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1913     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1914     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1915
1916     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01\\", 4);
1917     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1918
1919     /* INSTALLSTATE_SOURCE */
1920     state = MAGIC_ERROR;
1921     SetLastError(0xdeadbeef);
1922     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
1923     error = GetLastError();
1924     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1925     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
1926     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1927
1928     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
1929     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1930
1931     /* bad INSTALLSTATE_SOURCE */
1932     state = MAGIC_ERROR;
1933     SetLastError(0xdeadbeef);
1934     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
1935     error = GetLastError();
1936     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1937     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1938     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1939
1940     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01a", 4);
1941     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1942
1943     /* INSTALLSTATE_SOURCE */
1944     state = MAGIC_ERROR;
1945     SetLastError(0xdeadbeef);
1946     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
1947     error = GetLastError();
1948     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1949     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
1950     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1951
1952     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01:", 4);
1953     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1954
1955     /* registry component */
1956     state = MAGIC_ERROR;
1957     SetLastError(0xdeadbeef);
1958     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
1959     error = GetLastError();
1960     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1961     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1962     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1963
1964     RegDeleteValueA(prodkey, "LocalPackage");
1965     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
1966     RegDeleteValueA(compkey, prod_squashed);
1967     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
1968     RegCloseKey(prodkey);
1969     RegCloseKey(compkey);
1970
1971     /* MSIINSTALLCONTEXT_USERUNMANAGED */
1972
1973     state = MAGIC_ERROR;
1974     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
1975     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1976     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
1977
1978     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
1979     lstrcatA(keypath, prod_squashed);
1980
1981     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
1982     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1983
1984     state = MAGIC_ERROR;
1985     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
1986     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
1987     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1988
1989     RegDeleteKeyA(prodkey, "");
1990     RegCloseKey(prodkey);
1991
1992     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1993     lstrcatA(keypath, usersid);
1994     lstrcatA(keypath, "\\Products\\");
1995     lstrcatA(keypath, prod_squashed);
1996     lstrcatA(keypath, "\\InstallProperties");
1997
1998     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
1999     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2000
2001     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2002     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2003
2004     RegCloseKey(prodkey);
2005
2006     state = MAGIC_ERROR;
2007     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2008     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2009     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2010
2011     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2012     lstrcatA(keypath, usersid);
2013     lstrcatA(keypath, "\\Components\\");
2014     lstrcatA(keypath, comp_squashed);
2015
2016     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2017     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2018
2019     /* component key exists */
2020     state = MAGIC_ERROR;
2021     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2022     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2023     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2024
2025     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
2026     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2027
2028     /* component\product exists */
2029     state = MAGIC_ERROR;
2030     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2031     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2032     ok(state == INSTALLSTATE_NOTUSED || state == INSTALLSTATE_LOCAL,
2033        "Expected INSTALLSTATE_NOTUSED or INSTALLSTATE_LOCAL, got %d\n", state);
2034
2035     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
2036     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2037
2038     state = MAGIC_ERROR;
2039     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2040     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2041     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2042
2043     /* MSIINSTALLCONTEXT_USERMANAGED */
2044
2045     state = MAGIC_ERROR;
2046     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2047     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2048     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2049
2050     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2051     lstrcatA(keypath, prod_squashed);
2052
2053     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
2054     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2055
2056     state = MAGIC_ERROR;
2057     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2058     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2059     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2060
2061     RegDeleteKeyA(prodkey, "");
2062     RegCloseKey(prodkey);
2063
2064     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
2065     lstrcatA(keypath, usersid);
2066     lstrcatA(keypath, "\\Installer\\Products\\");
2067     lstrcatA(keypath, prod_squashed);
2068
2069     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2070     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2071
2072     state = MAGIC_ERROR;
2073     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2074     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2075     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2076
2077     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2078     RegCloseKey(prodkey);
2079
2080     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2081     lstrcatA(keypath, usersid);
2082     lstrcatA(keypath, "\\Products\\");
2083     lstrcatA(keypath, prod_squashed);
2084     lstrcatA(keypath, "\\InstallProperties");
2085
2086     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2087     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2088
2089     res = RegSetValueExA(prodkey, "ManagedLocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2090     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2091
2092     state = MAGIC_ERROR;
2093     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2094     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2095     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2096
2097     RegDeleteValueA(prodkey, "LocalPackage");
2098     RegDeleteValueA(prodkey, "ManagedLocalPackage");
2099     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2100     RegDeleteValueA(compkey, prod_squashed);
2101     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2102     RegCloseKey(prodkey);
2103     RegCloseKey(compkey);
2104     LocalFree(usersid);
2105 }
2106
2107 static void test_MsiGetComponentPath(void)
2108 {
2109     HKEY compkey, prodkey, installprop;
2110     CHAR prodcode[MAX_PATH];
2111     CHAR prod_squashed[MAX_PATH];
2112     CHAR component[MAX_PATH];
2113     CHAR comp_base85[MAX_PATH];
2114     CHAR comp_squashed[MAX_PATH];
2115     CHAR keypath[MAX_PATH];
2116     CHAR path[MAX_PATH];
2117     INSTALLSTATE state;
2118     LPSTR usersid;
2119     DWORD size, val;
2120     REGSAM access = KEY_ALL_ACCESS;
2121     LONG res;
2122
2123     create_test_guid(prodcode, prod_squashed);
2124     compose_base85_guid(component, comp_base85, comp_squashed);
2125     usersid = get_user_sid();
2126
2127     if (is_wow64)
2128         access |= KEY_WOW64_64KEY;
2129
2130     /* NULL szProduct */
2131     size = MAX_PATH;
2132     state = MsiGetComponentPathA(NULL, component, path, &size);
2133     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2134     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2135
2136     /* NULL szComponent */
2137     size = MAX_PATH;
2138     state = MsiGetComponentPathA(prodcode, NULL, path, &size);
2139     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2140     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2141
2142     size = MAX_PATH;
2143     state = MsiLocateComponentA(NULL, path, &size);
2144     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2145     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2146
2147     /* NULL lpPathBuf */
2148     size = MAX_PATH;
2149     state = MsiGetComponentPathA(prodcode, component, NULL, &size);
2150     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2151     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2152
2153     size = MAX_PATH;
2154     state = MsiLocateComponentA(component, NULL, &size);
2155     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2156     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2157
2158     /* NULL pcchBuf */
2159     size = MAX_PATH;
2160     state = MsiGetComponentPathA(prodcode, component, path, NULL);
2161     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2162     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2163
2164     size = MAX_PATH;
2165     state = MsiLocateComponentA(component, path, NULL);
2166     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2167     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2168
2169     /* all params valid */
2170     size = MAX_PATH;
2171     state = MsiGetComponentPathA(prodcode, component, path, &size);
2172     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2173     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2174
2175     size = MAX_PATH;
2176     state = MsiLocateComponentA(component, path, &size);
2177     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2178     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2179
2180     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2181     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
2182     lstrcatA(keypath, comp_squashed);
2183
2184     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2185     if (res == ERROR_ACCESS_DENIED)
2186     {
2187         skip("Not enough rights to perform tests\n");
2188         LocalFree(usersid);
2189         return;
2190     }
2191     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2192
2193     /* local system component key exists */
2194     size = MAX_PATH;
2195     state = MsiGetComponentPathA(prodcode, component, path, &size);
2196     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2197     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2198
2199     size = MAX_PATH;
2200     state = MsiLocateComponentA(component, path, &size);
2201     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2202     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2203
2204     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2205     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2206
2207     /* product value exists */
2208     path[0] = 0;
2209     size = MAX_PATH;
2210     state = MsiGetComponentPathA(prodcode, component, path, &size);
2211     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2212     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2213     ok(size == 10, "Expected 10, got %d\n", size);
2214
2215     path[0] = 0;
2216     size = MAX_PATH;
2217     state = MsiLocateComponentA(component, path, &size);
2218     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2219     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2220     ok(size == 10, "Expected 10, got %d\n", size);
2221
2222     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2223     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
2224     lstrcatA(keypath, prod_squashed);
2225     lstrcatA(keypath, "\\InstallProperties");
2226
2227     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &installprop, NULL);
2228     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2229
2230     val = 1;
2231     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
2232     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2233
2234     /* install properties key exists */
2235     path[0] = 0;
2236     size = MAX_PATH;
2237     state = MsiGetComponentPathA(prodcode, component, path, &size);
2238     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2239     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2240     ok(size == 10, "Expected 10, got %d\n", size);
2241
2242     path[0] = 0;
2243     size = MAX_PATH;
2244     state = MsiLocateComponentA(component, path, &size);
2245     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2246     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2247     ok(size == 10, "Expected 10, got %d\n", size);
2248
2249     create_file("C:\\imapath", "C:\\imapath", 11);
2250
2251     /* file exists */
2252     path[0] = 0;
2253     size = MAX_PATH;
2254     state = MsiGetComponentPathA(prodcode, component, path, &size);
2255     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2256     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2257     ok(size == 10, "Expected 10, got %d\n", size);
2258
2259     path[0] = 0;
2260     size = MAX_PATH;
2261     state = MsiLocateComponentA(component, path, &size);
2262     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2263     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2264     ok(size == 10, "Expected 10, got %d\n", size);
2265
2266     RegDeleteValueA(compkey, prod_squashed);
2267     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2268     RegDeleteValueA(installprop, "WindowsInstaller");
2269     delete_key(installprop, "", access & KEY_WOW64_64KEY);
2270     RegCloseKey(compkey);
2271     RegCloseKey(installprop);
2272     DeleteFileA("C:\\imapath");
2273
2274     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2275     lstrcatA(keypath, "Installer\\UserData\\");
2276     lstrcatA(keypath, usersid);
2277     lstrcatA(keypath, "\\Components\\");
2278     lstrcatA(keypath, comp_squashed);
2279
2280     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2281     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2282
2283     /* user managed component key exists */
2284     size = MAX_PATH;
2285     state = MsiGetComponentPathA(prodcode, component, path, &size);
2286     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2287     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2288
2289     size = MAX_PATH;
2290     state = MsiLocateComponentA(component, path, &size);
2291     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2292     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2293
2294     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2295     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2296
2297     /* product value exists */
2298     path[0] = 0;
2299     size = MAX_PATH;
2300     state = MsiGetComponentPathA(prodcode, component, path, &size);
2301     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2302     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2303     ok(size == 10, "Expected 10, got %d\n", size);
2304
2305     path[0] = 0;
2306     size = MAX_PATH;
2307     state = MsiLocateComponentA(component, path, &size);
2308     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2309     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2310     ok(size == 10, "Expected 10, got %d\n", size);
2311
2312     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2313     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
2314     lstrcatA(keypath, prod_squashed);
2315     lstrcatA(keypath, "\\InstallProperties");
2316
2317     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &installprop, NULL);
2318     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2319
2320     val = 1;
2321     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
2322     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2323
2324     /* install properties key exists */
2325     path[0] = 0;
2326     size = MAX_PATH;
2327     state = MsiGetComponentPathA(prodcode, component, path, &size);
2328     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2329     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2330     ok(size == 10, "Expected 10, got %d\n", size);
2331
2332     path[0] = 0;
2333     size = MAX_PATH;
2334     state = MsiLocateComponentA(component, path, &size);
2335     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2336     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2337     ok(size == 10, "Expected 10, got %d\n", size);
2338
2339     create_file("C:\\imapath", "C:\\imapath", 11);
2340
2341     /* file exists */
2342     path[0] = 0;
2343     size = MAX_PATH;
2344     state = MsiGetComponentPathA(prodcode, component, path, &size);
2345     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2346     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2347     ok(size == 10, "Expected 10, got %d\n", size);
2348
2349     path[0] = 0;
2350     size = MAX_PATH;
2351     state = MsiLocateComponentA(component, path, &size);
2352     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2353     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2354     ok(size == 10, "Expected 10, got %d\n", size);
2355
2356     RegDeleteValueA(compkey, prod_squashed);
2357     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2358     RegDeleteValueA(installprop, "WindowsInstaller");
2359     delete_key(installprop, "", access & KEY_WOW64_64KEY);
2360     RegCloseKey(compkey);
2361     RegCloseKey(installprop);
2362     DeleteFileA("C:\\imapath");
2363
2364     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2365     lstrcatA(keypath, "Installer\\Managed\\");
2366     lstrcatA(keypath, usersid);
2367     lstrcatA(keypath, "\\Installer\\Products\\");
2368     lstrcatA(keypath, prod_squashed);
2369
2370     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2371     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2372
2373     /* user managed product key exists */
2374     size = MAX_PATH;
2375     state = MsiGetComponentPathA(prodcode, component, path, &size);
2376     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2377     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2378
2379     size = MAX_PATH;
2380     state = MsiLocateComponentA(component, path, &size);
2381     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2382     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2383
2384     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2385     lstrcatA(keypath, "Installer\\UserData\\");
2386     lstrcatA(keypath, usersid);
2387     lstrcatA(keypath, "\\Components\\");
2388     lstrcatA(keypath, comp_squashed);
2389
2390     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2391     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2392
2393     /* user managed component key exists */
2394     size = MAX_PATH;
2395     state = MsiGetComponentPathA(prodcode, component, path, &size);
2396     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2397     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2398
2399     size = MAX_PATH;
2400     state = MsiLocateComponentA(component, path, &size);
2401     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2402     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2403
2404     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2405     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2406
2407     /* product value exists */
2408     path[0] = 0;
2409     size = MAX_PATH;
2410     state = MsiGetComponentPathA(prodcode, component, path, &size);
2411     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2412     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2413     ok(size == 10, "Expected 10, got %d\n", size);
2414
2415     path[0] = 0;
2416     size = MAX_PATH;
2417     state = MsiLocateComponentA(component, path, &size);
2418     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2419     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2420     ok(size == 10, "Expected 10, got %d\n", size);
2421
2422     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2423     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
2424     lstrcatA(keypath, prod_squashed);
2425     lstrcatA(keypath, "\\InstallProperties");
2426
2427     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &installprop, NULL);
2428     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2429
2430     val = 1;
2431     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
2432     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2433
2434     /* install properties key exists */
2435     path[0] = 0;
2436     size = MAX_PATH;
2437     state = MsiGetComponentPathA(prodcode, component, path, &size);
2438     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2439     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2440     ok(size == 10, "Expected 10, got %d\n", size);
2441
2442     path[0] = 0;
2443     size = MAX_PATH;
2444     state = MsiLocateComponentA(component, path, &size);
2445     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2446     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2447     ok(size == 10, "Expected 10, got %d\n", size);
2448
2449     create_file("C:\\imapath", "C:\\imapath", 11);
2450
2451     /* file exists */
2452     path[0] = 0;
2453     size = MAX_PATH;
2454     state = MsiGetComponentPathA(prodcode, component, path, &size);
2455     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2456     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2457     ok(size == 10, "Expected 10, got %d\n", size);
2458
2459     path[0] = 0;
2460     size = MAX_PATH;
2461     state = MsiLocateComponentA(component, path, &size);
2462     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2463     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2464     ok(size == 10, "Expected 10, got %d\n", size);
2465
2466     RegDeleteValueA(compkey, prod_squashed);
2467     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2468     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2469     RegDeleteValueA(installprop, "WindowsInstaller");
2470     delete_key(installprop, "", access & KEY_WOW64_64KEY);
2471     RegCloseKey(prodkey);
2472     RegCloseKey(compkey);
2473     RegCloseKey(installprop);
2474     DeleteFileA("C:\\imapath");
2475
2476     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2477     lstrcatA(keypath, prod_squashed);
2478
2479     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
2480     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2481
2482     /* user unmanaged product key exists */
2483     size = MAX_PATH;
2484     state = MsiGetComponentPathA(prodcode, 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 %d\n", size);
2487
2488     size = MAX_PATH;
2489     state = MsiLocateComponentA(component, path, &size);
2490     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2491     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2492
2493     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2494     lstrcatA(keypath, "Installer\\UserData\\");
2495     lstrcatA(keypath, usersid);
2496     lstrcatA(keypath, "\\Components\\");
2497     lstrcatA(keypath, comp_squashed);
2498
2499     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2500     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2501
2502     /* user unmanaged component key exists */
2503     size = MAX_PATH;
2504     state = MsiGetComponentPathA(prodcode, component, path, &size);
2505     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2506     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2507
2508     size = MAX_PATH;
2509     state = MsiLocateComponentA(component, path, &size);
2510     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2511     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2512
2513     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2514     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2515
2516     /* product value exists */
2517     path[0] = 0;
2518     size = MAX_PATH;
2519     state = MsiGetComponentPathA(prodcode, component, path, &size);
2520     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2521     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2522     ok(size == 10, "Expected 10, got %d\n", size);
2523
2524     path[0] = 0;
2525     size = MAX_PATH;
2526     state = MsiLocateComponentA(component, path, &size);
2527     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2528     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2529     ok(size == 10, "Expected 10, got %d\n", size);
2530
2531     create_file("C:\\imapath", "C:\\imapath", 11);
2532
2533     /* file exists */
2534     path[0] = 0;
2535     size = MAX_PATH;
2536     state = MsiGetComponentPathA(prodcode, component, path, &size);
2537     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2538     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2539     ok(size == 10, "Expected 10, got %d\n", size);
2540
2541     path[0] = 0;
2542     size = MAX_PATH;
2543     state = MsiLocateComponentA(component, path, &size);
2544     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2545     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2546     ok(size == 10, "Expected 10, got %d\n", size);
2547
2548     RegDeleteValueA(compkey, prod_squashed);
2549     RegDeleteKeyA(prodkey, "");
2550     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2551     RegCloseKey(prodkey);
2552     RegCloseKey(compkey);
2553     DeleteFileA("C:\\imapath");
2554
2555     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
2556     lstrcatA(keypath, prod_squashed);
2557
2558     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2559     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2560
2561     /* local classes product key exists */
2562     size = MAX_PATH;
2563     state = MsiGetComponentPathA(prodcode, component, path, &size);
2564     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2565     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2566
2567     size = MAX_PATH;
2568     state = MsiLocateComponentA(component, path, &size);
2569     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2570     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2571
2572     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2573     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
2574     lstrcatA(keypath, comp_squashed);
2575
2576     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2577     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2578
2579     /* local user component key exists */
2580     size = MAX_PATH;
2581     state = MsiGetComponentPathA(prodcode, component, path, &size);
2582     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2583     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2584
2585     size = MAX_PATH;
2586     state = MsiLocateComponentA(component, path, &size);
2587     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2588     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2589
2590     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2591     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2592
2593     /* product value exists */
2594     path[0] = 0;
2595     size = MAX_PATH;
2596     state = MsiGetComponentPathA(prodcode, component, path, &size);
2597     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2598     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2599     ok(size == 10, "Expected 10, got %d\n", size);
2600
2601     path[0] = 0;
2602     size = MAX_PATH;
2603     state = MsiLocateComponentA(component, path, &size);
2604     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2605     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2606     ok(size == 10, "Expected 10, got %d\n", size);
2607
2608     create_file("C:\\imapath", "C:\\imapath", 11);
2609
2610     /* file exists */
2611     path[0] = 0;
2612     size = MAX_PATH;
2613     state = MsiGetComponentPathA(prodcode, component, path, &size);
2614     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2615     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2616     ok(size == 10, "Expected 10, got %d\n", size);
2617
2618     path[0] = 0;
2619     size = MAX_PATH;
2620     state = MsiLocateComponentA(component, path, &size);
2621     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2622     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2623     ok(size == 10, "Expected 10, got %d\n", size);
2624
2625     RegDeleteValueA(compkey, prod_squashed);
2626     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2627     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2628     RegCloseKey(prodkey);
2629     RegCloseKey(compkey);
2630     DeleteFileA("C:\\imapath");
2631     LocalFree(usersid);
2632 }
2633
2634 static void test_MsiGetProductCode(void)
2635 {
2636     HKEY compkey, prodkey;
2637     CHAR prodcode[MAX_PATH];
2638     CHAR prod_squashed[MAX_PATH];
2639     CHAR prodcode2[MAX_PATH];
2640     CHAR prod2_squashed[MAX_PATH];
2641     CHAR component[MAX_PATH];
2642     CHAR comp_base85[MAX_PATH];
2643     CHAR comp_squashed[MAX_PATH];
2644     CHAR keypath[MAX_PATH];
2645     CHAR product[MAX_PATH];
2646     LPSTR usersid;
2647     LONG res;
2648     UINT r;
2649     REGSAM access = KEY_ALL_ACCESS;
2650
2651     create_test_guid(prodcode, prod_squashed);
2652     create_test_guid(prodcode2, prod2_squashed);
2653     compose_base85_guid(component, comp_base85, comp_squashed);
2654     usersid = get_user_sid();
2655
2656     if (is_wow64)
2657         access |= KEY_WOW64_64KEY;
2658
2659     /* szComponent is NULL */
2660     lstrcpyA(product, "prod");
2661     r = MsiGetProductCodeA(NULL, product);
2662     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2663     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
2664
2665     /* szComponent is empty */
2666     lstrcpyA(product, "prod");
2667     r = MsiGetProductCodeA("", product);
2668     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2669     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
2670
2671     /* garbage szComponent */
2672     lstrcpyA(product, "prod");
2673     r = MsiGetProductCodeA("garbage", product);
2674     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2675     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
2676
2677     /* guid without brackets */
2678     lstrcpyA(product, "prod");
2679     r = MsiGetProductCodeA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", product);
2680     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2681     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
2682
2683     /* guid with brackets */
2684     lstrcpyA(product, "prod");
2685     r = MsiGetProductCodeA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", product);
2686     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2687     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
2688
2689     /* same length as guid, but random */
2690     lstrcpyA(product, "prod");
2691     r = MsiGetProductCodeA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", product);
2692     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2693     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
2694
2695     /* all params correct, szComponent not published */
2696     lstrcpyA(product, "prod");
2697     r = MsiGetProductCodeA(component, product);
2698     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2699     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
2700
2701     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2702     lstrcatA(keypath, "Installer\\UserData\\");
2703     lstrcatA(keypath, usersid);
2704     lstrcatA(keypath, "\\Components\\");
2705     lstrcatA(keypath, comp_squashed);
2706
2707     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2708     if (res == ERROR_ACCESS_DENIED)
2709     {
2710         skip("Not enough rights to perform tests\n");
2711         LocalFree(usersid);
2712         return;
2713     }
2714     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2715
2716     /* user unmanaged component key exists */
2717     lstrcpyA(product, "prod");
2718     r = MsiGetProductCodeA(component, product);
2719     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2720     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
2721
2722     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2723     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2724
2725     /* product value exists */
2726     lstrcpyA(product, "prod");
2727     r = MsiGetProductCodeA(component, product);
2728     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2729     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
2730
2731     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
2732     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2733
2734     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2735     lstrcatA(keypath, "Installer\\Managed\\");
2736     lstrcatA(keypath, usersid);
2737     lstrcatA(keypath, "\\Installer\\Products\\");
2738     lstrcatA(keypath, prod_squashed);
2739
2740     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2741     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2742
2743     /* user managed product key of first product exists */
2744     lstrcpyA(product, "prod");
2745     r = MsiGetProductCodeA(component, product);
2746     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2747     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
2748
2749     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2750     RegCloseKey(prodkey);
2751
2752     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2753     lstrcatA(keypath, prod_squashed);
2754
2755     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
2756     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2757
2758     /* user unmanaged product key exists */
2759     lstrcpyA(product, "prod");
2760     r = MsiGetProductCodeA(component, product);
2761     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2762     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
2763
2764     RegDeleteKeyA(prodkey, "");
2765     RegCloseKey(prodkey);
2766
2767     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
2768     lstrcatA(keypath, prod_squashed);
2769
2770     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2771     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2772
2773     /* local classes product key exists */
2774     lstrcpyA(product, "prod");
2775     r = MsiGetProductCodeA(component, product);
2776     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2777     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
2778
2779     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2780     RegCloseKey(prodkey);
2781
2782     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2783     lstrcatA(keypath, "Installer\\Managed\\");
2784     lstrcatA(keypath, usersid);
2785     lstrcatA(keypath, "\\Installer\\Products\\");
2786     lstrcatA(keypath, prod2_squashed);
2787
2788     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2789     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2790
2791     /* user managed product key of second product exists */
2792     lstrcpyA(product, "prod");
2793     r = MsiGetProductCodeA(component, product);
2794     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2795     ok(!lstrcmpA(product, prodcode2), "Expected %s, got %s\n", prodcode2, product);
2796
2797     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2798     RegCloseKey(prodkey);
2799     RegDeleteValueA(compkey, prod_squashed);
2800     RegDeleteValueA(compkey, prod2_squashed);
2801     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2802     RegCloseKey(compkey);
2803
2804     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2805     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
2806     lstrcatA(keypath, comp_squashed);
2807
2808     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2809     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2810
2811     /* local user component key exists */
2812     lstrcpyA(product, "prod");
2813     r = MsiGetProductCodeA(component, product);
2814     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2815     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
2816
2817     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2818     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2819
2820     /* product value exists */
2821     lstrcpyA(product, "prod");
2822     r = MsiGetProductCodeA(component, product);
2823     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2824     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
2825
2826     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
2827     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2828
2829     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2830     lstrcatA(keypath, "Installer\\Managed\\");
2831     lstrcatA(keypath, usersid);
2832     lstrcatA(keypath, "\\Installer\\Products\\");
2833     lstrcatA(keypath, prod_squashed);
2834
2835     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2836     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2837
2838     /* user managed product key of first product exists */
2839     lstrcpyA(product, "prod");
2840     r = MsiGetProductCodeA(component, product);
2841     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2842     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
2843
2844     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2845     RegCloseKey(prodkey);
2846
2847     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2848     lstrcatA(keypath, prod_squashed);
2849
2850     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
2851     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2852
2853     /* user unmanaged product key exists */
2854     lstrcpyA(product, "prod");
2855     r = MsiGetProductCodeA(component, product);
2856     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2857     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
2858
2859     RegDeleteKeyA(prodkey, "");
2860     RegCloseKey(prodkey);
2861
2862     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
2863     lstrcatA(keypath, prod_squashed);
2864
2865     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2866     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2867
2868     /* local classes product key exists */
2869     lstrcpyA(product, "prod");
2870     r = MsiGetProductCodeA(component, product);
2871     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2872     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
2873
2874     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2875     RegCloseKey(prodkey);
2876
2877     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2878     lstrcatA(keypath, "Installer\\Managed\\");
2879     lstrcatA(keypath, usersid);
2880     lstrcatA(keypath, "\\Installer\\Products\\");
2881     lstrcatA(keypath, prod2_squashed);
2882
2883     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2884     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2885
2886     /* user managed product key of second product exists */
2887     lstrcpyA(product, "prod");
2888     r = MsiGetProductCodeA(component, product);
2889     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2890     ok(!lstrcmpA(product, prodcode2), "Expected %s, got %s\n", prodcode2, product);
2891
2892     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2893     RegCloseKey(prodkey);
2894     RegDeleteValueA(compkey, prod_squashed);
2895     RegDeleteValueA(compkey, prod2_squashed);
2896     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2897     RegCloseKey(compkey);
2898     LocalFree(usersid);
2899 }
2900
2901 static void test_MsiEnumClients(void)
2902 {
2903     HKEY compkey;
2904     CHAR prodcode[MAX_PATH];
2905     CHAR prod_squashed[MAX_PATH];
2906     CHAR prodcode2[MAX_PATH];
2907     CHAR prod2_squashed[MAX_PATH];
2908     CHAR component[MAX_PATH];
2909     CHAR comp_base85[MAX_PATH];
2910     CHAR comp_squashed[MAX_PATH];
2911     CHAR product[MAX_PATH];
2912     CHAR keypath[MAX_PATH];
2913     LPSTR usersid;
2914     LONG res;
2915     UINT r;
2916     REGSAM access = KEY_ALL_ACCESS;
2917
2918     create_test_guid(prodcode, prod_squashed);
2919     create_test_guid(prodcode2, prod2_squashed);
2920     compose_base85_guid(component, comp_base85, comp_squashed);
2921     usersid = get_user_sid();
2922
2923     if (is_wow64)
2924         access |= KEY_WOW64_64KEY;
2925
2926     /* NULL szComponent */
2927     product[0] = '\0';
2928     r = MsiEnumClientsA(NULL, 0, product);
2929     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2930     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
2931
2932     /* empty szComponent */
2933     product[0] = '\0';
2934     r = MsiEnumClientsA("", 0, product);
2935     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2936     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
2937
2938     /* NULL lpProductBuf */
2939     r = MsiEnumClientsA(component, 0, NULL);
2940     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2941
2942     /* all params correct, component missing */
2943     product[0] = '\0';
2944     r = MsiEnumClientsA(component, 0, product);
2945     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2946     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
2947
2948     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2949     lstrcatA(keypath, "Installer\\UserData\\");
2950     lstrcatA(keypath, usersid);
2951     lstrcatA(keypath, "\\Components\\");
2952     lstrcatA(keypath, comp_squashed);
2953
2954     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2955     if (res == ERROR_ACCESS_DENIED)
2956     {
2957         skip("Not enough rights to perform tests\n");
2958         LocalFree(usersid);
2959         return;
2960     }
2961     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2962
2963     /* user unmanaged component key exists */
2964     product[0] = '\0';
2965     r = MsiEnumClientsA(component, 0, product);
2966     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2967     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
2968
2969     /* index > 0, no products exist */
2970     product[0] = '\0';
2971     r = MsiEnumClientsA(component, 1, product);
2972     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2973     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
2974
2975     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2976     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2977
2978     /* product value exists */
2979     r = MsiEnumClientsA(component, 0, product);
2980     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2981     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
2982
2983     /* try index 0 again */
2984     product[0] = '\0';
2985     r = MsiEnumClientsA(component, 0, product);
2986     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2987     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
2988
2989     /* try index 1, second product value does not exist */
2990     product[0] = '\0';
2991     r = MsiEnumClientsA(component, 1, product);
2992     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
2993     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
2994
2995     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
2996     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2997
2998     /* try index 1, second product value does exist */
2999     product[0] = '\0';
3000     r = MsiEnumClientsA(component, 1, product);
3001     todo_wine
3002     {
3003         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3004         ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3005     }
3006
3007     /* start the enumeration over */
3008     product[0] = '\0';
3009     r = MsiEnumClientsA(component, 0, product);
3010     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3011     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
3012        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
3013
3014     /* correctly query second product */
3015     product[0] = '\0';
3016     r = MsiEnumClientsA(component, 1, product);
3017     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3018     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
3019        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
3020
3021     RegDeleteValueA(compkey, prod_squashed);
3022     RegDeleteValueA(compkey, prod2_squashed);
3023     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3024     RegCloseKey(compkey);
3025
3026     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3027     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
3028     lstrcatA(keypath, comp_squashed);
3029
3030     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3031     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3032
3033     /* user local component key exists */
3034     product[0] = '\0';
3035     r = MsiEnumClientsA(component, 0, product);
3036     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3037     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3038
3039     /* index > 0, no products exist */
3040     product[0] = '\0';
3041     r = MsiEnumClientsA(component, 1, product);
3042     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3043     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3044
3045     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3046     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3047
3048     /* product value exists */
3049     product[0] = '\0';
3050     r = MsiEnumClientsA(component, 0, product);
3051     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3052     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3053
3054     /* try index 0 again */
3055     product[0] = '\0';
3056     r = MsiEnumClientsA(component, 0, product);
3057     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3058
3059     /* try index 1, second product value does not exist */
3060     product[0] = '\0';
3061     r = MsiEnumClientsA(component, 1, product);
3062     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3063     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3064
3065     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
3066     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3067
3068     /* try index 1, second product value does exist */
3069     product[0] = '\0';
3070     r = MsiEnumClientsA(component, 1, product);
3071     todo_wine
3072     {
3073         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3074         ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3075     }
3076
3077     /* start the enumeration over */
3078     product[0] = '\0';
3079     r = MsiEnumClientsA(component, 0, product);
3080     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3081     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
3082        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
3083
3084     /* correctly query second product */
3085     product[0] = '\0';
3086     r = MsiEnumClientsA(component, 1, product);
3087     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3088     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
3089        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
3090
3091     RegDeleteValueA(compkey, prod_squashed);
3092     RegDeleteValueA(compkey, prod2_squashed);
3093     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3094     RegCloseKey(compkey);
3095     LocalFree(usersid);
3096 }
3097
3098 static void get_version_info(LPSTR path, LPSTR *vercheck, LPDWORD verchecksz,
3099                              LPSTR *langcheck, LPDWORD langchecksz)
3100 {
3101     LPSTR version;
3102     VS_FIXEDFILEINFO *ffi;
3103     DWORD size = GetFileVersionInfoSizeA(path, NULL);
3104     USHORT *lang;
3105
3106     version = HeapAlloc(GetProcessHeap(), 0, size);
3107     GetFileVersionInfoA(path, 0, size, version);
3108
3109     VerQueryValueA(version, "\\", (LPVOID *)&ffi, &size);
3110     *vercheck = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
3111     sprintf(*vercheck, "%d.%d.%d.%d", HIWORD(ffi->dwFileVersionMS),
3112             LOWORD(ffi->dwFileVersionMS), HIWORD(ffi->dwFileVersionLS),
3113             LOWORD(ffi->dwFileVersionLS));
3114     *verchecksz = lstrlenA(*vercheck);
3115
3116     VerQueryValue(version, "\\VarFileInfo\\Translation", (void **)&lang, &size);
3117     *langcheck = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
3118     sprintf(*langcheck, "%d", *lang);
3119     *langchecksz = lstrlenA(*langcheck);
3120
3121     HeapFree(GetProcessHeap(), 0, version);
3122 }
3123
3124 static void test_MsiGetFileVersion(void)
3125 {
3126     UINT r;
3127     DWORD versz, langsz;
3128     char version[MAX_PATH];
3129     char lang[MAX_PATH];
3130     char path[MAX_PATH];
3131     LPSTR vercheck, langcheck;
3132     DWORD verchecksz, langchecksz;
3133
3134     /* NULL szFilePath */
3135     r = MsiGetFileVersionA(NULL, NULL, NULL, NULL, NULL);
3136     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3137
3138     versz = MAX_PATH;
3139     langsz = MAX_PATH;
3140     lstrcpyA(version, "version");
3141     lstrcpyA(lang, "lang");
3142     r = MsiGetFileVersionA(NULL, version, &versz, lang, &langsz);
3143     ok(r == ERROR_INVALID_PARAMETER,
3144        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3145     ok(!lstrcmpA(version, "version"),
3146        "Expected version to be unchanged, got %s\n", version);
3147     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
3148     ok(!lstrcmpA(lang, "lang"),
3149        "Expected lang to be unchanged, got %s\n", lang);
3150     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
3151
3152     /* empty szFilePath */
3153     r = MsiGetFileVersionA("", NULL, NULL, NULL, NULL);
3154     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
3155
3156     versz = MAX_PATH;
3157     langsz = MAX_PATH;
3158     lstrcpyA(version, "version");
3159     lstrcpyA(lang, "lang");
3160     r = MsiGetFileVersionA("", version, &versz, lang, &langsz);
3161     ok(r == ERROR_FILE_NOT_FOUND,
3162        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
3163     ok(!lstrcmpA(version, "version"),
3164        "Expected version to be unchanged, got %s\n", version);
3165     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
3166     ok(!lstrcmpA(lang, "lang"),
3167        "Expected lang to be unchanged, got %s\n", lang);
3168     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
3169
3170     /* nonexistent szFilePath */
3171     versz = MAX_PATH;
3172     langsz = MAX_PATH;
3173     lstrcpyA(version, "version");
3174     lstrcpyA(lang, "lang");
3175     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
3176     ok(r == ERROR_FILE_NOT_FOUND,
3177        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
3178     ok(!lstrcmpA(version, "version"),
3179        "Expected version to be unchanged, got %s\n", version);
3180     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
3181     ok(!lstrcmpA(lang, "lang"),
3182        "Expected lang to be unchanged, got %s\n", lang);
3183     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
3184
3185     /* nonexistent szFilePath, valid lpVersionBuf, NULL pcchVersionBuf */
3186     versz = MAX_PATH;
3187     langsz = MAX_PATH;
3188     lstrcpyA(version, "version");
3189     lstrcpyA(lang, "lang");
3190     r = MsiGetFileVersionA("nonexistent", version, NULL, lang, &langsz);
3191     ok(r == ERROR_INVALID_PARAMETER,
3192        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3193     ok(!lstrcmpA(version, "version"),
3194        "Expected version to be unchanged, got %s\n", version);
3195     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
3196     ok(!lstrcmpA(lang, "lang"),
3197        "Expected lang to be unchanged, got %s\n", lang);
3198     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
3199
3200     /* nonexistent szFilePath, valid lpLangBuf, NULL pcchLangBuf */
3201     versz = MAX_PATH;
3202     langsz = MAX_PATH;
3203     lstrcpyA(version, "version");
3204     lstrcpyA(lang, "lang");
3205     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, NULL);
3206     ok(r == ERROR_INVALID_PARAMETER,
3207        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3208     ok(!lstrcmpA(version, "version"),
3209        "Expected version to be unchanged, got %s\n", version);
3210     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
3211     ok(!lstrcmpA(lang, "lang"),
3212        "Expected lang to be unchanged, got %s\n", lang);
3213     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
3214
3215     /* nonexistent szFilePath, valid lpVersionBuf, pcchVersionBuf is zero */
3216     versz = 0;
3217     langsz = MAX_PATH;
3218     lstrcpyA(version, "version");
3219     lstrcpyA(lang, "lang");
3220     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
3221     ok(r == ERROR_FILE_NOT_FOUND,
3222        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
3223     ok(!lstrcmpA(version, "version"),
3224        "Expected version to be unchanged, got %s\n", version);
3225     ok(versz == 0, "Expected 0, got %d\n", versz);
3226     ok(!lstrcmpA(lang, "lang"),
3227        "Expected lang to be unchanged, got %s\n", lang);
3228     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
3229
3230     /* nonexistent szFilePath, valid lpLangBuf, pcchLangBuf is zero */
3231     versz = MAX_PATH;
3232     langsz = 0;
3233     lstrcpyA(version, "version");
3234     lstrcpyA(lang, "lang");
3235     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
3236     ok(r == ERROR_FILE_NOT_FOUND,
3237        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
3238     ok(!lstrcmpA(version, "version"),
3239        "Expected version to be unchanged, got %s\n", version);
3240     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
3241     ok(!lstrcmpA(lang, "lang"),
3242        "Expected lang to be unchanged, got %s\n", lang);
3243     ok(langsz == 0, "Expected 0, got %d\n", langsz);
3244
3245     /* nonexistent szFilePath, rest NULL */
3246     r = MsiGetFileVersionA("nonexistent", NULL, NULL, NULL, NULL);
3247     ok(r == ERROR_FILE_NOT_FOUND,
3248        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
3249
3250     create_file("ver.txt", "ver.txt", 20);
3251
3252     /* file exists, no version information */
3253     r = MsiGetFileVersionA("ver.txt", NULL, NULL, NULL, NULL);
3254     ok(r == ERROR_FILE_INVALID, "Expected ERROR_FILE_INVALID, got %d\n", r);
3255
3256     versz = MAX_PATH;
3257     langsz = MAX_PATH;
3258     lstrcpyA(version, "version");
3259     lstrcpyA(lang, "lang");
3260     r = MsiGetFileVersionA("ver.txt", version, &versz, lang, &langsz);
3261     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
3262     ok(!lstrcmpA(version, "version"),
3263        "Expected version to be unchanged, got %s\n", version);
3264     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
3265     ok(!lstrcmpA(lang, "lang"),
3266        "Expected lang to be unchanged, got %s\n", lang);
3267     ok(r == ERROR_FILE_INVALID,
3268        "Expected ERROR_FILE_INVALID, got %d\n", r);
3269
3270     DeleteFileA("ver.txt");
3271
3272     /* relative path, has version information */
3273     versz = MAX_PATH;
3274     langsz = MAX_PATH;
3275     lstrcpyA(version, "version");
3276     lstrcpyA(lang, "lang");
3277     r = MsiGetFileVersionA("kernel32.dll", version, &versz, lang, &langsz);
3278     todo_wine
3279     {
3280         ok(r == ERROR_FILE_NOT_FOUND,
3281            "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
3282         ok(!lstrcmpA(version, "version"),
3283            "Expected version to be unchanged, got %s\n", version);
3284         ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
3285         ok(!lstrcmpA(lang, "lang"),
3286            "Expected lang to be unchanged, got %s\n", lang);
3287         ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
3288     }
3289
3290     GetSystemDirectoryA(path, MAX_PATH);
3291     lstrcatA(path, "\\kernel32.dll");
3292
3293     get_version_info(path, &vercheck, &verchecksz, &langcheck, &langchecksz);
3294
3295     /* absolute path, has version information */
3296     versz = MAX_PATH;
3297     langsz = MAX_PATH;
3298     lstrcpyA(version, "version");
3299     lstrcpyA(lang, "lang");
3300     r = MsiGetFileVersionA(path, version, &versz, lang, &langsz);
3301     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3302     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
3303     ok(strstr(lang, langcheck) != NULL, "Expected %s in %s\n", langcheck, lang);
3304     ok(!lstrcmpA(version, vercheck),
3305         "Expected %s, got %s\n", vercheck, version);
3306
3307     /* only check version */
3308     versz = MAX_PATH;
3309     lstrcpyA(version, "version");
3310     r = MsiGetFileVersionA(path, version, &versz, NULL, NULL);
3311     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3312     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
3313     ok(!lstrcmpA(version, vercheck),
3314        "Expected %s, got %s\n", vercheck, version);
3315
3316     /* only check language */
3317     langsz = MAX_PATH;
3318     lstrcpyA(lang, "lang");
3319     r = MsiGetFileVersionA(path, NULL, NULL, lang, &langsz);
3320     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3321     ok(strstr(lang, langcheck) != NULL, "Expected %s in %s\n", langcheck, lang);
3322
3323     /* check neither version nor language */
3324     r = MsiGetFileVersionA(path, NULL, NULL, NULL, NULL);
3325     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3326
3327     /* get pcchVersionBuf */
3328     versz = MAX_PATH;
3329     r = MsiGetFileVersionA(path, NULL, &versz, NULL, NULL);
3330     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3331     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
3332
3333     /* get pcchLangBuf */
3334     langsz = MAX_PATH;
3335     r = MsiGetFileVersionA(path, NULL, NULL, NULL, &langsz);
3336     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3337     ok(langsz >= langchecksz, "Expected %d >= %d\n", langsz, langchecksz);
3338
3339     /* pcchVersionBuf not big enough */
3340     versz = 5;
3341     lstrcpyA(version, "version");
3342     r = MsiGetFileVersionA(path, version, &versz, NULL, NULL);
3343     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
3344     ok(!strncmp(version, vercheck, 4),
3345        "Expected first 4 characters of %s, got %s\n", vercheck, version);
3346     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
3347
3348     /* pcchLangBuf not big enough */
3349     langsz = 3;
3350     lstrcpyA(lang, "lang");
3351     r = MsiGetFileVersionA(path, NULL, NULL, lang, &langsz);
3352     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
3353     ok(!strncmp(lang, langcheck, 2),
3354        "Expected first character of %s, got %s\n", langcheck, lang);
3355     ok(langsz >= langchecksz, "Expected %d >= %d\n", langsz, langchecksz);
3356
3357     /* pcchVersionBuf big enough, pcchLangBuf not big enough */
3358     versz = MAX_PATH;
3359     langsz = 0;
3360     lstrcpyA(version, "version");
3361     r = MsiGetFileVersionA(path, version, &versz, NULL, &langsz);
3362     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3363     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
3364     ok(!lstrcmpA(version, vercheck), "Expected %s, got %s\n", vercheck, version);
3365     ok(langsz >= langchecksz && langsz < MAX_PATH, "Expected %d >= %d\n", langsz, langchecksz);
3366
3367     /* pcchVersionBuf not big enough, pcchLangBuf big enough */
3368     versz = 5;
3369     langsz = MAX_PATH;
3370     lstrcpyA(lang, "lang");
3371     r = MsiGetFileVersionA(path, NULL, &versz, lang, &langsz);
3372     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3373     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
3374     ok(langsz >= langchecksz && langsz < MAX_PATH, "Expected %d >= %d\n", langsz, langchecksz);
3375     ok(lstrcmpA(lang, "lang"), "lang buffer not modified\n");
3376
3377     /* NULL pcchVersionBuf and pcchLangBuf */
3378     r = MsiGetFileVersionA(path, version, NULL, lang, NULL);
3379     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3380
3381     /* All NULL except szFilePath */
3382     r = MsiGetFileVersionA(path, NULL, NULL, NULL, NULL);
3383     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3384
3385     HeapFree(GetProcessHeap(), 0, vercheck);
3386     HeapFree(GetProcessHeap(), 0, langcheck);
3387 }
3388
3389 static void test_MsiGetProductInfo(void)
3390 {
3391     UINT r;
3392     LONG res;
3393     HKEY propkey, source;
3394     HKEY prodkey, localkey;
3395     CHAR prodcode[MAX_PATH];
3396     CHAR prod_squashed[MAX_PATH];
3397     CHAR packcode[MAX_PATH];
3398     CHAR pack_squashed[MAX_PATH];
3399     CHAR buf[MAX_PATH];
3400     CHAR keypath[MAX_PATH];
3401     LPSTR usersid;
3402     DWORD sz, val = 42;
3403     REGSAM access = KEY_ALL_ACCESS;
3404
3405     create_test_guid(prodcode, prod_squashed);
3406     create_test_guid(packcode, pack_squashed);
3407     usersid = get_user_sid();
3408
3409     if (is_wow64)
3410         access |= KEY_WOW64_64KEY;
3411
3412     /* NULL szProduct */
3413     sz = MAX_PATH;
3414     lstrcpyA(buf, "apple");
3415     r = MsiGetProductInfoA(NULL, INSTALLPROPERTY_HELPLINK, buf, &sz);
3416     ok(r == ERROR_INVALID_PARAMETER,
3417        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3418     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
3419     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
3420
3421     /* empty szProduct */
3422     sz = MAX_PATH;
3423     lstrcpyA(buf, "apple");
3424     r = MsiGetProductInfoA("", INSTALLPROPERTY_HELPLINK, buf, &sz);
3425     ok(r == ERROR_INVALID_PARAMETER,
3426        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3427     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
3428     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
3429
3430     /* garbage szProduct */
3431     sz = MAX_PATH;
3432     lstrcpyA(buf, "apple");
3433     r = MsiGetProductInfoA("garbage", INSTALLPROPERTY_HELPLINK, buf, &sz);
3434     ok(r == ERROR_INVALID_PARAMETER,
3435        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3436     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
3437     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
3438
3439     /* guid without brackets */
3440     sz = MAX_PATH;
3441     lstrcpyA(buf, "apple");
3442     r = MsiGetProductInfoA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
3443                            INSTALLPROPERTY_HELPLINK, buf, &sz);
3444     ok(r == ERROR_INVALID_PARAMETER,
3445        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3446     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
3447     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
3448
3449     /* guid with brackets */
3450     sz = MAX_PATH;
3451     lstrcpyA(buf, "apple");
3452     r = MsiGetProductInfoA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
3453                            INSTALLPROPERTY_HELPLINK, buf, &sz);
3454     ok(r == ERROR_UNKNOWN_PRODUCT,
3455        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3456     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
3457     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
3458
3459     /* same length as guid, but random */
3460     sz = MAX_PATH;
3461     lstrcpyA(buf, "apple");
3462     r = MsiGetProductInfoA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
3463                            INSTALLPROPERTY_HELPLINK, buf, &sz);
3464     ok(r == ERROR_INVALID_PARAMETER,
3465        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3466     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
3467     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
3468
3469     /* not installed, NULL szAttribute */
3470     sz = MAX_PATH;
3471     lstrcpyA(buf, "apple");
3472     r = MsiGetProductInfoA(prodcode, NULL, buf, &sz);
3473     ok(r == ERROR_INVALID_PARAMETER,
3474        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3475     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
3476     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
3477
3478     /* not installed, NULL lpValueBuf */
3479     sz = MAX_PATH;
3480     lstrcpyA(buf, "apple");
3481     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, NULL, &sz);
3482     ok(r == ERROR_UNKNOWN_PRODUCT,
3483        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3484     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
3485     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
3486
3487     /* not installed, NULL pcchValueBuf */
3488     sz = MAX_PATH;
3489     lstrcpyA(buf, "apple");
3490     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, NULL);
3491     ok(r == ERROR_INVALID_PARAMETER,
3492        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3493     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
3494     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
3495
3496     /* created guid cannot possibly be an installed product code */
3497     sz = MAX_PATH;
3498     lstrcpyA(buf, "apple");
3499     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
3500     ok(r == ERROR_UNKNOWN_PRODUCT,
3501        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3502     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
3503     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
3504
3505     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
3506     lstrcatA(keypath, usersid);
3507     lstrcatA(keypath, "\\Installer\\Products\\");
3508     lstrcatA(keypath, prod_squashed);
3509
3510     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3511     if (res == ERROR_ACCESS_DENIED)
3512     {
3513         skip("Not enough rights to perform tests\n");
3514         LocalFree(usersid);
3515         return;
3516     }
3517     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3518
3519     /* managed product code exists */
3520     sz = MAX_PATH;
3521     lstrcpyA(buf, "apple");
3522     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
3523     ok(r == ERROR_UNKNOWN_PROPERTY,
3524        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
3525     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
3526     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
3527
3528     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3529     RegCloseKey(prodkey);
3530
3531     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
3532     lstrcatA(keypath, usersid);
3533     lstrcatA(keypath, "\\Products\\");
3534     lstrcatA(keypath, prod_squashed);
3535
3536     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
3537     if (res == ERROR_ACCESS_DENIED)
3538     {
3539         skip("Not enough rights to perform tests\n");
3540         LocalFree(usersid);
3541         return;
3542     }
3543     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3544
3545     /* local user product code exists */
3546     sz = MAX_PATH;
3547     lstrcpyA(buf, "apple");
3548     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
3549     ok(r == ERROR_UNKNOWN_PRODUCT,
3550        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3551     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
3552     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
3553
3554     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
3555     lstrcatA(keypath, usersid);
3556     lstrcatA(keypath, "\\Installer\\Products\\");
3557     lstrcatA(keypath, prod_squashed);
3558
3559     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3560     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3561
3562     /* both local and managed product code exist */
3563     sz = MAX_PATH;
3564     lstrcpyA(buf, "apple");
3565     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
3566     ok(r == ERROR_UNKNOWN_PROPERTY,
3567        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
3568     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
3569     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
3570
3571     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
3572     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3573
3574     /* InstallProperties key exists */
3575     sz = MAX_PATH;
3576     lstrcpyA(buf, "apple");
3577     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
3578     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3579     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
3580     ok(sz == 0, "Expected 0, got %d\n", sz);
3581
3582     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
3583     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3584
3585     /* HelpLink value exists */
3586     sz = MAX_PATH;
3587     lstrcpyA(buf, "apple");
3588     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
3589     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3590     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
3591     ok(sz == 4, "Expected 4, got %d\n", sz);
3592
3593     /* pcchBuf is NULL */
3594     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, NULL, NULL);
3595     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3596
3597     /* lpValueBuf is NULL */
3598     sz = MAX_PATH;
3599     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, NULL, &sz);
3600     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3601     ok(sz == 4, "Expected 4, got %d\n", sz);
3602
3603     /* lpValueBuf is NULL, pcchValueBuf is too small */
3604     sz = 2;
3605     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, NULL, &sz);
3606     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3607     ok(sz == 4, "Expected 4, got %d\n", sz);
3608
3609     /* lpValueBuf is non-NULL, pcchValueBuf is too small */
3610     sz = 2;
3611     lstrcpyA(buf, "apple");
3612     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
3613     ok(!lstrcmpA(buf, "apple"), "Expected buf to remain unchanged, got \"%s\"\n", buf);
3614     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
3615     ok(sz == 4, "Expected 4, got %d\n", sz);
3616
3617     /* lpValueBuf is non-NULL, pcchValueBuf is exactly 4 */
3618     sz = 4;
3619     lstrcpyA(buf, "apple");
3620     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
3621     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
3622     ok(!lstrcmpA(buf, "apple"),
3623        "Expected buf to remain unchanged, got \"%s\"\n", buf);
3624     ok(sz == 4, "Expected 4, got %d\n", sz);
3625
3626     res = RegSetValueExA(propkey, "IMadeThis", 0, REG_SZ, (LPBYTE)"random", 7);
3627     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3628
3629     /* random property not supported by MSI, value exists */
3630     sz = MAX_PATH;
3631     lstrcpyA(buf, "apple");
3632     r = MsiGetProductInfoA(prodcode, "IMadeThis", buf, &sz);
3633     ok(r == ERROR_UNKNOWN_PROPERTY,
3634        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
3635     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
3636     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
3637
3638     RegDeleteValueA(propkey, "IMadeThis");
3639     RegDeleteValueA(propkey, "HelpLink");
3640     delete_key(propkey, "", access & KEY_WOW64_64KEY);
3641     delete_key(localkey, "", access & KEY_WOW64_64KEY);
3642     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3643     RegCloseKey(propkey);
3644     RegCloseKey(localkey);
3645     RegCloseKey(prodkey);
3646
3647     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
3648     lstrcatA(keypath, prod_squashed);
3649
3650     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
3651     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3652
3653     /* user product key exists */
3654     sz = MAX_PATH;
3655     lstrcpyA(buf, "apple");
3656     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
3657     ok(r == ERROR_UNKNOWN_PROPERTY,
3658        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
3659     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
3660     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
3661
3662     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
3663     lstrcatA(keypath, usersid);
3664     lstrcatA(keypath, "\\Products\\");
3665     lstrcatA(keypath, prod_squashed);
3666
3667     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
3668     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3669
3670     /* local user product key exists */
3671     sz = MAX_PATH;
3672     lstrcpyA(buf, "apple");
3673     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
3674     ok(r == ERROR_UNKNOWN_PROPERTY,
3675        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
3676     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
3677     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
3678
3679     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
3680     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3681
3682     /* InstallProperties key exists */
3683     sz = MAX_PATH;
3684     lstrcpyA(buf, "apple");
3685     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
3686     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3687     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
3688     ok(sz == 0, "Expected 0, got %d\n", sz);
3689
3690     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
3691     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3692
3693     /* HelpLink value exists */
3694     sz = MAX_PATH;
3695     lstrcpyA(buf, "apple");
3696     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
3697     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3698     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
3699     ok(sz == 4, "Expected 4, got %d\n", sz);
3700
3701     RegDeleteValueA(propkey, "HelpLink");
3702     delete_key(propkey, "", access & KEY_WOW64_64KEY);
3703     delete_key(localkey, "", access & KEY_WOW64_64KEY);
3704     RegDeleteKeyA(prodkey, "");
3705     RegCloseKey(propkey);
3706     RegCloseKey(localkey);
3707     RegCloseKey(prodkey);
3708
3709     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
3710     lstrcatA(keypath, prod_squashed);
3711
3712     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3713     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3714
3715     /* classes product key exists */
3716     sz = MAX_PATH;
3717     lstrcpyA(buf, "apple");
3718     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
3719     ok(r == ERROR_UNKNOWN_PROPERTY,
3720        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
3721     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
3722     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
3723
3724     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
3725     lstrcatA(keypath, usersid);
3726     lstrcatA(keypath, "\\Products\\");
3727     lstrcatA(keypath, prod_squashed);
3728
3729     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
3730     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3731
3732     /* local user product key exists */
3733     sz = MAX_PATH;
3734     lstrcpyA(buf, "apple");
3735     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
3736     ok(r == ERROR_UNKNOWN_PROPERTY,
3737        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
3738     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
3739     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
3740
3741     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
3742     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3743
3744     /* InstallProperties key exists */
3745     sz = MAX_PATH;
3746     lstrcpyA(buf, "apple");
3747     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
3748     ok(r == ERROR_UNKNOWN_PROPERTY,
3749        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
3750     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
3751     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
3752
3753     delete_key(propkey, "", access & KEY_WOW64_64KEY);
3754     delete_key(localkey, "", access & KEY_WOW64_64KEY);
3755     RegCloseKey(propkey);
3756     RegCloseKey(localkey);
3757
3758     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
3759     lstrcatA(keypath, "S-1-5-18\\\\Products\\");
3760     lstrcatA(keypath, prod_squashed);
3761
3762     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
3763     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3764
3765     /* Local System product key exists */
3766     sz = MAX_PATH;
3767     lstrcpyA(buf, "apple");
3768     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
3769     ok(r == ERROR_UNKNOWN_PROPERTY,
3770         "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
3771     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
3772     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
3773
3774     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
3775     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3776
3777     /* InstallProperties key exists */
3778     sz = MAX_PATH;
3779     lstrcpyA(buf, "apple");
3780     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
3781     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3782     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
3783     ok(sz == 0, "Expected 0, got %d\n", sz);
3784
3785     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
3786     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3787
3788     /* HelpLink value exists */
3789     sz = MAX_PATH;
3790     lstrcpyA(buf, "apple");
3791     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
3792     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3793     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
3794     ok(sz == 4, "Expected 4, got %d\n", sz);
3795
3796     res = RegSetValueExA(propkey, "HelpLink", 0, REG_DWORD,
3797                          (const BYTE *)&val, sizeof(DWORD));
3798     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3799
3800     /* HelpLink type is REG_DWORD */
3801     sz = MAX_PATH;
3802     lstrcpyA(buf, "apple");
3803     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
3804     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3805     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
3806     ok(sz == 2, "Expected 2, got %d\n", sz);
3807
3808     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
3809     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3810
3811     /* DisplayName value exists */
3812     sz = MAX_PATH;
3813     lstrcpyA(buf, "apple");
3814     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLEDPRODUCTNAME, buf, &sz);
3815     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3816     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
3817     ok(sz == 4, "Expected 4, got %d\n", sz);
3818
3819     res = RegSetValueExA(propkey, "DisplayName", 0, REG_DWORD,
3820                          (const BYTE *)&val, sizeof(DWORD));
3821     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3822
3823     /* DisplayName type is REG_DWORD */
3824     sz = MAX_PATH;
3825     lstrcpyA(buf, "apple");
3826     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLEDPRODUCTNAME, buf, &sz);
3827     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3828     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
3829     ok(sz == 2, "Expected 2, got %d\n", sz);
3830
3831     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"1.1.1", 6);
3832     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3833
3834     /* DisplayVersion value exists */
3835     sz = MAX_PATH;
3836     lstrcpyA(buf, "apple");
3837     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONSTRING, buf, &sz);
3838     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3839     ok(!lstrcmpA(buf, "1.1.1"), "Expected \"1.1.1\", got \"%s\"\n", buf);
3840     ok(sz == 5, "Expected 5, got %d\n", sz);
3841
3842     res = RegSetValueExA(propkey, "DisplayVersion", 0,
3843                          REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
3844     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3845
3846     /* DisplayVersion type is REG_DWORD */
3847     sz = MAX_PATH;
3848     lstrcpyA(buf, "apple");
3849     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONSTRING, buf, &sz);
3850     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3851     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
3852     ok(sz == 2, "Expected 2, got %d\n", sz);
3853
3854     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"tele", 5);
3855     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3856
3857     /* HelpTelephone value exists */
3858     sz = MAX_PATH;
3859     lstrcpyA(buf, "apple");
3860     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPTELEPHONE, buf, &sz);
3861     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3862     ok(!lstrcmpA(buf, "tele"), "Expected \"tele\", got \"%s\"\n", buf);
3863     ok(sz == 4, "Expected 4, got %d\n", sz);
3864
3865     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_DWORD,
3866                          (const BYTE *)&val, sizeof(DWORD));
3867     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3868
3869     /* HelpTelephone type is REG_DWORD */
3870     sz = MAX_PATH;
3871     lstrcpyA(buf, "apple");
3872     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPTELEPHONE, buf, &sz);
3873     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3874     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
3875     ok(sz == 2, "Expected 2, got %d\n", sz);
3876
3877     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
3878     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3879
3880     /* InstallLocation value exists */
3881     sz = MAX_PATH;
3882     lstrcpyA(buf, "apple");
3883     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLLOCATION, buf, &sz);
3884     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3885     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
3886     ok(sz == 3, "Expected 3, got %d\n", sz);
3887
3888     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_DWORD,
3889                          (const BYTE *)&val, sizeof(DWORD));
3890     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3891
3892     /* InstallLocation type is REG_DWORD */
3893     sz = MAX_PATH;
3894     lstrcpyA(buf, "apple");
3895     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLLOCATION, buf, &sz);
3896     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3897     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
3898     ok(sz == 2, "Expected 2, got %d\n", sz);
3899
3900     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
3901     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3902
3903     /* InstallSource value exists */
3904     sz = MAX_PATH;
3905     lstrcpyA(buf, "apple");
3906     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLSOURCE, buf, &sz);
3907     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3908     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
3909     ok(sz == 6, "Expected 6, got %d\n", sz);
3910
3911     res = RegSetValueExA(propkey, "InstallSource", 0, REG_DWORD,
3912                          (const BYTE *)&val, sizeof(DWORD));
3913     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3914
3915     /* InstallSource type is REG_DWORD */
3916     sz = MAX_PATH;
3917     lstrcpyA(buf, "apple");
3918     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLSOURCE, buf, &sz);
3919     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3920     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
3921     ok(sz == 2, "Expected 2, got %d\n", sz);
3922
3923     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
3924     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3925
3926     /* InstallDate value exists */
3927     sz = MAX_PATH;
3928     lstrcpyA(buf, "apple");
3929     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLDATE, buf, &sz);
3930     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3931     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
3932     ok(sz == 4, "Expected 4, got %d\n", sz);
3933
3934     res = RegSetValueExA(propkey, "InstallDate", 0, REG_DWORD,
3935                          (const BYTE *)&val, sizeof(DWORD));
3936     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3937
3938     /* InstallDate type is REG_DWORD */
3939     sz = MAX_PATH;
3940     lstrcpyA(buf, "apple");
3941     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLDATE, buf, &sz);
3942     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3943     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
3944     ok(sz == 2, "Expected 2, got %d\n", sz);
3945
3946     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
3947     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3948
3949     /* Publisher value exists */
3950     sz = MAX_PATH;
3951     lstrcpyA(buf, "apple");
3952     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PUBLISHER, buf, &sz);
3953     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3954     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
3955     ok(sz == 3, "Expected 3, got %d\n", sz);
3956
3957     res = RegSetValueExA(propkey, "Publisher", 0, REG_DWORD,
3958                          (const BYTE *)&val, sizeof(DWORD));
3959     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3960
3961     /* Publisher type is REG_DWORD */
3962     sz = MAX_PATH;
3963     lstrcpyA(buf, "apple");
3964     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PUBLISHER, buf, &sz);
3965     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3966     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
3967     ok(sz == 2, "Expected 2, got %d\n", sz);
3968
3969     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"pack", 5);
3970     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3971
3972     /* LocalPackage value exists */
3973     sz = MAX_PATH;
3974     lstrcpyA(buf, "apple");
3975     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LOCALPACKAGE, buf, &sz);
3976     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3977     ok(!lstrcmpA(buf, "pack"), "Expected \"pack\", got \"%s\"\n", buf);
3978     ok(sz == 4, "Expected 4, got %d\n", sz);
3979
3980     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_DWORD,
3981                          (const BYTE *)&val, sizeof(DWORD));
3982     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3983
3984     /* LocalPackage type is REG_DWORD */
3985     sz = MAX_PATH;
3986     lstrcpyA(buf, "apple");
3987     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LOCALPACKAGE, buf, &sz);
3988     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3989     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
3990     ok(sz == 2, "Expected 2, got %d\n", sz);
3991
3992     res = RegSetValueExA(propkey, "UrlInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
3993     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3994
3995     /* UrlInfoAbout value exists */
3996     sz = MAX_PATH;
3997     lstrcpyA(buf, "apple");
3998     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLINFOABOUT, buf, &sz);
3999     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4000     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
4001     ok(sz == 5, "Expected 5, got %d\n", sz);
4002
4003     res = RegSetValueExA(propkey, "UrlInfoAbout", 0, REG_DWORD,
4004                          (const BYTE *)&val, sizeof(DWORD));
4005     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4006
4007     /* UrlInfoAbout type is REG_DWORD */
4008     sz = MAX_PATH;
4009     lstrcpyA(buf, "apple");
4010     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLINFOABOUT, buf, &sz);
4011     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4012     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4013     ok(sz == 2, "Expected 2, got %d\n", sz);
4014
4015     res = RegSetValueExA(propkey, "UrlUpdateInfo", 0, REG_SZ, (LPBYTE)"info", 5);
4016     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4017
4018     /* UrlUpdateInfo value exists */
4019     sz = MAX_PATH;
4020     lstrcpyA(buf, "apple");
4021     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLUPDATEINFO, buf, &sz);
4022     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4023     ok(!lstrcmpA(buf, "info"), "Expected \"info\", got \"%s\"\n", buf);
4024     ok(sz == 4, "Expected 4, got %d\n", sz);
4025
4026     res = RegSetValueExA(propkey, "UrlUpdateInfo", 0, REG_DWORD,
4027                          (const BYTE *)&val, sizeof(DWORD));
4028     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4029
4030     /* UrlUpdateInfo type is REG_DWORD */
4031     sz = MAX_PATH;
4032     lstrcpyA(buf, "apple");
4033     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLUPDATEINFO, buf, &sz);
4034     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4035     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4036     ok(sz == 2, "Expected 2, got %d\n", sz);
4037
4038     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"1", 2);
4039     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4040
4041     /* VersionMinor value exists */
4042     sz = MAX_PATH;
4043     lstrcpyA(buf, "apple");
4044     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMINOR, buf, &sz);
4045     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4046     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
4047     ok(sz == 1, "Expected 1, got %d\n", sz);
4048
4049     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_DWORD,
4050                          (const BYTE *)&val, sizeof(DWORD));
4051     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4052
4053     /* VersionMinor type is REG_DWORD */
4054     sz = MAX_PATH;
4055     lstrcpyA(buf, "apple");
4056     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMINOR, buf, &sz);
4057     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4058     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4059     ok(sz == 2, "Expected 2, got %d\n", sz);
4060
4061     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"1", 2);
4062     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4063
4064     /* VersionMajor value exists */
4065     sz = MAX_PATH;
4066     lstrcpyA(buf, "apple");
4067     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMAJOR, buf, &sz);
4068     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4069     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
4070     ok(sz == 1, "Expected 1, got %d\n", sz);
4071
4072     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_DWORD,
4073                          (const BYTE *)&val, sizeof(DWORD));
4074     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4075
4076     /* VersionMajor type is REG_DWORD */
4077     sz = MAX_PATH;
4078     lstrcpyA(buf, "apple");
4079     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMAJOR, buf, &sz);
4080     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4081     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4082     ok(sz == 2, "Expected 2, got %d\n", sz);
4083
4084     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
4085     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4086
4087     /* ProductID value exists */
4088     sz = MAX_PATH;
4089     lstrcpyA(buf, "apple");
4090     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTID, buf, &sz);
4091     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4092     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
4093     ok(sz == 2, "Expected 2, got %d\n", sz);
4094
4095     res = RegSetValueExA(propkey, "ProductID", 0, REG_DWORD,
4096                          (const BYTE *)&val, sizeof(DWORD));
4097     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4098
4099     /* ProductID type is REG_DWORD */
4100     sz = MAX_PATH;
4101     lstrcpyA(buf, "apple");
4102     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTID, buf, &sz);
4103     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4104     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4105     ok(sz == 2, "Expected 2, got %d\n", sz);
4106
4107     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
4108     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4109
4110     /* RegCompany value exists */
4111     sz = MAX_PATH;
4112     lstrcpyA(buf, "apple");
4113     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGCOMPANY, buf, &sz);
4114     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4115     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
4116     ok(sz == 4, "Expected 4, got %d\n", sz);
4117
4118     res = RegSetValueExA(propkey, "RegCompany", 0, REG_DWORD,
4119                          (const BYTE *)&val, sizeof(DWORD));
4120     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4121
4122     /* RegCompany type is REG_DWORD */
4123     sz = MAX_PATH;
4124     lstrcpyA(buf, "apple");
4125     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGCOMPANY, buf, &sz);
4126     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4127     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4128     ok(sz == 2, "Expected 2, got %d\n", sz);
4129
4130     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"own", 4);
4131     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4132
4133     /* RegOwner value exists */
4134     sz = MAX_PATH;
4135     lstrcpyA(buf, "apple");
4136     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGOWNER, buf, &sz);
4137     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4138     ok(!lstrcmpA(buf, "own"), "Expected \"own\", got \"%s\"\n", buf);
4139     ok(sz == 3, "Expected 3, got %d\n", sz);
4140
4141     res = RegSetValueExA(propkey, "RegOwner", 0, REG_DWORD,
4142                          (const BYTE *)&val, sizeof(DWORD));
4143     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4144
4145     /* RegOwner type is REG_DWORD */
4146     sz = MAX_PATH;
4147     lstrcpyA(buf, "apple");
4148     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGOWNER, buf, &sz);
4149     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4150     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4151     ok(sz == 2, "Expected 2, got %d\n", sz);
4152
4153     res = RegSetValueExA(propkey, "InstanceType", 0, REG_SZ, (LPBYTE)"type", 5);
4154     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4155
4156     /* InstanceType value exists */
4157     sz = MAX_PATH;
4158     lstrcpyA(buf, "apple");
4159     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPE, buf, &sz);
4160     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4161     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4162     ok(sz == 0, "Expected 0, got %d\n", sz);
4163
4164     res = RegSetValueExA(propkey, "InstanceType", 0, REG_DWORD,
4165                          (const BYTE *)&val, sizeof(DWORD));
4166     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4167
4168     /* InstanceType type is REG_DWORD */
4169     sz = MAX_PATH;
4170     lstrcpyA(buf, "apple");
4171     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPE, buf, &sz);
4172     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4173     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4174     ok(sz == 0, "Expected 0, got %d\n", sz);
4175
4176     res = RegSetValueExA(prodkey, "InstanceType", 0, REG_SZ, (LPBYTE)"type", 5);
4177     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4178
4179     /* InstanceType value exists */
4180     sz = MAX_PATH;
4181     lstrcpyA(buf, "apple");
4182     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPE, buf, &sz);
4183     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4184     ok(!lstrcmpA(buf, "type"), "Expected \"type\", got \"%s\"\n", buf);
4185     ok(sz == 4, "Expected 4, got %d\n", sz);
4186
4187     res = RegSetValueExA(prodkey, "InstanceType", 0, REG_DWORD,
4188                          (const BYTE *)&val, sizeof(DWORD));
4189     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4190
4191     /* InstanceType type is REG_DWORD */
4192     sz = MAX_PATH;
4193     lstrcpyA(buf, "apple");
4194     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPE, buf, &sz);
4195     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4196     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4197     ok(sz == 2, "Expected 2, got %d\n", sz);
4198
4199     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"tforms", 7);
4200     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4201
4202     /* Transforms value exists */
4203     sz = MAX_PATH;
4204     lstrcpyA(buf, "apple");
4205     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMS, buf, &sz);
4206     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4207     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4208     ok(sz == 0, "Expected 0, got %d\n", sz);
4209
4210     res = RegSetValueExA(propkey, "Transforms", 0, REG_DWORD,
4211                          (const BYTE *)&val, sizeof(DWORD));
4212     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4213
4214     /* Transforms type is REG_DWORD */
4215     sz = MAX_PATH;
4216     lstrcpyA(buf, "apple");
4217     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMS, buf, &sz);
4218     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4219     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4220     ok(sz == 0, "Expected 0, got %d\n", sz);
4221
4222     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"tforms", 7);
4223     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4224
4225     /* Transforms value exists */
4226     sz = MAX_PATH;
4227     lstrcpyA(buf, "apple");
4228     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMS, buf, &sz);
4229     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4230     ok(!lstrcmpA(buf, "tforms"), "Expected \"tforms\", got \"%s\"\n", buf);
4231     ok(sz == 6, "Expected 6, got %d\n", sz);
4232
4233     res = RegSetValueExA(prodkey, "Transforms", 0, REG_DWORD,
4234                          (const BYTE *)&val, sizeof(DWORD));
4235     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4236
4237     /* Transforms type is REG_DWORD */
4238     sz = MAX_PATH;
4239     lstrcpyA(buf, "apple");
4240     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMS, buf, &sz);
4241     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4242     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4243     ok(sz == 2, "Expected 2, got %d\n", sz);
4244
4245     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
4246     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4247
4248     /* Language value exists */
4249     sz = MAX_PATH;
4250     lstrcpyA(buf, "apple");
4251     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGE, buf, &sz);
4252     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4253     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4254     ok(sz == 0, "Expected 0, got %d\n", sz);
4255
4256     res = RegSetValueExA(propkey, "Language", 0, REG_DWORD,
4257                          (const BYTE *)&val, sizeof(DWORD));
4258     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4259
4260     /* Language type is REG_DWORD */
4261     sz = MAX_PATH;
4262     lstrcpyA(buf, "apple");
4263     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGE, buf, &sz);
4264     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4265     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4266     ok(sz == 0, "Expected 0, got %d\n", sz);
4267
4268     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
4269     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4270
4271     /* Language value exists */
4272     sz = MAX_PATH;
4273     lstrcpyA(buf, "apple");
4274     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGE, buf, &sz);
4275     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4276     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
4277     ok(sz == 4, "Expected 4, got %d\n", sz);
4278
4279     res = RegSetValueExA(prodkey, "Language", 0, REG_DWORD,
4280                          (const BYTE *)&val, sizeof(DWORD));
4281     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4282
4283     /* Language type is REG_DWORD */
4284     sz = MAX_PATH;
4285     lstrcpyA(buf, "apple");
4286     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGE, buf, &sz);
4287     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4288     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4289     ok(sz == 2, "Expected 2, got %d\n", sz);
4290
4291     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
4292     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4293
4294     /* ProductName value exists */
4295     sz = MAX_PATH;
4296     lstrcpyA(buf, "apple");
4297     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAME, buf, &sz);
4298     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4299     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4300     ok(sz == 0, "Expected 0, got %d\n", sz);
4301
4302     res = RegSetValueExA(propkey, "ProductName", 0, REG_DWORD,
4303                          (const BYTE *)&val, sizeof(DWORD));
4304     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4305
4306     /* ProductName type is REG_DWORD */
4307     sz = MAX_PATH;
4308     lstrcpyA(buf, "apple");
4309     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAME, buf, &sz);
4310     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4311     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4312     ok(sz == 0, "Expected 0, got %d\n", sz);
4313
4314     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
4315     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4316
4317     /* ProductName value exists */
4318     sz = MAX_PATH;
4319     lstrcpyA(buf, "apple");
4320     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAME, buf, &sz);
4321     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4322     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
4323     ok(sz == 4, "Expected 4, got %d\n", sz);
4324
4325     res = RegSetValueExA(prodkey, "ProductName", 0, REG_DWORD,
4326                          (const BYTE *)&val, sizeof(DWORD));
4327     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4328
4329     /* ProductName type is REG_DWORD */
4330     sz = MAX_PATH;
4331     lstrcpyA(buf, "apple");
4332     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAME, buf, &sz);
4333     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4334     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4335     ok(sz == 2, "Expected 2, got %d\n", sz);
4336
4337     res = RegSetValueExA(propkey, "Assignment", 0, REG_SZ, (LPBYTE)"at", 3);
4338     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4339
4340     /* Assignment value exists */
4341     sz = MAX_PATH;
4342     lstrcpyA(buf, "apple");
4343     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPE, buf, &sz);
4344     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4345     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4346     ok(sz == 0, "Expected 0, got %d\n", sz);
4347
4348     res = RegSetValueExA(propkey, "Assignment", 0, REG_DWORD,
4349                          (const BYTE *)&val, sizeof(DWORD));
4350     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4351
4352     /* Assignment type is REG_DWORD */
4353     sz = MAX_PATH;
4354     lstrcpyA(buf, "apple");
4355     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPE, buf, &sz);
4356     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4357     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4358     ok(sz == 0, "Expected 0, got %d\n", sz);
4359
4360     res = RegSetValueExA(prodkey, "Assignment", 0, REG_SZ, (LPBYTE)"at", 3);
4361     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4362
4363     /* Assignment value exists */
4364     sz = MAX_PATH;
4365     lstrcpyA(buf, "apple");
4366     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPE, buf, &sz);
4367     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4368     ok(!lstrcmpA(buf, "at"), "Expected \"at\", got \"%s\"\n", buf);
4369     ok(sz == 2, "Expected 2, got %d\n", sz);
4370
4371     res = RegSetValueExA(prodkey, "Assignment", 0, REG_DWORD,
4372                          (const BYTE *)&val, sizeof(DWORD));
4373     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4374
4375     /* Assignment type is REG_DWORD */
4376     sz = MAX_PATH;
4377     lstrcpyA(buf, "apple");
4378     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPE, buf, &sz);
4379     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4380     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4381     ok(sz == 2, "Expected 2, got %d\n", sz);
4382
4383     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
4384     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4385
4386     /* PackageCode value exists */
4387     sz = MAX_PATH;
4388     lstrcpyA(buf, "apple");
4389     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODE, buf, &sz);
4390     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4391     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4392     ok(sz == 0, "Expected 0, got %d\n", sz);
4393
4394     res = RegSetValueExA(propkey, "PackageCode", 0, REG_DWORD,
4395                          (const BYTE *)&val, sizeof(DWORD));
4396     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4397
4398     /* PackageCode type is REG_DWORD */
4399     sz = MAX_PATH;
4400     lstrcpyA(buf, "apple");
4401     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODE, buf, &sz);
4402     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4403     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4404     ok(sz == 0, "Expected 0, got %d\n", sz);
4405
4406     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
4407     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4408
4409     /* PackageCode value exists */
4410     sz = MAX_PATH;
4411     lstrcpyA(buf, "apple");
4412     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODE, buf, &sz);
4413     ok(r == ERROR_BAD_CONFIGURATION,
4414        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
4415     ok(!lstrcmpA(buf, "code"), "Expected \"code\", got \"%s\"\n", buf);
4416     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4417
4418     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_DWORD,
4419                          (const BYTE *)&val, sizeof(DWORD));
4420     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4421
4422     /* PackageCode type is REG_DWORD */
4423     sz = MAX_PATH;
4424     lstrcpyA(buf, "apple");
4425     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODE, buf, &sz);
4426     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4427     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4428     ok(sz == 2, "Expected 2, got %d\n", sz);
4429
4430     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)pack_squashed, 33);
4431     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4432
4433     /* PackageCode value exists */
4434     sz = MAX_PATH;
4435     lstrcpyA(buf, "apple");
4436     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODE, buf, &sz);
4437     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4438     ok(!lstrcmpA(buf, packcode), "Expected \"%s\", got \"%s\"\n", packcode, buf);
4439     ok(sz == 38, "Expected 38, got %d\n", sz);
4440
4441     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
4442     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4443
4444     /* Version value exists */
4445     sz = MAX_PATH;
4446     lstrcpyA(buf, "apple");
4447     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSION, buf, &sz);
4448     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4449     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4450     ok(sz == 0, "Expected 0, got %d\n", sz);
4451
4452     res = RegSetValueExA(propkey, "Version", 0, REG_DWORD,
4453                          (const BYTE *)&val, sizeof(DWORD));
4454     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4455
4456     /* Version type is REG_DWORD */
4457     sz = MAX_PATH;
4458     lstrcpyA(buf, "apple");
4459     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSION, buf, &sz);
4460     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4461     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4462     ok(sz == 0, "Expected 0, got %d\n", sz);
4463
4464     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
4465     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4466
4467     /* Version value exists */
4468     sz = MAX_PATH;
4469     lstrcpyA(buf, "apple");
4470     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSION, buf, &sz);
4471     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4472     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
4473     ok(sz == 3, "Expected 3, got %d\n", sz);
4474
4475     res = RegSetValueExA(prodkey, "Version", 0, REG_DWORD,
4476                          (const BYTE *)&val, sizeof(DWORD));
4477     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4478
4479     /* Version type is REG_DWORD */
4480     sz = MAX_PATH;
4481     lstrcpyA(buf, "apple");
4482     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSION, buf, &sz);
4483     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4484     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4485     ok(sz == 2, "Expected 2, got %d\n", sz);
4486
4487     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"ico", 4);
4488     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4489
4490     /* ProductIcon value exists */
4491     sz = MAX_PATH;
4492     lstrcpyA(buf, "apple");
4493     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICON, buf, &sz);
4494     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4495     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4496     ok(sz == 0, "Expected 0, got %d\n", sz);
4497
4498     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_DWORD,
4499                          (const BYTE *)&val, sizeof(DWORD));
4500     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4501
4502     /* ProductIcon type is REG_DWORD */
4503     sz = MAX_PATH;
4504     lstrcpyA(buf, "apple");
4505     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICON, buf, &sz);
4506     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4507     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4508     ok(sz == 0, "Expected 0, got %d\n", sz);
4509
4510     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"ico", 4);
4511     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4512
4513     /* ProductIcon value exists */
4514     sz = MAX_PATH;
4515     lstrcpyA(buf, "apple");
4516     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICON, buf, &sz);
4517     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4518     ok(!lstrcmpA(buf, "ico"), "Expected \"ico\", got \"%s\"\n", buf);
4519     ok(sz == 3, "Expected 3, got %d\n", sz);
4520
4521     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_DWORD,
4522                          (const BYTE *)&val, sizeof(DWORD));
4523     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4524
4525     /* ProductIcon type is REG_DWORD */
4526     sz = MAX_PATH;
4527     lstrcpyA(buf, "apple");
4528     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICON, buf, &sz);
4529     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4530     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4531     ok(sz == 2, "Expected 2, got %d\n", sz);
4532
4533     /* SourceList key does not exist */
4534     sz = MAX_PATH;
4535     lstrcpyA(buf, "apple");
4536     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAME, buf, &sz);
4537     ok(r == ERROR_UNKNOWN_PRODUCT,
4538        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4539     ok(!lstrcmpA(buf, "apple"),
4540        "Expected buf to be unchanged, got \"%s\"\n", buf);
4541     ok(sz == MAX_PATH, "Expected sz to be unchanged, got %d\n", sz);
4542
4543     res = RegCreateKeyExA(prodkey, "SourceList", 0, NULL, 0, access, NULL, &source, NULL);
4544     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4545
4546     /* SourceList key exists, but PackageName val does not exist */
4547     sz = MAX_PATH;
4548     lstrcpyA(buf, "apple");
4549     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAME, buf, &sz);
4550     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4551     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4552     ok(sz == 0, "Expected 0, got %d\n", sz);
4553
4554     res = RegSetValueExA(source, "PackageName", 0, REG_SZ, (LPBYTE)"packname", 9);
4555     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4556
4557     /* PackageName val exists */
4558     sz = MAX_PATH;
4559     lstrcpyA(buf, "apple");
4560     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAME, buf, &sz);
4561     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4562     ok(!lstrcmpA(buf, "packname"), "Expected \"packname\", got \"%s\"\n", buf);
4563     ok(sz == 8, "Expected 8, got %d\n", sz);
4564
4565     res = RegSetValueExA(source, "PackageName", 0, REG_DWORD,
4566                          (const BYTE *)&val, sizeof(DWORD));
4567     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4568
4569     /* PackageName type is REG_DWORD */
4570     sz = MAX_PATH;
4571     lstrcpyA(buf, "apple");
4572     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAME, buf, &sz);
4573     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4574     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4575     ok(sz == 2, "Expected 2, got %d\n", sz);
4576
4577     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
4578     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4579
4580     /* Authorized value exists */
4581     sz = MAX_PATH;
4582     lstrcpyA(buf, "apple");
4583     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APP, buf, &sz);
4584     if (r != ERROR_UNKNOWN_PROPERTY)
4585     {
4586         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4587         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4588         ok(sz == 0, "Expected 0, got %d\n", sz);
4589     }
4590
4591     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_DWORD,
4592                          (const BYTE *)&val, sizeof(DWORD));
4593     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4594
4595     /* AuthorizedLUAApp type is REG_DWORD */
4596     sz = MAX_PATH;
4597     lstrcpyA(buf, "apple");
4598     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APP, buf, &sz);
4599     if (r != ERROR_UNKNOWN_PROPERTY)
4600     {
4601         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4602         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4603         ok(sz == 0, "Expected 0, got %d\n", sz);
4604     }
4605
4606     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
4607     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4608
4609     /* Authorized value exists */
4610     sz = MAX_PATH;
4611     lstrcpyA(buf, "apple");
4612     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APP, buf, &sz);
4613     if (r != ERROR_UNKNOWN_PROPERTY)
4614     {
4615         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4616         ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
4617         ok(sz == 4, "Expected 4, got %d\n", sz);
4618     }
4619
4620     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_DWORD,
4621                          (const BYTE *)&val, sizeof(DWORD));
4622     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4623
4624     /* AuthorizedLUAApp type is REG_DWORD */
4625     sz = MAX_PATH;
4626     lstrcpyA(buf, "apple");
4627     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APP, buf, &sz);
4628     if (r != ERROR_UNKNOWN_PROPERTY)
4629     {
4630         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4631         ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
4632         ok(sz == 2, "Expected 2, got %d\n", sz);
4633     }
4634
4635     RegDeleteValueA(propkey, "HelpLink");
4636     RegDeleteValueA(propkey, "DisplayName");
4637     RegDeleteValueA(propkey, "DisplayVersion");
4638     RegDeleteValueA(propkey, "HelpTelephone");
4639     RegDeleteValueA(propkey, "InstallLocation");
4640     RegDeleteValueA(propkey, "InstallSource");
4641     RegDeleteValueA(propkey, "InstallDate");
4642     RegDeleteValueA(propkey, "Publisher");
4643     RegDeleteValueA(propkey, "LocalPackage");
4644     RegDeleteValueA(propkey, "UrlInfoAbout");
4645     RegDeleteValueA(propkey, "UrlUpdateInfo");
4646     RegDeleteValueA(propkey, "VersionMinor");
4647     RegDeleteValueA(propkey, "VersionMajor");
4648     RegDeleteValueA(propkey, "ProductID");
4649     RegDeleteValueA(propkey, "RegCompany");
4650     RegDeleteValueA(propkey, "RegOwner");
4651     RegDeleteValueA(propkey, "InstanceType");
4652     RegDeleteValueA(propkey, "Transforms");
4653     RegDeleteValueA(propkey, "Language");
4654     RegDeleteValueA(propkey, "ProductName");
4655     RegDeleteValueA(propkey, "Assignment");
4656     RegDeleteValueA(propkey, "PackageCode");
4657     RegDeleteValueA(propkey, "Version");
4658     RegDeleteValueA(propkey, "ProductIcon");
4659     RegDeleteValueA(propkey, "AuthorizedLUAApp");
4660     delete_key(propkey, "", access & KEY_WOW64_64KEY);
4661     delete_key(localkey, "", access & KEY_WOW64_64KEY);
4662     RegDeleteValueA(prodkey, "InstanceType");
4663     RegDeleteValueA(prodkey, "Transforms");
4664     RegDeleteValueA(prodkey, "Language");
4665     RegDeleteValueA(prodkey, "ProductName");
4666     RegDeleteValueA(prodkey, "Assignment");
4667     RegDeleteValueA(prodkey, "PackageCode");
4668     RegDeleteValueA(prodkey, "Version");
4669     RegDeleteValueA(prodkey, "ProductIcon");
4670     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
4671     RegDeleteValueA(source, "PackageName");
4672     delete_key(source, "", access & KEY_WOW64_64KEY);
4673     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4674     RegCloseKey(propkey);
4675     RegCloseKey(localkey);
4676     RegCloseKey(source);
4677     RegCloseKey(prodkey);
4678     LocalFree(usersid);
4679 }
4680
4681 static void test_MsiGetProductInfoEx(void)
4682 {
4683     UINT r;
4684     LONG res;
4685     HKEY propkey, userkey;
4686     HKEY prodkey, localkey;
4687     CHAR prodcode[MAX_PATH];
4688     CHAR prod_squashed[MAX_PATH];
4689     CHAR packcode[MAX_PATH];
4690     CHAR pack_squashed[MAX_PATH];
4691     CHAR buf[MAX_PATH];
4692     CHAR keypath[MAX_PATH];
4693     LPSTR usersid;
4694     DWORD sz;
4695     REGSAM access = KEY_ALL_ACCESS;
4696
4697     if (!pMsiGetProductInfoExA)
4698     {
4699         win_skip("MsiGetProductInfoExA is not available\n");
4700         return;
4701     }
4702
4703     create_test_guid(prodcode, prod_squashed);
4704     create_test_guid(packcode, pack_squashed);
4705     usersid = get_user_sid();
4706
4707     if (is_wow64)
4708         access |= KEY_WOW64_64KEY;
4709
4710     /* NULL szProductCode */
4711     sz = MAX_PATH;
4712     lstrcpyA(buf, "apple");
4713     r = pMsiGetProductInfoExA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
4714                               INSTALLPROPERTY_PRODUCTSTATE, buf, &sz);
4715     ok(r == ERROR_INVALID_PARAMETER,
4716        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4717     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4718     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4719
4720     /* empty szProductCode */
4721     sz = MAX_PATH;
4722     lstrcpyA(buf, "apple");
4723     r = pMsiGetProductInfoExA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
4724                               INSTALLPROPERTY_PRODUCTSTATE, buf, &sz);
4725     ok(r == ERROR_INVALID_PARAMETER,
4726        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4727     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4728     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4729
4730     /* garbage szProductCode */
4731     sz = MAX_PATH;
4732     lstrcpyA(buf, "apple");
4733     r = pMsiGetProductInfoExA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
4734                               INSTALLPROPERTY_PRODUCTSTATE, buf, &sz);
4735     ok(r == ERROR_INVALID_PARAMETER,
4736        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4737     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4738     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4739
4740     /* guid without brackets */
4741     sz = MAX_PATH;
4742     lstrcpyA(buf, "apple");
4743     r = pMsiGetProductInfoExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", usersid,
4744                               MSIINSTALLCONTEXT_USERUNMANAGED,
4745                               INSTALLPROPERTY_PRODUCTSTATE, buf, &sz);
4746     ok(r == ERROR_INVALID_PARAMETER,
4747        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4748     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4749     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4750
4751     /* guid with brackets */
4752     sz = MAX_PATH;
4753     lstrcpyA(buf, "apple");
4754     r = pMsiGetProductInfoExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", usersid,
4755                               MSIINSTALLCONTEXT_USERUNMANAGED,
4756                               INSTALLPROPERTY_PRODUCTSTATE, buf, &sz);
4757     ok(r == ERROR_UNKNOWN_PRODUCT,
4758        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4759     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4760     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4761
4762     /* szValue is non-NULL while pcchValue is NULL */
4763     lstrcpyA(buf, "apple");
4764     r = pMsiGetProductInfoExA(prodcode, usersid,
4765                               MSIINSTALLCONTEXT_USERUNMANAGED,
4766                               INSTALLPROPERTY_PRODUCTSTATE, buf, NULL);
4767     ok(r == ERROR_INVALID_PARAMETER,
4768        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4769     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4770
4771     /* dwContext is out of range */
4772     sz = MAX_PATH;
4773     lstrcpyA(buf, "apple");
4774     r = pMsiGetProductInfoExA(prodcode, usersid, 42,
4775                               INSTALLPROPERTY_PRODUCTSTATE, buf, &sz);
4776     ok(r == ERROR_INVALID_PARAMETER,
4777        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4778     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4779     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4780
4781     /* szProperty is NULL */
4782     sz = MAX_PATH;
4783     lstrcpyA(buf, "apple");
4784     r = pMsiGetProductInfoExA(prodcode, usersid,
4785                               MSIINSTALLCONTEXT_USERUNMANAGED,
4786                               NULL, buf, &sz);
4787     ok(r == ERROR_INVALID_PARAMETER,
4788        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4789     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4790     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4791
4792     /* szProperty is empty */
4793     sz = MAX_PATH;
4794     lstrcpyA(buf, "apple");
4795     r = pMsiGetProductInfoExA(prodcode, usersid,
4796                               MSIINSTALLCONTEXT_USERUNMANAGED,
4797                               "", buf, &sz);
4798     ok(r == ERROR_INVALID_PARAMETER,
4799        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4800     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4801     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4802
4803     /* szProperty is not a valid property */
4804     sz = MAX_PATH;
4805     lstrcpyA(buf, "apple");
4806     r = pMsiGetProductInfoExA(prodcode, usersid,
4807                               MSIINSTALLCONTEXT_USERUNMANAGED,
4808                               "notvalid", buf, &sz);
4809     ok(r == ERROR_UNKNOWN_PRODUCT,
4810        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4811     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4812     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4813
4814     /* same length as guid, but random */
4815     sz = MAX_PATH;
4816     lstrcpyA(buf, "apple");
4817     r = pMsiGetProductInfoExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", usersid,
4818                               MSIINSTALLCONTEXT_USERUNMANAGED,
4819                               INSTALLPROPERTY_PRODUCTSTATE, buf, &sz);
4820     ok(r == ERROR_INVALID_PARAMETER,
4821        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4822     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4823     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4824
4825     /* MSIINSTALLCONTEXT_USERUNMANAGED */
4826
4827     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
4828     lstrcatA(keypath, usersid);
4829     lstrcatA(keypath, "\\Products\\");
4830     lstrcatA(keypath, prod_squashed);
4831
4832     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
4833     if (res == ERROR_ACCESS_DENIED)
4834     {
4835         skip("Not enough rights to perform tests\n");
4836         LocalFree(usersid);
4837         return;
4838     }
4839     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4840
4841     /* local user product key exists */
4842     sz = MAX_PATH;
4843     lstrcpyA(buf, "apple");
4844     r = pMsiGetProductInfoExA(prodcode, usersid,
4845                               MSIINSTALLCONTEXT_USERUNMANAGED,
4846                               INSTALLPROPERTY_PRODUCTSTATE, buf, &sz);
4847     ok(r == ERROR_UNKNOWN_PRODUCT,
4848        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4849     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4850     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4851
4852     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
4853     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4854
4855     /* InstallProperties key exists */
4856     sz = MAX_PATH;
4857     lstrcpyA(buf, "apple");
4858     r = pMsiGetProductInfoExA(prodcode, usersid,
4859                               MSIINSTALLCONTEXT_USERUNMANAGED,
4860                               INSTALLPROPERTY_PRODUCTSTATE, buf, &sz);
4861     ok(r == ERROR_UNKNOWN_PRODUCT,
4862        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4863     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4864     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4865
4866     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
4867     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4868
4869     /* LocalPackage value exists */
4870     sz = MAX_PATH;
4871     lstrcpyA(buf, "apple");
4872     r = pMsiGetProductInfoExA(prodcode, usersid,
4873                               MSIINSTALLCONTEXT_USERUNMANAGED,
4874                               INSTALLPROPERTY_PRODUCTSTATE, buf, &sz);
4875     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4876     ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
4877     ok(sz == 1, "Expected 1, got %d\n", sz);
4878
4879     RegDeleteValueA(propkey, "LocalPackage");
4880
4881     /* LocalPackage value must exist */
4882     sz = MAX_PATH;
4883     lstrcpyA(buf, "apple");
4884     r = pMsiGetProductInfoExA(prodcode, usersid,
4885                               MSIINSTALLCONTEXT_USERUNMANAGED,
4886                               INSTALLPROPERTY_HELPLINK, buf, &sz);
4887     ok(r == ERROR_UNKNOWN_PRODUCT,
4888        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4889     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4890     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4891
4892     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
4893     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4894
4895     /* LocalPackage exists, but HelpLink does not exist */
4896     sz = MAX_PATH;
4897     lstrcpyA(buf, "apple");
4898     r = pMsiGetProductInfoExA(prodcode, usersid,
4899                               MSIINSTALLCONTEXT_USERUNMANAGED,
4900                               INSTALLPROPERTY_HELPLINK, buf, &sz);
4901     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4902     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4903     ok(sz == 0, "Expected 0, got %d\n", sz);
4904
4905     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
4906     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4907
4908     /* HelpLink value exists */
4909     sz = MAX_PATH;
4910     lstrcpyA(buf, "apple");
4911     r = pMsiGetProductInfoExA(prodcode, usersid,
4912                               MSIINSTALLCONTEXT_USERUNMANAGED,
4913                               INSTALLPROPERTY_HELPLINK, buf, &sz);
4914     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4915     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
4916     ok(sz == 4, "Expected 4, got %d\n", sz);
4917
4918     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
4919     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4920
4921     /* HelpTelephone value exists */
4922     sz = MAX_PATH;
4923     lstrcpyA(buf, "apple");
4924     r = pMsiGetProductInfoExA(prodcode, usersid,
4925                               MSIINSTALLCONTEXT_USERUNMANAGED,
4926                               INSTALLPROPERTY_HELPTELEPHONE, buf, &sz);
4927     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4928     ok(!lstrcmpA(buf, "phone"), "Expected \"phone\", got \"%s\"\n", buf);
4929     ok(sz == 5, "Expected 5, got %d\n", sz);
4930
4931     /* szValue and pcchValue are NULL */
4932     r = pMsiGetProductInfoExA(prodcode, usersid,
4933                               MSIINSTALLCONTEXT_USERUNMANAGED,
4934                               INSTALLPROPERTY_HELPTELEPHONE, NULL, NULL);
4935     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4936
4937     /* pcchValue is exactly 5 */
4938     sz = 5;
4939     lstrcpyA(buf, "apple");
4940     r = pMsiGetProductInfoExA(prodcode, usersid,
4941                               MSIINSTALLCONTEXT_USERUNMANAGED,
4942                               INSTALLPROPERTY_HELPTELEPHONE, buf, &sz);
4943     ok(r == ERROR_MORE_DATA,
4944        "Expected ERROR_MORE_DATA, got %d\n", r);
4945     ok(sz == 10, "Expected 10, got %d\n", sz);
4946
4947     /* szValue is NULL, pcchValue is exactly 5 */
4948     sz = 5;
4949     r = pMsiGetProductInfoExA(prodcode, usersid,
4950                               MSIINSTALLCONTEXT_USERUNMANAGED,
4951                               INSTALLPROPERTY_HELPTELEPHONE, NULL, &sz);
4952     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4953     ok(sz == 10, "Expected 10, got %d\n", sz);
4954
4955     /* szValue is NULL, pcchValue is MAX_PATH */
4956     sz = MAX_PATH;
4957     r = pMsiGetProductInfoExA(prodcode, usersid,
4958                               MSIINSTALLCONTEXT_USERUNMANAGED,
4959                               INSTALLPROPERTY_HELPTELEPHONE, NULL, &sz);
4960     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4961     ok(sz == 10, "Expected 10, got %d\n", sz);
4962
4963     /* pcchValue is exactly 0 */
4964     sz = 0;
4965     lstrcpyA(buf, "apple");
4966     r = pMsiGetProductInfoExA(prodcode, usersid,
4967                               MSIINSTALLCONTEXT_USERUNMANAGED,
4968                               INSTALLPROPERTY_HELPTELEPHONE, buf, &sz);
4969     ok(r == ERROR_MORE_DATA,
4970        "Expected ERROR_MORE_DATA, got %d\n", r);
4971     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4972     ok(sz == 10, "Expected 10, got %d\n", sz);
4973
4974     res = RegSetValueExA(propkey, "notvalid", 0, REG_SZ, (LPBYTE)"invalid", 8);
4975     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4976
4977     /* szProperty is not a valid property */
4978     sz = MAX_PATH;
4979     lstrcpyA(buf, "apple");
4980     r = pMsiGetProductInfoExA(prodcode, usersid,
4981                               MSIINSTALLCONTEXT_USERUNMANAGED,
4982                               "notvalid", buf, &sz);
4983     ok(r == ERROR_UNKNOWN_PROPERTY,
4984        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4985     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4986     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4987
4988     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
4989     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4990
4991     /* InstallDate value exists */
4992     sz = MAX_PATH;
4993     lstrcpyA(buf, "apple");
4994     r = pMsiGetProductInfoExA(prodcode, usersid,
4995                               MSIINSTALLCONTEXT_USERUNMANAGED,
4996                               INSTALLPROPERTY_INSTALLDATE, buf, &sz);
4997     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4998     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
4999     ok(sz == 4, "Expected 4, got %d\n", sz);
5000
5001     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
5002     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5003
5004     /* DisplayName value exists */
5005     sz = MAX_PATH;
5006     lstrcpyA(buf, "apple");
5007     r = pMsiGetProductInfoExA(prodcode, usersid,
5008                               MSIINSTALLCONTEXT_USERUNMANAGED,
5009                               INSTALLPROPERTY_INSTALLEDPRODUCTNAME, buf, &sz);
5010     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5011     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
5012     ok(sz == 4, "Expected 4, got %d\n", sz);
5013
5014     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
5015     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5016
5017     /* InstallLocation value exists */
5018     sz = MAX_PATH;
5019     lstrcpyA(buf, "apple");
5020     r = pMsiGetProductInfoExA(prodcode, usersid,
5021                               MSIINSTALLCONTEXT_USERUNMANAGED,
5022                               INSTALLPROPERTY_INSTALLLOCATION, buf, &sz);
5023     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5024     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
5025     ok(sz == 3, "Expected 3, got %d\n", sz);
5026
5027     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
5028     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5029
5030     /* InstallSource value exists */
5031     sz = MAX_PATH;
5032     lstrcpyA(buf, "apple");
5033     r = pMsiGetProductInfoExA(prodcode, usersid,
5034                               MSIINSTALLCONTEXT_USERUNMANAGED,
5035                               INSTALLPROPERTY_INSTALLSOURCE, buf, &sz);
5036     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5037     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
5038     ok(sz == 6, "Expected 6, got %d\n", sz);
5039
5040     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
5041     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5042
5043     /* LocalPackage value exists */
5044     sz = MAX_PATH;
5045     lstrcpyA(buf, "apple");
5046     r = pMsiGetProductInfoExA(prodcode, usersid,
5047                               MSIINSTALLCONTEXT_USERUNMANAGED,
5048                               INSTALLPROPERTY_LOCALPACKAGE, buf, &sz);
5049     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5050     ok(!lstrcmpA(buf, "local"), "Expected \"local\", got \"%s\"\n", buf);
5051     ok(sz == 5, "Expected 5, got %d\n", sz);
5052
5053     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
5054     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5055
5056     /* Publisher value exists */
5057     sz = MAX_PATH;
5058     lstrcpyA(buf, "apple");
5059     r = pMsiGetProductInfoExA(prodcode, usersid,
5060                               MSIINSTALLCONTEXT_USERUNMANAGED,
5061                               INSTALLPROPERTY_PUBLISHER, buf, &sz);
5062     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5063     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
5064     ok(sz == 3, "Expected 3, got %d\n", sz);
5065
5066     res = RegSetValueExA(propkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
5067     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5068
5069     /* URLInfoAbout value exists */
5070     sz = MAX_PATH;
5071     lstrcpyA(buf, "apple");
5072     r = pMsiGetProductInfoExA(prodcode, usersid,
5073                               MSIINSTALLCONTEXT_USERUNMANAGED,
5074                               INSTALLPROPERTY_URLINFOABOUT, buf, &sz);
5075     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5076     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
5077     ok(sz == 5, "Expected 5, got %d\n", sz);
5078
5079     res = RegSetValueExA(propkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
5080     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5081
5082     /* URLUpdateInfo value exists */
5083     sz = MAX_PATH;
5084     lstrcpyA(buf, "apple");
5085     r = pMsiGetProductInfoExA(prodcode, usersid,
5086                               MSIINSTALLCONTEXT_USERUNMANAGED,
5087                               INSTALLPROPERTY_URLUPDATEINFO, buf, &sz);
5088     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5089     ok(!lstrcmpA(buf, "update"), "Expected \"update\", got \"%s\"\n", buf);
5090     ok(sz == 6, "Expected 6, got %d\n", sz);
5091
5092     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
5093     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5094
5095     /* VersionMinor value exists */
5096     sz = MAX_PATH;
5097     lstrcpyA(buf, "apple");
5098     r = pMsiGetProductInfoExA(prodcode, usersid,
5099                               MSIINSTALLCONTEXT_USERUNMANAGED,
5100                               INSTALLPROPERTY_VERSIONMINOR, buf, &sz);
5101     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5102     ok(!lstrcmpA(buf, "2"), "Expected \"2\", got \"%s\"\n", buf);
5103     ok(sz == 1, "Expected 1, got %d\n", sz);
5104
5105     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
5106     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5107
5108     /* VersionMajor value exists */
5109     sz = MAX_PATH;
5110     lstrcpyA(buf, "apple");
5111     r = pMsiGetProductInfoExA(prodcode, usersid,
5112                               MSIINSTALLCONTEXT_USERUNMANAGED,
5113                               INSTALLPROPERTY_VERSIONMAJOR, buf, &sz);
5114     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5115     ok(!lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
5116     ok(sz == 1, "Expected 1, got %d\n", sz);
5117
5118     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
5119     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5120
5121     /* DisplayVersion value exists */
5122     sz = MAX_PATH;
5123     lstrcpyA(buf, "apple");
5124     r = pMsiGetProductInfoExA(prodcode, usersid,
5125                               MSIINSTALLCONTEXT_USERUNMANAGED,
5126                               INSTALLPROPERTY_VERSIONSTRING, buf, &sz);
5127     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5128     ok(!lstrcmpA(buf, "3.2.1"), "Expected \"3.2.1\", got \"%s\"\n", buf);
5129     ok(sz == 5, "Expected 5, got %d\n", sz);
5130
5131     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
5132     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5133
5134     /* ProductID value exists */
5135     sz = MAX_PATH;
5136     lstrcpyA(buf, "apple");
5137     r = pMsiGetProductInfoExA(prodcode, usersid,
5138                               MSIINSTALLCONTEXT_USERUNMANAGED,
5139                               INSTALLPROPERTY_PRODUCTID, buf, &sz);
5140     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5141     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
5142     ok(sz == 2, "Expected 2, got %d\n", sz);
5143
5144     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
5145     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5146
5147     /* RegCompany value exists */
5148     sz = MAX_PATH;
5149     lstrcpyA(buf, "apple");
5150     r = pMsiGetProductInfoExA(prodcode, usersid,
5151                               MSIINSTALLCONTEXT_USERUNMANAGED,
5152                               INSTALLPROPERTY_REGCOMPANY, buf, &sz);
5153     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5154     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
5155     ok(sz == 4, "Expected 4, got %d\n", sz);
5156
5157     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
5158     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5159
5160     /* RegOwner value exists */
5161     sz = MAX_PATH;
5162     lstrcpyA(buf, "apple");
5163     r = pMsiGetProductInfoExA(prodcode, usersid,
5164                               MSIINSTALLCONTEXT_USERUNMANAGED,
5165                               INSTALLPROPERTY_REGOWNER, buf, &sz);
5166     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5167     ok(!lstrcmpA(buf, "owner"), "Expected \"owner\", got \"%s\"\n", buf);
5168     ok(sz == 5, "Expected 5, got %d\n", sz);
5169
5170     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
5171     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5172
5173     /* Transforms value exists */
5174     sz = MAX_PATH;
5175     lstrcpyA(buf, "apple");
5176     r = pMsiGetProductInfoExA(prodcode, usersid,
5177                               MSIINSTALLCONTEXT_USERUNMANAGED,
5178                               INSTALLPROPERTY_TRANSFORMS, buf, &sz);
5179     ok(r == ERROR_UNKNOWN_PRODUCT,
5180        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5181     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5182     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5183
5184     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
5185     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5186
5187     /* Language value exists */
5188     sz = MAX_PATH;
5189     lstrcpyA(buf, "apple");
5190     r = pMsiGetProductInfoExA(prodcode, usersid,
5191                               MSIINSTALLCONTEXT_USERUNMANAGED,
5192                               INSTALLPROPERTY_LANGUAGE, buf, &sz);
5193     ok(r == ERROR_UNKNOWN_PRODUCT,
5194        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5195     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5196     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5197
5198     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
5199     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5200
5201     /* ProductName value exists */
5202     sz = MAX_PATH;
5203     lstrcpyA(buf, "apple");
5204     r = pMsiGetProductInfoExA(prodcode, usersid,
5205                               MSIINSTALLCONTEXT_USERUNMANAGED,
5206                               INSTALLPROPERTY_PRODUCTNAME, buf, &sz);
5207     ok(r == ERROR_UNKNOWN_PRODUCT,
5208        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5209     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5210     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5211
5212     res = RegSetValueExA(propkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
5213     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5214
5215     /* FIXME */
5216
5217     /* AssignmentType value exists */
5218     sz = MAX_PATH;
5219     lstrcpyA(buf, "apple");
5220     r = pMsiGetProductInfoExA(prodcode, usersid,
5221                               MSIINSTALLCONTEXT_USERUNMANAGED,
5222                               INSTALLPROPERTY_ASSIGNMENTTYPE, buf, &sz);
5223     ok(r == ERROR_UNKNOWN_PRODUCT,
5224        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5225     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5226     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5227
5228     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
5229     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5230
5231     /* PackageCode value exists */
5232     sz = MAX_PATH;
5233     lstrcpyA(buf, "apple");
5234     r = pMsiGetProductInfoExA(prodcode, usersid,
5235                               MSIINSTALLCONTEXT_USERUNMANAGED,
5236                               INSTALLPROPERTY_PACKAGECODE, buf, &sz);
5237     ok(r == ERROR_UNKNOWN_PRODUCT,
5238        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5239     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5240     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5241
5242     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
5243     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5244
5245     /* Version value exists */
5246     sz = MAX_PATH;
5247     lstrcpyA(buf, "apple");
5248     r = pMsiGetProductInfoExA(prodcode, usersid,
5249                               MSIINSTALLCONTEXT_USERUNMANAGED,
5250                               INSTALLPROPERTY_VERSION, buf, &sz);
5251     ok(r == ERROR_UNKNOWN_PRODUCT,
5252        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5253     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5254     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5255
5256     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
5257     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5258
5259     /* ProductIcon value exists */
5260     sz = MAX_PATH;
5261     lstrcpyA(buf, "apple");
5262     r = pMsiGetProductInfoExA(prodcode, usersid,
5263                               MSIINSTALLCONTEXT_USERUNMANAGED,
5264                               INSTALLPROPERTY_PRODUCTICON, buf, &sz);
5265     ok(r == ERROR_UNKNOWN_PRODUCT,
5266        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5267     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5268     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5269
5270     res = RegSetValueExA(propkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
5271     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5272
5273     /* PackageName value exists */
5274     sz = MAX_PATH;
5275     lstrcpyA(buf, "apple");
5276     r = pMsiGetProductInfoExA(prodcode, usersid,
5277                               MSIINSTALLCONTEXT_USERUNMANAGED,
5278                               INSTALLPROPERTY_PACKAGENAME, buf, &sz);
5279     ok(r == ERROR_UNKNOWN_PRODUCT,
5280        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5281     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5282     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5283
5284     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
5285     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5286
5287     /* AuthorizedLUAApp value exists */
5288     sz = MAX_PATH;
5289     lstrcpyA(buf, "apple");
5290     r = pMsiGetProductInfoExA(prodcode, usersid,
5291                               MSIINSTALLCONTEXT_USERUNMANAGED,
5292                               INSTALLPROPERTY_AUTHORIZED_LUA_APP, buf, &sz);
5293     ok(r == ERROR_UNKNOWN_PRODUCT,
5294        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5295     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5296     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5297
5298     RegDeleteValueA(propkey, "AuthorizedLUAApp");
5299     RegDeleteValueA(propkey, "PackageName");
5300     RegDeleteValueA(propkey, "ProductIcon");
5301     RegDeleteValueA(propkey, "Version");
5302     RegDeleteValueA(propkey, "PackageCode");
5303     RegDeleteValueA(propkey, "AssignmentType");
5304     RegDeleteValueA(propkey, "ProductName");
5305     RegDeleteValueA(propkey, "Language");
5306     RegDeleteValueA(propkey, "Transforms");
5307     RegDeleteValueA(propkey, "RegOwner");
5308     RegDeleteValueA(propkey, "RegCompany");
5309     RegDeleteValueA(propkey, "ProductID");
5310     RegDeleteValueA(propkey, "DisplayVersion");
5311     RegDeleteValueA(propkey, "VersionMajor");
5312     RegDeleteValueA(propkey, "VersionMinor");
5313     RegDeleteValueA(propkey, "URLUpdateInfo");
5314     RegDeleteValueA(propkey, "URLInfoAbout");
5315     RegDeleteValueA(propkey, "Publisher");
5316     RegDeleteValueA(propkey, "LocalPackage");
5317     RegDeleteValueA(propkey, "InstallSource");
5318     RegDeleteValueA(propkey, "InstallLocation");
5319     RegDeleteValueA(propkey, "DisplayName");
5320     RegDeleteValueA(propkey, "InstallDate");
5321     RegDeleteValueA(propkey, "HelpTelephone");
5322     RegDeleteValueA(propkey, "HelpLink");
5323     RegDeleteValueA(propkey, "LocalPackage");
5324     RegDeleteKeyA(propkey, "");
5325     RegCloseKey(propkey);
5326     RegDeleteKeyA(localkey, "");
5327     RegCloseKey(localkey);
5328
5329     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
5330     lstrcatA(keypath, usersid);
5331     lstrcatA(keypath, "\\Installer\\Products\\");
5332     lstrcatA(keypath, prod_squashed);
5333
5334     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
5335     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5336
5337     /* user product key exists */
5338     sz = MAX_PATH;
5339     lstrcpyA(buf, "apple");
5340     r = pMsiGetProductInfoExA(prodcode, usersid,
5341                               MSIINSTALLCONTEXT_USERUNMANAGED,
5342                               INSTALLPROPERTY_PRODUCTSTATE, buf, &sz);
5343     ok(r == ERROR_UNKNOWN_PRODUCT,
5344        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5345     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5346     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5347
5348     RegDeleteKeyA(userkey, "");
5349     RegCloseKey(userkey);
5350
5351     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
5352     lstrcatA(keypath, prod_squashed);
5353
5354     res = RegCreateKeyExA(HKEY_CURRENT_USER, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
5355     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5356
5357     sz = MAX_PATH;
5358     lstrcpyA(buf, "apple");
5359     r = pMsiGetProductInfoExA(prodcode, usersid,
5360                               MSIINSTALLCONTEXT_USERUNMANAGED,
5361                               INSTALLPROPERTY_PRODUCTSTATE, buf, &sz);
5362     ok(r == ERROR_SUCCESS || broken(r == ERROR_UNKNOWN_PRODUCT), "Expected ERROR_SUCCESS, got %d\n", r);
5363     if (r == ERROR_UNKNOWN_PRODUCT)
5364     {
5365         win_skip("skipping remaining tests for MsiGetProductInfoEx\n");
5366         delete_key(prodkey, "", access);
5367         RegCloseKey(prodkey);
5368         return;
5369     }
5370     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
5371     ok(sz == 1, "Expected 1, got %d\n", sz);
5372
5373     res = RegSetValueExA(prodkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
5374     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5375
5376     /* HelpLink value exists */
5377     sz = MAX_PATH;
5378     lstrcpyA(buf, "apple");
5379     r = pMsiGetProductInfoExA(prodcode, usersid,
5380                               MSIINSTALLCONTEXT_USERUNMANAGED,
5381                               INSTALLPROPERTY_HELPLINK, buf, &sz);
5382     ok(r == ERROR_UNKNOWN_PROPERTY,
5383        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5384     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5385     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5386
5387     res = RegSetValueExA(prodkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
5388     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5389
5390     /* HelpTelephone value exists */
5391     sz = MAX_PATH;
5392     lstrcpyA(buf, "apple");
5393     r = pMsiGetProductInfoExA(prodcode, usersid,
5394                               MSIINSTALLCONTEXT_USERUNMANAGED,
5395                               INSTALLPROPERTY_HELPTELEPHONE, buf, &sz);
5396     ok(r == ERROR_UNKNOWN_PROPERTY,
5397        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5398     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5399     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5400
5401     res = RegSetValueExA(prodkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
5402     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5403
5404     /* InstallDate value exists */
5405     sz = MAX_PATH;
5406     lstrcpyA(buf, "apple");
5407     r = pMsiGetProductInfoExA(prodcode, usersid,
5408                               MSIINSTALLCONTEXT_USERUNMANAGED,
5409                               INSTALLPROPERTY_INSTALLDATE, buf, &sz);
5410     ok(r == ERROR_UNKNOWN_PROPERTY,
5411        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5412     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5413     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5414
5415     res = RegSetValueExA(prodkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
5416     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5417
5418     /* DisplayName value exists */
5419     sz = MAX_PATH;
5420     lstrcpyA(buf, "apple");
5421     r = pMsiGetProductInfoExA(prodcode, usersid,
5422                               MSIINSTALLCONTEXT_USERUNMANAGED,
5423                               INSTALLPROPERTY_INSTALLEDPRODUCTNAME, buf, &sz);
5424     ok(r == ERROR_UNKNOWN_PROPERTY,
5425        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5426     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5427     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5428
5429     res = RegSetValueExA(prodkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
5430     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5431
5432     /* InstallLocation value exists */
5433     sz = MAX_PATH;
5434     lstrcpyA(buf, "apple");
5435     r = pMsiGetProductInfoExA(prodcode, usersid,
5436                               MSIINSTALLCONTEXT_USERUNMANAGED,
5437                               INSTALLPROPERTY_INSTALLLOCATION, buf, &sz);
5438     ok(r == ERROR_UNKNOWN_PROPERTY,
5439        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5440     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5441     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5442
5443     res = RegSetValueExA(prodkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
5444     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5445
5446     /* InstallSource value exists */
5447     sz = MAX_PATH;
5448     lstrcpyA(buf, "apple");
5449     r = pMsiGetProductInfoExA(prodcode, usersid,
5450                               MSIINSTALLCONTEXT_USERUNMANAGED,
5451                               INSTALLPROPERTY_INSTALLSOURCE, buf, &sz);
5452     ok(r == ERROR_UNKNOWN_PROPERTY,
5453        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5454     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5455     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5456
5457     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
5458     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5459
5460     /* LocalPackage value exists */
5461     sz = MAX_PATH;
5462     lstrcpyA(buf, "apple");
5463     r = pMsiGetProductInfoExA(prodcode, usersid,
5464                               MSIINSTALLCONTEXT_USERUNMANAGED,
5465                               INSTALLPROPERTY_LOCALPACKAGE, buf, &sz);
5466     ok(r == ERROR_UNKNOWN_PROPERTY,
5467        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5468     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5469     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5470
5471     res = RegSetValueExA(prodkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
5472     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5473
5474     /* Publisher value exists */
5475     sz = MAX_PATH;
5476     lstrcpyA(buf, "apple");
5477     r = pMsiGetProductInfoExA(prodcode, usersid,
5478                               MSIINSTALLCONTEXT_USERUNMANAGED,
5479                               INSTALLPROPERTY_PUBLISHER, buf, &sz);
5480     ok(r == ERROR_UNKNOWN_PROPERTY,
5481        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5482     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5483     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5484
5485     res = RegSetValueExA(prodkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
5486     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5487
5488     /* URLInfoAbout value exists */
5489     sz = MAX_PATH;
5490     lstrcpyA(buf, "apple");
5491     r = pMsiGetProductInfoExA(prodcode, usersid,
5492                               MSIINSTALLCONTEXT_USERUNMANAGED,
5493                               INSTALLPROPERTY_URLINFOABOUT, buf, &sz);
5494     ok(r == ERROR_UNKNOWN_PROPERTY,
5495        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5496     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5497     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5498
5499     res = RegSetValueExA(prodkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
5500     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5501
5502     /* URLUpdateInfo value exists */
5503     sz = MAX_PATH;
5504     lstrcpyA(buf, "apple");
5505     r = pMsiGetProductInfoExA(prodcode, usersid,
5506                               MSIINSTALLCONTEXT_USERUNMANAGED,
5507                               INSTALLPROPERTY_URLUPDATEINFO, buf, &sz);
5508     ok(r == ERROR_UNKNOWN_PROPERTY,
5509        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5510     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5511     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5512
5513     res = RegSetValueExA(prodkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
5514     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5515
5516     /* VersionMinor value exists */
5517     sz = MAX_PATH;
5518     lstrcpyA(buf, "apple");
5519     r = pMsiGetProductInfoExA(prodcode, usersid,
5520                               MSIINSTALLCONTEXT_USERUNMANAGED,
5521                               INSTALLPROPERTY_VERSIONMINOR, buf, &sz);
5522     ok(r == ERROR_UNKNOWN_PROPERTY,
5523        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5524     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5525     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5526
5527     res = RegSetValueExA(prodkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
5528     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5529
5530     /* VersionMajor value exists */
5531     sz = MAX_PATH;
5532     lstrcpyA(buf, "apple");
5533     r = pMsiGetProductInfoExA(prodcode, usersid,
5534                               MSIINSTALLCONTEXT_USERUNMANAGED,
5535                               INSTALLPROPERTY_VERSIONMAJOR, buf, &sz);
5536     ok(r == ERROR_UNKNOWN_PROPERTY,
5537        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5538     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5539     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5540
5541     res = RegSetValueExA(prodkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
5542     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5543
5544     /* DisplayVersion value exists */
5545     sz = MAX_PATH;
5546     lstrcpyA(buf, "apple");
5547     r = pMsiGetProductInfoExA(prodcode, usersid,
5548                               MSIINSTALLCONTEXT_USERUNMANAGED,
5549                               INSTALLPROPERTY_VERSIONSTRING, buf, &sz);
5550     ok(r == ERROR_UNKNOWN_PROPERTY,
5551        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5552     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5553     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5554
5555     res = RegSetValueExA(prodkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
5556     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5557
5558     /* ProductID value exists */
5559     sz = MAX_PATH;
5560     lstrcpyA(buf, "apple");
5561     r = pMsiGetProductInfoExA(prodcode, usersid,
5562                               MSIINSTALLCONTEXT_USERUNMANAGED,
5563                               INSTALLPROPERTY_PRODUCTID, buf, &sz);
5564     ok(r == ERROR_UNKNOWN_PROPERTY,
5565        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5566     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5567     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5568
5569     res = RegSetValueExA(prodkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
5570     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5571
5572     /* RegCompany value exists */
5573     sz = MAX_PATH;
5574     lstrcpyA(buf, "apple");
5575     r = pMsiGetProductInfoExA(prodcode, usersid,
5576                               MSIINSTALLCONTEXT_USERUNMANAGED,
5577                               INSTALLPROPERTY_REGCOMPANY, buf, &sz);
5578     ok(r == ERROR_UNKNOWN_PROPERTY,
5579        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5580     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5581     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5582
5583     res = RegSetValueExA(prodkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
5584     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5585
5586     /* RegOwner value exists */
5587     sz = MAX_PATH;
5588     lstrcpyA(buf, "apple");
5589     r = pMsiGetProductInfoExA(prodcode, usersid,
5590                               MSIINSTALLCONTEXT_USERUNMANAGED,
5591                               INSTALLPROPERTY_REGOWNER, buf, &sz);
5592     ok(r == ERROR_UNKNOWN_PROPERTY,
5593        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5594     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5595     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5596
5597     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
5598     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5599
5600     /* Transforms value exists */
5601     sz = MAX_PATH;
5602     lstrcpyA(buf, "apple");
5603     r = pMsiGetProductInfoExA(prodcode, usersid,
5604                               MSIINSTALLCONTEXT_USERUNMANAGED,
5605                               INSTALLPROPERTY_TRANSFORMS, buf, &sz);
5606     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5607     ok(!lstrcmpA(buf, "trans"), "Expected \"trans\", got \"%s\"\n", buf);
5608     ok(sz == 5, "Expected 5, got %d\n", sz);
5609
5610     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
5611     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5612
5613     /* Language value exists */
5614     sz = MAX_PATH;
5615     lstrcpyA(buf, "apple");
5616     r = pMsiGetProductInfoExA(prodcode, usersid,
5617                               MSIINSTALLCONTEXT_USERUNMANAGED,
5618                               INSTALLPROPERTY_LANGUAGE, buf, &sz);
5619     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5620     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
5621     ok(sz == 4, "Expected 4, got %d\n", sz);
5622
5623     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
5624     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5625
5626     /* ProductName value exists */
5627     sz = MAX_PATH;
5628     lstrcpyA(buf, "apple");
5629     r = pMsiGetProductInfoExA(prodcode, usersid,
5630                               MSIINSTALLCONTEXT_USERUNMANAGED,
5631                               INSTALLPROPERTY_PRODUCTNAME, buf, &sz);
5632     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5633     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
5634     ok(sz == 4, "Expected 4, got %d\n", sz);
5635
5636     res = RegSetValueExA(prodkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
5637     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5638
5639     /* FIXME */
5640
5641     /* AssignmentType value exists */
5642     sz = MAX_PATH;
5643     lstrcpyA(buf, "apple");
5644     r = pMsiGetProductInfoExA(prodcode, usersid,
5645                               MSIINSTALLCONTEXT_USERUNMANAGED,
5646                               INSTALLPROPERTY_ASSIGNMENTTYPE, buf, &sz);
5647     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5648     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5649     ok(sz == 0, "Expected 0, got %d\n", sz);
5650
5651     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
5652     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5653
5654     /* FIXME */
5655
5656     /* PackageCode value exists */
5657     sz = MAX_PATH;
5658     lstrcpyA(buf, "apple");
5659     r = pMsiGetProductInfoExA(prodcode, usersid,
5660                               MSIINSTALLCONTEXT_USERUNMANAGED,
5661                               INSTALLPROPERTY_PACKAGECODE, buf, &sz);
5662     todo_wine
5663     {
5664         ok(r == ERROR_BAD_CONFIGURATION,
5665            "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
5666         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5667         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5668     }
5669
5670     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
5671     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5672
5673     /* Version value exists */
5674     sz = MAX_PATH;
5675     lstrcpyA(buf, "apple");
5676     r = pMsiGetProductInfoExA(prodcode, usersid,
5677                               MSIINSTALLCONTEXT_USERUNMANAGED,
5678                               INSTALLPROPERTY_VERSION, buf, &sz);
5679     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5680     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
5681     ok(sz == 3, "Expected 3, got %d\n", sz);
5682
5683     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
5684     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5685
5686     /* ProductIcon value exists */
5687     sz = MAX_PATH;
5688     lstrcpyA(buf, "apple");
5689     r = pMsiGetProductInfoExA(prodcode, usersid,
5690                               MSIINSTALLCONTEXT_USERUNMANAGED,
5691                               INSTALLPROPERTY_PRODUCTICON, buf, &sz);
5692     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5693     ok(!lstrcmpA(buf, "icon"), "Expected \"icon\", got \"%s\"\n", buf);
5694     ok(sz == 4, "Expected 4, got %d\n", sz);
5695
5696     res = RegSetValueExA(prodkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
5697     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5698
5699     /* PackageName value exists */
5700     sz = MAX_PATH;
5701     lstrcpyA(buf, "apple");
5702     r = pMsiGetProductInfoExA(prodcode, usersid,
5703                               MSIINSTALLCONTEXT_USERUNMANAGED,
5704                               INSTALLPROPERTY_PACKAGENAME, buf, &sz);
5705     todo_wine
5706     {
5707         ok(r == ERROR_UNKNOWN_PRODUCT,
5708            "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5709         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5710         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5711     }
5712
5713     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
5714     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5715
5716     /* AuthorizedLUAApp value exists */
5717     sz = MAX_PATH;
5718     lstrcpyA(buf, "apple");
5719     r = pMsiGetProductInfoExA(prodcode, usersid,
5720                               MSIINSTALLCONTEXT_USERUNMANAGED,
5721                               INSTALLPROPERTY_AUTHORIZED_LUA_APP, buf, &sz);
5722     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5723     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
5724     ok(sz == 4, "Expected 4, got %d\n", sz);
5725
5726     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
5727     RegDeleteValueA(prodkey, "PackageName");
5728     RegDeleteValueA(prodkey, "ProductIcon");
5729     RegDeleteValueA(prodkey, "Version");
5730     RegDeleteValueA(prodkey, "PackageCode");
5731     RegDeleteValueA(prodkey, "AssignmentType");
5732     RegDeleteValueA(prodkey, "ProductName");
5733     RegDeleteValueA(prodkey, "Language");
5734     RegDeleteValueA(prodkey, "Transforms");
5735     RegDeleteValueA(prodkey, "RegOwner");
5736     RegDeleteValueA(prodkey, "RegCompany");
5737     RegDeleteValueA(prodkey, "ProductID");
5738     RegDeleteValueA(prodkey, "DisplayVersion");
5739     RegDeleteValueA(prodkey, "VersionMajor");
5740     RegDeleteValueA(prodkey, "VersionMinor");
5741     RegDeleteValueA(prodkey, "URLUpdateInfo");
5742     RegDeleteValueA(prodkey, "URLInfoAbout");
5743     RegDeleteValueA(prodkey, "Publisher");
5744     RegDeleteValueA(prodkey, "LocalPackage");
5745     RegDeleteValueA(prodkey, "InstallSource");
5746     RegDeleteValueA(prodkey, "InstallLocation");
5747     RegDeleteValueA(prodkey, "DisplayName");
5748     RegDeleteValueA(prodkey, "InstallDate");
5749     RegDeleteValueA(prodkey, "HelpTelephone");
5750     RegDeleteValueA(prodkey, "HelpLink");
5751     RegDeleteValueA(prodkey, "LocalPackage");
5752     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
5753     RegCloseKey(prodkey);
5754
5755     /* MSIINSTALLCONTEXT_USERMANAGED */
5756
5757     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
5758     lstrcatA(keypath, usersid);
5759     lstrcatA(keypath, "\\Products\\");
5760     lstrcatA(keypath, prod_squashed);
5761
5762     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
5763     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5764
5765     /* local user product key exists */
5766     sz = MAX_PATH;
5767     lstrcpyA(buf, "apple");
5768     r = pMsiGetProductInfoExA(prodcode, usersid,
5769                               MSIINSTALLCONTEXT_USERMANAGED,
5770                               INSTALLPROPERTY_PRODUCTSTATE, buf, &sz);
5771     ok(r == ERROR_UNKNOWN_PRODUCT,
5772        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5773     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5774     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5775
5776     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
5777     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5778
5779     /* InstallProperties key exists */
5780     sz = MAX_PATH;
5781     lstrcpyA(buf, "apple");
5782     r = pMsiGetProductInfoExA(prodcode, usersid,
5783                               MSIINSTALLCONTEXT_USERMANAGED,
5784                               INSTALLPROPERTY_PRODUCTSTATE, buf, &sz);
5785     ok(r == ERROR_UNKNOWN_PRODUCT,
5786        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5787     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
5788     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5789
5790     res = RegSetValueExA(propkey, "ManagedLocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
5791     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5792
5793     /* ManagedLocalPackage value exists */
5794     sz = MAX_PATH;
5795     lstrcpyA(buf, "apple");
5796     r = pMsiGetProductInfoExA(prodcode, usersid,
5797                               MSIINSTALLCONTEXT_USERMANAGED,
5798                               INSTALLPROPERTY_PRODUCTSTATE, buf, &sz);
5799     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5800     ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
5801     ok(sz == 1, "Expected 1, got %d\n", sz);
5802
5803     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
5804     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5805
5806     /* HelpLink value exists */
5807     sz = MAX_PATH;
5808     lstrcpyA(buf, "apple");
5809     r = pMsiGetProductInfoExA(prodcode, usersid,
5810                               MSIINSTALLCONTEXT_USERMANAGED,
5811                               INSTALLPROPERTY_HELPLINK, buf, &sz);
5812     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5813     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
5814     ok(sz == 4, "Expected 4, got %d\n", sz);
5815
5816     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
5817     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5818
5819     /* HelpTelephone value exists */
5820     sz = MAX_PATH;
5821     lstrcpyA(buf, "apple");
5822     r = pMsiGetProductInfoExA(prodcode, usersid,
5823                               MSIINSTALLCONTEXT_USERMANAGED,
5824                               INSTALLPROPERTY_HELPTELEPHONE, buf, &sz);
5825     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5826     ok(!lstrcmpA(buf, "phone"), "Expected \"phone\", got \"%s\"\n", buf);
5827     ok(sz == 5, "Expected 5, got %d\n", sz);
5828
5829     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
5830     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5831
5832     /* InstallDate value exists */
5833     sz = MAX_PATH;
5834     lstrcpyA(buf, "apple");
5835     r = pMsiGetProductInfoExA(prodcode, usersid,
5836                               MSIINSTALLCONTEXT_USERMANAGED,
5837                               INSTALLPROPERTY_INSTALLDATE, buf, &sz);
5838     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5839     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
5840     ok(sz == 4, "Expected 4, got %d\n", sz);
5841
5842     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
5843     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5844
5845     /* DisplayName value exists */
5846     sz = MAX_PATH;
5847     lstrcpyA(buf, "apple");
5848     r = pMsiGetProductInfoExA(prodcode, usersid,
5849                               MSIINSTALLCONTEXT_USERMANAGED,
5850                               INSTALLPROPERTY_INSTALLEDPRODUCTNAME, buf, &sz);
5851     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5852     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
5853     ok(sz == 4, "Expected 4, got %d\n", sz);
5854
5855     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
5856     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5857
5858     /* InstallLocation value exists */
5859     sz = MAX_PATH;
5860     lstrcpyA(buf, "apple");
5861     r = pMsiGetProductInfoExA(prodcode, usersid,
5862                               MSIINSTALLCONTEXT_USERMANAGED,
5863                               INSTALLPROPERTY_INSTALLLOCATION, buf, &sz);
5864     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5865     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
5866     ok(sz == 3, "Expected 3, got %d\n", sz);
5867
5868     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
5869     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5870
5871     /* InstallSource value exists */
5872     sz = MAX_PATH;
5873     lstrcpyA(buf, "apple");
5874     r = pMsiGetProductInfoExA(prodcode, usersid,
5875                               MSIINSTALLCONTEXT_USERMANAGED,
5876                               INSTALLPROPERTY_INSTALLSOURCE, buf, &sz);
5877     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5878     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
5879     ok(sz == 6, "Expected 6, got %d\n", sz);
5880
5881     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
5882     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5883
5884     /* LocalPackage value exists */
5885     sz = MAX_PATH;
5886     lstrcpyA(buf, "apple");
5887     r = pMsiGetProductInfoExA(prodcode, usersid,
5888                               MSIINSTALLCONTEXT_USERMANAGED,
5889                               INSTALLPROPERTY_LOCALPACKAGE, buf, &sz);
5890     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5891     ok(!lstrcmpA(buf, "local"), "Expected \"local\", got \"%s\"\n", buf);
5892     ok(sz == 5, "Expected 5, got %d\n", sz);
5893
5894     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
5895     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5896
5897     /* Publisher value exists */
5898     sz = MAX_PATH;
5899     lstrcpyA(buf, "apple");
5900     r = pMsiGetProductInfoExA(prodcode, usersid,
5901                               MSIINSTALLCONTEXT_USERMANAGED,
5902                               INSTALLPROPERTY_PUBLISHER, buf, &sz);
5903     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5904     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
5905     ok(sz == 3, "Expected 3, got %d\n", sz);
5906
5907     res = RegSetValueExA(propkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
5908     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5909
5910     /* URLInfoAbout value exists */
5911     sz = MAX_PATH;
5912     lstrcpyA(buf, "apple");
5913     r = pMsiGetProductInfoExA(prodcode, usersid,
5914                               MSIINSTALLCONTEXT_USERMANAGED,
5915                               INSTALLPROPERTY_URLINFOABOUT, buf, &sz);
5916     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5917     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
5918     ok(sz == 5, "Expected 5, got %d\n", sz);
5919
5920     res = RegSetValueExA(propkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
5921     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5922
5923     /* URLUpdateInfo value exists */
5924     sz = MAX_PATH;
5925     lstrcpyA(buf, "apple");
5926     r = pMsiGetProductInfoExA(prodcode, usersid,
5927                               MSIINSTALLCONTEXT_USERMANAGED,
5928                               INSTALLPROPERTY_URLUPDATEINFO, buf, &sz);
5929     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5930     ok(!lstrcmpA(buf, "update"), "Expected \"update\", got \"%s\"\n", buf);
5931     ok(sz == 6, "Expected 6, got %d\n", sz);
5932
5933     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
5934     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5935
5936     /* VersionMinor value exists */
5937     sz = MAX_PATH;
5938     lstrcpyA(buf, "apple");
5939     r = pMsiGetProductInfoExA(prodcode, usersid,
5940                               MSIINSTALLCONTEXT_USERMANAGED,
5941                               INSTALLPROPERTY_VERSIONMINOR, buf, &sz);
5942     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5943     ok(!lstrcmpA(buf, "2"), "Expected \"2\", got \"%s\"\n", buf);
5944     ok(sz == 1, "Expected 1, got %d\n", sz);
5945
5946     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
5947     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5948
5949     /* VersionMajor value exists */
5950     sz = MAX_PATH;
5951     lstrcpyA(buf, "apple");
5952     r = pMsiGetProductInfoExA(prodcode, usersid,
5953                               MSIINSTALLCONTEXT_USERMANAGED,
5954                               INSTALLPROPERTY_VERSIONMAJOR, buf, &sz);
5955     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5956     ok(!lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
5957     ok(sz == 1, "Expected 1, got %d\n", sz);
5958
5959     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
5960     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5961
5962     /* DisplayVersion value exists */
5963     sz = MAX_PATH;
5964     lstrcpyA(buf, "apple");
5965     r = pMsiGetProductInfoExA(prodcode, usersid,
5966                               MSIINSTALLCONTEXT_USERMANAGED,
5967                               INSTALLPROPERTY_VERSIONSTRING, buf, &sz);
5968     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5969     ok(!lstrcmpA(buf, "3.2.1"), "Expected \"3.2.1\", got \"%s\"\n", buf);
5970     ok(sz == 5, "Expected 5, got %d\n", sz);
5971
5972     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
5973     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5974
5975     /* ProductID value exists */
5976     sz = MAX_PATH;
5977     lstrcpyA(buf, "apple");
5978     r = pMsiGetProductInfoExA(prodcode, usersid,
5979                               MSIINSTALLCONTEXT_USERMANAGED,
5980                               INSTALLPROPERTY_PRODUCTID, buf, &sz);
5981     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5982     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
5983     ok(sz == 2, "Expected 2, got %d\n", sz);
5984
5985     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
5986     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5987
5988     /* RegCompany value exists */
5989     sz = MAX_PATH;
5990     lstrcpyA(buf, "apple");
5991     r = pMsiGetProductInfoExA(prodcode, usersid,
5992                               MSIINSTALLCONTEXT_USERMANAGED,
5993                               INSTALLPROPERTY_REGCOMPANY, buf, &sz);
5994     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5995     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
5996     ok(sz == 4, "Expected 4, got %d\n", sz);
5997
5998     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
5999     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6000
6001     /* RegOwner value exists */
6002     sz = MAX_PATH;
6003     lstrcpyA(buf, "apple");
6004     r = pMsiGetProductInfoExA(prodcode, usersid,
6005                               MSIINSTALLCONTEXT_USERMANAGED,
6006                               INSTALLPROPERTY_REGOWNER, buf, &sz);
6007     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6008     ok(!lstrcmpA(buf, "owner"), "Expected \"owner\", got \"%s\"\n", buf);
6009     ok(sz == 5, "Expected 5, got %d\n", sz);
6010
6011     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
6012     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6013
6014     /* Transforms value exists */
6015     sz = MAX_PATH;
6016     lstrcpyA(buf, "apple");
6017     r = pMsiGetProductInfoExA(prodcode, usersid,
6018                               MSIINSTALLCONTEXT_USERMANAGED,
6019                               INSTALLPROPERTY_TRANSFORMS, buf, &sz);
6020     ok(r == ERROR_UNKNOWN_PRODUCT,
6021        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6022     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6023     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6024
6025     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
6026     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6027
6028     /* Language value exists */
6029     sz = MAX_PATH;
6030     lstrcpyA(buf, "apple");
6031     r = pMsiGetProductInfoExA(prodcode, usersid,
6032                               MSIINSTALLCONTEXT_USERMANAGED,
6033                               INSTALLPROPERTY_LANGUAGE, buf, &sz);
6034     ok(r == ERROR_UNKNOWN_PRODUCT,
6035        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6036     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6037     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6038
6039     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
6040     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6041
6042     /* ProductName value exists */
6043     sz = MAX_PATH;
6044     lstrcpyA(buf, "apple");
6045     r = pMsiGetProductInfoExA(prodcode, usersid,
6046                               MSIINSTALLCONTEXT_USERMANAGED,
6047                               INSTALLPROPERTY_PRODUCTNAME, buf, &sz);
6048     ok(r == ERROR_UNKNOWN_PRODUCT,
6049        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6050     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6051     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6052
6053     res = RegSetValueExA(propkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
6054     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6055
6056     /* FIXME */
6057
6058     /* AssignmentType value exists */
6059     sz = MAX_PATH;
6060     lstrcpyA(buf, "apple");
6061     r = pMsiGetProductInfoExA(prodcode, usersid,
6062                               MSIINSTALLCONTEXT_USERMANAGED,
6063                               INSTALLPROPERTY_ASSIGNMENTTYPE, buf, &sz);
6064     ok(r == ERROR_UNKNOWN_PRODUCT,
6065        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6066     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6067     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6068
6069     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
6070     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6071
6072     /* PackageCode value exists */
6073     sz = MAX_PATH;
6074     lstrcpyA(buf, "apple");
6075     r = pMsiGetProductInfoExA(prodcode, usersid,
6076                               MSIINSTALLCONTEXT_USERMANAGED,
6077                               INSTALLPROPERTY_PACKAGECODE, buf, &sz);
6078     ok(r == ERROR_UNKNOWN_PRODUCT,
6079        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6080     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6081     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6082
6083     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
6084     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6085
6086     /* Version value exists */
6087     sz = MAX_PATH;
6088     lstrcpyA(buf, "apple");
6089     r = pMsiGetProductInfoExA(prodcode, usersid,
6090                               MSIINSTALLCONTEXT_USERMANAGED,
6091                               INSTALLPROPERTY_VERSION, buf, &sz);
6092     ok(r == ERROR_UNKNOWN_PRODUCT,
6093        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6094     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6095     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6096
6097     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
6098     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6099
6100     /* ProductIcon value exists */
6101     sz = MAX_PATH;
6102     lstrcpyA(buf, "apple");
6103     r = pMsiGetProductInfoExA(prodcode, usersid,
6104                               MSIINSTALLCONTEXT_USERMANAGED,
6105                               INSTALLPROPERTY_PRODUCTICON, buf, &sz);
6106     ok(r == ERROR_UNKNOWN_PRODUCT,
6107        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6108     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6109     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6110
6111     res = RegSetValueExA(propkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
6112     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6113
6114     /* PackageName value exists */
6115     sz = MAX_PATH;
6116     lstrcpyA(buf, "apple");
6117     r = pMsiGetProductInfoExA(prodcode, usersid,
6118                               MSIINSTALLCONTEXT_USERMANAGED,
6119                               INSTALLPROPERTY_PACKAGENAME, buf, &sz);
6120     ok(r == ERROR_UNKNOWN_PRODUCT,
6121        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6122     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6123     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6124
6125     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
6126     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6127
6128     /* AuthorizedLUAApp value exists */
6129     sz = MAX_PATH;
6130     lstrcpyA(buf, "apple");
6131     r = pMsiGetProductInfoExA(prodcode, usersid,
6132                               MSIINSTALLCONTEXT_USERMANAGED,
6133                               INSTALLPROPERTY_AUTHORIZED_LUA_APP, buf, &sz);
6134     ok(r == ERROR_UNKNOWN_PRODUCT,
6135        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6136     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6137     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6138
6139     RegDeleteValueA(propkey, "AuthorizedLUAApp");
6140     RegDeleteValueA(propkey, "PackageName");
6141     RegDeleteValueA(propkey, "ProductIcon");
6142     RegDeleteValueA(propkey, "Version");
6143     RegDeleteValueA(propkey, "PackageCode");
6144     RegDeleteValueA(propkey, "AssignmentType");
6145     RegDeleteValueA(propkey, "ProductName");
6146     RegDeleteValueA(propkey, "Language");
6147     RegDeleteValueA(propkey, "Transforms");
6148     RegDeleteValueA(propkey, "RegOwner");
6149     RegDeleteValueA(propkey, "RegCompany");
6150     RegDeleteValueA(propkey, "ProductID");
6151     RegDeleteValueA(propkey, "DisplayVersion");
6152     RegDeleteValueA(propkey, "VersionMajor");
6153     RegDeleteValueA(propkey, "VersionMinor");
6154     RegDeleteValueA(propkey, "URLUpdateInfo");
6155     RegDeleteValueA(propkey, "URLInfoAbout");
6156     RegDeleteValueA(propkey, "Publisher");
6157     RegDeleteValueA(propkey, "LocalPackage");
6158     RegDeleteValueA(propkey, "InstallSource");
6159     RegDeleteValueA(propkey, "InstallLocation");
6160     RegDeleteValueA(propkey, "DisplayName");
6161     RegDeleteValueA(propkey, "InstallDate");
6162     RegDeleteValueA(propkey, "HelpTelephone");
6163     RegDeleteValueA(propkey, "HelpLink");
6164     RegDeleteValueA(propkey, "ManagedLocalPackage");
6165     delete_key(propkey, "", access & KEY_WOW64_64KEY);
6166     RegCloseKey(propkey);
6167     delete_key(localkey, "", access & KEY_WOW64_64KEY);
6168     RegCloseKey(localkey);
6169
6170     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
6171     lstrcatA(keypath, usersid);
6172     lstrcatA(keypath, "\\Installer\\Products\\");
6173     lstrcatA(keypath, prod_squashed);
6174
6175     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
6176     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6177
6178     /* user product key exists */
6179     sz = MAX_PATH;
6180     lstrcpyA(buf, "apple");
6181     r = pMsiGetProductInfoExA(prodcode, usersid,
6182                               MSIINSTALLCONTEXT_USERMANAGED,
6183                               INSTALLPROPERTY_PRODUCTSTATE, buf, &sz);
6184     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6185     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
6186     ok(sz == 1, "Expected 1, got %d\n", sz);
6187
6188     delete_key(userkey, "", access & KEY_WOW64_64KEY);
6189     RegCloseKey(userkey);
6190
6191     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
6192     lstrcatA(keypath, prod_squashed);
6193
6194     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
6195     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6196
6197     /* current user product key exists */
6198     sz = MAX_PATH;
6199     lstrcpyA(buf, "apple");
6200     r = pMsiGetProductInfoExA(prodcode, usersid,
6201                               MSIINSTALLCONTEXT_USERMANAGED,
6202                               INSTALLPROPERTY_PRODUCTSTATE, buf, &sz);
6203     ok(r == ERROR_UNKNOWN_PRODUCT,
6204        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6205     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6206     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6207
6208     res = RegSetValueExA(prodkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
6209     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6210
6211     /* HelpLink value exists, user product key does not exist */
6212     sz = MAX_PATH;
6213     lstrcpyA(buf, "apple");
6214     r = pMsiGetProductInfoExA(prodcode, usersid,
6215                               MSIINSTALLCONTEXT_USERMANAGED,
6216                               INSTALLPROPERTY_HELPLINK, buf, &sz);
6217     ok(r == ERROR_UNKNOWN_PRODUCT,
6218        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6219     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6220     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6221
6222     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
6223     lstrcatA(keypath, usersid);
6224     lstrcatA(keypath, "\\Installer\\Products\\");
6225     lstrcatA(keypath, prod_squashed);
6226
6227     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
6228     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6229
6230     res = RegSetValueExA(userkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
6231     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6232
6233     /* HelpLink value exists, user product key does exist */
6234     sz = MAX_PATH;
6235     lstrcpyA(buf, "apple");
6236     r = pMsiGetProductInfoExA(prodcode, usersid,
6237                               MSIINSTALLCONTEXT_USERMANAGED,
6238                               INSTALLPROPERTY_HELPLINK, buf, &sz);
6239     ok(r == ERROR_UNKNOWN_PROPERTY,
6240        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6241     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6242     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6243
6244     res = RegSetValueExA(userkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
6245     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6246
6247     /* HelpTelephone value exists */
6248     sz = MAX_PATH;
6249     lstrcpyA(buf, "apple");
6250     r = pMsiGetProductInfoExA(prodcode, usersid,
6251                               MSIINSTALLCONTEXT_USERMANAGED,
6252                               INSTALLPROPERTY_HELPTELEPHONE, buf, &sz);
6253     ok(r == ERROR_UNKNOWN_PROPERTY,
6254        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6255     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6256     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6257
6258     res = RegSetValueExA(userkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
6259     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6260
6261     /* InstallDate value exists */
6262     sz = MAX_PATH;
6263     lstrcpyA(buf, "apple");
6264     r = pMsiGetProductInfoExA(prodcode, usersid,
6265                               MSIINSTALLCONTEXT_USERMANAGED,
6266                               INSTALLPROPERTY_INSTALLDATE, buf, &sz);
6267     ok(r == ERROR_UNKNOWN_PROPERTY,
6268        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6269     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6270     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6271
6272     res = RegSetValueExA(userkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
6273     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6274
6275     /* DisplayName value exists */
6276     sz = MAX_PATH;
6277     lstrcpyA(buf, "apple");
6278     r = pMsiGetProductInfoExA(prodcode, usersid,
6279                               MSIINSTALLCONTEXT_USERMANAGED,
6280                               INSTALLPROPERTY_INSTALLEDPRODUCTNAME, buf, &sz);
6281     ok(r == ERROR_UNKNOWN_PROPERTY,
6282        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6283     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6284     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6285
6286     res = RegSetValueExA(userkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
6287     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6288
6289     /* InstallLocation value exists */
6290     sz = MAX_PATH;
6291     lstrcpyA(buf, "apple");
6292     r = pMsiGetProductInfoExA(prodcode, usersid,
6293                               MSIINSTALLCONTEXT_USERMANAGED,
6294                               INSTALLPROPERTY_INSTALLLOCATION, buf, &sz);
6295     ok(r == ERROR_UNKNOWN_PROPERTY,
6296        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6297     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6298     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6299
6300     res = RegSetValueExA(userkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
6301     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6302
6303     /* InstallSource value exists */
6304     sz = MAX_PATH;
6305     lstrcpyA(buf, "apple");
6306     r = pMsiGetProductInfoExA(prodcode, usersid,
6307                               MSIINSTALLCONTEXT_USERMANAGED,
6308                               INSTALLPROPERTY_INSTALLSOURCE, buf, &sz);
6309     ok(r == ERROR_UNKNOWN_PROPERTY,
6310        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6311     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6312     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6313
6314     res = RegSetValueExA(userkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6315     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6316
6317     /* LocalPackage value exists */
6318     sz = MAX_PATH;
6319     lstrcpyA(buf, "apple");
6320     r = pMsiGetProductInfoExA(prodcode, usersid,
6321                               MSIINSTALLCONTEXT_USERMANAGED,
6322                               INSTALLPROPERTY_LOCALPACKAGE, buf, &sz);
6323     ok(r == ERROR_UNKNOWN_PROPERTY,
6324        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6325     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6326     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6327
6328     res = RegSetValueExA(userkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
6329     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6330
6331     /* Publisher value exists */
6332     sz = MAX_PATH;
6333     lstrcpyA(buf, "apple");
6334     r = pMsiGetProductInfoExA(prodcode, usersid,
6335                               MSIINSTALLCONTEXT_USERMANAGED,
6336                               INSTALLPROPERTY_PUBLISHER, buf, &sz);
6337     ok(r == ERROR_UNKNOWN_PROPERTY,
6338        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6339     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6340     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6341
6342     res = RegSetValueExA(userkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
6343     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6344
6345     /* URLInfoAbout value exists */
6346     sz = MAX_PATH;
6347     lstrcpyA(buf, "apple");
6348     r = pMsiGetProductInfoExA(prodcode, usersid,
6349                               MSIINSTALLCONTEXT_USERMANAGED,
6350                               INSTALLPROPERTY_URLINFOABOUT, buf, &sz);
6351     ok(r == ERROR_UNKNOWN_PROPERTY,
6352        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6353     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6354     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6355
6356     res = RegSetValueExA(userkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
6357     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6358
6359     /* URLUpdateInfo value exists */
6360     sz = MAX_PATH;
6361     lstrcpyA(buf, "apple");
6362     r = pMsiGetProductInfoExA(prodcode, usersid,
6363                               MSIINSTALLCONTEXT_USERMANAGED,
6364                               INSTALLPROPERTY_URLUPDATEINFO, buf, &sz);
6365     ok(r == ERROR_UNKNOWN_PROPERTY,
6366        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6367     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6368     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6369
6370     res = RegSetValueExA(userkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
6371     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6372
6373     /* VersionMinor value exists */
6374     sz = MAX_PATH;
6375     lstrcpyA(buf, "apple");
6376     r = pMsiGetProductInfoExA(prodcode, usersid,
6377                               MSIINSTALLCONTEXT_USERMANAGED,
6378                               INSTALLPROPERTY_VERSIONMINOR, buf, &sz);
6379     ok(r == ERROR_UNKNOWN_PROPERTY,
6380        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6381     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6382     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6383
6384     res = RegSetValueExA(userkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
6385     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6386
6387     /* VersionMajor value exists */
6388     sz = MAX_PATH;
6389     lstrcpyA(buf, "apple");
6390     r = pMsiGetProductInfoExA(prodcode, usersid,
6391                               MSIINSTALLCONTEXT_USERMANAGED,
6392                               INSTALLPROPERTY_VERSIONMAJOR, buf, &sz);
6393     ok(r == ERROR_UNKNOWN_PROPERTY,
6394        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6395     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6396     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6397
6398     res = RegSetValueExA(userkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
6399     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6400
6401     /* DisplayVersion value exists */
6402     sz = MAX_PATH;
6403     lstrcpyA(buf, "apple");
6404     r = pMsiGetProductInfoExA(prodcode, usersid,
6405                               MSIINSTALLCONTEXT_USERMANAGED,
6406                               INSTALLPROPERTY_VERSIONSTRING, buf, &sz);
6407     ok(r == ERROR_UNKNOWN_PROPERTY,
6408        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6409     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6410     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6411
6412     res = RegSetValueExA(userkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
6413     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6414
6415     /* ProductID value exists */
6416     sz = MAX_PATH;
6417     lstrcpyA(buf, "apple");
6418     r = pMsiGetProductInfoExA(prodcode, usersid,
6419                               MSIINSTALLCONTEXT_USERMANAGED,
6420                               INSTALLPROPERTY_PRODUCTID, buf, &sz);
6421     ok(r == ERROR_UNKNOWN_PROPERTY,
6422        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6423     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6424     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6425
6426     res = RegSetValueExA(userkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
6427     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6428
6429     /* RegCompany value exists */
6430     sz = MAX_PATH;
6431     lstrcpyA(buf, "apple");
6432     r = pMsiGetProductInfoExA(prodcode, usersid,
6433                               MSIINSTALLCONTEXT_USERMANAGED,
6434                               INSTALLPROPERTY_REGCOMPANY, buf, &sz);
6435     ok(r == ERROR_UNKNOWN_PROPERTY,
6436        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6437     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6438     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6439
6440     res = RegSetValueExA(userkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
6441     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6442
6443     /* RegOwner value exists */
6444     sz = MAX_PATH;
6445     lstrcpyA(buf, "apple");
6446     r = pMsiGetProductInfoExA(prodcode, usersid,
6447                               MSIINSTALLCONTEXT_USERMANAGED,
6448                               INSTALLPROPERTY_REGOWNER, buf, &sz);
6449     ok(r == ERROR_UNKNOWN_PROPERTY,
6450        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6451     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6452     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6453
6454     res = RegSetValueExA(userkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
6455     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6456
6457     /* Transforms value exists */
6458     sz = MAX_PATH;
6459     lstrcpyA(buf, "apple");
6460     r = pMsiGetProductInfoExA(prodcode, usersid,
6461                               MSIINSTALLCONTEXT_USERMANAGED,
6462                               INSTALLPROPERTY_TRANSFORMS, buf, &sz);
6463     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6464     ok(!lstrcmpA(buf, "trans"), "Expected \"trans\", got \"%s\"\n", buf);
6465     ok(sz == 5, "Expected 5, got %d\n", sz);
6466
6467     res = RegSetValueExA(userkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
6468     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6469
6470     /* Language value exists */
6471     sz = MAX_PATH;
6472     lstrcpyA(buf, "apple");
6473     r = pMsiGetProductInfoExA(prodcode, usersid,
6474                               MSIINSTALLCONTEXT_USERMANAGED,
6475                               INSTALLPROPERTY_LANGUAGE, buf, &sz);
6476     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6477     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
6478     ok(sz == 4, "Expected 4, got %d\n", sz);
6479
6480     res = RegSetValueExA(userkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
6481     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6482
6483     /* ProductName value exists */
6484     sz = MAX_PATH;
6485     lstrcpyA(buf, "apple");
6486     r = pMsiGetProductInfoExA(prodcode, usersid,
6487                               MSIINSTALLCONTEXT_USERMANAGED,
6488                               INSTALLPROPERTY_PRODUCTNAME, buf, &sz);
6489     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6490     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
6491     ok(sz == 4, "Expected 4, got %d\n", sz);
6492
6493     res = RegSetValueExA(userkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
6494     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6495
6496     /* FIXME */
6497
6498     /* AssignmentType value exists */
6499     sz = MAX_PATH;
6500     lstrcpyA(buf, "apple");
6501     r = pMsiGetProductInfoExA(prodcode, usersid,
6502                               MSIINSTALLCONTEXT_USERMANAGED,
6503                               INSTALLPROPERTY_ASSIGNMENTTYPE, buf, &sz);
6504     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6505     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
6506     ok(sz == 0, "Expected 0, got %d\n", sz);
6507
6508     res = RegSetValueExA(userkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
6509     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6510
6511     /* FIXME */
6512
6513     /* PackageCode value exists */
6514     sz = MAX_PATH;
6515     lstrcpyA(buf, "apple");
6516     r = pMsiGetProductInfoExA(prodcode, usersid,
6517                               MSIINSTALLCONTEXT_USERMANAGED,
6518                               INSTALLPROPERTY_PACKAGECODE, buf, &sz);
6519     todo_wine
6520     {
6521         ok(r == ERROR_BAD_CONFIGURATION,
6522            "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
6523         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6524         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6525     }
6526
6527     res = RegSetValueExA(userkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
6528     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6529
6530     /* Version value exists */
6531     sz = MAX_PATH;
6532     lstrcpyA(buf, "apple");
6533     r = pMsiGetProductInfoExA(prodcode, usersid,
6534                               MSIINSTALLCONTEXT_USERMANAGED,
6535                               INSTALLPROPERTY_VERSION, buf, &sz);
6536     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6537     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
6538     ok(sz == 3, "Expected 3, got %d\n", sz);
6539
6540     res = RegSetValueExA(userkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
6541     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6542
6543     /* ProductIcon value exists */
6544     sz = MAX_PATH;
6545     lstrcpyA(buf, "apple");
6546     r = pMsiGetProductInfoExA(prodcode, usersid,
6547                               MSIINSTALLCONTEXT_USERMANAGED,
6548                               INSTALLPROPERTY_PRODUCTICON, buf, &sz);
6549     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6550     ok(!lstrcmpA(buf, "icon"), "Expected \"icon\", got \"%s\"\n", buf);
6551     ok(sz == 4, "Expected 4, got %d\n", sz);
6552
6553     res = RegSetValueExA(userkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
6554     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6555
6556     /* PackageName value exists */
6557     sz = MAX_PATH;
6558     lstrcpyA(buf, "apple");
6559     r = pMsiGetProductInfoExA(prodcode, usersid,
6560                               MSIINSTALLCONTEXT_USERMANAGED,
6561                               INSTALLPROPERTY_PACKAGENAME, buf, &sz);
6562     todo_wine
6563     {
6564         ok(r == ERROR_UNKNOWN_PRODUCT,
6565            "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6566         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6567         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6568     }
6569
6570     res = RegSetValueExA(userkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
6571     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6572
6573     /* AuthorizedLUAApp value exists */
6574     sz = MAX_PATH;
6575     lstrcpyA(buf, "apple");
6576     r = pMsiGetProductInfoExA(prodcode, usersid,
6577                               MSIINSTALLCONTEXT_USERMANAGED,
6578                               INSTALLPROPERTY_AUTHORIZED_LUA_APP, buf, &sz);
6579     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6580     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
6581     ok(sz == 4, "Expected 4, got %d\n", sz);
6582
6583     RegDeleteValueA(userkey, "AuthorizedLUAApp");
6584     RegDeleteValueA(userkey, "PackageName");
6585     RegDeleteValueA(userkey, "ProductIcon");
6586     RegDeleteValueA(userkey, "Version");
6587     RegDeleteValueA(userkey, "PackageCode");
6588     RegDeleteValueA(userkey, "AssignmentType");
6589     RegDeleteValueA(userkey, "ProductName");
6590     RegDeleteValueA(userkey, "Language");
6591     RegDeleteValueA(userkey, "Transforms");
6592     RegDeleteValueA(userkey, "RegOwner");
6593     RegDeleteValueA(userkey, "RegCompany");
6594     RegDeleteValueA(userkey, "ProductID");
6595     RegDeleteValueA(userkey, "DisplayVersion");
6596     RegDeleteValueA(userkey, "VersionMajor");
6597     RegDeleteValueA(userkey, "VersionMinor");
6598     RegDeleteValueA(userkey, "URLUpdateInfo");
6599     RegDeleteValueA(userkey, "URLInfoAbout");
6600     RegDeleteValueA(userkey, "Publisher");
6601     RegDeleteValueA(userkey, "LocalPackage");
6602     RegDeleteValueA(userkey, "InstallSource");
6603     RegDeleteValueA(userkey, "InstallLocation");
6604     RegDeleteValueA(userkey, "DisplayName");
6605     RegDeleteValueA(userkey, "InstallDate");
6606     RegDeleteValueA(userkey, "HelpTelephone");
6607     RegDeleteValueA(userkey, "HelpLink");
6608     delete_key(userkey, "", access & KEY_WOW64_64KEY);
6609     RegCloseKey(userkey);
6610     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
6611     RegCloseKey(prodkey);
6612
6613     /* MSIINSTALLCONTEXT_MACHINE */
6614
6615     /* szUserSid is non-NULL */
6616     sz = MAX_PATH;
6617     lstrcpyA(buf, "apple");
6618     r = pMsiGetProductInfoExA(prodcode, usersid,
6619                               MSIINSTALLCONTEXT_MACHINE,
6620                               INSTALLPROPERTY_PRODUCTSTATE, buf, &sz);
6621     ok(r == ERROR_INVALID_PARAMETER,
6622        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6623     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6624     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6625
6626     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\");
6627     lstrcatA(keypath, prod_squashed);
6628
6629     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
6630     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6631
6632     /* local system product key exists */
6633     sz = MAX_PATH;
6634     lstrcpyA(buf, "apple");
6635     r = pMsiGetProductInfoExA(prodcode, NULL,
6636                               MSIINSTALLCONTEXT_MACHINE,
6637                               INSTALLPROPERTY_PRODUCTSTATE, buf, &sz);
6638     ok(r == ERROR_UNKNOWN_PRODUCT,
6639        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6640     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6641     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6642
6643     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
6644     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6645
6646     /* InstallProperties key exists */
6647     sz = MAX_PATH;
6648     lstrcpyA(buf, "apple");
6649     r = pMsiGetProductInfoExA(prodcode, NULL,
6650                               MSIINSTALLCONTEXT_MACHINE,
6651                               INSTALLPROPERTY_PRODUCTSTATE, buf, &sz);
6652     ok(r == ERROR_UNKNOWN_PRODUCT,
6653        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6654     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6655     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6656
6657     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6658     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6659
6660     /* LocalPackage value exists */
6661     sz = MAX_PATH;
6662     lstrcpyA(buf, "apple");
6663     r = pMsiGetProductInfoExA(prodcode, NULL,
6664                               MSIINSTALLCONTEXT_MACHINE,
6665                               INSTALLPROPERTY_PRODUCTSTATE, buf, &sz);
6666     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6667     ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
6668     ok(sz == 1, "Expected 1, got %d\n", sz);
6669
6670     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
6671     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6672
6673     /* HelpLink value exists */
6674     sz = MAX_PATH;
6675     lstrcpyA(buf, "apple");
6676     r = pMsiGetProductInfoExA(prodcode, NULL,
6677                               MSIINSTALLCONTEXT_MACHINE,
6678                               INSTALLPROPERTY_HELPLINK, buf, &sz);
6679     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6680     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
6681     ok(sz == 4, "Expected 4, got %d\n", sz);
6682
6683     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
6684     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6685
6686     /* HelpTelephone value exists */
6687     sz = MAX_PATH;
6688     lstrcpyA(buf, "apple");
6689     r = pMsiGetProductInfoExA(prodcode, NULL,
6690                               MSIINSTALLCONTEXT_MACHINE,
6691                               INSTALLPROPERTY_HELPTELEPHONE, buf, &sz);
6692     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6693     ok(!lstrcmpA(buf, "phone"), "Expected \"phone\", got \"%s\"\n", buf);
6694     ok(sz == 5, "Expected 5, got %d\n", sz);
6695
6696     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
6697     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6698
6699     /* InstallDate value exists */
6700     sz = MAX_PATH;
6701     lstrcpyA(buf, "apple");
6702     r = pMsiGetProductInfoExA(prodcode, NULL,
6703                               MSIINSTALLCONTEXT_MACHINE,
6704                               INSTALLPROPERTY_INSTALLDATE, buf, &sz);
6705     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6706     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
6707     ok(sz == 4, "Expected 4, got %d\n", sz);
6708
6709     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
6710     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6711
6712     /* DisplayName value exists */
6713     sz = MAX_PATH;
6714     lstrcpyA(buf, "apple");
6715     r = pMsiGetProductInfoExA(prodcode, NULL,
6716                               MSIINSTALLCONTEXT_MACHINE,
6717                               INSTALLPROPERTY_INSTALLEDPRODUCTNAME, buf, &sz);
6718     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6719     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
6720     ok(sz == 4, "Expected 4, got %d\n", sz);
6721
6722     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
6723     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6724
6725     /* InstallLocation value exists */
6726     sz = MAX_PATH;
6727     lstrcpyA(buf, "apple");
6728     r = pMsiGetProductInfoExA(prodcode, NULL,
6729                               MSIINSTALLCONTEXT_MACHINE,
6730                               INSTALLPROPERTY_INSTALLLOCATION, buf, &sz);
6731     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6732     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
6733     ok(sz == 3, "Expected 3, got %d\n", sz);
6734
6735     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
6736     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6737
6738     /* InstallSource value exists */
6739     sz = MAX_PATH;
6740     lstrcpyA(buf, "apple");
6741     r = pMsiGetProductInfoExA(prodcode, NULL,
6742                               MSIINSTALLCONTEXT_MACHINE,
6743                               INSTALLPROPERTY_INSTALLSOURCE, buf, &sz);
6744     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6745     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
6746     ok(sz == 6, "Expected 6, got %d\n", sz);
6747
6748     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6749     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6750
6751     /* LocalPackage value exists */
6752     sz = MAX_PATH;
6753     lstrcpyA(buf, "apple");
6754     r = pMsiGetProductInfoExA(prodcode, NULL,
6755                               MSIINSTALLCONTEXT_MACHINE,
6756                               INSTALLPROPERTY_LOCALPACKAGE, buf, &sz);
6757     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6758     ok(!lstrcmpA(buf, "local"), "Expected \"local\", got \"%s\"\n", buf);
6759     ok(sz == 5, "Expected 5, got %d\n", sz);
6760
6761     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
6762     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6763
6764     /* Publisher value exists */
6765     sz = MAX_PATH;
6766     lstrcpyA(buf, "apple");
6767     r = pMsiGetProductInfoExA(prodcode, NULL,
6768                               MSIINSTALLCONTEXT_MACHINE,
6769                               INSTALLPROPERTY_PUBLISHER, buf, &sz);
6770     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6771     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
6772     ok(sz == 3, "Expected 3, got %d\n", sz);
6773
6774     res = RegSetValueExA(propkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
6775     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6776
6777     /* URLInfoAbout value exists */
6778     sz = MAX_PATH;
6779     lstrcpyA(buf, "apple");
6780     r = pMsiGetProductInfoExA(prodcode, NULL,
6781                               MSIINSTALLCONTEXT_MACHINE,
6782                               INSTALLPROPERTY_URLINFOABOUT, buf, &sz);
6783     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6784     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
6785     ok(sz == 5, "Expected 5, got %d\n", sz);
6786
6787     res = RegSetValueExA(propkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
6788     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6789
6790     /* URLUpdateInfo value exists */
6791     sz = MAX_PATH;
6792     lstrcpyA(buf, "apple");
6793     r = pMsiGetProductInfoExA(prodcode, NULL,
6794                               MSIINSTALLCONTEXT_MACHINE,
6795                               INSTALLPROPERTY_URLUPDATEINFO, buf, &sz);
6796     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6797     ok(!lstrcmpA(buf, "update"), "Expected \"update\", got \"%s\"\n", buf);
6798     ok(sz == 6, "Expected 6, got %d\n", sz);
6799
6800     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
6801     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6802
6803     /* VersionMinor value exists */
6804     sz = MAX_PATH;
6805     lstrcpyA(buf, "apple");
6806     r = pMsiGetProductInfoExA(prodcode, NULL,
6807                               MSIINSTALLCONTEXT_MACHINE,
6808                               INSTALLPROPERTY_VERSIONMINOR, buf, &sz);
6809     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6810     ok(!lstrcmpA(buf, "2"), "Expected \"2\", got \"%s\"\n", buf);
6811     ok(sz == 1, "Expected 1, got %d\n", sz);
6812
6813     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
6814     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6815
6816     /* VersionMajor value exists */
6817     sz = MAX_PATH;
6818     lstrcpyA(buf, "apple");
6819     r = pMsiGetProductInfoExA(prodcode, NULL,
6820                               MSIINSTALLCONTEXT_MACHINE,
6821                               INSTALLPROPERTY_VERSIONMAJOR, buf, &sz);
6822     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6823     ok(!lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
6824     ok(sz == 1, "Expected 1, got %d\n", sz);
6825
6826     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
6827     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6828
6829     /* DisplayVersion value exists */
6830     sz = MAX_PATH;
6831     lstrcpyA(buf, "apple");
6832     r = pMsiGetProductInfoExA(prodcode, NULL,
6833                               MSIINSTALLCONTEXT_MACHINE,
6834                               INSTALLPROPERTY_VERSIONSTRING, buf, &sz);
6835     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6836     ok(!lstrcmpA(buf, "3.2.1"), "Expected \"3.2.1\", got \"%s\"\n", buf);
6837     ok(sz == 5, "Expected 5, got %d\n", sz);
6838
6839     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
6840     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6841
6842     /* ProductID value exists */
6843     sz = MAX_PATH;
6844     lstrcpyA(buf, "apple");
6845     r = pMsiGetProductInfoExA(prodcode, NULL,
6846                               MSIINSTALLCONTEXT_MACHINE,
6847                               INSTALLPROPERTY_PRODUCTID, buf, &sz);
6848     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6849     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
6850     ok(sz == 2, "Expected 2, got %d\n", sz);
6851
6852     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
6853     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6854
6855     /* RegCompany value exists */
6856     sz = MAX_PATH;
6857     lstrcpyA(buf, "apple");
6858     r = pMsiGetProductInfoExA(prodcode, NULL,
6859                               MSIINSTALLCONTEXT_MACHINE,
6860                               INSTALLPROPERTY_REGCOMPANY, buf, &sz);
6861     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6862     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
6863     ok(sz == 4, "Expected 4, got %d\n", sz);
6864
6865     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
6866     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6867
6868     /* RegOwner value exists */
6869     sz = MAX_PATH;
6870     lstrcpyA(buf, "apple");
6871     r = pMsiGetProductInfoExA(prodcode, NULL,
6872                               MSIINSTALLCONTEXT_MACHINE,
6873                               INSTALLPROPERTY_REGOWNER, buf, &sz);
6874     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6875     ok(!lstrcmpA(buf, "owner"), "Expected \"owner\", got \"%s\"\n", buf);
6876     ok(sz == 5, "Expected 5, got %d\n", sz);
6877
6878     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
6879     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6880
6881     /* Transforms value exists */
6882     sz = MAX_PATH;
6883     lstrcpyA(buf, "apple");
6884     r = pMsiGetProductInfoExA(prodcode, NULL,
6885                               MSIINSTALLCONTEXT_MACHINE,
6886                               INSTALLPROPERTY_TRANSFORMS, buf, &sz);
6887     ok(r == ERROR_UNKNOWN_PRODUCT,
6888        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6889     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6890     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6891
6892     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
6893     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6894
6895     /* Language value exists */
6896     sz = MAX_PATH;
6897     lstrcpyA(buf, "apple");
6898     r = pMsiGetProductInfoExA(prodcode, NULL,
6899                               MSIINSTALLCONTEXT_MACHINE,
6900                               INSTALLPROPERTY_LANGUAGE, buf, &sz);
6901     ok(r == ERROR_UNKNOWN_PRODUCT,
6902        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6903     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6904     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6905
6906     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
6907     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6908
6909     /* ProductName value exists */
6910     sz = MAX_PATH;
6911     lstrcpyA(buf, "apple");
6912     r = pMsiGetProductInfoExA(prodcode, NULL,
6913                               MSIINSTALLCONTEXT_MACHINE,
6914                               INSTALLPROPERTY_PRODUCTNAME, buf, &sz);
6915     ok(r == ERROR_UNKNOWN_PRODUCT,
6916        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6917     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6918     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6919
6920     res = RegSetValueExA(propkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
6921     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6922
6923     /* FIXME */
6924
6925     /* AssignmentType value exists */
6926     sz = MAX_PATH;
6927     lstrcpyA(buf, "apple");
6928     r = pMsiGetProductInfoExA(prodcode, NULL,
6929                               MSIINSTALLCONTEXT_MACHINE,
6930                               INSTALLPROPERTY_ASSIGNMENTTYPE, buf, &sz);
6931     ok(r == ERROR_UNKNOWN_PRODUCT,
6932        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6933     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6934     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6935
6936     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
6937     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6938
6939     /* PackageCode value exists */
6940     sz = MAX_PATH;
6941     lstrcpyA(buf, "apple");
6942     r = pMsiGetProductInfoExA(prodcode, NULL,
6943                               MSIINSTALLCONTEXT_MACHINE,
6944                               INSTALLPROPERTY_PACKAGECODE, buf, &sz);
6945     ok(r == ERROR_UNKNOWN_PRODUCT,
6946        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6947     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6948     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6949
6950     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
6951     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6952
6953     /* Version value exists */
6954     sz = MAX_PATH;
6955     lstrcpyA(buf, "apple");
6956     r = pMsiGetProductInfoExA(prodcode, NULL,
6957                               MSIINSTALLCONTEXT_MACHINE,
6958                               INSTALLPROPERTY_VERSION, buf, &sz);
6959     ok(r == ERROR_UNKNOWN_PRODUCT,
6960        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6961     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6962     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6963
6964     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
6965     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6966
6967     /* ProductIcon value exists */
6968     sz = MAX_PATH;
6969     lstrcpyA(buf, "apple");
6970     r = pMsiGetProductInfoExA(prodcode, NULL,
6971                               MSIINSTALLCONTEXT_MACHINE,
6972                               INSTALLPROPERTY_PRODUCTICON, buf, &sz);
6973     ok(r == ERROR_UNKNOWN_PRODUCT,
6974        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6975     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6976     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6977
6978     res = RegSetValueExA(propkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
6979     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6980
6981     /* PackageName value exists */
6982     sz = MAX_PATH;
6983     lstrcpyA(buf, "apple");
6984     r = pMsiGetProductInfoExA(prodcode, NULL,
6985                               MSIINSTALLCONTEXT_MACHINE,
6986                               INSTALLPROPERTY_PACKAGENAME, buf, &sz);
6987     ok(r == ERROR_UNKNOWN_PRODUCT,
6988        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6989     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6990     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6991
6992     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
6993     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6994
6995     /* AuthorizedLUAApp value exists */
6996     sz = MAX_PATH;
6997     lstrcpyA(buf, "apple");
6998     r = pMsiGetProductInfoExA(prodcode, NULL,
6999                               MSIINSTALLCONTEXT_MACHINE,
7000                               INSTALLPROPERTY_AUTHORIZED_LUA_APP, buf, &sz);
7001     ok(r == ERROR_UNKNOWN_PRODUCT,
7002        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7003     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7004     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7005
7006     RegDeleteValueA(propkey, "AuthorizedLUAApp");
7007     RegDeleteValueA(propkey, "PackageName");
7008     RegDeleteValueA(propkey, "ProductIcon");
7009     RegDeleteValueA(propkey, "Version");
7010     RegDeleteValueA(propkey, "PackageCode");
7011     RegDeleteValueA(propkey, "AssignmentType");
7012     RegDeleteValueA(propkey, "ProductName");
7013     RegDeleteValueA(propkey, "Language");
7014     RegDeleteValueA(propkey, "Transforms");
7015     RegDeleteValueA(propkey, "RegOwner");
7016     RegDeleteValueA(propkey, "RegCompany");
7017     RegDeleteValueA(propkey, "ProductID");
7018     RegDeleteValueA(propkey, "DisplayVersion");
7019     RegDeleteValueA(propkey, "VersionMajor");
7020     RegDeleteValueA(propkey, "VersionMinor");
7021     RegDeleteValueA(propkey, "URLUpdateInfo");
7022     RegDeleteValueA(propkey, "URLInfoAbout");
7023     RegDeleteValueA(propkey, "Publisher");
7024     RegDeleteValueA(propkey, "LocalPackage");
7025     RegDeleteValueA(propkey, "InstallSource");
7026     RegDeleteValueA(propkey, "InstallLocation");
7027     RegDeleteValueA(propkey, "DisplayName");
7028     RegDeleteValueA(propkey, "InstallDate");
7029     RegDeleteValueA(propkey, "HelpTelephone");
7030     RegDeleteValueA(propkey, "HelpLink");
7031     RegDeleteValueA(propkey, "LocalPackage");
7032     delete_key(propkey, "", access & KEY_WOW64_64KEY);
7033     RegCloseKey(propkey);
7034     delete_key(localkey, "", access & KEY_WOW64_64KEY);
7035     RegCloseKey(localkey);
7036
7037     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
7038     lstrcatA(keypath, prod_squashed);
7039
7040     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
7041     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7042
7043     /* local classes product key exists */
7044     sz = MAX_PATH;
7045     lstrcpyA(buf, "apple");
7046     r = pMsiGetProductInfoExA(prodcode, NULL,
7047                               MSIINSTALLCONTEXT_MACHINE,
7048                               INSTALLPROPERTY_PRODUCTSTATE, buf, &sz);
7049     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7050     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
7051     ok(sz == 1, "Expected 1, got %d\n", sz);
7052
7053     res = RegSetValueExA(prodkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
7054     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7055
7056     /* HelpLink value exists */
7057     sz = MAX_PATH;
7058     lstrcpyA(buf, "apple");
7059     r = pMsiGetProductInfoExA(prodcode, NULL,
7060                               MSIINSTALLCONTEXT_MACHINE,
7061                               INSTALLPROPERTY_HELPLINK, buf, &sz);
7062     ok(r == ERROR_UNKNOWN_PROPERTY,
7063        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7064     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7065     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7066
7067     res = RegSetValueExA(prodkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
7068     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7069
7070     /* HelpTelephone value exists */
7071     sz = MAX_PATH;
7072     lstrcpyA(buf, "apple");
7073     r = pMsiGetProductInfoExA(prodcode, NULL,
7074                               MSIINSTALLCONTEXT_MACHINE,
7075                               INSTALLPROPERTY_HELPTELEPHONE, buf, &sz);
7076     ok(r == ERROR_UNKNOWN_PROPERTY,
7077        "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 %d\n", sz);
7080
7081     res = RegSetValueExA(prodkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
7082     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7083
7084     /* InstallDate value exists */
7085     sz = MAX_PATH;
7086     lstrcpyA(buf, "apple");
7087     r = pMsiGetProductInfoExA(prodcode, NULL,
7088                               MSIINSTALLCONTEXT_MACHINE,
7089                               INSTALLPROPERTY_INSTALLDATE, buf, &sz);
7090     ok(r == ERROR_UNKNOWN_PROPERTY,
7091        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7092     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7093     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7094
7095     res = RegSetValueExA(prodkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
7096     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7097
7098     /* DisplayName value exists */
7099     sz = MAX_PATH;
7100     lstrcpyA(buf, "apple");
7101     r = pMsiGetProductInfoExA(prodcode, NULL,
7102                               MSIINSTALLCONTEXT_MACHINE,
7103                               INSTALLPROPERTY_INSTALLEDPRODUCTNAME, buf, &sz);
7104     ok(r == ERROR_UNKNOWN_PROPERTY,
7105        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7106     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7107     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7108
7109     res = RegSetValueExA(prodkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
7110     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7111
7112     /* InstallLocation value exists */
7113     sz = MAX_PATH;
7114     lstrcpyA(buf, "apple");
7115     r = pMsiGetProductInfoExA(prodcode, NULL,
7116                               MSIINSTALLCONTEXT_MACHINE,
7117                               INSTALLPROPERTY_INSTALLLOCATION, buf, &sz);
7118     ok(r == ERROR_UNKNOWN_PROPERTY,
7119        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7120     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7121     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7122
7123     res = RegSetValueExA(prodkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
7124     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7125
7126     /* InstallSource value exists */
7127     sz = MAX_PATH;
7128     lstrcpyA(buf, "apple");
7129     r = pMsiGetProductInfoExA(prodcode, NULL,
7130                               MSIINSTALLCONTEXT_MACHINE,
7131                               INSTALLPROPERTY_INSTALLSOURCE, buf, &sz);
7132     ok(r == ERROR_UNKNOWN_PROPERTY,
7133        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7134     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7135     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7136
7137     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
7138     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7139
7140     /* LocalPackage value exists */
7141     sz = MAX_PATH;
7142     lstrcpyA(buf, "apple");
7143     r = pMsiGetProductInfoExA(prodcode, NULL,
7144                               MSIINSTALLCONTEXT_MACHINE,
7145                               INSTALLPROPERTY_LOCALPACKAGE, buf, &sz);
7146     ok(r == ERROR_UNKNOWN_PROPERTY,
7147        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7148     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7149     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7150
7151     res = RegSetValueExA(prodkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
7152     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7153
7154     /* Publisher value exists */
7155     sz = MAX_PATH;
7156     lstrcpyA(buf, "apple");
7157     r = pMsiGetProductInfoExA(prodcode, NULL,
7158                               MSIINSTALLCONTEXT_MACHINE,
7159                               INSTALLPROPERTY_PUBLISHER, buf, &sz);
7160     ok(r == ERROR_UNKNOWN_PROPERTY,
7161        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7162     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7163     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7164
7165     res = RegSetValueExA(prodkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
7166     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7167
7168     /* URLInfoAbout value exists */
7169     sz = MAX_PATH;
7170     lstrcpyA(buf, "apple");
7171     r = pMsiGetProductInfoExA(prodcode, NULL,
7172                               MSIINSTALLCONTEXT_MACHINE,
7173                               INSTALLPROPERTY_URLINFOABOUT, buf, &sz);
7174     ok(r == ERROR_UNKNOWN_PROPERTY,
7175        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7176     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7177     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7178
7179     res = RegSetValueExA(prodkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
7180     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7181
7182     /* URLUpdateInfo value exists */
7183     sz = MAX_PATH;
7184     lstrcpyA(buf, "apple");
7185     r = pMsiGetProductInfoExA(prodcode, NULL,
7186                               MSIINSTALLCONTEXT_MACHINE,
7187                               INSTALLPROPERTY_URLUPDATEINFO, buf, &sz);
7188     ok(r == ERROR_UNKNOWN_PROPERTY,
7189        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7190     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7191     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7192
7193     res = RegSetValueExA(prodkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
7194     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7195
7196     /* VersionMinor value exists */
7197     sz = MAX_PATH;
7198     lstrcpyA(buf, "apple");
7199     r = pMsiGetProductInfoExA(prodcode, NULL,
7200                               MSIINSTALLCONTEXT_MACHINE,
7201                               INSTALLPROPERTY_VERSIONMINOR, buf, &sz);
7202     ok(r == ERROR_UNKNOWN_PROPERTY,
7203        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7204     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7205     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7206
7207     res = RegSetValueExA(prodkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
7208     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7209
7210     /* VersionMajor value exists */
7211     sz = MAX_PATH;
7212     lstrcpyA(buf, "apple");
7213     r = pMsiGetProductInfoExA(prodcode, NULL,
7214                               MSIINSTALLCONTEXT_MACHINE,
7215                               INSTALLPROPERTY_VERSIONMAJOR, buf, &sz);
7216     ok(r == ERROR_UNKNOWN_PROPERTY,
7217        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7218     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7219     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7220
7221     res = RegSetValueExA(prodkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
7222     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7223
7224     /* DisplayVersion value exists */
7225     sz = MAX_PATH;
7226     lstrcpyA(buf, "apple");
7227     r = pMsiGetProductInfoExA(prodcode, NULL,
7228                               MSIINSTALLCONTEXT_MACHINE,
7229                               INSTALLPROPERTY_VERSIONSTRING, buf, &sz);
7230     ok(r == ERROR_UNKNOWN_PROPERTY,
7231        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7232     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7233     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7234
7235     res = RegSetValueExA(prodkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
7236     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7237
7238     /* ProductID value exists */
7239     sz = MAX_PATH;
7240     lstrcpyA(buf, "apple");
7241     r = pMsiGetProductInfoExA(prodcode, NULL,
7242                               MSIINSTALLCONTEXT_MACHINE,
7243                               INSTALLPROPERTY_PRODUCTID, buf, &sz);
7244     ok(r == ERROR_UNKNOWN_PROPERTY,
7245        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7246     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7247     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7248
7249     res = RegSetValueExA(prodkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
7250     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7251
7252     /* RegCompany value exists */
7253     sz = MAX_PATH;
7254     lstrcpyA(buf, "apple");
7255     r = pMsiGetProductInfoExA(prodcode, NULL,
7256                               MSIINSTALLCONTEXT_MACHINE,
7257                               INSTALLPROPERTY_REGCOMPANY, buf, &sz);
7258     ok(r == ERROR_UNKNOWN_PROPERTY,
7259        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7260     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7261     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7262
7263     res = RegSetValueExA(prodkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
7264     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7265
7266     /* RegOwner value exists */
7267     sz = MAX_PATH;
7268     lstrcpyA(buf, "apple");
7269     r = pMsiGetProductInfoExA(prodcode, NULL,
7270                               MSIINSTALLCONTEXT_MACHINE,
7271                               INSTALLPROPERTY_REGOWNER, buf, &sz);
7272     ok(r == ERROR_UNKNOWN_PROPERTY,
7273        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7274     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7275     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7276
7277     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
7278     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7279
7280     /* Transforms value exists */
7281     sz = MAX_PATH;
7282     lstrcpyA(buf, "apple");
7283     r = pMsiGetProductInfoExA(prodcode, NULL,
7284                               MSIINSTALLCONTEXT_MACHINE,
7285                               INSTALLPROPERTY_TRANSFORMS, buf, &sz);
7286     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7287     ok(!lstrcmpA(buf, "trans"), "Expected \"trans\", got \"%s\"\n", buf);
7288     ok(sz == 5, "Expected 5, got %d\n", sz);
7289
7290     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
7291     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7292
7293     /* Language value exists */
7294     sz = MAX_PATH;
7295     lstrcpyA(buf, "apple");
7296     r = pMsiGetProductInfoExA(prodcode, NULL,
7297                               MSIINSTALLCONTEXT_MACHINE,
7298                               INSTALLPROPERTY_LANGUAGE, buf, &sz);
7299     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7300     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
7301     ok(sz == 4, "Expected 4, got %d\n", sz);
7302
7303     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
7304     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7305
7306     /* ProductName value exists */
7307     sz = MAX_PATH;
7308     lstrcpyA(buf, "apple");
7309     r = pMsiGetProductInfoExA(prodcode, NULL,
7310                               MSIINSTALLCONTEXT_MACHINE,
7311                               INSTALLPROPERTY_PRODUCTNAME, buf, &sz);
7312     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7313     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
7314     ok(sz == 4, "Expected 4, got %d\n", sz);
7315
7316     res = RegSetValueExA(prodkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
7317     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7318
7319     /* FIXME */
7320
7321     /* AssignmentType value exists */
7322     sz = MAX_PATH;
7323     lstrcpyA(buf, "apple");
7324     r = pMsiGetProductInfoExA(prodcode, NULL,
7325                               MSIINSTALLCONTEXT_MACHINE,
7326                               INSTALLPROPERTY_ASSIGNMENTTYPE, buf, &sz);
7327     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7328     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7329     ok(sz == 0, "Expected 0, got %d\n", sz);
7330
7331     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
7332     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7333
7334     /* FIXME */
7335
7336     /* PackageCode value exists */
7337     sz = MAX_PATH;
7338     lstrcpyA(buf, "apple");
7339     r = pMsiGetProductInfoExA(prodcode, NULL,
7340                               MSIINSTALLCONTEXT_MACHINE,
7341                               INSTALLPROPERTY_PACKAGECODE, buf, &sz);
7342     todo_wine
7343     {
7344         ok(r == ERROR_BAD_CONFIGURATION,
7345            "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
7346         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7347         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7348     }
7349
7350     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
7351     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7352
7353     /* Version value exists */
7354     sz = MAX_PATH;
7355     lstrcpyA(buf, "apple");
7356     r = pMsiGetProductInfoExA(prodcode, NULL,
7357                               MSIINSTALLCONTEXT_MACHINE,
7358                               INSTALLPROPERTY_VERSION, buf, &sz);
7359     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7360     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
7361     ok(sz == 3, "Expected 3, got %d\n", sz);
7362
7363     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
7364     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7365
7366     /* ProductIcon value exists */
7367     sz = MAX_PATH;
7368     lstrcpyA(buf, "apple");
7369     r = pMsiGetProductInfoExA(prodcode, NULL,
7370                               MSIINSTALLCONTEXT_MACHINE,
7371                               INSTALLPROPERTY_PRODUCTICON, buf, &sz);
7372     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7373     ok(!lstrcmpA(buf, "icon"), "Expected \"icon\", got \"%s\"\n", buf);
7374     ok(sz == 4, "Expected 4, got %d\n", sz);
7375
7376     res = RegSetValueExA(prodkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
7377     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7378
7379     /* PackageName value exists */
7380     sz = MAX_PATH;
7381     lstrcpyA(buf, "apple");
7382     r = pMsiGetProductInfoExA(prodcode, NULL,
7383                               MSIINSTALLCONTEXT_MACHINE,
7384                               INSTALLPROPERTY_PACKAGENAME, buf, &sz);
7385     todo_wine
7386     {
7387         ok(r == ERROR_UNKNOWN_PRODUCT,
7388            "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7389         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7390         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7391     }
7392
7393     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
7394     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7395
7396     /* AuthorizedLUAApp value exists */
7397     sz = MAX_PATH;
7398     lstrcpyA(buf, "apple");
7399     r = pMsiGetProductInfoExA(prodcode, NULL,
7400                               MSIINSTALLCONTEXT_MACHINE,
7401                               INSTALLPROPERTY_AUTHORIZED_LUA_APP, buf, &sz);
7402     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7403     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
7404     ok(sz == 4, "Expected 4, got %d\n", sz);
7405
7406     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
7407     RegDeleteValueA(prodkey, "PackageName");
7408     RegDeleteValueA(prodkey, "ProductIcon");
7409     RegDeleteValueA(prodkey, "Version");
7410     RegDeleteValueA(prodkey, "PackageCode");
7411     RegDeleteValueA(prodkey, "AssignmentType");
7412     RegDeleteValueA(prodkey, "ProductName");
7413     RegDeleteValueA(prodkey, "Language");
7414     RegDeleteValueA(prodkey, "Transforms");
7415     RegDeleteValueA(prodkey, "RegOwner");
7416     RegDeleteValueA(prodkey, "RegCompany");
7417     RegDeleteValueA(prodkey, "ProductID");
7418     RegDeleteValueA(prodkey, "DisplayVersion");
7419     RegDeleteValueA(prodkey, "VersionMajor");
7420     RegDeleteValueA(prodkey, "VersionMinor");
7421     RegDeleteValueA(prodkey, "URLUpdateInfo");
7422     RegDeleteValueA(prodkey, "URLInfoAbout");
7423     RegDeleteValueA(prodkey, "Publisher");
7424     RegDeleteValueA(prodkey, "LocalPackage");
7425     RegDeleteValueA(prodkey, "InstallSource");
7426     RegDeleteValueA(prodkey, "InstallLocation");
7427     RegDeleteValueA(prodkey, "DisplayName");
7428     RegDeleteValueA(prodkey, "InstallDate");
7429     RegDeleteValueA(prodkey, "HelpTelephone");
7430     RegDeleteValueA(prodkey, "HelpLink");
7431     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
7432     RegCloseKey(prodkey);
7433     LocalFree(usersid);
7434 }
7435
7436 #define INIT_USERINFO() \
7437     lstrcpyA(user, "apple"); \
7438     lstrcpyA(org, "orange"); \
7439     lstrcpyA(serial, "banana"); \
7440     usersz = orgsz = serialsz = MAX_PATH;
7441
7442 static void test_MsiGetUserInfo(void)
7443 {
7444     USERINFOSTATE state;
7445     CHAR user[MAX_PATH];
7446     CHAR org[MAX_PATH];
7447     CHAR serial[MAX_PATH];
7448     DWORD usersz, orgsz, serialsz;
7449     CHAR keypath[MAX_PATH * 2];
7450     CHAR prodcode[MAX_PATH];
7451     CHAR prod_squashed[MAX_PATH];
7452     HKEY prodkey, userprod, props;
7453     LPSTR usersid;
7454     LONG res;
7455     REGSAM access = KEY_ALL_ACCESS;
7456
7457     create_test_guid(prodcode, prod_squashed);
7458     usersid = get_user_sid();
7459
7460     if (is_wow64)
7461         access |= KEY_WOW64_64KEY;
7462
7463     /* NULL szProduct */
7464     INIT_USERINFO();
7465     state = MsiGetUserInfoA(NULL, user, &usersz, org, &orgsz, serial, &serialsz);
7466     ok(state == USERINFOSTATE_INVALIDARG,
7467        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
7468     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
7469     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
7470     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7471     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
7472     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
7473     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
7474
7475     /* empty szProductCode */
7476     INIT_USERINFO();
7477     state = MsiGetUserInfoA("", user, &usersz, org, &orgsz, serial, &serialsz);
7478     ok(state == USERINFOSTATE_INVALIDARG,
7479        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
7480     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
7481     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
7482     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7483     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
7484     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
7485     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
7486
7487     /* garbage szProductCode */
7488     INIT_USERINFO();
7489     state = MsiGetUserInfoA("garbage", user, &usersz, org, &orgsz, serial, &serialsz);
7490     ok(state == USERINFOSTATE_INVALIDARG,
7491        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
7492     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
7493     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
7494     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7495     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
7496     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
7497     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
7498
7499     /* guid without brackets */
7500     INIT_USERINFO();
7501     state = MsiGetUserInfoA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
7502                             user, &usersz, org, &orgsz, serial, &serialsz);
7503     ok(state == USERINFOSTATE_INVALIDARG,
7504        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
7505     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
7506     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
7507     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7508     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
7509     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
7510     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
7511
7512     /* guid with brackets */
7513     INIT_USERINFO();
7514     state = MsiGetUserInfoA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
7515                             user, &usersz, org, &orgsz, serial, &serialsz);
7516     ok(state == USERINFOSTATE_UNKNOWN,
7517        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
7518     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
7519     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
7520     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7521     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
7522     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
7523     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
7524
7525     /* NULL lpUserNameBuf */
7526     INIT_USERINFO();
7527     state = MsiGetUserInfoA(prodcode, NULL, &usersz, org, &orgsz, serial, &serialsz);
7528     ok(state == USERINFOSTATE_UNKNOWN,
7529        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
7530     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
7531     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7532     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
7533     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
7534     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
7535
7536     /* NULL pcchUserNameBuf */
7537     INIT_USERINFO();
7538     state = MsiGetUserInfoA(prodcode, user, NULL, org, &orgsz, serial, &serialsz);
7539     ok(state == USERINFOSTATE_INVALIDARG,
7540        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
7541     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
7542     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
7543     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7544     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
7545     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
7546
7547     /* both lpUserNameBuf and pcchUserNameBuf NULL */
7548     INIT_USERINFO();
7549     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
7550     ok(state == USERINFOSTATE_UNKNOWN,
7551        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
7552     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
7553     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7554     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
7555     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
7556
7557     /* NULL lpOrgNameBuf */
7558     INIT_USERINFO();
7559     state = MsiGetUserInfoA(prodcode, user, &usersz, NULL, &orgsz, serial, &serialsz);
7560     ok(state == USERINFOSTATE_UNKNOWN,
7561        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
7562     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
7563     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7564     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
7565     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
7566     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
7567
7568     /* NULL pcchOrgNameBuf */
7569     INIT_USERINFO();
7570     state = MsiGetUserInfoA(prodcode, user, &usersz, org, NULL, serial, &serialsz);
7571     ok(state == USERINFOSTATE_INVALIDARG,
7572        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
7573     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
7574     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
7575     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7576     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
7577     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
7578
7579     /* both lpOrgNameBuf and pcchOrgNameBuf NULL */
7580     INIT_USERINFO();
7581     state = MsiGetUserInfoA(prodcode, user, &usersz, NULL, NULL, serial, &serialsz);
7582     ok(state == USERINFOSTATE_UNKNOWN,
7583        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
7584     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
7585     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7586     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
7587     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
7588
7589     /* NULL lpSerialBuf */
7590     INIT_USERINFO();
7591     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, NULL, &serialsz);
7592     ok(state == USERINFOSTATE_UNKNOWN,
7593        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
7594     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
7595     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
7596     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
7597     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
7598     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
7599
7600     /* NULL pcchSerialBuf */
7601     INIT_USERINFO();
7602     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, NULL);
7603     ok(state == USERINFOSTATE_INVALIDARG,
7604        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
7605     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
7606     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
7607     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7608     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
7609     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
7610
7611     /* both lpSerialBuf and pcchSerialBuf NULL */
7612     INIT_USERINFO();
7613     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, NULL, NULL);
7614     ok(state == USERINFOSTATE_UNKNOWN,
7615        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
7616     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
7617     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
7618     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
7619     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
7620
7621     /* MSIINSTALLCONTEXT_USERMANAGED */
7622
7623     /* create local system product key */
7624     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
7625     lstrcatA(keypath, usersid);
7626     lstrcatA(keypath, "\\Installer\\Products\\");
7627     lstrcatA(keypath, prod_squashed);
7628
7629     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
7630     if (res == ERROR_ACCESS_DENIED)
7631     {
7632         skip("Not enough rights to perform tests\n");
7633         LocalFree(usersid);
7634         return;
7635     }
7636     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7637
7638     /* managed product key exists */
7639     INIT_USERINFO();
7640     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
7641     ok(state == USERINFOSTATE_ABSENT,
7642        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
7643     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
7644     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
7645     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7646     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
7647     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
7648     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
7649
7650     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
7651     lstrcatA(keypath, "Installer\\UserData\\");
7652     lstrcatA(keypath, usersid);
7653     lstrcatA(keypath, "\\Products\\");
7654     lstrcatA(keypath, prod_squashed);
7655
7656     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL);
7657     if (res == ERROR_ACCESS_DENIED)
7658     {
7659         skip("Not enough rights to perform tests\n");
7660         LocalFree(usersid);
7661         return;
7662     }
7663     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7664
7665     res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
7666     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7667
7668     /* InstallProperties key exists */
7669     INIT_USERINFO();
7670     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
7671     ok(state == USERINFOSTATE_ABSENT,
7672        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
7673     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
7674     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
7675     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7676     ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", usersz);
7677     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
7678     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
7679
7680     /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */
7681     INIT_USERINFO();
7682     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
7683     ok(state == USERINFOSTATE_ABSENT,
7684        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
7685     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
7686     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7687     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
7688     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
7689
7690     /* RegOwner, RegCompany don't exist, out params are NULL */
7691     INIT_USERINFO();
7692     state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz);
7693     ok(state == USERINFOSTATE_ABSENT,
7694        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
7695     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7696     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
7697
7698     res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
7699     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7700
7701     /* RegOwner value exists */
7702     INIT_USERINFO();
7703     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
7704     ok(state == USERINFOSTATE_ABSENT,
7705        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
7706     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
7707     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
7708     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7709     ok(usersz == 5, "Expected 5, got %d\n", usersz);
7710     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
7711     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
7712
7713     res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8);
7714     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7715
7716     /* RegCompany value exists */
7717     INIT_USERINFO();
7718     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
7719     ok(state == USERINFOSTATE_ABSENT,
7720        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
7721     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
7722     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
7723     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7724     ok(usersz == 5, "Expected 5, got %d\n", usersz);
7725     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
7726     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
7727
7728     res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3);
7729     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7730
7731     /* ProductID value exists */
7732     INIT_USERINFO();
7733     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
7734     ok(state == USERINFOSTATE_PRESENT,
7735        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
7736     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
7737     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
7738     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
7739     ok(usersz == 5, "Expected 5, got %d\n", usersz);
7740     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
7741     ok(serialsz == 2, "Expected 2, got %d\n", serialsz);
7742
7743     /* pcchUserNameBuf is too small */
7744     INIT_USERINFO();
7745     usersz = 0;
7746     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
7747     ok(state == USERINFOSTATE_MOREDATA,
7748        "Expected USERINFOSTATE_MOREDATA, got %d\n", state);
7749     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
7750     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
7751     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7752     ok(usersz == 5, "Expected 5, got %d\n", usersz);
7753     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
7754     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
7755
7756     /* pcchUserNameBuf has no room for NULL terminator */
7757     INIT_USERINFO();
7758     usersz = 5;
7759     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
7760     ok(state == USERINFOSTATE_MOREDATA,
7761        "Expected USERINFOSTATE_MOREDATA, got %d\n", state);
7762     todo_wine
7763     {
7764         ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
7765     }
7766     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
7767     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7768     ok(usersz == 5, "Expected 5, got %d\n", usersz);
7769     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
7770     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
7771
7772     /* pcchUserNameBuf is too small, lpUserNameBuf is NULL */
7773     INIT_USERINFO();
7774     usersz = 0;
7775     state = MsiGetUserInfoA(prodcode, NULL, &usersz, org, &orgsz, serial, &serialsz);
7776     ok(state == USERINFOSTATE_PRESENT,
7777        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
7778     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
7779     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
7780     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
7781     ok(usersz == 5, "Expected 5, got %d\n", usersz);
7782     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
7783     ok(serialsz == 2, "Expected 2, got %d\n", serialsz);
7784
7785     RegDeleteValueA(props, "ProductID");
7786     RegDeleteValueA(props, "RegCompany");
7787     RegDeleteValueA(props, "RegOwner");
7788     delete_key(props, "", access & KEY_WOW64_64KEY);
7789     RegCloseKey(props);
7790     delete_key(userprod, "", access & KEY_WOW64_64KEY);
7791     RegCloseKey(userprod);
7792     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
7793     RegCloseKey(prodkey);
7794
7795     /* MSIINSTALLCONTEXT_USERUNMANAGED */
7796
7797     /* create local system product key */
7798     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
7799     lstrcatA(keypath, prod_squashed);
7800
7801     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
7802     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7803
7804     /* product key exists */
7805     INIT_USERINFO();
7806     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
7807     ok(state == USERINFOSTATE_ABSENT,
7808        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
7809     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
7810     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
7811     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7812     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
7813     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
7814     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
7815
7816     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
7817     lstrcatA(keypath, "Installer\\UserData\\");
7818     lstrcatA(keypath, usersid);
7819     lstrcatA(keypath, "\\Products\\");
7820     lstrcatA(keypath, prod_squashed);
7821
7822     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL);
7823     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7824
7825     res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
7826     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7827
7828     /* InstallProperties key exists */
7829     INIT_USERINFO();
7830     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
7831     ok(state == USERINFOSTATE_ABSENT,
7832        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
7833     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
7834     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
7835     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7836     ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", usersz);
7837     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
7838     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
7839
7840     /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */
7841     INIT_USERINFO();
7842     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
7843     ok(state == USERINFOSTATE_ABSENT,
7844        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
7845     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
7846     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7847     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
7848     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
7849
7850     /* RegOwner, RegCompany don't exist, out params are NULL */
7851     INIT_USERINFO();
7852     state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz);
7853     ok(state == USERINFOSTATE_ABSENT,
7854        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
7855     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7856     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
7857
7858     res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
7859     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7860
7861     /* RegOwner value exists */
7862     INIT_USERINFO();
7863     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
7864     ok(state == USERINFOSTATE_ABSENT,
7865        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
7866     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
7867     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
7868     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7869     ok(usersz == 5, "Expected 5, got %d\n", usersz);
7870     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
7871     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
7872
7873     res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8);
7874     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7875
7876     /* RegCompany value exists */
7877     INIT_USERINFO();
7878     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
7879     ok(state == USERINFOSTATE_ABSENT,
7880        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
7881     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
7882     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
7883     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7884     ok(usersz == 5, "Expected 5, got %d\n", usersz);
7885     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
7886     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
7887
7888     res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3);
7889     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7890
7891     /* ProductID value exists */
7892     INIT_USERINFO();
7893     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
7894     ok(state == USERINFOSTATE_PRESENT,
7895        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
7896     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
7897     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
7898     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
7899     ok(usersz == 5, "Expected 5, got %d\n", usersz);
7900     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
7901     ok(serialsz == 2, "Expected 2, got %d\n", serialsz);
7902
7903     RegDeleteValueA(props, "ProductID");
7904     RegDeleteValueA(props, "RegCompany");
7905     RegDeleteValueA(props, "RegOwner");
7906     delete_key(props, "", access & KEY_WOW64_64KEY);
7907     RegCloseKey(props);
7908     delete_key(userprod, "", access & KEY_WOW64_64KEY);
7909     RegCloseKey(userprod);
7910     RegDeleteKeyA(prodkey, "");
7911     RegCloseKey(prodkey);
7912
7913     /* MSIINSTALLCONTEXT_MACHINE */
7914
7915     /* create local system product key */
7916     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
7917     lstrcatA(keypath, prod_squashed);
7918
7919     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
7920     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7921
7922     /* product key exists */
7923     INIT_USERINFO();
7924     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
7925     ok(state == USERINFOSTATE_ABSENT,
7926        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
7927     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
7928     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
7929     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7930     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
7931     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
7932     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
7933
7934     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
7935     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18");
7936     lstrcatA(keypath, "\\Products\\");
7937     lstrcatA(keypath, prod_squashed);
7938
7939     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL);
7940     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7941
7942     res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
7943     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7944
7945     /* InstallProperties key exists */
7946     INIT_USERINFO();
7947     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
7948     ok(state == USERINFOSTATE_ABSENT,
7949        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
7950     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
7951     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
7952     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7953     ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", usersz);
7954     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
7955     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
7956
7957     /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */
7958     INIT_USERINFO();
7959     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
7960     ok(state == USERINFOSTATE_ABSENT,
7961        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
7962     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
7963     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7964     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
7965     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
7966
7967     /* RegOwner, RegCompany don't exist, out params are NULL */
7968     INIT_USERINFO();
7969     state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz);
7970     ok(state == USERINFOSTATE_ABSENT,
7971        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
7972     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7973     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
7974
7975     res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
7976     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7977
7978     /* RegOwner value exists */
7979     INIT_USERINFO();
7980     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
7981     ok(state == USERINFOSTATE_ABSENT,
7982        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
7983     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
7984     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
7985     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
7986     ok(usersz == 5, "Expected 5, got %d\n", usersz);
7987     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
7988     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
7989
7990     res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8);
7991     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7992
7993     /* RegCompany value exists */
7994     INIT_USERINFO();
7995     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
7996     ok(state == USERINFOSTATE_ABSENT,
7997        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
7998     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
7999     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8000     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8001     ok(usersz == 5, "Expected 5, got %d\n", usersz);
8002     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
8003     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
8004
8005     res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3);
8006     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8007
8008     /* ProductID value exists */
8009     INIT_USERINFO();
8010     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8011     ok(state == USERINFOSTATE_PRESENT,
8012        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
8013     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
8014     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
8015     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
8016     ok(usersz == 5, "Expected 5, got %d\n", usersz);
8017     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
8018     ok(serialsz == 2, "Expected 2, got %d\n", serialsz);
8019
8020     RegDeleteValueA(props, "ProductID");
8021     RegDeleteValueA(props, "RegCompany");
8022     RegDeleteValueA(props, "RegOwner");
8023     delete_key(props, "", access & KEY_WOW64_64KEY);
8024     RegCloseKey(props);
8025     delete_key(userprod, "", access & KEY_WOW64_64KEY);
8026     RegCloseKey(userprod);
8027     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
8028     RegCloseKey(prodkey);
8029     LocalFree(usersid);
8030 }
8031
8032 static void test_MsiOpenProduct(void)
8033 {
8034     MSIHANDLE hprod, hdb;
8035     CHAR val[MAX_PATH];
8036     CHAR path[MAX_PATH];
8037     CHAR keypath[MAX_PATH*2];
8038     CHAR prodcode[MAX_PATH];
8039     CHAR prod_squashed[MAX_PATH];
8040     HKEY prodkey, userkey, props;
8041     LPSTR usersid;
8042     DWORD size;
8043     LONG res;
8044     UINT r;
8045     REGSAM access = KEY_ALL_ACCESS;
8046
8047     GetCurrentDirectoryA(MAX_PATH, path);
8048     lstrcatA(path, "\\");
8049
8050     create_test_guid(prodcode, prod_squashed);
8051     usersid = get_user_sid();
8052
8053     if (is_wow64)
8054         access |= KEY_WOW64_64KEY;
8055
8056     hdb = create_package_db(prodcode);
8057     MsiCloseHandle(hdb);
8058
8059     /* NULL szProduct */
8060     hprod = 0xdeadbeef;
8061     r = MsiOpenProductA(NULL, &hprod);
8062     ok(r == ERROR_INVALID_PARAMETER,
8063        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8064     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8065
8066     /* empty szProduct */
8067     hprod = 0xdeadbeef;
8068     r = MsiOpenProductA("", &hprod);
8069     ok(r == ERROR_INVALID_PARAMETER,
8070        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8071     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8072
8073     /* garbage szProduct */
8074     hprod = 0xdeadbeef;
8075     r = MsiOpenProductA("garbage", &hprod);
8076     ok(r == ERROR_INVALID_PARAMETER,
8077        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8078     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8079
8080     /* guid without brackets */
8081     hprod = 0xdeadbeef;
8082     r = MsiOpenProductA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", &hprod);
8083     ok(r == ERROR_INVALID_PARAMETER,
8084        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8085     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8086
8087     /* guid with brackets */
8088     hprod = 0xdeadbeef;
8089     r = MsiOpenProductA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", &hprod);
8090     ok(r == ERROR_UNKNOWN_PRODUCT,
8091        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8092     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8093
8094     /* same length as guid, but random */
8095     hprod = 0xdeadbeef;
8096     r = MsiOpenProductA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", &hprod);
8097     ok(r == ERROR_INVALID_PARAMETER,
8098        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8099     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8100
8101     /* hProduct is NULL */
8102     hprod = 0xdeadbeef;
8103     r = MsiOpenProductA(prodcode, NULL);
8104     ok(r == ERROR_INVALID_PARAMETER,
8105        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8106     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8107
8108     /* MSIINSTALLCONTEXT_USERMANAGED */
8109
8110     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8111     lstrcatA(keypath, "Installer\\Managed\\");
8112     lstrcatA(keypath, usersid);
8113     lstrcatA(keypath, "\\Installer\\Products\\");
8114     lstrcatA(keypath, prod_squashed);
8115
8116     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8117     if (res == ERROR_ACCESS_DENIED)
8118     {
8119         skip("Not enough rights to perform tests\n");
8120         LocalFree(usersid);
8121         return;
8122     }
8123     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8124
8125     /* managed product key exists */
8126     hprod = 0xdeadbeef;
8127     r = MsiOpenProductA(prodcode, &hprod);
8128     ok(r == ERROR_UNKNOWN_PRODUCT,
8129        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8130     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8131
8132     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8133     lstrcatA(keypath, "Installer\\UserData\\");
8134     lstrcatA(keypath, usersid);
8135     lstrcatA(keypath, "\\Products\\");
8136     lstrcatA(keypath, prod_squashed);
8137
8138     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
8139     if (res == ERROR_ACCESS_DENIED)
8140     {
8141         skip("Not enough rights to perform tests\n");
8142         LocalFree(usersid);
8143         return;
8144     }
8145     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8146
8147     /* user product key exists */
8148     hprod = 0xdeadbeef;
8149     r = MsiOpenProductA(prodcode, &hprod);
8150     ok(r == ERROR_UNKNOWN_PRODUCT,
8151        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8152     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8153
8154     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8155     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8156
8157     /* InstallProperties key exists */
8158     hprod = 0xdeadbeef;
8159     r = MsiOpenProductA(prodcode, &hprod);
8160     ok(r == ERROR_UNKNOWN_PRODUCT,
8161        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8162     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8163
8164     lstrcpyA(val, path);
8165     lstrcatA(val, "\\winetest.msi");
8166     res = RegSetValueExA(props, "ManagedLocalPackage", 0, REG_SZ,
8167                          (const BYTE *)val, lstrlenA(val) + 1);
8168     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8169
8170     /* ManagedLocalPackage value exists */
8171     hprod = 0xdeadbeef;
8172     r = MsiOpenProductA(prodcode, &hprod);
8173     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8174     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
8175
8176     size = MAX_PATH;
8177     r = MsiGetPropertyA(hprod, "ProductCode", val, &size);
8178     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8179     ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val);
8180     ok(size == lstrlenA(prodcode), "Expected %d, got %d\n", lstrlenA(prodcode), size);
8181
8182     MsiCloseHandle(hprod);
8183
8184     RegDeleteValueA(props, "ManagedLocalPackage");
8185     delete_key(props, "", access & KEY_WOW64_64KEY);
8186     RegCloseKey(props);
8187     delete_key(userkey, "", access & KEY_WOW64_64KEY);
8188     RegCloseKey(userkey);
8189     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
8190     RegCloseKey(prodkey);
8191
8192     /* MSIINSTALLCONTEXT_USERUNMANAGED */
8193
8194     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
8195     lstrcatA(keypath, prod_squashed);
8196
8197     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
8198     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8199
8200     /* unmanaged product key exists */
8201     hprod = 0xdeadbeef;
8202     r = MsiOpenProductA(prodcode, &hprod);
8203     ok(r == ERROR_UNKNOWN_PRODUCT,
8204        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8205     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8206
8207     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8208     lstrcatA(keypath, "Installer\\UserData\\");
8209     lstrcatA(keypath, usersid);
8210     lstrcatA(keypath, "\\Products\\");
8211     lstrcatA(keypath, prod_squashed);
8212
8213     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
8214     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8215
8216     /* user product key exists */
8217     hprod = 0xdeadbeef;
8218     r = MsiOpenProductA(prodcode, &hprod);
8219     ok(r == ERROR_UNKNOWN_PRODUCT,
8220        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8221     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8222
8223     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8224     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8225
8226     /* InstallProperties key exists */
8227     hprod = 0xdeadbeef;
8228     r = MsiOpenProductA(prodcode, &hprod);
8229     ok(r == ERROR_UNKNOWN_PRODUCT,
8230        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8231     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8232
8233     lstrcpyA(val, path);
8234     lstrcatA(val, "\\winetest.msi");
8235     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
8236                          (const BYTE *)val, lstrlenA(val) + 1);
8237     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8238
8239     /* LocalPackage value exists */
8240     hprod = 0xdeadbeef;
8241     r = MsiOpenProductA(prodcode, &hprod);
8242     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8243     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
8244
8245     size = MAX_PATH;
8246     r = MsiGetPropertyA(hprod, "ProductCode", val, &size);
8247     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8248     ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val);
8249     ok(size == lstrlenA(prodcode), "Expected %d, got %d\n", lstrlenA(prodcode), size);
8250
8251     MsiCloseHandle(hprod);
8252
8253     RegDeleteValueA(props, "LocalPackage");
8254     delete_key(props, "", access & KEY_WOW64_64KEY);
8255     RegCloseKey(props);
8256     delete_key(userkey, "", access & KEY_WOW64_64KEY);
8257     RegCloseKey(userkey);
8258     RegDeleteKeyA(prodkey, "");
8259     RegCloseKey(prodkey);
8260
8261     /* MSIINSTALLCONTEXT_MACHINE */
8262
8263     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
8264     lstrcatA(keypath, prod_squashed);
8265
8266     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8267     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8268
8269     /* managed product key exists */
8270     hprod = 0xdeadbeef;
8271     r = MsiOpenProductA(prodcode, &hprod);
8272     ok(r == ERROR_UNKNOWN_PRODUCT,
8273        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8274     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8275
8276     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8277     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
8278     lstrcatA(keypath, prod_squashed);
8279
8280     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
8281     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8282
8283     /* user product key exists */
8284     hprod = 0xdeadbeef;
8285     r = MsiOpenProductA(prodcode, &hprod);
8286     ok(r == ERROR_UNKNOWN_PRODUCT,
8287        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8288     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8289
8290     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8291     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8292
8293     /* InstallProperties key exists */
8294     hprod = 0xdeadbeef;
8295     r = MsiOpenProductA(prodcode, &hprod);
8296     ok(r == ERROR_UNKNOWN_PRODUCT,
8297        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8298     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8299
8300     lstrcpyA(val, path);
8301     lstrcatA(val, "\\winetest.msi");
8302     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
8303                          (const BYTE *)val, lstrlenA(val) + 1);
8304     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8305
8306     /* LocalPackage value exists */
8307     hprod = 0xdeadbeef;
8308     r = MsiOpenProductA(prodcode, &hprod);
8309     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8310     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
8311
8312     size = MAX_PATH;
8313     r = MsiGetPropertyA(hprod, "ProductCode", val, &size);
8314     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8315     ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val);
8316     ok(size == lstrlenA(prodcode), "Expected %d, got %d\n", lstrlenA(prodcode), size);
8317
8318     MsiCloseHandle(hprod);
8319
8320     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
8321                          (const BYTE *)"winetest.msi", 13);
8322     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8323
8324     /* LocalPackage has just the package name */
8325     hprod = 0xdeadbeef;
8326     r = MsiOpenProductA(prodcode, &hprod);
8327     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8328     {
8329         skip("Not enough rights to perform tests\n");
8330         goto error;
8331     }
8332     ok(r == ERROR_INSTALL_PACKAGE_OPEN_FAILED || r == ERROR_SUCCESS,
8333        "Expected ERROR_INSTALL_PACKAGE_OPEN_FAILED or ERROR_SUCCESS, got %d\n", r);
8334     if (r == ERROR_SUCCESS)
8335         MsiCloseHandle(hprod);
8336     else
8337         ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8338
8339     lstrcpyA(val, path);
8340     lstrcatA(val, "\\winetest.msi");
8341     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
8342                          (const BYTE *)val, lstrlenA(val) + 1);
8343     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8344
8345     DeleteFileA(msifile);
8346
8347     /* local package does not exist */
8348     hprod = 0xdeadbeef;
8349     r = MsiOpenProductA(prodcode, &hprod);
8350     ok(r == ERROR_UNKNOWN_PRODUCT,
8351        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8352     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
8353
8354 error:
8355     RegDeleteValueA(props, "LocalPackage");
8356     delete_key(props, "", access & KEY_WOW64_64KEY);
8357     RegCloseKey(props);
8358     delete_key(userkey, "", access & KEY_WOW64_64KEY);
8359     RegCloseKey(userkey);
8360     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
8361     RegCloseKey(prodkey);
8362
8363     DeleteFileA(msifile);
8364     LocalFree(usersid);
8365 }
8366
8367 static void test_MsiEnumPatchesEx_usermanaged(LPCSTR usersid, LPCSTR expectedsid)
8368 {
8369     MSIINSTALLCONTEXT context;
8370     CHAR keypath[MAX_PATH], patch[MAX_PATH];
8371     CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
8372     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
8373     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
8374     HKEY prodkey, patches, udprod, udpatch, hpatch;
8375     DWORD size, data;
8376     LONG res;
8377     UINT r;
8378     REGSAM access = KEY_ALL_ACCESS;
8379
8380     create_test_guid(prodcode, prod_squashed);
8381     create_test_guid(patch, patch_squashed);
8382
8383     if (is_wow64)
8384         access |= KEY_WOW64_64KEY;
8385
8386     /* MSIPATCHSTATE_APPLIED */
8387
8388     lstrcpyA(patchcode, "apple");
8389     lstrcpyA(targetprod, "banana");
8390     context = 0xdeadbeef;
8391     lstrcpyA(targetsid, "kiwi");
8392     size = MAX_PATH;
8393     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8394                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
8395                            &context, targetsid, &size);
8396     if (r == ERROR_ACCESS_DENIED)
8397     {
8398         skip("Not enough rights to perform tests\n");
8399         return;
8400     }
8401     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8402     ok(!lstrcmpA(patchcode, "apple"),
8403        "Expected patchcode to be unchanged, got %s\n", patchcode);
8404     ok(!lstrcmpA(targetprod, "banana"),
8405        "Expected targetprod to be unchanged, got %s\n", targetprod);
8406     ok(context == 0xdeadbeef,
8407        "Expected context to be unchanged, got %d\n", context);
8408     ok(!lstrcmpA(targetsid, "kiwi"),
8409        "Expected targetsid to be unchanged, got %s\n", targetsid);
8410     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8411
8412     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
8413     lstrcatA(keypath, expectedsid);
8414     lstrcatA(keypath, "\\Installer\\Products\\");
8415     lstrcatA(keypath, prod_squashed);
8416
8417     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8418     if (res == ERROR_ACCESS_DENIED)
8419     {
8420         skip("Not enough rights to perform tests\n");
8421         return;
8422     }
8423     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8424
8425     /* managed product key exists */
8426     lstrcpyA(patchcode, "apple");
8427     lstrcpyA(targetprod, "banana");
8428     context = 0xdeadbeef;
8429     lstrcpyA(targetsid, "kiwi");
8430     size = MAX_PATH;
8431     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8432                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
8433                            &context, targetsid, &size);
8434     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8435     ok(!lstrcmpA(patchcode, "apple"),
8436        "Expected patchcode to be unchanged, got %s\n", patchcode);
8437     ok(!lstrcmpA(targetprod, "banana"),
8438        "Expected targetprod to be unchanged, got %s\n", targetprod);
8439     ok(context == 0xdeadbeef,
8440        "Expected context to be unchanged, got %d\n", context);
8441     ok(!lstrcmpA(targetsid, "kiwi"),
8442        "Expected targetsid to be unchanged, got %s\n", targetsid);
8443     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8444
8445     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
8446     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8447
8448     /* patches key exists */
8449     lstrcpyA(patchcode, "apple");
8450     lstrcpyA(targetprod, "banana");
8451     context = 0xdeadbeef;
8452     lstrcpyA(targetsid, "kiwi");
8453     size = MAX_PATH;
8454     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8455                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
8456                            &context, targetsid, &size);
8457     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8458     ok(!lstrcmpA(patchcode, "apple"),
8459        "Expected patchcode to be unchanged, got %s\n", patchcode);
8460     ok(!lstrcmpA(targetprod, "banana"),
8461        "Expected targetprod to be unchanged, got %s\n", targetprod);
8462     ok(context == 0xdeadbeef,
8463        "Expected context to be unchanged, got %d\n", context);
8464     ok(!lstrcmpA(targetsid, "kiwi"),
8465        "Expected targetsid to be unchanged, got %s\n", targetsid);
8466     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8467
8468     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
8469                          (const BYTE *)patch_squashed,
8470                          lstrlenA(patch_squashed) + 1);
8471     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8472
8473     /* Patches value exists, is not REG_MULTI_SZ */
8474     lstrcpyA(patchcode, "apple");
8475     lstrcpyA(targetprod, "banana");
8476     context = 0xdeadbeef;
8477     lstrcpyA(targetsid, "kiwi");
8478     size = MAX_PATH;
8479     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8480                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
8481                            &context, targetsid, &size);
8482     ok(r == ERROR_BAD_CONFIGURATION,
8483        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
8484     ok(!lstrcmpA(patchcode, "apple"),
8485        "Expected patchcode to be unchanged, got %s\n", patchcode);
8486     ok(!lstrcmpA(targetprod, "banana"),
8487        "Expected targetprod to be unchanged, got %s\n", targetprod);
8488     ok(context == 0xdeadbeef,
8489        "Expected context to be unchanged, got %d\n", context);
8490     ok(!lstrcmpA(targetsid, "kiwi"),
8491        "Expected targetsid to be unchanged, got %s\n", targetsid);
8492     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8493
8494     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
8495                          (const BYTE *)"a\0b\0c\0\0", 7);
8496     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8497
8498     /* Patches value exists, is not a squashed guid */
8499     lstrcpyA(patchcode, "apple");
8500     lstrcpyA(targetprod, "banana");
8501     context = 0xdeadbeef;
8502     lstrcpyA(targetsid, "kiwi");
8503     size = MAX_PATH;
8504     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8505                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
8506                            &context, targetsid, &size);
8507     ok(r == ERROR_BAD_CONFIGURATION,
8508        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
8509     ok(!lstrcmpA(patchcode, "apple"),
8510        "Expected patchcode to be unchanged, got %s\n", patchcode);
8511     ok(!lstrcmpA(targetprod, "banana"),
8512        "Expected targetprod to be unchanged, got %s\n", targetprod);
8513     ok(context == 0xdeadbeef,
8514        "Expected context to be unchanged, got %d\n", context);
8515     ok(!lstrcmpA(targetsid, "kiwi"),
8516        "Expected targetsid to be unchanged, got %s\n", targetsid);
8517     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8518
8519     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
8520     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
8521                          (const BYTE *)patch_squashed,
8522                          lstrlenA(patch_squashed) + 2);
8523     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8524
8525     /* Patches value exists */
8526     lstrcpyA(patchcode, "apple");
8527     lstrcpyA(targetprod, "banana");
8528     context = 0xdeadbeef;
8529     lstrcpyA(targetsid, "kiwi");
8530     size = MAX_PATH;
8531     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8532                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
8533                            &context, targetsid, &size);
8534     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8535     ok(!lstrcmpA(patchcode, "apple"),
8536        "Expected patchcode to be unchanged, got %s\n", patchcode);
8537     ok(!lstrcmpA(targetprod, "banana"),
8538        "Expected targetprod to be unchanged, got %s\n", targetprod);
8539     ok(context == 0xdeadbeef,
8540        "Expected context to be unchanged, got %d\n", context);
8541     ok(!lstrcmpA(targetsid, "kiwi"),
8542        "Expected targetsid to be unchanged, got %s\n", targetsid);
8543     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8544
8545     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
8546                          (const BYTE *)"whatever", 9);
8547     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8548
8549     /* patch squashed value exists */
8550     lstrcpyA(patchcode, "apple");
8551     lstrcpyA(targetprod, "banana");
8552     context = 0xdeadbeef;
8553     lstrcpyA(targetsid, "kiwi");
8554     size = MAX_PATH;
8555     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8556                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
8557                            &context, targetsid, &size);
8558     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8559     ok(!lstrcmpA(patchcode, patch),
8560        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
8561     ok(!lstrcmpA(targetprod, prodcode),
8562        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
8563     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
8564        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
8565     ok(!lstrcmpA(targetsid, expectedsid),
8566        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
8567     ok(size == lstrlenA(expectedsid),
8568        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
8569
8570     /* increase the index */
8571     lstrcpyA(patchcode, "apple");
8572     lstrcpyA(targetprod, "banana");
8573     context = 0xdeadbeef;
8574     lstrcpyA(targetsid, "kiwi");
8575     size = MAX_PATH;
8576     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8577                            MSIPATCHSTATE_APPLIED, 1, patchcode, targetprod,
8578                            &context, targetsid, &size);
8579     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8580     ok(!lstrcmpA(patchcode, "apple"),
8581        "Expected patchcode to be unchanged, got %s\n", patchcode);
8582     ok(!lstrcmpA(targetprod, "banana"),
8583        "Expected targetprod to be unchanged, got %s\n", targetprod);
8584     ok(context == 0xdeadbeef,
8585        "Expected context to be unchanged, got %d\n", context);
8586     ok(!lstrcmpA(targetsid, "kiwi"),
8587        "Expected targetsid to be unchanged, got %s\n", targetsid);
8588     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8589
8590     /* increase again */
8591     lstrcpyA(patchcode, "apple");
8592     lstrcpyA(targetprod, "banana");
8593     context = 0xdeadbeef;
8594     lstrcpyA(targetsid, "kiwi");
8595     size = MAX_PATH;
8596     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8597                            MSIPATCHSTATE_APPLIED, 2, patchcode, targetprod,
8598                            &context, targetsid, &size);
8599     ok(r == ERROR_INVALID_PARAMETER,
8600        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8601     ok(!lstrcmpA(patchcode, "apple"),
8602        "Expected patchcode to be unchanged, got %s\n", patchcode);
8603     ok(!lstrcmpA(targetprod, "banana"),
8604        "Expected targetprod to be unchanged, got %s\n", targetprod);
8605     ok(context == 0xdeadbeef,
8606        "Expected context to be unchanged, got %d\n", context);
8607     ok(!lstrcmpA(targetsid, "kiwi"),
8608        "Expected targetsid to be unchanged, got %s\n", targetsid);
8609     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8610
8611     /* szPatchCode is NULL */
8612     lstrcpyA(targetprod, "banana");
8613     context = 0xdeadbeef;
8614     lstrcpyA(targetsid, "kiwi");
8615     size = MAX_PATH;
8616     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8617                            MSIPATCHSTATE_APPLIED, 0, NULL, targetprod,
8618                            &context, targetsid, &size);
8619     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8620     ok(!lstrcmpA(targetprod, prodcode),
8621        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
8622     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
8623        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
8624     ok(!lstrcmpA(targetsid, expectedsid),
8625        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
8626     ok(size == lstrlenA(expectedsid),
8627        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
8628
8629     /* szTargetProductCode is NULL */
8630     lstrcpyA(patchcode, "apple");
8631     context = 0xdeadbeef;
8632     lstrcpyA(targetsid, "kiwi");
8633     size = MAX_PATH;
8634     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8635                            MSIPATCHSTATE_APPLIED, 0, patchcode, NULL,
8636                            &context, targetsid, &size);
8637     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8638     ok(!lstrcmpA(patchcode, patch),
8639        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
8640     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
8641        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
8642     ok(!lstrcmpA(targetsid, expectedsid),
8643        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
8644     ok(size == lstrlenA(expectedsid),
8645        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
8646
8647     /* pdwTargetProductContext is NULL */
8648     lstrcpyA(patchcode, "apple");
8649     lstrcpyA(targetprod, "banana");
8650     lstrcpyA(targetsid, "kiwi");
8651     size = MAX_PATH;
8652     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8653                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
8654                            NULL, targetsid, &size);
8655     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8656     ok(!lstrcmpA(patchcode, patch),
8657        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
8658     ok(!lstrcmpA(targetprod, prodcode),
8659        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
8660     ok(!lstrcmpA(targetsid, expectedsid),
8661        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
8662     ok(size == lstrlenA(expectedsid),
8663        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
8664
8665     /* szTargetUserSid is NULL */
8666     lstrcpyA(patchcode, "apple");
8667     lstrcpyA(targetprod, "banana");
8668     context = 0xdeadbeef;
8669     size = MAX_PATH;
8670     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8671                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
8672                            &context, NULL, &size);
8673     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8674     ok(!lstrcmpA(patchcode, patch),
8675        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
8676     ok(!lstrcmpA(targetprod, prodcode),
8677        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
8678     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
8679        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
8680     ok(size == lstrlenA(expectedsid) * sizeof(WCHAR),
8681        "Expected %d*sizeof(WCHAR), got %d\n", lstrlenA(expectedsid), size);
8682
8683     /* pcchTargetUserSid is exactly the length of szTargetUserSid */
8684     lstrcpyA(patchcode, "apple");
8685     lstrcpyA(targetprod, "banana");
8686     context = 0xdeadbeef;
8687     lstrcpyA(targetsid, "kiwi");
8688     size = lstrlenA(expectedsid);
8689     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8690                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
8691                            &context, targetsid, &size);
8692     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8693     ok(!lstrcmpA(patchcode, patch),
8694        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
8695     ok(!lstrcmpA(targetprod, prodcode),
8696        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
8697     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
8698        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
8699     ok(!strncmp(targetsid, expectedsid, lstrlenA(expectedsid) - 1),
8700        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
8701     ok(size == lstrlenA(expectedsid) * sizeof(WCHAR),
8702        "Expected %d*sizeof(WCHAR), got %d\n", lstrlenA(expectedsid), size);
8703
8704     /* pcchTargetUserSid has enough room for NULL terminator */
8705     lstrcpyA(patchcode, "apple");
8706     lstrcpyA(targetprod, "banana");
8707     context = 0xdeadbeef;
8708     lstrcpyA(targetsid, "kiwi");
8709     size = lstrlenA(expectedsid) + 1;
8710     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8711                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
8712                            &context, targetsid, &size);
8713     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8714     ok(!lstrcmpA(patchcode, patch),
8715        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
8716     ok(!lstrcmpA(targetprod, prodcode),
8717        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
8718     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
8719        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
8720     ok(!lstrcmpA(targetsid, expectedsid),
8721        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
8722     ok(size == lstrlenA(expectedsid),
8723        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
8724
8725     /* both szTargetuserSid and pcchTargetUserSid are NULL */
8726     lstrcpyA(patchcode, "apple");
8727     lstrcpyA(targetprod, "banana");
8728     context = 0xdeadbeef;
8729     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8730                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
8731                            &context, NULL, NULL);
8732     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8733     ok(!lstrcmpA(patchcode, patch),
8734        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
8735     ok(!lstrcmpA(targetprod, prodcode),
8736        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
8737     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
8738        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
8739
8740     /* MSIPATCHSTATE_SUPERSEDED */
8741
8742     lstrcpyA(patchcode, "apple");
8743     lstrcpyA(targetprod, "banana");
8744     context = 0xdeadbeef;
8745     lstrcpyA(targetsid, "kiwi");
8746     size = MAX_PATH;
8747     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8748                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
8749                            &context, targetsid, &size);
8750     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8751     ok(!lstrcmpA(patchcode, "apple"),
8752        "Expected patchcode to be unchanged, got %s\n", patchcode);
8753     ok(!lstrcmpA(targetprod, "banana"),
8754        "Expected targetprod to be unchanged, got %s\n", targetprod);
8755     ok(context == 0xdeadbeef,
8756        "Expected context to be unchanged, got %d\n", context);
8757     ok(!lstrcmpA(targetsid, "kiwi"),
8758        "Expected targetsid to be unchanged, got %s\n", targetsid);
8759     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8760
8761     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
8762     lstrcatA(keypath, expectedsid);
8763     lstrcatA(keypath, "\\Products\\");
8764     lstrcatA(keypath, prod_squashed);
8765
8766     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
8767     if (res == ERROR_ACCESS_DENIED)
8768     {
8769         skip("Not enough rights to perform tests\n");
8770         return;
8771     }
8772     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8773
8774     /* UserData product key exists */
8775     lstrcpyA(patchcode, "apple");
8776     lstrcpyA(targetprod, "banana");
8777     context = 0xdeadbeef;
8778     lstrcpyA(targetsid, "kiwi");
8779     size = MAX_PATH;
8780     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8781                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
8782                            &context, targetsid, &size);
8783     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8784     ok(!lstrcmpA(patchcode, "apple"),
8785        "Expected patchcode to be unchanged, got %s\n", patchcode);
8786     ok(!lstrcmpA(targetprod, "banana"),
8787        "Expected targetprod to be unchanged, got %s\n", targetprod);
8788     ok(context == 0xdeadbeef,
8789        "Expected context to be unchanged, got %d\n", context);
8790     ok(!lstrcmpA(targetsid, "kiwi"),
8791        "Expected targetsid to be unchanged, got %s\n", targetsid);
8792     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8793
8794     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
8795     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8796
8797     /* UserData patches key exists */
8798     lstrcpyA(patchcode, "apple");
8799     lstrcpyA(targetprod, "banana");
8800     context = 0xdeadbeef;
8801     lstrcpyA(targetsid, "kiwi");
8802     size = MAX_PATH;
8803     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8804                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
8805                            &context, targetsid, &size);
8806     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8807     ok(!lstrcmpA(patchcode, "apple"),
8808        "Expected patchcode to be unchanged, got %s\n", patchcode);
8809     ok(!lstrcmpA(targetprod, "banana"),
8810        "Expected targetprod to be unchanged, got %s\n", targetprod);
8811     ok(context == 0xdeadbeef,
8812        "Expected context to be unchanged, got %d\n", context);
8813     ok(!lstrcmpA(targetsid, "kiwi"),
8814        "Expected targetsid to be unchanged, got %s\n", targetsid);
8815     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8816
8817     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
8818     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8819
8820     /* specific UserData patch key exists */
8821     lstrcpyA(patchcode, "apple");
8822     lstrcpyA(targetprod, "banana");
8823     context = 0xdeadbeef;
8824     lstrcpyA(targetsid, "kiwi");
8825     size = MAX_PATH;
8826     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8827                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
8828                            &context, targetsid, &size);
8829     ok(r == ERROR_BAD_CONFIGURATION,
8830        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
8831     ok(!lstrcmpA(patchcode, "apple"),
8832        "Expected patchcode to be unchanged, got %s\n", patchcode);
8833     ok(!lstrcmpA(targetprod, "banana"),
8834        "Expected targetprod to be unchanged, got %s\n", targetprod);
8835     ok(context == 0xdeadbeef,
8836        "Expected context to be unchanged, got %d\n", context);
8837     ok(!lstrcmpA(targetsid, "kiwi"),
8838        "Expected targetsid to be unchanged, got %s\n", targetsid);
8839     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8840
8841     data = MSIPATCHSTATE_SUPERSEDED;
8842     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
8843                          (const BYTE *)&data, sizeof(DWORD));
8844     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8845
8846     /* State value exists */
8847     lstrcpyA(patchcode, "apple");
8848     lstrcpyA(targetprod, "banana");
8849     context = 0xdeadbeef;
8850     lstrcpyA(targetsid, "kiwi");
8851     size = MAX_PATH;
8852     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8853                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
8854                            &context, targetsid, &size);
8855     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8856     ok(!lstrcmpA(patchcode, patch),
8857        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
8858     ok(!lstrcmpA(targetprod, prodcode),
8859        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
8860     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
8861        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
8862     ok(!lstrcmpA(targetsid, expectedsid),
8863        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
8864     ok(size == lstrlenA(expectedsid),
8865        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
8866
8867     /* MSIPATCHSTATE_OBSOLETED */
8868
8869     lstrcpyA(patchcode, "apple");
8870     lstrcpyA(targetprod, "banana");
8871     context = 0xdeadbeef;
8872     lstrcpyA(targetsid, "kiwi");
8873     size = MAX_PATH;
8874     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8875                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
8876                            &context, targetsid, &size);
8877     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8878     ok(!lstrcmpA(patchcode, "apple"),
8879        "Expected patchcode to be unchanged, got %s\n", patchcode);
8880     ok(!lstrcmpA(targetprod, "banana"),
8881        "Expected targetprod to be unchanged, got %s\n", targetprod);
8882     ok(context == 0xdeadbeef,
8883        "Expected context to be unchanged, got %d\n", context);
8884     ok(!lstrcmpA(targetsid, "kiwi"),
8885        "Expected targetsid to be unchanged, got %s\n", targetsid);
8886     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8887
8888     data = MSIPATCHSTATE_OBSOLETED;
8889     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
8890                          (const BYTE *)&data, sizeof(DWORD));
8891     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8892
8893     /* State value is obsoleted */
8894     lstrcpyA(patchcode, "apple");
8895     lstrcpyA(targetprod, "banana");
8896     context = 0xdeadbeef;
8897     lstrcpyA(targetsid, "kiwi");
8898     size = MAX_PATH;
8899     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8900                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
8901                            &context, targetsid, &size);
8902     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8903     ok(!lstrcmpA(patchcode, patch),
8904        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
8905     ok(!lstrcmpA(targetprod, prodcode),
8906        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
8907     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
8908        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
8909     ok(!lstrcmpA(targetsid, expectedsid),
8910        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
8911     ok(size == lstrlenA(expectedsid),
8912        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
8913
8914     /* MSIPATCHSTATE_REGISTERED */
8915     /* FIXME */
8916
8917     /* MSIPATCHSTATE_ALL */
8918
8919     /* 1st */
8920     lstrcpyA(patchcode, "apple");
8921     lstrcpyA(targetprod, "banana");
8922     context = 0xdeadbeef;
8923     lstrcpyA(targetsid, "kiwi");
8924     size = MAX_PATH;
8925     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8926                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
8927                            &context, targetsid, &size);
8928     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8929     ok(!lstrcmpA(patchcode, patch),
8930        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
8931     ok(!lstrcmpA(targetprod, prodcode),
8932        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
8933     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
8934        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
8935     ok(!lstrcmpA(targetsid, expectedsid),
8936        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
8937     ok(size == lstrlenA(expectedsid),
8938        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
8939
8940     /* same patch in multiple places, only one is enumerated */
8941     lstrcpyA(patchcode, "apple");
8942     lstrcpyA(targetprod, "banana");
8943     context = 0xdeadbeef;
8944     lstrcpyA(targetsid, "kiwi");
8945     size = MAX_PATH;
8946     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
8947                            MSIPATCHSTATE_ALL, 1, patchcode, targetprod,
8948                            &context, targetsid, &size);
8949     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8950     ok(!lstrcmpA(patchcode, "apple"),
8951        "Expected patchcode to be unchanged, got %s\n", patchcode);
8952     ok(!lstrcmpA(targetprod, "banana"),
8953        "Expected targetprod to be unchanged, got %s\n", targetprod);
8954     ok(context == 0xdeadbeef,
8955        "Expected context to be unchanged, got %d\n", context);
8956     ok(!lstrcmpA(targetsid, "kiwi"),
8957        "Expected targetsid to be unchanged, got %s\n", targetsid);
8958     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8959
8960     RegDeleteValueA(hpatch, "State");
8961     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
8962     RegCloseKey(hpatch);
8963     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
8964     RegCloseKey(udpatch);
8965     delete_key(udprod, "", access & KEY_WOW64_64KEY);
8966     RegCloseKey(udprod);
8967     RegDeleteValueA(patches, "Patches");
8968     delete_key(patches, "", access & KEY_WOW64_64KEY);
8969     RegCloseKey(patches);
8970     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
8971     RegCloseKey(prodkey);
8972 }
8973
8974 static void test_MsiEnumPatchesEx_userunmanaged(LPCSTR usersid, LPCSTR expectedsid)
8975 {
8976     MSIINSTALLCONTEXT context;
8977     CHAR keypath[MAX_PATH], patch[MAX_PATH];
8978     CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
8979     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
8980     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
8981     HKEY prodkey, patches, udprod, udpatch;
8982     HKEY userkey, hpatch;
8983     DWORD size, data;
8984     LONG res;
8985     UINT r;
8986     REGSAM access = KEY_ALL_ACCESS;
8987
8988     create_test_guid(prodcode, prod_squashed);
8989     create_test_guid(patch, patch_squashed);
8990
8991     if (is_wow64)
8992         access |= KEY_WOW64_64KEY;
8993
8994     /* MSIPATCHSTATE_APPLIED */
8995
8996     lstrcpyA(patchcode, "apple");
8997     lstrcpyA(targetprod, "banana");
8998     context = 0xdeadbeef;
8999     lstrcpyA(targetsid, "kiwi");
9000     size = MAX_PATH;
9001     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9002                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9003                            &context, targetsid, &size);
9004     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9005     ok(!lstrcmpA(patchcode, "apple"),
9006        "Expected patchcode to be unchanged, got %s\n", patchcode);
9007     ok(!lstrcmpA(targetprod, "banana"),
9008        "Expected targetprod to be unchanged, got %s\n", targetprod);
9009     ok(context == 0xdeadbeef,
9010        "Expected context to be unchanged, got %d\n", context);
9011     ok(!lstrcmpA(targetsid, "kiwi"),
9012        "Expected targetsid to be unchanged, got %s\n", targetsid);
9013     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9014
9015     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
9016     lstrcatA(keypath, prod_squashed);
9017
9018     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
9019     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9020
9021     /* current user product key exists */
9022     lstrcpyA(patchcode, "apple");
9023     lstrcpyA(targetprod, "banana");
9024     context = 0xdeadbeef;
9025     lstrcpyA(targetsid, "kiwi");
9026     size = MAX_PATH;
9027     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9028                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9029                            &context, targetsid, &size);
9030     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9031     ok(!lstrcmpA(patchcode, "apple"),
9032        "Expected patchcode to be unchanged, got %s\n", patchcode);
9033     ok(!lstrcmpA(targetprod, "banana"),
9034        "Expected targetprod to be unchanged, got %s\n", targetprod);
9035     ok(context == 0xdeadbeef,
9036        "Expected context to be unchanged, got %d\n", context);
9037     ok(!lstrcmpA(targetsid, "kiwi"),
9038        "Expected targetsid to be unchanged, got %s\n", targetsid);
9039     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9040
9041     res = RegCreateKeyA(prodkey, "Patches", &patches);
9042     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9043
9044     /* Patches key exists */
9045     lstrcpyA(patchcode, "apple");
9046     lstrcpyA(targetprod, "banana");
9047     context = 0xdeadbeef;
9048     lstrcpyA(targetsid, "kiwi");
9049     size = MAX_PATH;
9050     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9051                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9052                            &context, targetsid, &size);
9053     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9054     ok(!lstrcmpA(patchcode, "apple"),
9055        "Expected patchcode to be unchanged, got %s\n", patchcode);
9056     ok(!lstrcmpA(targetprod, "banana"),
9057        "Expected targetprod to be unchanged, got %s\n", targetprod);
9058     ok(context == 0xdeadbeef,
9059        "Expected context to be unchanged, got %d\n", context);
9060     ok(!lstrcmpA(targetsid, "kiwi"),
9061        "Expected targetsid to be unchanged, got %s\n", targetsid);
9062     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9063
9064     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
9065                          (const BYTE *)patch_squashed,
9066                          lstrlenA(patch_squashed) + 1);
9067     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9068
9069     /* Patches value exists, is not REG_MULTI_SZ */
9070     lstrcpyA(patchcode, "apple");
9071     lstrcpyA(targetprod, "banana");
9072     context = 0xdeadbeef;
9073     lstrcpyA(targetsid, "kiwi");
9074     size = MAX_PATH;
9075     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9076                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9077                            &context, targetsid, &size);
9078     ok(r == ERROR_BAD_CONFIGURATION,
9079        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9080     ok(!lstrcmpA(patchcode, "apple"),
9081        "Expected patchcode to be unchanged, got %s\n", patchcode);
9082     ok(!lstrcmpA(targetprod, "banana"),
9083        "Expected targetprod to be unchanged, got %s\n", targetprod);
9084     ok(context == 0xdeadbeef,
9085        "Expected context to be unchanged, got %d\n", context);
9086     ok(!lstrcmpA(targetsid, "kiwi"),
9087        "Expected targetsid to be unchanged, got %s\n", targetsid);
9088     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9089
9090     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
9091                          (const BYTE *)"a\0b\0c\0\0", 7);
9092     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9093
9094     /* Patches value exists, is not a squashed guid */
9095     lstrcpyA(patchcode, "apple");
9096     lstrcpyA(targetprod, "banana");
9097     context = 0xdeadbeef;
9098     lstrcpyA(targetsid, "kiwi");
9099     size = MAX_PATH;
9100     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9101                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9102                            &context, targetsid, &size);
9103     ok(r == ERROR_BAD_CONFIGURATION,
9104        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9105     ok(!lstrcmpA(patchcode, "apple"),
9106        "Expected patchcode to be unchanged, got %s\n", patchcode);
9107     ok(!lstrcmpA(targetprod, "banana"),
9108        "Expected targetprod to be unchanged, got %s\n", targetprod);
9109     ok(context == 0xdeadbeef,
9110        "Expected context to be unchanged, got %d\n", context);
9111     ok(!lstrcmpA(targetsid, "kiwi"),
9112        "Expected targetsid to be unchanged, got %s\n", targetsid);
9113     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9114
9115     patch_squashed[lstrlenA(patch_squashed) + 1] = 0;
9116     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
9117                          (const BYTE *)patch_squashed,
9118                          lstrlenA(patch_squashed) + 2);
9119     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9120
9121     /* Patches value exists */
9122     lstrcpyA(patchcode, "apple");
9123     lstrcpyA(targetprod, "banana");
9124     context = 0xdeadbeef;
9125     lstrcpyA(targetsid, "kiwi");
9126     size = MAX_PATH;
9127     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9128                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9129                            &context, targetsid, &size);
9130     ok(r == ERROR_NO_MORE_ITEMS ||
9131        broken(r == ERROR_BAD_CONFIGURATION), /* Windows Installer 3.0 */
9132        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9133     ok(!lstrcmpA(patchcode, "apple"),
9134        "Expected patchcode to be unchanged, got %s\n", patchcode);
9135     ok(!lstrcmpA(targetprod, "banana"),
9136        "Expected targetprod to be unchanged, got %s\n", targetprod);
9137     ok(context == 0xdeadbeef,
9138        "Expected context to be unchanged, got %d\n", context);
9139     ok(!lstrcmpA(targetsid, "kiwi"),
9140        "Expected targetsid to be unchanged, got %s\n", targetsid);
9141     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9142
9143     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
9144                          (const BYTE *)"whatever", 9);
9145     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9146
9147     /* patch code value exists */
9148     lstrcpyA(patchcode, "apple");
9149     lstrcpyA(targetprod, "banana");
9150     context = 0xdeadbeef;
9151     lstrcpyA(targetsid, "kiwi");
9152     size = MAX_PATH;
9153     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9154                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9155                            &context, targetsid, &size);
9156     ok(r == ERROR_NO_MORE_ITEMS ||
9157        broken(r == ERROR_BAD_CONFIGURATION), /* Windows Installer 3.0 */
9158        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9159     ok(!lstrcmpA(patchcode, "apple"),
9160        "Expected patchcode to be unchanged, got %s\n", patchcode);
9161     ok(!lstrcmpA(targetprod, "banana"),
9162        "Expected targetprod to be unchanged, got %s\n", targetprod);
9163     ok(context == 0xdeadbeef,
9164        "Expected context to be unchanged, got %d\n", context);
9165     ok(!lstrcmpA(targetsid, "kiwi"),
9166        "Expected targetsid to be unchanged, got %s\n", targetsid);
9167     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9168
9169     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
9170     lstrcatA(keypath, expectedsid);
9171     lstrcatA(keypath, "\\Patches\\");
9172     lstrcatA(keypath, patch_squashed);
9173
9174     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
9175     if (res == ERROR_ACCESS_DENIED)
9176     {
9177         skip("Not enough rights to perform tests\n");
9178         goto error;
9179     }
9180     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9181
9182     /* userdata patch key exists */
9183     lstrcpyA(patchcode, "apple");
9184     lstrcpyA(targetprod, "banana");
9185     context = 0xdeadbeef;
9186     lstrcpyA(targetsid, "kiwi");
9187     size = MAX_PATH;
9188     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9189                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9190                            &context, targetsid, &size);
9191     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9192     ok(!lstrcmpA(patchcode, patch),
9193        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9194     ok(!lstrcmpA(targetprod, prodcode),
9195        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9196     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
9197        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
9198     ok(!lstrcmpA(targetsid, expectedsid),
9199        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9200     ok(size == lstrlenA(expectedsid),
9201        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9202
9203     /* MSIPATCHSTATE_SUPERSEDED */
9204
9205     lstrcpyA(patchcode, "apple");
9206     lstrcpyA(targetprod, "banana");
9207     context = 0xdeadbeef;
9208     lstrcpyA(targetsid, "kiwi");
9209     size = MAX_PATH;
9210     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9211                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
9212                            &context, targetsid, &size);
9213     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9214     ok(!lstrcmpA(patchcode, "apple"),
9215        "Expected patchcode to be unchanged, got %s\n", patchcode);
9216     ok(!lstrcmpA(targetprod, "banana"),
9217        "Expected targetprod to be unchanged, got %s\n", targetprod);
9218     ok(context == 0xdeadbeef,
9219        "Expected context to be unchanged, got %d\n", context);
9220     ok(!lstrcmpA(targetsid, "kiwi"),
9221        "Expected targetsid to be unchanged, got %s\n", targetsid);
9222     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9223
9224     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
9225     lstrcatA(keypath, expectedsid);
9226     lstrcatA(keypath, "\\Products\\");
9227     lstrcatA(keypath, prod_squashed);
9228
9229     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
9230     if (res == ERROR_ACCESS_DENIED)
9231     {
9232         skip("Not enough rights to perform tests\n");
9233         goto error;
9234     }
9235     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9236
9237     /* UserData product key exists */
9238     lstrcpyA(patchcode, "apple");
9239     lstrcpyA(targetprod, "banana");
9240     context = 0xdeadbeef;
9241     lstrcpyA(targetsid, "kiwi");
9242     size = MAX_PATH;
9243     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9244                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
9245                            &context, targetsid, &size);
9246     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9247     ok(!lstrcmpA(patchcode, "apple"),
9248        "Expected patchcode to be unchanged, got %s\n", patchcode);
9249     ok(!lstrcmpA(targetprod, "banana"),
9250        "Expected targetprod to be unchanged, got %s\n", targetprod);
9251     ok(context == 0xdeadbeef,
9252        "Expected context to be unchanged, got %d\n", context);
9253     ok(!lstrcmpA(targetsid, "kiwi"),
9254        "Expected targetsid to be unchanged, got %s\n", targetsid);
9255     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9256
9257     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
9258     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9259
9260     /* UserData patches key exists */
9261     lstrcpyA(patchcode, "apple");
9262     lstrcpyA(targetprod, "banana");
9263     context = 0xdeadbeef;
9264     lstrcpyA(targetsid, "kiwi");
9265     size = MAX_PATH;
9266     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9267                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
9268                            &context, targetsid, &size);
9269     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9270     ok(!lstrcmpA(patchcode, "apple"),
9271        "Expected patchcode to be unchanged, got %s\n", patchcode);
9272     ok(!lstrcmpA(targetprod, "banana"),
9273        "Expected targetprod to be unchanged, got %s\n", targetprod);
9274     ok(context == 0xdeadbeef,
9275        "Expected context to be unchanged, got %d\n", context);
9276     ok(!lstrcmpA(targetsid, "kiwi"),
9277        "Expected targetsid to be unchanged, got %s\n", targetsid);
9278     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9279
9280     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
9281     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9282
9283     /* specific UserData patch key exists */
9284     lstrcpyA(patchcode, "apple");
9285     lstrcpyA(targetprod, "banana");
9286     context = 0xdeadbeef;
9287     lstrcpyA(targetsid, "kiwi");
9288     size = MAX_PATH;
9289     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9290                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
9291                            &context, targetsid, &size);
9292     ok(r == ERROR_BAD_CONFIGURATION,
9293        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9294     ok(!lstrcmpA(patchcode, "apple"),
9295        "Expected patchcode to be unchanged, got %s\n", patchcode);
9296     ok(!lstrcmpA(targetprod, "banana"),
9297        "Expected targetprod to be unchanged, got %s\n", targetprod);
9298     ok(context == 0xdeadbeef,
9299        "Expected context to be unchanged, got %d\n", context);
9300     ok(!lstrcmpA(targetsid, "kiwi"),
9301        "Expected targetsid to be unchanged, got %s\n", targetsid);
9302     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9303
9304     data = MSIPATCHSTATE_SUPERSEDED;
9305     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
9306                          (const BYTE *)&data, sizeof(DWORD));
9307     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9308
9309     /* State value exists */
9310     lstrcpyA(patchcode, "apple");
9311     lstrcpyA(targetprod, "banana");
9312     context = 0xdeadbeef;
9313     lstrcpyA(targetsid, "kiwi");
9314     size = MAX_PATH;
9315     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9316                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
9317                            &context, targetsid, &size);
9318     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9319     ok(!lstrcmpA(patchcode, patch),
9320        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9321     ok(!lstrcmpA(targetprod, prodcode),
9322        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9323     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
9324        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
9325     ok(!lstrcmpA(targetsid, expectedsid),
9326        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9327     ok(size == lstrlenA(expectedsid),
9328        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9329
9330     /* MSIPATCHSTATE_OBSOLETED */
9331
9332     lstrcpyA(patchcode, "apple");
9333     lstrcpyA(targetprod, "banana");
9334     context = 0xdeadbeef;
9335     lstrcpyA(targetsid, "kiwi");
9336     size = MAX_PATH;
9337     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9338                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
9339                            &context, targetsid, &size);
9340     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9341     ok(!lstrcmpA(patchcode, "apple"),
9342        "Expected patchcode to be unchanged, got %s\n", patchcode);
9343     ok(!lstrcmpA(targetprod, "banana"),
9344        "Expected targetprod to be unchanged, got %s\n", targetprod);
9345     ok(context == 0xdeadbeef,
9346        "Expected context to be unchanged, got %d\n", context);
9347     ok(!lstrcmpA(targetsid, "kiwi"),
9348        "Expected targetsid to be unchanged, got %s\n", targetsid);
9349     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9350
9351     data = MSIPATCHSTATE_OBSOLETED;
9352     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
9353                          (const BYTE *)&data, sizeof(DWORD));
9354     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9355
9356     /* State value is obsoleted */
9357     lstrcpyA(patchcode, "apple");
9358     lstrcpyA(targetprod, "banana");
9359     context = 0xdeadbeef;
9360     lstrcpyA(targetsid, "kiwi");
9361     size = MAX_PATH;
9362     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9363                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
9364                            &context, targetsid, &size);
9365     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9366     ok(!lstrcmpA(patchcode, patch),
9367        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9368     ok(!lstrcmpA(targetprod, prodcode),
9369        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9370     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
9371        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
9372     ok(!lstrcmpA(targetsid, expectedsid),
9373        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9374     ok(size == lstrlenA(expectedsid),
9375        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9376
9377     /* MSIPATCHSTATE_REGISTERED */
9378     /* FIXME */
9379
9380     /* MSIPATCHSTATE_ALL */
9381
9382     /* 1st */
9383     lstrcpyA(patchcode, "apple");
9384     lstrcpyA(targetprod, "banana");
9385     context = 0xdeadbeef;
9386     lstrcpyA(targetsid, "kiwi");
9387     size = MAX_PATH;
9388     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9389                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
9390                            &context, targetsid, &size);
9391     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9392     ok(!lstrcmpA(patchcode, patch),
9393        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9394     ok(!lstrcmpA(targetprod, prodcode),
9395        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9396     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
9397        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
9398     ok(!lstrcmpA(targetsid, expectedsid),
9399        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9400     ok(size == lstrlenA(expectedsid),
9401        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9402
9403     /* same patch in multiple places, only one is enumerated */
9404     lstrcpyA(patchcode, "apple");
9405     lstrcpyA(targetprod, "banana");
9406     context = 0xdeadbeef;
9407     lstrcpyA(targetsid, "kiwi");
9408     size = MAX_PATH;
9409     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9410                            MSIPATCHSTATE_ALL, 1, patchcode, targetprod,
9411                            &context, targetsid, &size);
9412     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9413     ok(!lstrcmpA(patchcode, "apple"),
9414        "Expected patchcode to be unchanged, got %s\n", patchcode);
9415     ok(!lstrcmpA(targetprod, "banana"),
9416        "Expected targetprod to be unchanged, got %s\n", targetprod);
9417     ok(context == 0xdeadbeef,
9418        "Expected context to be unchanged, got %d\n", context);
9419     ok(!lstrcmpA(targetsid, "kiwi"),
9420        "Expected targetsid to be unchanged, got %s\n", targetsid);
9421     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9422
9423     RegDeleteValueA(hpatch, "State");
9424     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
9425     RegCloseKey(hpatch);
9426     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
9427     RegCloseKey(udpatch);
9428     delete_key(udprod, "", access & KEY_WOW64_64KEY);
9429     RegCloseKey(udprod);
9430     delete_key(userkey, "", access & KEY_WOW64_64KEY);
9431     RegCloseKey(userkey);
9432     RegDeleteValueA(patches, patch_squashed);
9433     RegDeleteValueA(patches, "Patches");
9434
9435 error:
9436     RegDeleteKeyA(patches, "");
9437     RegCloseKey(patches);
9438     RegDeleteKeyA(prodkey, "");
9439     RegCloseKey(prodkey);
9440 }
9441
9442 static void test_MsiEnumPatchesEx_machine(void)
9443 {
9444     CHAR keypath[MAX_PATH], patch[MAX_PATH];
9445     CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
9446     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
9447     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
9448     HKEY prodkey, patches, udprod, udpatch;
9449     HKEY hpatch;
9450     MSIINSTALLCONTEXT context;
9451     DWORD size, data;
9452     LONG res;
9453     UINT r;
9454     REGSAM access = KEY_ALL_ACCESS;
9455
9456     create_test_guid(prodcode, prod_squashed);
9457     create_test_guid(patch, patch_squashed);
9458
9459     if (is_wow64)
9460         access |= KEY_WOW64_64KEY;
9461
9462     /* MSIPATCHSTATE_APPLIED */
9463
9464     lstrcpyA(patchcode, "apple");
9465     lstrcpyA(targetprod, "banana");
9466     context = 0xdeadbeef;
9467     lstrcpyA(targetsid, "kiwi");
9468     size = MAX_PATH;
9469     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
9470                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9471                            &context, targetsid, &size);
9472     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9473     ok(!lstrcmpA(patchcode, "apple"),
9474        "Expected patchcode to be unchanged, got %s\n", patchcode);
9475     ok(!lstrcmpA(targetprod, "banana"),
9476        "Expected targetprod to be unchanged, got %s\n", targetprod);
9477     ok(context == 0xdeadbeef,
9478        "Expected context to be unchanged, got %d\n", context);
9479     ok(!lstrcmpA(targetsid, "kiwi"),
9480        "Expected targetsid to be unchanged, got %s\n", targetsid);
9481     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9482
9483     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
9484     lstrcatA(keypath, prod_squashed);
9485
9486     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
9487     if (res == ERROR_ACCESS_DENIED)
9488     {
9489         skip("Not enough rights to perform tests\n");
9490         return;
9491     }
9492     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9493
9494     /* local product key exists */
9495     lstrcpyA(patchcode, "apple");
9496     lstrcpyA(targetprod, "banana");
9497     context = 0xdeadbeef;
9498     lstrcpyA(targetsid, "kiwi");
9499     size = MAX_PATH;
9500     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
9501                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9502                            &context, targetsid, &size);
9503     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9504     ok(!lstrcmpA(patchcode, "apple"),
9505        "Expected patchcode to be unchanged, got %s\n", patchcode);
9506     ok(!lstrcmpA(targetprod, "banana"),
9507        "Expected targetprod to be unchanged, got %s\n", targetprod);
9508     ok(context == 0xdeadbeef,
9509        "Expected context to be unchanged, got %d\n", context);
9510     ok(!lstrcmpA(targetsid, "kiwi"),
9511        "Expected targetsid to be unchanged, got %s\n", targetsid);
9512     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9513
9514     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
9515     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9516
9517     /* Patches key exists */
9518     lstrcpyA(patchcode, "apple");
9519     lstrcpyA(targetprod, "banana");
9520     context = 0xdeadbeef;
9521     lstrcpyA(targetsid, "kiwi");
9522     size = MAX_PATH;
9523     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
9524                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9525                            &context, targetsid, &size);
9526     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9527     ok(!lstrcmpA(patchcode, "apple"),
9528        "Expected patchcode to be unchanged, got %s\n", patchcode);
9529     ok(!lstrcmpA(targetprod, "banana"),
9530        "Expected targetprod to be unchanged, got %s\n", targetprod);
9531     ok(context == 0xdeadbeef,
9532        "Expected context to be unchanged, got %d\n", context);
9533     ok(!lstrcmpA(targetsid, "kiwi"),
9534        "Expected targetsid to be unchanged, got %s\n", targetsid);
9535     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9536
9537     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
9538                          (const BYTE *)patch_squashed,
9539                          lstrlenA(patch_squashed) + 1);
9540     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9541
9542     /* Patches value exists, is not REG_MULTI_SZ */
9543     lstrcpyA(patchcode, "apple");
9544     lstrcpyA(targetprod, "banana");
9545     context = 0xdeadbeef;
9546     lstrcpyA(targetsid, "kiwi");
9547     size = MAX_PATH;
9548     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
9549                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9550                            &context, targetsid, &size);
9551     ok(r == ERROR_BAD_CONFIGURATION,
9552        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9553     ok(!lstrcmpA(patchcode, "apple"),
9554        "Expected patchcode to be unchanged, got %s\n", patchcode);
9555     ok(!lstrcmpA(targetprod, "banana"),
9556        "Expected targetprod to be unchanged, got %s\n", targetprod);
9557     ok(context == 0xdeadbeef,
9558        "Expected context to be unchanged, got %d\n", context);
9559     ok(!lstrcmpA(targetsid, "kiwi"),
9560        "Expected targetsid to be unchanged, got %s\n", targetsid);
9561     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9562
9563     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
9564                          (const BYTE *)"a\0b\0c\0\0", 7);
9565     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9566
9567     /* Patches value exists, is not a squashed guid */
9568     lstrcpyA(patchcode, "apple");
9569     lstrcpyA(targetprod, "banana");
9570     context = 0xdeadbeef;
9571     lstrcpyA(targetsid, "kiwi");
9572     size = MAX_PATH;
9573     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
9574                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9575                            &context, targetsid, &size);
9576     ok(r == ERROR_BAD_CONFIGURATION,
9577        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9578     ok(!lstrcmpA(patchcode, "apple"),
9579        "Expected patchcode to be unchanged, got %s\n", patchcode);
9580     ok(!lstrcmpA(targetprod, "banana"),
9581        "Expected targetprod to be unchanged, got %s\n", targetprod);
9582     ok(context == 0xdeadbeef,
9583        "Expected context to be unchanged, got %d\n", context);
9584     ok(!lstrcmpA(targetsid, "kiwi"),
9585        "Expected targetsid to be unchanged, got %s\n", targetsid);
9586     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9587
9588     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
9589     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
9590                          (const BYTE *)patch_squashed,
9591                          lstrlenA(patch_squashed) + 2);
9592     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9593
9594     /* Patches value exists */
9595     lstrcpyA(patchcode, "apple");
9596     lstrcpyA(targetprod, "banana");
9597     context = 0xdeadbeef;
9598     lstrcpyA(targetsid, "kiwi");
9599     size = MAX_PATH;
9600     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
9601                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9602                            &context, targetsid, &size);
9603     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9604     ok(!lstrcmpA(patchcode, "apple"),
9605        "Expected patchcode to be unchanged, got %s\n", patchcode);
9606     ok(!lstrcmpA(targetprod, "banana"),
9607        "Expected targetprod to be unchanged, got %s\n", targetprod);
9608     ok(context == 0xdeadbeef,
9609        "Expected context to be unchanged, got %d\n", context);
9610     ok(!lstrcmpA(targetsid, "kiwi"),
9611        "Expected targetsid to be unchanged, got %s\n", targetsid);
9612     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9613
9614     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
9615                          (const BYTE *)"whatever", 9);
9616     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9617
9618     /* patch code value exists */
9619     lstrcpyA(patchcode, "apple");
9620     lstrcpyA(targetprod, "banana");
9621     context = 0xdeadbeef;
9622     lstrcpyA(targetsid, "kiwi");
9623     size = MAX_PATH;
9624     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
9625                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9626                            &context, targetsid, &size);
9627     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9628     ok(!lstrcmpA(patchcode, patch),
9629        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9630     ok(!lstrcmpA(targetprod, prodcode),
9631        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9632     ok(context == MSIINSTALLCONTEXT_MACHINE,
9633        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
9634     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
9635     ok(size == 0, "Expected 0, got %d\n", size);
9636
9637     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9638     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
9639     lstrcatA(keypath, prod_squashed);
9640
9641     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
9642     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9643
9644     /* local UserData product key exists */
9645     lstrcpyA(patchcode, "apple");
9646     lstrcpyA(targetprod, "banana");
9647     context = 0xdeadbeef;
9648     lstrcpyA(targetsid, "kiwi");
9649     size = MAX_PATH;
9650     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
9651                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9652                            &context, targetsid, &size);
9653     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9654     ok(!lstrcmpA(patchcode, patch),
9655        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9656     ok(!lstrcmpA(targetprod, prodcode),
9657        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9658     ok(context == MSIINSTALLCONTEXT_MACHINE,
9659        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
9660     ok(!lstrcmpA(targetsid, ""),
9661        "Expected \"\", got \"%s\"\n", targetsid);
9662     ok(size == 0, "Expected 0, got %d\n", size);
9663
9664     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
9665     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9666
9667     /* local UserData Patches key exists */
9668     lstrcpyA(patchcode, "apple");
9669     lstrcpyA(targetprod, "banana");
9670     context = 0xdeadbeef;
9671     lstrcpyA(targetsid, "kiwi");
9672     size = MAX_PATH;
9673     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
9674                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9675                            &context, targetsid, &size);
9676     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9677     ok(!lstrcmpA(patchcode, patch),
9678        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9679     ok(!lstrcmpA(targetprod, prodcode),
9680        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9681     ok(context == MSIINSTALLCONTEXT_MACHINE,
9682        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
9683     ok(!lstrcmpA(targetsid, ""),
9684        "Expected \"\", got \"%s\"\n", targetsid);
9685     ok(size == 0, "Expected 0, got %d\n", size);
9686
9687     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
9688     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9689
9690     /* local UserData Product patch key exists */
9691     lstrcpyA(patchcode, "apple");
9692     lstrcpyA(targetprod, "banana");
9693     context = 0xdeadbeef;
9694     lstrcpyA(targetsid, "kiwi");
9695     size = MAX_PATH;
9696     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
9697                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9698                            &context, targetsid, &size);
9699     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9700     ok(!lstrcmpA(patchcode, "apple"),
9701        "Expected patchcode to be unchanged, got %s\n", patchcode);
9702     ok(!lstrcmpA(targetprod, "banana"),
9703        "Expected targetprod to be unchanged, got %s\n", targetprod);
9704     ok(context == 0xdeadbeef,
9705        "Expected context to be unchanged, got %d\n", context);
9706     ok(!lstrcmpA(targetsid, "kiwi"),
9707        "Expected targetsid to be unchanged, got %s\n", targetsid);
9708     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9709
9710     data = MSIPATCHSTATE_APPLIED;
9711     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
9712                          (const BYTE *)&data, sizeof(DWORD));
9713     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9714
9715     /* State value exists */
9716     lstrcpyA(patchcode, "apple");
9717     lstrcpyA(targetprod, "banana");
9718     context = 0xdeadbeef;
9719     lstrcpyA(targetsid, "kiwi");
9720     size = MAX_PATH;
9721     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
9722                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9723                            &context, targetsid, &size);
9724     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9725     ok(!lstrcmpA(patchcode, patch),
9726        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9727     ok(!lstrcmpA(targetprod, prodcode),
9728        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9729     ok(context == MSIINSTALLCONTEXT_MACHINE,
9730        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
9731     ok(!lstrcmpA(targetsid, ""),
9732        "Expected \"\", got \"%s\"\n", targetsid);
9733     ok(size == 0, "Expected 0, got %d\n", size);
9734
9735     /* MSIPATCHSTATE_SUPERSEDED */
9736
9737     lstrcpyA(patchcode, "apple");
9738     lstrcpyA(targetprod, "banana");
9739     context = 0xdeadbeef;
9740     lstrcpyA(targetsid, "kiwi");
9741     size = MAX_PATH;
9742     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
9743                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
9744                            &context, targetsid, &size);
9745     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9746     ok(!lstrcmpA(patchcode, "apple"),
9747        "Expected patchcode to be unchanged, got %s\n", patchcode);
9748     ok(!lstrcmpA(targetprod, "banana"),
9749        "Expected targetprod to be unchanged, got %s\n", targetprod);
9750     ok(context == 0xdeadbeef,
9751        "Expected context to be unchanged, got %d\n", context);
9752     ok(!lstrcmpA(targetsid, "kiwi"),
9753        "Expected targetsid to be unchanged, got %s\n", targetsid);
9754     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9755
9756     data = MSIPATCHSTATE_SUPERSEDED;
9757     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
9758                          (const BYTE *)&data, sizeof(DWORD));
9759     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9760
9761     /* State value is MSIPATCHSTATE_SUPERSEDED */
9762     lstrcpyA(patchcode, "apple");
9763     lstrcpyA(targetprod, "banana");
9764     context = 0xdeadbeef;
9765     lstrcpyA(targetsid, "kiwi");
9766     size = MAX_PATH;
9767     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
9768                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
9769                            &context, targetsid, &size);
9770     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9771     ok(!lstrcmpA(patchcode, patch),
9772        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9773     ok(!lstrcmpA(targetprod, prodcode),
9774        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9775     ok(context == MSIINSTALLCONTEXT_MACHINE,
9776        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
9777     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
9778     ok(size == 0, "Expected 0, got %d\n", size);
9779
9780     /* MSIPATCHSTATE_OBSOLETED */
9781
9782     lstrcpyA(patchcode, "apple");
9783     lstrcpyA(targetprod, "banana");
9784     context = 0xdeadbeef;
9785     lstrcpyA(targetsid, "kiwi");
9786     size = MAX_PATH;
9787     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
9788                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
9789                            &context, targetsid, &size);
9790     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9791     ok(!lstrcmpA(patchcode, "apple"),
9792        "Expected patchcode to be unchanged, got %s\n", patchcode);
9793     ok(!lstrcmpA(targetprod, "banana"),
9794        "Expected targetprod to be unchanged, got %s\n", targetprod);
9795     ok(context == 0xdeadbeef,
9796        "Expected context to be unchanged, got %d\n", context);
9797     ok(!lstrcmpA(targetsid, "kiwi"),
9798        "Expected targetsid to be unchanged, got %s\n", targetsid);
9799     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9800
9801     data = MSIPATCHSTATE_OBSOLETED;
9802     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
9803                          (const BYTE *)&data, sizeof(DWORD));
9804     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9805
9806     /* State value is obsoleted */
9807     lstrcpyA(patchcode, "apple");
9808     lstrcpyA(targetprod, "banana");
9809     context = 0xdeadbeef;
9810     lstrcpyA(targetsid, "kiwi");
9811     size = MAX_PATH;
9812     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
9813                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
9814                            &context, targetsid, &size);
9815     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9816     ok(!lstrcmpA(patchcode, patch),
9817        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9818     ok(!lstrcmpA(targetprod, prodcode),
9819        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9820     ok(context == MSIINSTALLCONTEXT_MACHINE,
9821        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
9822     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
9823     ok(size == 0, "Expected 0, got %d\n", size);
9824
9825     /* MSIPATCHSTATE_REGISTERED */
9826     /* FIXME */
9827
9828     /* MSIPATCHSTATE_ALL */
9829
9830     /* 1st */
9831     lstrcpyA(patchcode, "apple");
9832     lstrcpyA(targetprod, "banana");
9833     context = 0xdeadbeef;
9834     lstrcpyA(targetsid, "kiwi");
9835     size = MAX_PATH;
9836     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
9837                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
9838                            &context, targetsid, &size);
9839     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9840     ok(!lstrcmpA(patchcode, patch),
9841        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9842     ok(!lstrcmpA(targetprod, prodcode),
9843        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9844     ok(context == MSIINSTALLCONTEXT_MACHINE,
9845        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
9846     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
9847     ok(size == 0, "Expected 0, got %d\n", size);
9848
9849     /* same patch in multiple places, only one is enumerated */
9850     lstrcpyA(patchcode, "apple");
9851     lstrcpyA(targetprod, "banana");
9852     context = 0xdeadbeef;
9853     lstrcpyA(targetsid, "kiwi");
9854     size = MAX_PATH;
9855     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
9856                            MSIPATCHSTATE_ALL, 1, patchcode, targetprod,
9857                            &context, targetsid, &size);
9858     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9859     ok(!lstrcmpA(patchcode, "apple"),
9860        "Expected patchcode to be unchanged, got %s\n", patchcode);
9861     ok(!lstrcmpA(targetprod, "banana"),
9862        "Expected targetprod to be unchanged, got %s\n", targetprod);
9863     ok(context == 0xdeadbeef,
9864        "Expected context to be unchanged, got %d\n", context);
9865     ok(!lstrcmpA(targetsid, "kiwi"),
9866        "Expected targetsid to be unchanged, got %s\n", targetsid);
9867     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9868
9869     RegDeleteValueA(patches, patch_squashed);
9870     RegDeleteValueA(patches, "Patches");
9871     delete_key(patches, "", access & KEY_WOW64_64KEY);
9872     RegCloseKey(patches);
9873     RegDeleteValueA(hpatch, "State");
9874     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
9875     RegCloseKey(hpatch);
9876     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
9877     RegCloseKey(udpatch);
9878     delete_key(udprod, "", access & KEY_WOW64_64KEY);
9879     RegCloseKey(udprod);
9880     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
9881     RegCloseKey(prodkey);
9882 }
9883
9884 static void test_MsiEnumPatchesEx(void)
9885 {
9886     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
9887     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
9888     CHAR patchcode[MAX_PATH];
9889     MSIINSTALLCONTEXT context;
9890     LPSTR usersid;
9891     DWORD size;
9892     UINT r;
9893
9894     if (!pMsiEnumPatchesExA)
9895     {
9896         win_skip("MsiEnumPatchesExA not implemented\n");
9897         return;
9898     }
9899
9900     create_test_guid(prodcode, prod_squashed);
9901     usersid = get_user_sid();
9902
9903     /* empty szProductCode */
9904     lstrcpyA(patchcode, "apple");
9905     lstrcpyA(targetprod, "banana");
9906     context = 0xdeadbeef;
9907     lstrcpyA(targetsid, "kiwi");
9908     size = MAX_PATH;
9909     r = pMsiEnumPatchesExA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9910                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod, &context,
9911                            targetsid, &size);
9912     ok(r == ERROR_INVALID_PARAMETER,
9913        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9914     ok(!lstrcmpA(patchcode, "apple"),
9915        "Expected patchcode to be unchanged, got %s\n", patchcode);
9916     ok(!lstrcmpA(targetprod, "banana"),
9917        "Expected targetprod to be unchanged, got %s\n", targetprod);
9918     ok(context == 0xdeadbeef,
9919        "Expected context to be unchanged, got %d\n", context);
9920     ok(!lstrcmpA(targetsid, "kiwi"),
9921        "Expected targetsid to be unchanged, got %s\n", targetsid);
9922     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9923
9924     /* garbage szProductCode */
9925     lstrcpyA(patchcode, "apple");
9926     lstrcpyA(targetprod, "banana");
9927     context = 0xdeadbeef;
9928     lstrcpyA(targetsid, "kiwi");
9929     size = MAX_PATH;
9930     r = pMsiEnumPatchesExA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
9931                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod, &context,
9932                            targetsid, &size);
9933     ok(r == ERROR_INVALID_PARAMETER,
9934        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9935     ok(!lstrcmpA(patchcode, "apple"),
9936        "Expected patchcode to be unchanged, got %s\n", patchcode);
9937     ok(!lstrcmpA(targetprod, "banana"),
9938        "Expected targetprod to be unchanged, got %s\n", targetprod);
9939     ok(context == 0xdeadbeef,
9940        "Expected context to be unchanged, got %d\n", context);
9941     ok(!lstrcmpA(targetsid, "kiwi"),
9942        "Expected targetsid to be unchanged, got %s\n", targetsid);
9943     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9944
9945     /* guid without brackets */
9946     lstrcpyA(patchcode, "apple");
9947     lstrcpyA(targetprod, "banana");
9948     context = 0xdeadbeef;
9949     lstrcpyA(targetsid, "kiwi");
9950     size = MAX_PATH;
9951     r = pMsiEnumPatchesExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", usersid,
9952                            MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
9953                            0, patchcode, targetprod, &context,
9954                            targetsid, &size);
9955     ok(r == ERROR_INVALID_PARAMETER,
9956        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9957     ok(!lstrcmpA(patchcode, "apple"),
9958        "Expected patchcode to be unchanged, got %s\n", patchcode);
9959     ok(!lstrcmpA(targetprod, "banana"),
9960        "Expected targetprod to be unchanged, got %s\n", targetprod);
9961     ok(context == 0xdeadbeef,
9962        "Expected context to be unchanged, got %d\n", context);
9963     ok(!lstrcmpA(targetsid, "kiwi"),
9964        "Expected targetsid to be unchanged, got %s\n", targetsid);
9965     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9966
9967     /* guid with brackets */
9968     lstrcpyA(patchcode, "apple");
9969     lstrcpyA(targetprod, "banana");
9970     context = 0xdeadbeef;
9971     lstrcpyA(targetsid, "kiwi");
9972     size = MAX_PATH;
9973     r = pMsiEnumPatchesExA("{6700E8CF-95AB-4D9C-BC2C-15840DDA7A5D}", usersid,
9974                            MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
9975                            0, patchcode, targetprod, &context,
9976                            targetsid, &size);
9977     ok(r == ERROR_NO_MORE_ITEMS,
9978        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9979     ok(!lstrcmpA(patchcode, "apple"),
9980        "Expected patchcode to be unchanged, got %s\n", patchcode);
9981     ok(!lstrcmpA(targetprod, "banana"),
9982        "Expected targetprod to be unchanged, got %s\n", targetprod);
9983     ok(context == 0xdeadbeef,
9984        "Expected context to be unchanged, got %d\n", context);
9985     ok(!lstrcmpA(targetsid, "kiwi"),
9986        "Expected targetsid to be unchanged, got %s\n", targetsid);
9987     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9988
9989     /* szUserSid is S-1-5-18 */
9990     lstrcpyA(patchcode, "apple");
9991     lstrcpyA(targetprod, "banana");
9992     context = 0xdeadbeef;
9993     lstrcpyA(targetsid, "kiwi");
9994     size = MAX_PATH;
9995     r = pMsiEnumPatchesExA(prodcode, "S-1-5-18",
9996                            MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
9997                            0, patchcode, targetprod, &context,
9998                            targetsid, &size);
9999     ok(r == ERROR_INVALID_PARAMETER,
10000        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10001     ok(!lstrcmpA(patchcode, "apple"),
10002        "Expected patchcode to be unchanged, got %s\n", patchcode);
10003     ok(!lstrcmpA(targetprod, "banana"),
10004        "Expected targetprod to be unchanged, got %s\n", targetprod);
10005     ok(context == 0xdeadbeef,
10006        "Expected context to be unchanged, got %d\n", context);
10007     ok(!lstrcmpA(targetsid, "kiwi"),
10008        "Expected targetsid to be unchanged, got %s\n", targetsid);
10009     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10010
10011     /* dwContext is MSIINSTALLCONTEXT_MACHINE, but szUserSid is non-NULL */
10012     lstrcpyA(patchcode, "apple");
10013     lstrcpyA(targetprod, "banana");
10014     context = 0xdeadbeef;
10015     lstrcpyA(targetsid, "kiwi");
10016     size = MAX_PATH;
10017     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_MACHINE,
10018                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
10019                            &context, targetsid, &size);
10020     ok(r == ERROR_INVALID_PARAMETER,
10021        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10022     ok(!lstrcmpA(patchcode, "apple"),
10023        "Expected patchcode to be unchanged, got %s\n", patchcode);
10024     ok(!lstrcmpA(targetprod, "banana"),
10025        "Expected targetprod to be unchanged, got %s\n", targetprod);
10026     ok(context == 0xdeadbeef,
10027        "Expected context to be unchanged, got %d\n", context);
10028     ok(!lstrcmpA(targetsid, "kiwi"),
10029        "Expected targetsid to be unchanged, got %s\n", targetsid);
10030     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10031
10032     /* dwContext is out of bounds */
10033     lstrcpyA(patchcode, "apple");
10034     lstrcpyA(targetprod, "banana");
10035     context = 0xdeadbeef;
10036     lstrcpyA(targetsid, "kiwi");
10037     size = MAX_PATH;
10038     r = pMsiEnumPatchesExA(prodcode, usersid, 0,
10039                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
10040                            &context, targetsid, &size);
10041     ok(r == ERROR_INVALID_PARAMETER,
10042        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10043     ok(!lstrcmpA(patchcode, "apple"),
10044        "Expected patchcode to be unchanged, got %s\n", patchcode);
10045     ok(!lstrcmpA(targetprod, "banana"),
10046        "Expected targetprod to be unchanged, got %s\n", targetprod);
10047     ok(context == 0xdeadbeef,
10048        "Expected context to be unchanged, got %d\n", context);
10049     ok(!lstrcmpA(targetsid, "kiwi"),
10050        "Expected targetsid to be unchanged, got %s\n", targetsid);
10051     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10052
10053     /* dwContext is out of bounds */
10054     lstrcpyA(patchcode, "apple");
10055     lstrcpyA(targetprod, "banana");
10056     context = 0xdeadbeef;
10057     lstrcpyA(targetsid, "kiwi");
10058     size = MAX_PATH;
10059     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_ALL + 1,
10060                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
10061                            &context, targetsid, &size);
10062     ok(r == ERROR_INVALID_PARAMETER,
10063        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10064     ok(!lstrcmpA(patchcode, "apple"),
10065        "Expected patchcode to be unchanged, got %s\n", patchcode);
10066     ok(!lstrcmpA(targetprod, "banana"),
10067        "Expected targetprod to be unchanged, got %s\n", targetprod);
10068     ok(context == 0xdeadbeef,
10069        "Expected context to be unchanged, got %d\n", context);
10070     ok(!lstrcmpA(targetsid, "kiwi"),
10071        "Expected targetsid to be unchanged, got %s\n", targetsid);
10072     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10073
10074     /* dwFilter is out of bounds */
10075     lstrcpyA(patchcode, "apple");
10076     lstrcpyA(targetprod, "banana");
10077     context = 0xdeadbeef;
10078     lstrcpyA(targetsid, "kiwi");
10079     size = MAX_PATH;
10080     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10081                            MSIPATCHSTATE_INVALID, 0, patchcode, targetprod,
10082                            &context, targetsid, &size);
10083     ok(r == ERROR_INVALID_PARAMETER,
10084        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10085     ok(!lstrcmpA(patchcode, "apple"),
10086        "Expected patchcode to be unchanged, got %s\n", patchcode);
10087     ok(!lstrcmpA(targetprod, "banana"),
10088        "Expected targetprod to be unchanged, got %s\n", targetprod);
10089     ok(context == 0xdeadbeef,
10090        "Expected context to be unchanged, got %d\n", context);
10091     ok(!lstrcmpA(targetsid, "kiwi"),
10092        "Expected targetsid to be unchanged, got %s\n", targetsid);
10093     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10094
10095     /* dwFilter is out of bounds */
10096     lstrcpyA(patchcode, "apple");
10097     lstrcpyA(targetprod, "banana");
10098     context = 0xdeadbeef;
10099     lstrcpyA(targetsid, "kiwi");
10100     size = MAX_PATH;
10101     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10102                            MSIPATCHSTATE_ALL + 1, 0, patchcode, targetprod,
10103                            &context, targetsid, &size);
10104     ok(r == ERROR_INVALID_PARAMETER,
10105        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10106     ok(!lstrcmpA(patchcode, "apple"),
10107        "Expected patchcode to be unchanged, got %s\n", patchcode);
10108     ok(!lstrcmpA(targetprod, "banana"),
10109        "Expected targetprod to be unchanged, got %s\n", targetprod);
10110     ok(context == 0xdeadbeef,
10111        "Expected context to be unchanged, got %d\n", context);
10112     ok(!lstrcmpA(targetsid, "kiwi"),
10113        "Expected targetsid to be unchanged, got %s\n", targetsid);
10114     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10115
10116     /* pcchTargetUserSid is NULL while szTargetUserSid is non-NULL */
10117     lstrcpyA(patchcode, "apple");
10118     lstrcpyA(targetprod, "banana");
10119     context = 0xdeadbeef;
10120     lstrcpyA(targetsid, "kiwi");
10121     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10122                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
10123                            &context, targetsid, NULL);
10124     ok(r == ERROR_INVALID_PARAMETER,
10125        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10126     ok(!lstrcmpA(patchcode, "apple"),
10127        "Expected patchcode to be unchanged, got %s\n", patchcode);
10128     ok(!lstrcmpA(targetprod, "banana"),
10129        "Expected targetprod to be unchanged, got %s\n", targetprod);
10130     ok(context == 0xdeadbeef,
10131        "Expected context to be unchanged, got %d\n", context);
10132     ok(!lstrcmpA(targetsid, "kiwi"),
10133        "Expected targetsid to be unchanged, got %s\n", targetsid);
10134
10135     test_MsiEnumPatchesEx_usermanaged(usersid, usersid);
10136     test_MsiEnumPatchesEx_usermanaged(NULL, usersid);
10137     test_MsiEnumPatchesEx_usermanaged("S-1-2-34", "S-1-2-34");
10138     test_MsiEnumPatchesEx_userunmanaged(usersid, usersid);
10139     test_MsiEnumPatchesEx_userunmanaged(NULL, usersid);
10140     /* FIXME: Successfully test userunmanaged with a different user */
10141     test_MsiEnumPatchesEx_machine();
10142     LocalFree(usersid);
10143 }
10144
10145 static void test_MsiEnumPatches(void)
10146 {
10147     CHAR keypath[MAX_PATH], patch[MAX_PATH];
10148     CHAR patchcode[MAX_PATH], patch_squashed[MAX_PATH];
10149     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
10150     CHAR transforms[MAX_PATH];
10151     WCHAR patchW[MAX_PATH], prodcodeW[MAX_PATH], transformsW[MAX_PATH];
10152     HKEY prodkey, patches, udprod;
10153     HKEY userkey, hpatch, udpatch;
10154     DWORD size, data;
10155     LPSTR usersid;
10156     LONG res;
10157     UINT r;
10158     REGSAM access = KEY_ALL_ACCESS;
10159
10160     create_test_guid(prodcode, prod_squashed);
10161     create_test_guid(patchcode, patch_squashed);
10162     usersid = get_user_sid();
10163
10164     if (is_wow64)
10165         access |= KEY_WOW64_64KEY;
10166
10167     /* NULL szProduct */
10168     size = MAX_PATH;
10169     lstrcpyA(patch, "apple");
10170     lstrcpyA(transforms, "banana");
10171     r = MsiEnumPatchesA(NULL, 0, patch, transforms, &size);
10172     ok(r == ERROR_INVALID_PARAMETER,
10173        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10174     ok(!lstrcmpA(patch, "apple"),
10175        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10176     ok(!lstrcmpA(transforms, "banana"),
10177        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10178     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10179
10180     /* empty szProduct */
10181     size = MAX_PATH;
10182     lstrcpyA(patch, "apple");
10183     lstrcpyA(transforms, "banana");
10184     r = MsiEnumPatchesA("", 0, patch, transforms, &size);
10185     ok(r == ERROR_INVALID_PARAMETER,
10186        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10187     ok(!lstrcmpA(patch, "apple"),
10188        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10189     ok(!lstrcmpA(transforms, "banana"),
10190        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10191     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10192
10193     /* garbage szProduct */
10194     size = MAX_PATH;
10195     lstrcpyA(patch, "apple");
10196     lstrcpyA(transforms, "banana");
10197     r = MsiEnumPatchesA("garbage", 0, patch, transforms, &size);
10198     ok(r == ERROR_INVALID_PARAMETER,
10199        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10200     ok(!lstrcmpA(patch, "apple"),
10201        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10202     ok(!lstrcmpA(transforms, "banana"),
10203        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10204     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10205
10206     /* guid without brackets */
10207     size = MAX_PATH;
10208     lstrcpyA(patch, "apple");
10209     lstrcpyA(transforms, "banana");
10210     r = MsiEnumPatchesA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", 0, patch,
10211                         transforms, &size);
10212     ok(r == ERROR_INVALID_PARAMETER,
10213        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10214     ok(!lstrcmpA(patch, "apple"),
10215        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10216     ok(!lstrcmpA(transforms, "banana"),
10217        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10218     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10219
10220     /* guid with brackets */
10221     size = MAX_PATH;
10222     lstrcpyA(patch, "apple");
10223     lstrcpyA(transforms, "banana");
10224     r = MsiEnumPatchesA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", 0, patch,
10225                         transforms, &size);
10226     ok(r == ERROR_UNKNOWN_PRODUCT,
10227        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
10228     ok(!lstrcmpA(patch, "apple"),
10229        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10230     ok(!lstrcmpA(transforms, "banana"),
10231        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10232     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10233
10234     /* same length as guid, but random */
10235     size = MAX_PATH;
10236     lstrcpyA(patch, "apple");
10237     lstrcpyA(transforms, "banana");
10238     r = MsiEnumPatchesA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", 0, patch,
10239                         transforms, &size);
10240     ok(r == ERROR_INVALID_PARAMETER,
10241        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10242     ok(!lstrcmpA(patch, "apple"),
10243        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10244     ok(!lstrcmpA(transforms, "banana"),
10245        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10246     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10247
10248     /* MSIINSTALLCONTEXT_USERMANAGED */
10249
10250     size = MAX_PATH;
10251     lstrcpyA(patch, "apple");
10252     lstrcpyA(transforms, "banana");
10253     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10254     ok(r == ERROR_UNKNOWN_PRODUCT,
10255        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
10256     ok(!lstrcmpA(patch, "apple"),
10257        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10258     ok(!lstrcmpA(transforms, "banana"),
10259        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10260     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10261
10262     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
10263     lstrcatA(keypath, usersid);
10264     lstrcatA(keypath, "\\Installer\\Products\\");
10265     lstrcatA(keypath, prod_squashed);
10266
10267     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
10268     if (res == ERROR_ACCESS_DENIED)
10269     {
10270         skip("Not enough rights to perform tests\n");
10271         LocalFree(usersid);
10272         return;
10273     }
10274     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10275
10276     /* managed product key exists */
10277     size = MAX_PATH;
10278     lstrcpyA(patch, "apple");
10279     lstrcpyA(transforms, "banana");
10280     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10281     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10282     ok(!lstrcmpA(patch, "apple"),
10283        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10284     ok(!lstrcmpA(transforms, "banana"),
10285        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10286     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10287
10288     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
10289     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10290
10291     /* patches key exists */
10292     size = MAX_PATH;
10293     lstrcpyA(patch, "apple");
10294     lstrcpyA(transforms, "banana");
10295     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10296     ok(r == ERROR_NO_MORE_ITEMS ||
10297        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
10298        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10299     ok(!lstrcmpA(patch, "apple"),
10300        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10301     ok(!lstrcmpA(transforms, "banana"),
10302        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10303     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10304
10305     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
10306                          (const BYTE *)patch_squashed,
10307                          lstrlenA(patch_squashed) + 1);
10308     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10309
10310     /* Patches value exists, is not REG_MULTI_SZ */
10311     size = MAX_PATH;
10312     lstrcpyA(patch, "apple");
10313     lstrcpyA(transforms, "banana");
10314     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10315     ok(r == ERROR_BAD_CONFIGURATION ||
10316        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
10317        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10318     ok(!lstrcmpA(patch, "apple"),
10319        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10320     ok(!lstrcmpA(transforms, "banana"),
10321        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10322     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10323
10324     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10325                          (const BYTE *)"a\0b\0c\0\0", 7);
10326     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10327
10328     /* Patches value exists, is not a squashed guid */
10329     size = MAX_PATH;
10330     lstrcpyA(patch, "apple");
10331     lstrcpyA(transforms, "banana");
10332     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10333     ok(r == ERROR_BAD_CONFIGURATION,
10334        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10335     ok(!lstrcmpA(patch, "apple"),
10336        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10337     ok(!lstrcmpA(transforms, "banana"),
10338        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10339     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10340
10341     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
10342     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10343                          (const BYTE *)patch_squashed,
10344                          lstrlenA(patch_squashed) + 2);
10345     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10346
10347     /* Patches value exists */
10348     size = MAX_PATH;
10349     lstrcpyA(patch, "apple");
10350     lstrcpyA(transforms, "banana");
10351     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10352     ok(r == ERROR_NO_MORE_ITEMS ||
10353        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
10354        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10355     ok(!lstrcmpA(patch, "apple") ||
10356        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
10357        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10358     ok(!lstrcmpA(transforms, "banana"),
10359        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10360     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10361
10362     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
10363                          (const BYTE *)"whatever", 9);
10364     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10365
10366     /* patch squashed value exists */
10367     size = MAX_PATH;
10368     lstrcpyA(patch, "apple");
10369     lstrcpyA(transforms, "banana");
10370     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10371     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10372     ok(!lstrcmpA(patch, patchcode),
10373        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10374     ok(!lstrcmpA(transforms, "whatever"),
10375        "Expected \"whatever\", got \"%s\"\n", transforms);
10376     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
10377
10378     /* lpPatchBuf is NULL */
10379     size = MAX_PATH;
10380     lstrcpyA(transforms, "banana");
10381     r = MsiEnumPatchesA(prodcode, 0, NULL, transforms, &size);
10382     ok(r == ERROR_INVALID_PARAMETER,
10383        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10384     ok(!lstrcmpA(transforms, "banana"),
10385        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10386     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10387
10388     /* lpTransformsBuf is NULL, pcchTransformsBuf is not */
10389     size = MAX_PATH;
10390     lstrcpyA(patch, "apple");
10391     r = MsiEnumPatchesA(prodcode, 0, patch, NULL, &size);
10392     ok(r == ERROR_INVALID_PARAMETER,
10393        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10394     ok(!lstrcmpA(patch, "apple"),
10395        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10396     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10397
10398     /* pcchTransformsBuf is NULL, lpTransformsBuf is not */
10399     lstrcpyA(patch, "apple");
10400     lstrcpyA(transforms, "banana");
10401     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, NULL);
10402     ok(r == ERROR_INVALID_PARAMETER,
10403        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10404     ok(!lstrcmpA(patch, "apple"),
10405        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10406     ok(!lstrcmpA(transforms, "banana"),
10407        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10408
10409     /* pcchTransformsBuf is too small */
10410     size = 6;
10411     lstrcpyA(patch, "apple");
10412     lstrcpyA(transforms, "banana");
10413     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10414     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
10415     ok(!lstrcmpA(patch, patchcode),
10416        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10417     ok(!lstrcmpA(transforms, "whate") ||
10418        broken(!lstrcmpA(transforms, "banana")), /* Windows Installer < 3.0 */
10419        "Expected \"whate\", got \"%s\"\n", transforms);
10420     ok(size == 8 || size == 16, "Expected 8 or 16, got %d\n", size);
10421
10422     /* increase the index */
10423     size = MAX_PATH;
10424     lstrcpyA(patch, "apple");
10425     lstrcpyA(transforms, "banana");
10426     r = MsiEnumPatchesA(prodcode, 1, patch, transforms, &size);
10427     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10428     ok(!lstrcmpA(patch, "apple"),
10429        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10430     ok(!lstrcmpA(transforms, "banana"),
10431        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10432     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10433
10434     /* increase again */
10435     size = MAX_PATH;
10436     lstrcpyA(patch, "apple");
10437     lstrcpyA(transforms, "banana");
10438     r = MsiEnumPatchesA(prodcode, 2, patch, transforms, &size);
10439     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10440     ok(!lstrcmpA(patch, "apple"),
10441        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10442     ok(!lstrcmpA(transforms, "banana"),
10443        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10444     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10445
10446     RegDeleteValueA(patches, "Patches");
10447     delete_key(patches, "", access & KEY_WOW64_64KEY);
10448     RegCloseKey(patches);
10449     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
10450     RegCloseKey(prodkey);
10451
10452     /* MSIINSTALLCONTEXT_USERUNMANAGED */
10453
10454     size = MAX_PATH;
10455     lstrcpyA(patch, "apple");
10456     lstrcpyA(transforms, "banana");
10457     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10458     ok(r == ERROR_UNKNOWN_PRODUCT,
10459        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
10460     ok(!lstrcmpA(patch, "apple"),
10461        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10462     ok(!lstrcmpA(transforms, "banana"),
10463        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10464     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10465
10466     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
10467     lstrcatA(keypath, prod_squashed);
10468
10469     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
10470     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10471
10472     /* current user product key exists */
10473     size = MAX_PATH;
10474     lstrcpyA(patch, "apple");
10475     lstrcpyA(transforms, "banana");
10476     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10477     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10478     ok(!lstrcmpA(patch, "apple"),
10479        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10480     ok(!lstrcmpA(transforms, "banana"),
10481        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10482     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10483
10484     res = RegCreateKeyA(prodkey, "Patches", &patches);
10485     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10486
10487     /* Patches key exists */
10488     size = MAX_PATH;
10489     lstrcpyA(patch, "apple");
10490     lstrcpyA(transforms, "banana");
10491     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10492     ok(r == ERROR_NO_MORE_ITEMS ||
10493        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
10494        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10495     ok(!lstrcmpA(patch, "apple"),
10496        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10497     ok(!lstrcmpA(transforms, "banana"),
10498        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10499     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10500
10501     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
10502                          (const BYTE *)patch_squashed,
10503                          lstrlenA(patch_squashed) + 1);
10504     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10505
10506     /* Patches value exists, is not REG_MULTI_SZ */
10507     size = MAX_PATH;
10508     lstrcpyA(patch, "apple");
10509     lstrcpyA(transforms, "banana");
10510     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10511     ok(r == ERROR_BAD_CONFIGURATION ||
10512        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
10513        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10514     ok(!lstrcmpA(patch, "apple"),
10515        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10516     ok(!lstrcmpA(transforms, "banana"),
10517        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10518     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10519
10520     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10521                          (const BYTE *)"a\0b\0c\0\0", 7);
10522     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10523
10524     /* Patches value exists, is not a squashed guid */
10525     size = MAX_PATH;
10526     lstrcpyA(patch, "apple");
10527     lstrcpyA(transforms, "banana");
10528     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10529     ok(r == ERROR_BAD_CONFIGURATION,
10530        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10531     ok(!lstrcmpA(patch, "apple"),
10532        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10533     ok(!lstrcmpA(transforms, "banana"),
10534        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10535     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10536
10537     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
10538     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10539                          (const BYTE *)patch_squashed,
10540                          lstrlenA(patch_squashed) + 2);
10541     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10542
10543     /* Patches value exists */
10544     size = MAX_PATH;
10545     lstrcpyA(patch, "apple");
10546     lstrcpyA(transforms, "banana");
10547     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10548     ok(r == ERROR_NO_MORE_ITEMS ||
10549        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
10550        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10551     ok(!lstrcmpA(patch, "apple") ||
10552        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
10553        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10554     ok(!lstrcmpA(transforms, "banana"),
10555        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10556     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10557
10558     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
10559                          (const BYTE *)"whatever", 9);
10560     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10561
10562     /* patch code value exists */
10563     size = MAX_PATH;
10564     lstrcpyA(patch, "apple");
10565     lstrcpyA(transforms, "banana");
10566     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10567     ok(r == ERROR_NO_MORE_ITEMS ||
10568        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
10569        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10570     ok(!lstrcmpA(patch, "apple") ||
10571        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
10572        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10573     ok(!lstrcmpA(transforms, "banana") ||
10574        broken(!lstrcmpA(transforms, "whatever")), /* Windows Installer < 3.0 */
10575        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10576     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10577
10578     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
10579     lstrcatA(keypath, usersid);
10580     lstrcatA(keypath, "\\Patches\\");
10581     lstrcatA(keypath, patch_squashed);
10582
10583     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
10584     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10585
10586     /* userdata patch key exists */
10587     size = MAX_PATH;
10588     lstrcpyA(patch, "apple");
10589     lstrcpyA(transforms, "banana");
10590     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10591     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10592     ok(!lstrcmpA(patch, patchcode),
10593        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10594     ok(!lstrcmpA(transforms, "whatever"),
10595        "Expected \"whatever\", got \"%s\"\n", transforms);
10596     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
10597
10598     delete_key(userkey, "", access & KEY_WOW64_64KEY);
10599     RegCloseKey(userkey);
10600     RegDeleteValueA(patches, patch_squashed);
10601     RegDeleteValueA(patches, "Patches");
10602     RegDeleteKeyA(patches, "");
10603     RegCloseKey(patches);
10604     RegDeleteKeyA(prodkey, "");
10605     RegCloseKey(prodkey);
10606
10607     /* MSIINSTALLCONTEXT_MACHINE */
10608
10609     size = MAX_PATH;
10610     lstrcpyA(patch, "apple");
10611     lstrcpyA(transforms, "banana");
10612     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10613     ok(r == ERROR_UNKNOWN_PRODUCT,
10614        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
10615     ok(!lstrcmpA(patch, "apple"),
10616        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10617     ok(!lstrcmpA(transforms, "banana"),
10618        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10619     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10620
10621     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
10622     lstrcatA(keypath, prod_squashed);
10623
10624     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
10625     if (res == ERROR_ACCESS_DENIED)
10626     {
10627         skip("Not enough rights to perform tests\n");
10628         LocalFree(usersid);
10629         return;
10630     }
10631     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10632
10633     /* local product key exists */
10634     size = MAX_PATH;
10635     lstrcpyA(patch, "apple");
10636     lstrcpyA(transforms, "banana");
10637     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10638     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10639     ok(!lstrcmpA(patch, "apple"),
10640        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10641     ok(!lstrcmpA(transforms, "banana"),
10642        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10643     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10644
10645     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
10646     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10647
10648     /* Patches key exists */
10649     size = MAX_PATH;
10650     lstrcpyA(patch, "apple");
10651     lstrcpyA(transforms, "banana");
10652     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10653     ok(r == ERROR_NO_MORE_ITEMS ||
10654        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
10655        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10656     ok(!lstrcmpA(patch, "apple"),
10657        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10658     ok(!lstrcmpA(transforms, "banana"),
10659        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10660     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10661
10662     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
10663                          (const BYTE *)patch_squashed,
10664                          lstrlenA(patch_squashed) + 1);
10665     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10666
10667     /* Patches value exists, is not REG_MULTI_SZ */
10668     size = MAX_PATH;
10669     lstrcpyA(patch, "apple");
10670     lstrcpyA(transforms, "banana");
10671     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10672     ok(r == ERROR_BAD_CONFIGURATION ||
10673        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
10674        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10675     ok(!lstrcmpA(patch, "apple"),
10676        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10677     ok(!lstrcmpA(transforms, "banana"),
10678        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10679     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10680
10681     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10682                          (const BYTE *)"a\0b\0c\0\0", 7);
10683     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10684
10685     /* Patches value exists, is not a squashed guid */
10686     size = MAX_PATH;
10687     lstrcpyA(patch, "apple");
10688     lstrcpyA(transforms, "banana");
10689     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10690     ok(r == ERROR_BAD_CONFIGURATION,
10691        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10692     ok(!lstrcmpA(patch, "apple"),
10693        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10694     ok(!lstrcmpA(transforms, "banana"),
10695        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10696     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10697
10698     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
10699     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10700                          (const BYTE *)patch_squashed,
10701                          lstrlenA(patch_squashed) + 2);
10702     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10703
10704     /* Patches value exists */
10705     size = MAX_PATH;
10706     lstrcpyA(patch, "apple");
10707     lstrcpyA(transforms, "banana");
10708     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10709     ok(r == ERROR_NO_MORE_ITEMS ||
10710        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
10711        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10712     ok(!lstrcmpA(patch, "apple") ||
10713        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
10714        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10715     ok(!lstrcmpA(transforms, "banana"),
10716        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10717     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10718
10719     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
10720                          (const BYTE *)"whatever", 9);
10721     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10722
10723     /* patch code value exists */
10724     size = MAX_PATH;
10725     lstrcpyA(patch, "apple");
10726     lstrcpyA(transforms, "banana");
10727     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10728     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10729     ok(!lstrcmpA(patch, patchcode),
10730        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10731     ok(!lstrcmpA(transforms, "whatever"),
10732        "Expected \"whatever\", got \"%s\"\n", transforms);
10733     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
10734
10735     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
10736     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
10737     lstrcatA(keypath, prod_squashed);
10738
10739     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
10740     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10741
10742     /* local UserData product key exists */
10743     size = MAX_PATH;
10744     lstrcpyA(patch, "apple");
10745     lstrcpyA(transforms, "banana");
10746     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10747     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10748     ok(!lstrcmpA(patch, patchcode),
10749        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10750     ok(!lstrcmpA(transforms, "whatever"),
10751        "Expected \"whatever\", got \"%s\"\n", transforms);
10752     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
10753
10754     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
10755     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10756
10757     /* local UserData Patches key exists */
10758     size = MAX_PATH;
10759     lstrcpyA(patch, "apple");
10760     lstrcpyA(transforms, "banana");
10761     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10762     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10763     ok(!lstrcmpA(patch, patchcode),
10764        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10765     ok(!lstrcmpA(transforms, "whatever"),
10766        "Expected \"whatever\", got \"%s\"\n", transforms);
10767     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
10768
10769     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
10770     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10771
10772     /* local UserData Product patch key exists */
10773     size = MAX_PATH;
10774     lstrcpyA(patch, "apple");
10775     lstrcpyA(transforms, "banana");
10776     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10777     ok(r == ERROR_NO_MORE_ITEMS ||
10778        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
10779        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10780     ok(!lstrcmpA(patch, "apple") ||
10781        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
10782        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10783     ok(!lstrcmpA(transforms, "banana") ||
10784        broken(!lstrcmpA(transforms, "whatever")), /* Windows Installer < 3.0 */
10785        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10786     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10787
10788     data = MSIPATCHSTATE_APPLIED;
10789     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10790                          (const BYTE *)&data, sizeof(DWORD));
10791     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10792
10793     /* State value exists */
10794     size = MAX_PATH;
10795     lstrcpyA(patch, "apple");
10796     lstrcpyA(transforms, "banana");
10797     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10798     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10799     ok(!lstrcmpA(patch, patchcode),
10800        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10801     ok(!lstrcmpA(transforms, "whatever"),
10802        "Expected \"whatever\", got \"%s\"\n", transforms);
10803     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
10804
10805     /* now duplicate some of the tests for the W version */
10806
10807     /* pcchTransformsBuf is too small */
10808     size = 6;
10809     MultiByteToWideChar( CP_ACP, 0, prodcode, -1, prodcodeW, MAX_PATH );
10810     MultiByteToWideChar( CP_ACP, 0, "apple", -1, patchW, MAX_PATH );
10811     MultiByteToWideChar( CP_ACP, 0, "banana", -1, transformsW, MAX_PATH );
10812     r = MsiEnumPatchesW(prodcodeW, 0, patchW, transformsW, &size);
10813     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
10814     WideCharToMultiByte( CP_ACP, 0, patchW, -1, patch, MAX_PATH, NULL, NULL );
10815     WideCharToMultiByte( CP_ACP, 0, transformsW, -1, transforms, MAX_PATH, NULL, NULL );
10816     ok(!lstrcmpA(patch, patchcode),
10817        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10818     ok(!lstrcmpA(transforms, "whate") ||
10819        broken(!lstrcmpA(transforms, "banana")), /* Windows Installer < 3.0 */
10820        "Expected \"whate\", got \"%s\"\n", transforms);
10821     ok(size == 8, "Expected 8, got %d\n", size);
10822
10823     /* patch code value exists */
10824     size = MAX_PATH;
10825     MultiByteToWideChar( CP_ACP, 0, "apple", -1, patchW, MAX_PATH );
10826     MultiByteToWideChar( CP_ACP, 0, "banana", -1, transformsW, MAX_PATH );
10827     r = MsiEnumPatchesW(prodcodeW, 0, patchW, transformsW, &size);
10828     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10829     WideCharToMultiByte( CP_ACP, 0, patchW, -1, patch, MAX_PATH, NULL, NULL );
10830     WideCharToMultiByte( CP_ACP, 0, transformsW, -1, transforms, MAX_PATH, NULL, NULL );
10831     ok(!lstrcmpA(patch, patchcode),
10832        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10833     ok(!lstrcmpA(transforms, "whatever"),
10834        "Expected \"whatever\", got \"%s\"\n", transforms);
10835     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
10836
10837     RegDeleteValueA(patches, patch_squashed);
10838     RegDeleteValueA(patches, "Patches");
10839     delete_key(patches, "", access & KEY_WOW64_64KEY);
10840     RegCloseKey(patches);
10841     RegDeleteValueA(hpatch, "State");
10842     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
10843     RegCloseKey(hpatch);
10844     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
10845     RegCloseKey(udpatch);
10846     delete_key(udprod, "", access & KEY_WOW64_64KEY);
10847     RegCloseKey(udprod);
10848     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
10849     RegCloseKey(prodkey);
10850     LocalFree(usersid);
10851 }
10852
10853 static void test_MsiGetPatchInfoEx(void)
10854 {
10855     CHAR keypath[MAX_PATH], val[MAX_PATH];
10856     CHAR patchcode[MAX_PATH], patch_squashed[MAX_PATH];
10857     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
10858     HKEY prodkey, patches, udprod, props;
10859     HKEY hpatch, udpatch, prodpatches;
10860     LPSTR usersid;
10861     DWORD size;
10862     LONG res;
10863     UINT r;
10864     REGSAM access = KEY_ALL_ACCESS;
10865
10866     if (!pMsiGetPatchInfoExA)
10867     {
10868         win_skip("MsiGetPatchInfoEx not implemented\n");
10869         return;
10870     }
10871
10872     create_test_guid(prodcode, prod_squashed);
10873     create_test_guid(patchcode, patch_squashed);
10874     usersid = get_user_sid();
10875
10876     if (is_wow64)
10877         access |= KEY_WOW64_64KEY;
10878
10879     /* NULL szPatchCode */
10880     lstrcpyA(val, "apple");
10881     size = MAX_PATH;
10882     r = pMsiGetPatchInfoExA(NULL, prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED,
10883                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
10884     ok(r == ERROR_INVALID_PARAMETER,
10885        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10886     ok(!lstrcmpA(val, "apple"),
10887        "Expected val to be unchanged, got \"%s\"\n", val);
10888     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10889
10890     /* empty szPatchCode */
10891     size = MAX_PATH;
10892     lstrcpyA(val, "apple");
10893     r = pMsiGetPatchInfoExA("", prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED,
10894                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
10895     ok(r == ERROR_INVALID_PARAMETER,
10896        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10897     ok(!lstrcmpA(val, "apple"),
10898        "Expected val to be unchanged, got \"%s\"\n", val);
10899     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10900
10901     /* garbage szPatchCode */
10902     size = MAX_PATH;
10903     lstrcpyA(val, "apple");
10904     r = pMsiGetPatchInfoExA("garbage", prodcode, NULL,
10905                             MSIINSTALLCONTEXT_USERMANAGED,
10906                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
10907     ok(r == ERROR_INVALID_PARAMETER,
10908        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10909     ok(!lstrcmpA(val, "apple"),
10910        "Expected val to be unchanged, got \"%s\"\n", val);
10911     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10912
10913     /* guid without brackets */
10914     size = MAX_PATH;
10915     lstrcpyA(val, "apple");
10916     r = pMsiGetPatchInfoExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", prodcode,
10917                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
10918                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
10919     ok(r == ERROR_INVALID_PARAMETER,
10920        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10921     ok(!lstrcmpA(val, "apple"),
10922        "Expected val to be unchanged, got \"%s\"\n", val);
10923     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10924
10925     /* guid with brackets */
10926     size = MAX_PATH;
10927     lstrcpyA(val, "apple");
10928     r = pMsiGetPatchInfoExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", prodcode,
10929                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
10930                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
10931     ok(r == ERROR_UNKNOWN_PRODUCT,
10932        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
10933     ok(!lstrcmpA(val, "apple"),
10934        "Expected val to be unchanged, got \"%s\"\n", val);
10935     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10936
10937     /* same length as guid, but random */
10938     size = MAX_PATH;
10939     lstrcpyA(val, "apple");
10940     r = pMsiGetPatchInfoExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", prodcode,
10941                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
10942                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
10943     ok(r == ERROR_INVALID_PARAMETER,
10944        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10945     ok(!lstrcmpA(val, "apple"),
10946        "Expected val to be unchanged, got \"%s\"\n", val);
10947     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10948
10949     /* NULL szProductCode */
10950     lstrcpyA(val, "apple");
10951     size = MAX_PATH;
10952     r = pMsiGetPatchInfoExA(patchcode, NULL, NULL, MSIINSTALLCONTEXT_USERMANAGED,
10953                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
10954     ok(r == ERROR_INVALID_PARAMETER,
10955        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10956     ok(!lstrcmpA(val, "apple"),
10957        "Expected val to be unchanged, got \"%s\"\n", val);
10958     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10959
10960     /* empty szProductCode */
10961     size = MAX_PATH;
10962     lstrcpyA(val, "apple");
10963     r = pMsiGetPatchInfoExA(patchcode, "", NULL, MSIINSTALLCONTEXT_USERMANAGED,
10964                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
10965     ok(r == ERROR_INVALID_PARAMETER,
10966        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10967     ok(!lstrcmpA(val, "apple"),
10968        "Expected val to be unchanged, got \"%s\"\n", val);
10969     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10970
10971     /* garbage szProductCode */
10972     size = MAX_PATH;
10973     lstrcpyA(val, "apple");
10974     r = pMsiGetPatchInfoExA(patchcode, "garbage", NULL,
10975                             MSIINSTALLCONTEXT_USERMANAGED,
10976                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
10977     ok(r == ERROR_INVALID_PARAMETER,
10978        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10979     ok(!lstrcmpA(val, "apple"),
10980        "Expected val to be unchanged, got \"%s\"\n", val);
10981     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10982
10983     /* guid without brackets */
10984     size = MAX_PATH;
10985     lstrcpyA(val, "apple");
10986     r = pMsiGetPatchInfoExA(patchcode, "6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
10987                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
10988                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
10989     ok(r == ERROR_INVALID_PARAMETER,
10990        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10991     ok(!lstrcmpA(val, "apple"),
10992        "Expected val to be unchanged, got \"%s\"\n", val);
10993     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10994
10995     /* guid with brackets */
10996     size = MAX_PATH;
10997     lstrcpyA(val, "apple");
10998     r = pMsiGetPatchInfoExA(patchcode, "{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
10999                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
11000                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11001     ok(r == ERROR_UNKNOWN_PRODUCT,
11002        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11003     ok(!lstrcmpA(val, "apple"),
11004        "Expected val to be unchanged, got \"%s\"\n", val);
11005     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11006
11007     /* same length as guid, but random */
11008     size = MAX_PATH;
11009     lstrcpyA(val, "apple");
11010     r = pMsiGetPatchInfoExA(patchcode, "A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
11011                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
11012                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11013     ok(r == ERROR_INVALID_PARAMETER,
11014        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11015     ok(!lstrcmpA(val, "apple"),
11016        "Expected val to be unchanged, got \"%s\"\n", val);
11017     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11018
11019     /* szUserSid cannot be S-1-5-18 for MSIINSTALLCONTEXT_USERMANAGED */
11020     size = MAX_PATH;
11021     lstrcpyA(val, "apple");
11022     r = pMsiGetPatchInfoExA(patchcode, prodcode, "S-1-5-18",
11023                             MSIINSTALLCONTEXT_USERMANAGED,
11024                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11025     ok(r == ERROR_INVALID_PARAMETER,
11026        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11027     ok(!lstrcmpA(val, "apple"),
11028        "Expected val to be unchanged, got \"%s\"\n", val);
11029     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11030
11031     /* szUserSid cannot be S-1-5-18 for MSIINSTALLCONTEXT_USERUNMANAGED */
11032     size = MAX_PATH;
11033     lstrcpyA(val, "apple");
11034     r = pMsiGetPatchInfoExA(patchcode, prodcode, "S-1-5-18",
11035                             MSIINSTALLCONTEXT_USERUNMANAGED,
11036                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11037     ok(r == ERROR_INVALID_PARAMETER,
11038        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11039     ok(!lstrcmpA(val, "apple"),
11040        "Expected val to be unchanged, got \"%s\"\n", val);
11041     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11042
11043     /* szUserSid cannot be S-1-5-18 for MSIINSTALLCONTEXT_MACHINE */
11044     size = MAX_PATH;
11045     lstrcpyA(val, "apple");
11046     r = pMsiGetPatchInfoExA(patchcode, prodcode, "S-1-5-18",
11047                             MSIINSTALLCONTEXT_MACHINE,
11048                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11049     ok(r == ERROR_INVALID_PARAMETER,
11050        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11051     ok(!lstrcmpA(val, "apple"),
11052        "Expected val to be unchanged, got \"%s\"\n", val);
11053     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11054
11055     /* szUserSid must be NULL for MSIINSTALLCONTEXT_MACHINE */
11056     size = MAX_PATH;
11057     lstrcpyA(val, "apple");
11058     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11059                             MSIINSTALLCONTEXT_MACHINE,
11060                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11061     ok(r == ERROR_INVALID_PARAMETER,
11062        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11063     ok(!lstrcmpA(val, "apple"),
11064        "Expected val to be unchanged, got \"%s\"\n", val);
11065     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11066
11067     /* dwContext is out of range */
11068     size = MAX_PATH;
11069     lstrcpyA(val, "apple");
11070     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11071                             MSIINSTALLCONTEXT_NONE,
11072                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11073     ok(r == ERROR_INVALID_PARAMETER,
11074        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11075     ok(!lstrcmpA(val, "apple"),
11076        "Expected val to be unchanged, got \"%s\"\n", val);
11077     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11078
11079     /* dwContext is out of range */
11080     size = MAX_PATH;
11081     lstrcpyA(val, "apple");
11082     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11083                             MSIINSTALLCONTEXT_ALL,
11084                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11085     ok(r == ERROR_INVALID_PARAMETER,
11086        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11087     ok(!lstrcmpA(val, "apple"),
11088        "Expected val to be unchanged, got \"%s\"\n", val);
11089     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11090
11091     /* dwContext is invalid */
11092     size = MAX_PATH;
11093     lstrcpyA(val, "apple");
11094     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid, 3,
11095                            INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11096     ok(r == ERROR_INVALID_PARAMETER,
11097        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11098     ok(!lstrcmpA(val, "apple"),
11099        "Expected val to be unchanged, got \"%s\"\n", val);
11100     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11101
11102     /* MSIINSTALLCONTEXT_USERMANAGED */
11103
11104     size = MAX_PATH;
11105     lstrcpyA(val, "apple");
11106     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11107                             MSIINSTALLCONTEXT_USERMANAGED,
11108                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11109     ok(r == ERROR_UNKNOWN_PRODUCT,
11110        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11111     ok(!lstrcmpA(val, "apple"),
11112        "Expected val to be unchanged, got \"%s\"\n", val);
11113     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11114
11115     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
11116     lstrcatA(keypath, usersid);
11117     lstrcatA(keypath, "\\Products\\");
11118     lstrcatA(keypath, prod_squashed);
11119
11120     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
11121     if (res == ERROR_ACCESS_DENIED)
11122     {
11123         skip("Not enough rights to perform tests\n");
11124         LocalFree(usersid);
11125         return;
11126     }
11127     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11128
11129     /* local UserData product key exists */
11130     size = MAX_PATH;
11131     lstrcpyA(val, "apple");
11132     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11133                             MSIINSTALLCONTEXT_USERMANAGED,
11134                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11135     ok(r == ERROR_UNKNOWN_PRODUCT,
11136        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11137     ok(!lstrcmpA(val, "apple"),
11138        "Expected val to be unchanged, got \"%s\"\n", val);
11139     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11140
11141     res = RegCreateKeyExA(udprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
11142     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11143
11144     /* InstallProperties key exists */
11145     size = MAX_PATH;
11146     lstrcpyA(val, "apple");
11147     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11148                             MSIINSTALLCONTEXT_USERMANAGED,
11149                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11150     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11151     ok(!lstrcmpA(val, "apple"),
11152        "Expected val to be unchanged, got \"%s\"\n", val);
11153     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11154
11155     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
11156     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11157
11158     /* Patches key exists */
11159     size = MAX_PATH;
11160     lstrcpyA(val, "apple");
11161     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11162                             MSIINSTALLCONTEXT_USERMANAGED,
11163                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11164     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11165     ok(!lstrcmpA(val, "apple"),
11166        "Expected val to be unchanged, got \"%s\"\n", val);
11167     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11168
11169     res = RegCreateKeyExA(patches, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
11170     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11171
11172     /* Patches key exists */
11173     size = MAX_PATH;
11174     lstrcpyA(val, "apple");
11175     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11176                             MSIINSTALLCONTEXT_USERMANAGED,
11177                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11178     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11179     ok(!lstrcmpA(val, "apple"),
11180        "Expected val to be unchanged, got \"%s\"\n", val);
11181     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11182
11183     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
11184     lstrcatA(keypath, usersid);
11185     lstrcatA(keypath, "\\Installer\\Products\\");
11186     lstrcatA(keypath, prod_squashed);
11187
11188     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
11189     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11190
11191     /* managed product key exists */
11192     size = MAX_PATH;
11193     lstrcpyA(val, "apple");
11194     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11195                             MSIINSTALLCONTEXT_USERMANAGED,
11196                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11197     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11198     ok(!lstrcmpA(val, "apple"),
11199        "Expected val to be unchanged, got \"%s\"\n", val);
11200     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11201
11202     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &prodpatches, NULL);
11203     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11204
11205     /* Patches key exists */
11206     size = MAX_PATH;
11207     lstrcpyA(val, "apple");
11208     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11209                             MSIINSTALLCONTEXT_USERMANAGED,
11210                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11211     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11212     ok(!lstrcmpA(val, "apple"),
11213        "Expected val to be unchanged, got \"%s\"\n", val);
11214     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11215
11216     res = RegSetValueExA(prodpatches, patch_squashed, 0, REG_SZ,
11217                          (const BYTE *)"transforms", 11);
11218     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11219
11220     /* specific patch value exists */
11221     size = MAX_PATH;
11222     lstrcpyA(val, "apple");
11223     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11224                             MSIINSTALLCONTEXT_USERMANAGED,
11225                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11226     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11227     ok(!lstrcmpA(val, "apple"),
11228        "Expected val to be unchanged, got \"%s\"\n", val);
11229     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11230
11231     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
11232     lstrcatA(keypath, usersid);
11233     lstrcatA(keypath, "\\Patches\\");
11234     lstrcatA(keypath, patch_squashed);
11235
11236     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udpatch, NULL);
11237     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11238
11239     /* UserData Patches key exists */
11240     size = MAX_PATH;
11241     lstrcpyA(val, "apple");
11242     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11243                             MSIINSTALLCONTEXT_USERMANAGED,
11244                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11245     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11246     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
11247     ok(size == 0, "Expected 0, got %d\n", size);
11248
11249     res = RegSetValueExA(udpatch, "ManagedLocalPackage", 0, REG_SZ,
11250                          (const BYTE *)"pack", 5);
11251     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11252
11253     /* ManagedLocalPatch value exists */
11254     size = MAX_PATH;
11255     lstrcpyA(val, "apple");
11256     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11257                             MSIINSTALLCONTEXT_USERMANAGED,
11258                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11259     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11260     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
11261     ok(size == 4, "Expected 4, got %d\n", size);
11262
11263     size = MAX_PATH;
11264     lstrcpyA(val, "apple");
11265     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11266                             MSIINSTALLCONTEXT_USERMANAGED,
11267                             INSTALLPROPERTY_TRANSFORMS, val, &size);
11268     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11269     ok(!lstrcmpA(val, "transforms"), "Expected \"transforms\", got \"%s\"\n", val);
11270     ok(size == 10, "Expected 10, got %d\n", size);
11271
11272     res = RegSetValueExA(hpatch, "Installed", 0, REG_SZ,
11273                          (const BYTE *)"mydate", 7);
11274     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11275
11276     /* Installed value exists */
11277     size = MAX_PATH;
11278     lstrcpyA(val, "apple");
11279     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11280                             MSIINSTALLCONTEXT_USERMANAGED,
11281                             INSTALLPROPERTY_INSTALLDATE, val, &size);
11282     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11283     ok(!lstrcmpA(val, "mydate"), "Expected \"mydate\", got \"%s\"\n", val);
11284     ok(size == 6, "Expected 6, got %d\n", size);
11285
11286     res = RegSetValueExA(hpatch, "Uninstallable", 0, REG_SZ,
11287                          (const BYTE *)"yes", 4);
11288     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11289
11290     /* Uninstallable value exists */
11291     size = MAX_PATH;
11292     lstrcpyA(val, "apple");
11293     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11294                             MSIINSTALLCONTEXT_USERMANAGED,
11295                             INSTALLPROPERTY_UNINSTALLABLE, val, &size);
11296     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11297     ok(!lstrcmpA(val, "yes"), "Expected \"yes\", got \"%s\"\n", val);
11298     ok(size == 3, "Expected 3, got %d\n", size);
11299
11300     res = RegSetValueExA(hpatch, "State", 0, REG_SZ,
11301                          (const BYTE *)"good", 5);
11302     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11303
11304     /* State value exists */
11305     size = MAX_PATH;
11306     lstrcpyA(val, "apple");
11307     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11308                             MSIINSTALLCONTEXT_USERMANAGED,
11309                             INSTALLPROPERTY_PATCHSTATE, val, &size);
11310     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11311     ok(!lstrcmpA(val, "good"), "Expected \"good\", got \"%s\"\n", val);
11312     ok(size == 4, "Expected 4, got %d\n", size);
11313
11314     size = 1;
11315     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
11316                          (const BYTE *)&size, sizeof(DWORD));
11317     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11318
11319     /* State value exists */
11320     size = MAX_PATH;
11321     lstrcpyA(val, "apple");
11322     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11323                             MSIINSTALLCONTEXT_USERMANAGED,
11324                             INSTALLPROPERTY_PATCHSTATE, val, &size);
11325     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11326     todo_wine ok(!lstrcmpA(val, "1"), "Expected \"1\", got \"%s\"\n", val);
11327     ok(size == 1, "Expected 1, got %d\n", size);
11328
11329     res = RegSetValueExA(hpatch, "DisplayName", 0, REG_SZ,
11330                          (const BYTE *)"display", 8);
11331     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11332
11333     /* DisplayName value exists */
11334     size = MAX_PATH;
11335     lstrcpyA(val, "apple");
11336     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11337                             MSIINSTALLCONTEXT_USERMANAGED,
11338                             INSTALLPROPERTY_DISPLAYNAME, val, &size);
11339     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11340     ok(!lstrcmpA(val, "display"), "Expected \"display\", got \"%s\"\n", val);
11341     ok(size == 7, "Expected 7, got %d\n", size);
11342
11343     res = RegSetValueExA(hpatch, "MoreInfoURL", 0, REG_SZ,
11344                          (const BYTE *)"moreinfo", 9);
11345     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11346
11347     /* MoreInfoURL value exists */
11348     size = MAX_PATH;
11349     lstrcpyA(val, "apple");
11350     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11351                             MSIINSTALLCONTEXT_USERMANAGED,
11352                             INSTALLPROPERTY_MOREINFOURL, val, &size);
11353     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11354     ok(!lstrcmpA(val, "moreinfo"), "Expected \"moreinfo\", got \"%s\"\n", val);
11355     ok(size == 8, "Expected 8, got %d\n", size);
11356
11357     /* szProperty is invalid */
11358     size = MAX_PATH;
11359     lstrcpyA(val, "apple");
11360     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11361                             MSIINSTALLCONTEXT_USERMANAGED,
11362                             "IDontExist", val, &size);
11363     ok(r == ERROR_UNKNOWN_PROPERTY,
11364        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
11365     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
11366     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
11367
11368     /* lpValue is NULL, while pcchValue is non-NULL */
11369     size = MAX_PATH;
11370     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11371                             MSIINSTALLCONTEXT_USERMANAGED,
11372                             INSTALLPROPERTY_MOREINFOURL, NULL, &size);
11373     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11374     ok(size == 16, "Expected 16, got %d\n", size);
11375
11376     /* pcchValue is NULL, while lpValue is non-NULL */
11377     lstrcpyA(val, "apple");
11378     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11379                             MSIINSTALLCONTEXT_USERMANAGED,
11380                             INSTALLPROPERTY_MOREINFOURL, val, NULL);
11381     ok(r == ERROR_INVALID_PARAMETER,
11382        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11383     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
11384
11385     /* both lpValue and pcchValue are NULL */
11386     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11387                             MSIINSTALLCONTEXT_USERMANAGED,
11388                             INSTALLPROPERTY_MOREINFOURL, NULL, NULL);
11389     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11390
11391     /* pcchValue doesn't have enough room for NULL terminator */
11392     size = 8;
11393     lstrcpyA(val, "apple");
11394     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11395                             MSIINSTALLCONTEXT_USERMANAGED,
11396                             INSTALLPROPERTY_MOREINFOURL, val, &size);
11397     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
11398     ok(!lstrcmpA(val, "moreinf"),
11399        "Expected \"moreinf\", got \"%s\"\n", val);
11400     ok(size == 16, "Expected 16, got %d\n", size);
11401
11402     /* pcchValue has exactly enough room for NULL terminator */
11403     size = 9;
11404     lstrcpyA(val, "apple");
11405     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11406                             MSIINSTALLCONTEXT_USERMANAGED,
11407                             INSTALLPROPERTY_MOREINFOURL, val, &size);
11408     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11409     ok(!lstrcmpA(val, "moreinfo"),
11410        "Expected \"moreinfo\", got \"%s\"\n", val);
11411     ok(size == 8, "Expected 8, got %d\n", size);
11412
11413     /* pcchValue is too small, lpValue is NULL */
11414     size = 0;
11415     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11416                             MSIINSTALLCONTEXT_USERMANAGED,
11417                             INSTALLPROPERTY_MOREINFOURL, NULL, &size);
11418     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11419     ok(size == 16, "Expected 16, got %d\n", size);
11420
11421     RegDeleteValueA(prodpatches, patch_squashed);
11422     delete_key(prodpatches, "", access & KEY_WOW64_64KEY);
11423     RegCloseKey(prodpatches);
11424     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
11425     RegCloseKey(prodkey);
11426
11427     /* UserData is sufficient for all properties
11428      * except INSTALLPROPERTY_TRANSFORMS
11429      */
11430     size = MAX_PATH;
11431     lstrcpyA(val, "apple");
11432     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11433                             MSIINSTALLCONTEXT_USERMANAGED,
11434                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11435     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11436     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
11437     ok(size == 4, "Expected 4, got %d\n", size);
11438
11439     /* UserData is sufficient for all properties
11440      * except INSTALLPROPERTY_TRANSFORMS
11441      */
11442     size = MAX_PATH;
11443     lstrcpyA(val, "apple");
11444     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11445                             MSIINSTALLCONTEXT_USERMANAGED,
11446                             INSTALLPROPERTY_TRANSFORMS, val, &size);
11447     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11448     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
11449     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
11450
11451     RegDeleteValueA(hpatch, "MoreInfoURL");
11452     RegDeleteValueA(hpatch, "Display");
11453     RegDeleteValueA(hpatch, "State");
11454     RegDeleteValueA(hpatch, "Uninstallable");
11455     RegDeleteValueA(hpatch, "Installed");
11456     RegDeleteValueA(udpatch, "ManagedLocalPackage");
11457     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
11458     RegCloseKey(udpatch);
11459     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
11460     RegCloseKey(hpatch);
11461     delete_key(patches, "", access & KEY_WOW64_64KEY);
11462     RegCloseKey(patches);
11463     delete_key(props, "", access & KEY_WOW64_64KEY);
11464     RegCloseKey(props);
11465     delete_key(udprod, "", access & KEY_WOW64_64KEY);
11466     RegCloseKey(udprod);
11467
11468     /* MSIINSTALLCONTEXT_USERUNMANAGED */
11469
11470     size = MAX_PATH;
11471     lstrcpyA(val, "apple");
11472     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11473                             MSIINSTALLCONTEXT_USERUNMANAGED,
11474                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11475     ok(r == ERROR_UNKNOWN_PRODUCT,
11476        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11477     ok(!lstrcmpA(val, "apple"),
11478        "Expected val to be unchanged, got \"%s\"\n", val);
11479     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11480
11481     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
11482     lstrcatA(keypath, usersid);
11483     lstrcatA(keypath, "\\Products\\");
11484     lstrcatA(keypath, prod_squashed);
11485
11486     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
11487     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11488
11489     /* local UserData product key exists */
11490     size = MAX_PATH;
11491     lstrcpyA(val, "apple");
11492     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11493                             MSIINSTALLCONTEXT_USERUNMANAGED,
11494                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11495     ok(r == ERROR_UNKNOWN_PRODUCT,
11496        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11497     ok(!lstrcmpA(val, "apple"),
11498        "Expected val to be unchanged, got \"%s\"\n", val);
11499     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11500
11501     res = RegCreateKeyExA(udprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
11502     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11503
11504     /* InstallProperties key exists */
11505     size = MAX_PATH;
11506     lstrcpyA(val, "apple");
11507     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11508                             MSIINSTALLCONTEXT_USERUNMANAGED,
11509                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11510     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11511     ok(!lstrcmpA(val, "apple"),
11512        "Expected val to be unchanged, got \"%s\"\n", val);
11513     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11514
11515     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
11516     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11517
11518     /* Patches key exists */
11519     size = MAX_PATH;
11520     lstrcpyA(val, "apple");
11521     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11522                             MSIINSTALLCONTEXT_USERUNMANAGED,
11523                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11524     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11525     ok(!lstrcmpA(val, "apple"),
11526        "Expected val to be unchanged, got \"%s\"\n", val);
11527     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11528
11529     res = RegCreateKeyExA(patches, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
11530     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11531
11532     /* Patches key exists */
11533     size = MAX_PATH;
11534     lstrcpyA(val, "apple");
11535     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11536                             MSIINSTALLCONTEXT_USERUNMANAGED,
11537                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11538     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11539     ok(!lstrcmpA(val, "apple"),
11540        "Expected val to be unchanged, got \"%s\"\n", val);
11541     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11542
11543     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
11544     lstrcatA(keypath, prod_squashed);
11545
11546     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
11547     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11548
11549     /* current user product key exists */
11550     size = MAX_PATH;
11551     lstrcpyA(val, "apple");
11552     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11553                             MSIINSTALLCONTEXT_USERUNMANAGED,
11554                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11555     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11556     ok(!lstrcmpA(val, "apple"),
11557        "Expected val to be unchanged, got \"%s\"\n", val);
11558     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11559
11560     res = RegCreateKeyA(prodkey, "Patches", &prodpatches);
11561     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11562
11563     /* Patches key exists */
11564     size = MAX_PATH;
11565     lstrcpyA(val, "apple");
11566     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11567                             MSIINSTALLCONTEXT_USERUNMANAGED,
11568                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11569     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11570     ok(!lstrcmpA(val, "apple"),
11571        "Expected val to be unchanged, got \"%s\"\n", val);
11572     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11573
11574     res = RegSetValueExA(prodpatches, patch_squashed, 0, REG_SZ,
11575                          (const BYTE *)"transforms", 11);
11576     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11577
11578     /* specific patch value exists */
11579     size = MAX_PATH;
11580     lstrcpyA(val, "apple");
11581     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11582                             MSIINSTALLCONTEXT_USERUNMANAGED,
11583                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11584     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11585     ok(!lstrcmpA(val, "apple"),
11586        "Expected val to be unchanged, got \"%s\"\n", val);
11587     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11588
11589     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
11590     lstrcatA(keypath, usersid);
11591     lstrcatA(keypath, "\\Patches\\");
11592     lstrcatA(keypath, patch_squashed);
11593
11594     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udpatch, NULL);
11595     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11596
11597     /* UserData Patches key exists */
11598     size = MAX_PATH;
11599     lstrcpyA(val, "apple");
11600     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11601                             MSIINSTALLCONTEXT_USERUNMANAGED,
11602                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11603     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11604     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
11605     ok(size == 0, "Expected 0, got %d\n", size);
11606
11607     res = RegSetValueExA(udpatch, "LocalPackage", 0, REG_SZ,
11608                          (const BYTE *)"pack", 5);
11609     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11610
11611     /* LocalPatch value exists */
11612     size = MAX_PATH;
11613     lstrcpyA(val, "apple");
11614     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11615                             MSIINSTALLCONTEXT_USERUNMANAGED,
11616                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11617     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11618     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
11619     ok(size == 4, "Expected 4, got %d\n", size);
11620
11621     size = MAX_PATH;
11622     lstrcpyA(val, "apple");
11623     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11624                             MSIINSTALLCONTEXT_USERUNMANAGED,
11625                             INSTALLPROPERTY_TRANSFORMS, val, &size);
11626     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11627     ok(!lstrcmpA(val, "transforms"), "Expected \"transforms\", got \"%s\"\n", val);
11628     ok(size == 10, "Expected 10, got %d\n", size);
11629
11630     RegDeleteValueA(prodpatches, patch_squashed);
11631     delete_key(prodpatches, "", access & KEY_WOW64_64KEY);
11632     RegCloseKey(prodpatches);
11633     RegDeleteKeyA(prodkey, "");
11634     RegCloseKey(prodkey);
11635
11636     /* UserData is sufficient for all properties
11637      * except INSTALLPROPERTY_TRANSFORMS
11638      */
11639     size = MAX_PATH;
11640     lstrcpyA(val, "apple");
11641     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11642                             MSIINSTALLCONTEXT_USERUNMANAGED,
11643                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11644     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11645     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
11646     ok(size == 4, "Expected 4, got %d\n", size);
11647
11648     /* UserData is sufficient for all properties
11649      * except INSTALLPROPERTY_TRANSFORMS
11650      */
11651     size = MAX_PATH;
11652     lstrcpyA(val, "apple");
11653     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
11654                             MSIINSTALLCONTEXT_USERUNMANAGED,
11655                             INSTALLPROPERTY_TRANSFORMS, val, &size);
11656     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11657     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
11658     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
11659
11660     RegDeleteValueA(udpatch, "LocalPackage");
11661     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
11662     RegCloseKey(udpatch);
11663     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
11664     RegCloseKey(hpatch);
11665     delete_key(patches, "", access & KEY_WOW64_64KEY);
11666     RegCloseKey(patches);
11667     delete_key(props, "", access & KEY_WOW64_64KEY);
11668     RegCloseKey(props);
11669     delete_key(udprod, "", access & KEY_WOW64_64KEY);
11670     RegCloseKey(udprod);
11671
11672     /* MSIINSTALLCONTEXT_MACHINE */
11673
11674     size = MAX_PATH;
11675     lstrcpyA(val, "apple");
11676     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
11677                             MSIINSTALLCONTEXT_MACHINE,
11678                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11679     ok(r == ERROR_UNKNOWN_PRODUCT,
11680        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11681     ok(!lstrcmpA(val, "apple"),
11682        "Expected val to be unchanged, got \"%s\"\n", val);
11683     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11684
11685     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
11686     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Products\\");
11687     lstrcatA(keypath, prod_squashed);
11688
11689     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
11690     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11691
11692     /* local UserData product key exists */
11693     size = MAX_PATH;
11694     lstrcpyA(val, "apple");
11695     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
11696                             MSIINSTALLCONTEXT_MACHINE,
11697                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11698     ok(r == ERROR_UNKNOWN_PRODUCT,
11699        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11700     ok(!lstrcmpA(val, "apple"),
11701        "Expected val to be unchanged, got \"%s\"\n", val);
11702     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11703
11704     res = RegCreateKeyExA(udprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
11705     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11706
11707     /* InstallProperties key exists */
11708     size = MAX_PATH;
11709     lstrcpyA(val, "apple");
11710     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
11711                             MSIINSTALLCONTEXT_MACHINE,
11712                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11713     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11714     ok(!lstrcmpA(val, "apple"),
11715        "Expected val to be unchanged, got \"%s\"\n", val);
11716     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11717
11718     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
11719     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11720
11721     /* Patches key exists */
11722     size = MAX_PATH;
11723     lstrcpyA(val, "apple");
11724     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
11725                             MSIINSTALLCONTEXT_MACHINE,
11726                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11727     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11728     ok(!lstrcmpA(val, "apple"),
11729        "Expected val to be unchanged, got \"%s\"\n", val);
11730     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11731
11732     res = RegCreateKeyExA(patches, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
11733     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11734
11735     /* Patches key exists */
11736     size = MAX_PATH;
11737     lstrcpyA(val, "apple");
11738     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
11739                             MSIINSTALLCONTEXT_MACHINE,
11740                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11741     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11742     ok(!lstrcmpA(val, "apple"),
11743        "Expected val to be unchanged, got \"%s\"\n", val);
11744     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11745
11746     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
11747     lstrcatA(keypath, prod_squashed);
11748
11749     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
11750     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11751
11752     /* local product key exists */
11753     size = MAX_PATH;
11754     lstrcpyA(val, "apple");
11755     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
11756                             MSIINSTALLCONTEXT_MACHINE,
11757                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11758     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11759     ok(!lstrcmpA(val, "apple"),
11760        "Expected val to be unchanged, got \"%s\"\n", val);
11761     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11762
11763     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &prodpatches, NULL);
11764     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11765
11766     /* Patches key exists */
11767     size = MAX_PATH;
11768     lstrcpyA(val, "apple");
11769     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
11770                             MSIINSTALLCONTEXT_MACHINE,
11771                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11772     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11773     ok(!lstrcmpA(val, "apple"),
11774        "Expected val to be unchanged, got \"%s\"\n", val);
11775     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11776
11777     res = RegSetValueExA(prodpatches, patch_squashed, 0, REG_SZ,
11778                          (const BYTE *)"transforms", 11);
11779     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11780
11781     /* specific patch value exists */
11782     size = MAX_PATH;
11783     lstrcpyA(val, "apple");
11784     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
11785                             MSIINSTALLCONTEXT_MACHINE,
11786                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11787     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11788     ok(!lstrcmpA(val, "apple"),
11789        "Expected val to be unchanged, got \"%s\"\n", val);
11790     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11791
11792     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
11793     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Patches\\");
11794     lstrcatA(keypath, patch_squashed);
11795
11796     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udpatch, NULL);
11797     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11798
11799     /* UserData Patches key exists */
11800     size = MAX_PATH;
11801     lstrcpyA(val, "apple");
11802     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
11803                             MSIINSTALLCONTEXT_MACHINE,
11804                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11805     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11806     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
11807     ok(size == 0, "Expected 0, got %d\n", size);
11808
11809     res = RegSetValueExA(udpatch, "LocalPackage", 0, REG_SZ,
11810                          (const BYTE *)"pack", 5);
11811     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11812
11813     /* LocalPatch value exists */
11814     size = MAX_PATH;
11815     lstrcpyA(val, "apple");
11816     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
11817                             MSIINSTALLCONTEXT_MACHINE,
11818                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11819     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11820     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
11821     ok(size == 4, "Expected 4, got %d\n", size);
11822
11823     size = MAX_PATH;
11824     lstrcpyA(val, "apple");
11825     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
11826                             MSIINSTALLCONTEXT_MACHINE,
11827                             INSTALLPROPERTY_TRANSFORMS, val, &size);
11828     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11829     ok(!lstrcmpA(val, "transforms"), "Expected \"transforms\", got \"%s\"\n", val);
11830     ok(size == 10, "Expected 10, got %d\n", size);
11831
11832     RegDeleteValueA(prodpatches, patch_squashed);
11833     delete_key(prodpatches, "", access & KEY_WOW64_64KEY);
11834     RegCloseKey(prodpatches);
11835     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
11836     RegCloseKey(prodkey);
11837
11838     /* UserData is sufficient for all properties
11839      * except INSTALLPROPERTY_TRANSFORMS
11840      */
11841     size = MAX_PATH;
11842     lstrcpyA(val, "apple");
11843     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
11844                             MSIINSTALLCONTEXT_MACHINE,
11845                             INSTALLPROPERTY_LOCALPACKAGE, val, &size);
11846     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11847     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
11848     ok(size == 4, "Expected 4, got %d\n", size);
11849
11850     /* UserData is sufficient for all properties
11851      * except INSTALLPROPERTY_TRANSFORMS
11852      */
11853     size = MAX_PATH;
11854     lstrcpyA(val, "apple");
11855     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
11856                             MSIINSTALLCONTEXT_MACHINE,
11857                             INSTALLPROPERTY_TRANSFORMS, val, &size);
11858     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
11859     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
11860     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
11861
11862     RegDeleteValueA(udpatch, "LocalPackage");
11863     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
11864     RegCloseKey(udpatch);
11865     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
11866     RegCloseKey(hpatch);
11867     delete_key(patches, "", access & KEY_WOW64_64KEY);
11868     RegCloseKey(patches);
11869     delete_key(props, "", access & KEY_WOW64_64KEY);
11870     RegCloseKey(props);
11871     delete_key(udprod, "", access & KEY_WOW64_64KEY);
11872     RegCloseKey(udprod);
11873     LocalFree(usersid);
11874 }
11875
11876 static void test_MsiGetPatchInfo(void)
11877 {
11878     UINT r;
11879     char prod_code[MAX_PATH], prod_squashed[MAX_PATH], val[MAX_PATH];
11880     char patch_code[MAX_PATH], patch_squashed[MAX_PATH], keypath[MAX_PATH];
11881     WCHAR valW[MAX_PATH], patch_codeW[MAX_PATH];
11882     HKEY hkey_product, hkey_patch, hkey_patches, hkey_udprops, hkey_udproduct;
11883     HKEY hkey_udpatch, hkey_udpatches, hkey_udproductpatches, hkey_udproductpatch;
11884     DWORD size;
11885     LONG res;
11886     REGSAM access = KEY_ALL_ACCESS;
11887
11888     create_test_guid(patch_code, patch_squashed);
11889     create_test_guid(prod_code, prod_squashed);
11890     MultiByteToWideChar(CP_ACP, 0, patch_code, -1, patch_codeW, MAX_PATH);
11891
11892     if (is_wow64)
11893         access |= KEY_WOW64_64KEY;
11894
11895     r = MsiGetPatchInfoA(NULL, NULL, NULL, NULL);
11896     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
11897
11898     r = MsiGetPatchInfoA(patch_code, NULL, NULL, NULL);
11899     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
11900
11901     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, NULL, NULL);
11902     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
11903
11904     size = 0;
11905     r = MsiGetPatchInfoA(patch_code, NULL, NULL, &size);
11906     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
11907
11908     r = MsiGetPatchInfoA(patch_code, "", NULL, &size);
11909     ok(r == ERROR_UNKNOWN_PROPERTY, "expected ERROR_UNKNOWN_PROPERTY, got %u\n", r);
11910
11911     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
11912     lstrcatA(keypath, prod_squashed);
11913
11914     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey_product, NULL);
11915     if (res == ERROR_ACCESS_DENIED)
11916     {
11917         skip("Not enough rights to perform tests\n");
11918         return;
11919     }
11920     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
11921
11922     /* product key exists */
11923     size = MAX_PATH;
11924     lstrcpyA(val, "apple");
11925     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11926     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
11927     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged, got \"%s\"\n", val);
11928     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
11929
11930     res = RegCreateKeyExA(hkey_product, "Patches", 0, NULL, 0, access, NULL, &hkey_patches, NULL);
11931     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
11932
11933     /* patches key exists */
11934     size = MAX_PATH;
11935     lstrcpyA(val, "apple");
11936     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11937     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
11938     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
11939     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
11940
11941     res = RegCreateKeyExA(hkey_patches, patch_squashed, 0, NULL, 0, access, NULL, &hkey_patch, NULL);
11942     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
11943
11944     /* patch key exists */
11945     size = MAX_PATH;
11946     lstrcpyA(val, "apple");
11947     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11948     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
11949     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
11950     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
11951
11952     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
11953     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Products\\");
11954     lstrcatA(keypath, prod_squashed);
11955
11956     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey_udproduct, NULL);
11957     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
11958
11959     /* UserData product key exists */
11960     size = MAX_PATH;
11961     lstrcpyA(val, "apple");
11962     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11963     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
11964     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
11965     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
11966
11967     res = RegCreateKeyExA(hkey_udproduct, "InstallProperties", 0, NULL, 0, access, NULL, &hkey_udprops, NULL);
11968     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
11969
11970     /* InstallProperties key exists */
11971     size = MAX_PATH;
11972     lstrcpyA(val, "apple");
11973     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11974     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
11975     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged, got \"%s\"\n", val);
11976     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
11977
11978     res = RegCreateKeyExA(hkey_udproduct, "Patches", 0, NULL, 0, access, NULL, &hkey_udpatches, NULL);
11979     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
11980
11981     /* UserData Patches key exists */
11982     size = MAX_PATH;
11983     lstrcpyA(val, "apple");
11984     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11985     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
11986     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
11987     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
11988
11989     res = RegCreateKeyExA(hkey_udproduct, "Patches", 0, NULL, 0, access, NULL, &hkey_udproductpatches, NULL);
11990     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11991
11992     res = RegCreateKeyExA(hkey_udproductpatches, patch_squashed, 0, NULL, 0, access, NULL, &hkey_udproductpatch, NULL);
11993     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11994
11995     /* UserData product patch key exists */
11996     size = MAX_PATH;
11997     lstrcpyA(val, "apple");
11998     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
11999     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
12000     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
12001     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
12002
12003     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
12004     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Patches\\");
12005     lstrcatA(keypath, patch_squashed);
12006
12007     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey_udpatch, NULL);
12008     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
12009
12010     res = RegSetValueExA(hkey_udpatch, "LocalPackage", 0, REG_SZ, (const BYTE *)"c:\\test.msp", 12);
12011     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
12012
12013     /* UserData Patch key exists */
12014     size = 0;
12015     lstrcpyA(val, "apple");
12016     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12017     ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", r);
12018     ok(!lstrcmpA(val, "apple"), "expected \"apple\", got \"%s\"\n", val);
12019     ok(size == 11, "expected 11 got %u\n", size);
12020
12021     size = MAX_PATH;
12022     lstrcpyA(val, "apple");
12023     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12024     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS got %u\n", r);
12025     ok(!lstrcmpA(val, "c:\\test.msp"), "expected \"c:\\test.msp\", got \"%s\"\n", val);
12026     ok(size == 11, "expected 11 got %u\n", size);
12027
12028     size = 0;
12029     valW[0] = 0;
12030     r = MsiGetPatchInfoW(patch_codeW, INSTALLPROPERTY_LOCALPACKAGEW, valW, &size);
12031     ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", r);
12032     ok(!valW[0], "expected 0 got %u\n", valW[0]);
12033     ok(size == 11, "expected 11 got %u\n", size);
12034
12035     size = MAX_PATH;
12036     valW[0] = 0;
12037     r = MsiGetPatchInfoW(patch_codeW, INSTALLPROPERTY_LOCALPACKAGEW, valW, &size);
12038     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS got %u\n", r);
12039     ok(valW[0], "expected > 0 got %u\n", valW[0]);
12040     ok(size == 11, "expected 11 got %u\n", size);
12041
12042     delete_key(hkey_udproductpatch, "", access & KEY_WOW64_64KEY);
12043     RegCloseKey(hkey_udproductpatch);
12044     delete_key(hkey_udproductpatches, "", access & KEY_WOW64_64KEY);
12045     RegCloseKey(hkey_udproductpatches);
12046     delete_key(hkey_udpatch, "", access & KEY_WOW64_64KEY);
12047     RegCloseKey(hkey_udpatch);
12048     delete_key(hkey_patches, "", access & KEY_WOW64_64KEY);
12049     RegCloseKey(hkey_patches);
12050     delete_key(hkey_product, "", access & KEY_WOW64_64KEY);
12051     RegCloseKey(hkey_product);
12052     delete_key(hkey_patch, "", access & KEY_WOW64_64KEY);
12053     RegCloseKey(hkey_patch);
12054     delete_key(hkey_udpatches, "", access & KEY_WOW64_64KEY);
12055     RegCloseKey(hkey_udpatches);
12056     delete_key(hkey_udprops, "", access & KEY_WOW64_64KEY);
12057     RegCloseKey(hkey_udprops);
12058     delete_key(hkey_udproduct, "", access & KEY_WOW64_64KEY);
12059     RegCloseKey(hkey_udproduct);
12060 }
12061
12062 static void test_MsiEnumProducts(void)
12063 {
12064     UINT r;
12065     int found1, found2, found3;
12066     DWORD index;
12067     char product1[39], product2[39], product3[39], guid[39];
12068     char product_squashed1[33], product_squashed2[33], product_squashed3[33];
12069     char keypath1[MAX_PATH], keypath2[MAX_PATH], keypath3[MAX_PATH];
12070     char *usersid;
12071     HKEY key1, key2, key3;
12072     REGSAM access = KEY_ALL_ACCESS;
12073
12074     create_test_guid(product1, product_squashed1);
12075     create_test_guid(product2, product_squashed2);
12076     create_test_guid(product3, product_squashed3);
12077     usersid = get_user_sid();
12078
12079     if (is_wow64)
12080         access |= KEY_WOW64_64KEY;
12081
12082     strcpy(keypath1, "Software\\Classes\\Installer\\Products\\");
12083     strcat(keypath1, product_squashed1);
12084
12085     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL);
12086     if (r == ERROR_ACCESS_DENIED)
12087     {
12088         skip("Not enough rights to perform tests\n");
12089         LocalFree(usersid);
12090         return;
12091     }
12092     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12093
12094     strcpy(keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
12095     strcat(keypath2, usersid);
12096     strcat(keypath2, "\\Installer\\Products\\");
12097     strcat(keypath2, product_squashed2);
12098
12099     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL);
12100     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12101
12102     strcpy(keypath3, "Software\\Microsoft\\Installer\\Products\\");
12103     strcat(keypath3, product_squashed3);
12104
12105     r = RegCreateKeyA(HKEY_CURRENT_USER, keypath3, &key3);
12106     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12107
12108     index = 0;
12109     r = MsiEnumProductsA(index, guid);
12110     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
12111
12112     r = MsiEnumProductsA(index, NULL);
12113     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
12114
12115     index = 2;
12116     r = MsiEnumProductsA(index, guid);
12117     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
12118
12119     index = 0;
12120     r = MsiEnumProductsA(index, guid);
12121     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
12122
12123     found1 = found2 = found3 = 0;
12124     while ((r = MsiEnumProductsA(index, guid)) == ERROR_SUCCESS)
12125     {
12126         if (!strcmp(product1, guid)) found1 = 1;
12127         if (!strcmp(product2, guid)) found2 = 1;
12128         if (!strcmp(product3, guid)) found3 = 1;
12129         index++;
12130     }
12131     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %u\n", r);
12132     ok(found1, "product1 not found\n");
12133     ok(found2, "product2 not found\n");
12134     ok(found3, "product3 not found\n");
12135
12136     delete_key(key1, "", access & KEY_WOW64_64KEY);
12137     delete_key(key2, "", access & KEY_WOW64_64KEY);
12138     RegDeleteKeyA(key3, "");
12139     RegCloseKey(key1);
12140     RegCloseKey(key2);
12141     RegCloseKey(key3);
12142     LocalFree(usersid);
12143 }
12144
12145 static void test_MsiGetFileSignatureInformation(void)
12146 {
12147     HRESULT hr;
12148     const CERT_CONTEXT *cert;
12149     DWORD len;
12150
12151     hr = MsiGetFileSignatureInformationA( NULL, 0, NULL, NULL, NULL );
12152     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
12153
12154     hr = MsiGetFileSignatureInformationA( NULL, 0, NULL, NULL, &len );
12155     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
12156
12157     hr = MsiGetFileSignatureInformationA( NULL, 0, &cert, NULL, &len );
12158     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
12159
12160     hr = MsiGetFileSignatureInformationA( "", 0, NULL, NULL, NULL );
12161     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
12162
12163     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, NULL );
12164     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
12165
12166     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, &len );
12167     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
12168
12169     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, &cert, NULL, &len );
12170     todo_wine ok(hr == CRYPT_E_FILE_ERROR, "expected CRYPT_E_FILE_ERROR got 0x%08x\n", hr);
12171
12172     create_file( "signature.bin", "signature", sizeof("signature") );
12173
12174     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, NULL );
12175     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
12176
12177     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, &len );
12178     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
12179
12180     cert = (const CERT_CONTEXT *)0xdeadbeef;
12181     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, &cert, NULL, &len );
12182     todo_wine ok(hr == HRESULT_FROM_WIN32(ERROR_FUNCTION_FAILED), "got 0x%08x\n", hr);
12183     ok(cert == NULL, "got %p\n", cert);
12184
12185     DeleteFileA( "signature.bin" );
12186 }
12187
12188 static void test_MsiEnumProductsEx(void)
12189 {
12190     UINT r;
12191     DWORD len, index;
12192     MSIINSTALLCONTEXT context;
12193     char product0[39], product1[39], product2[39], product3[39], guid[39], sid[128];
12194     char product_squashed1[33], product_squashed2[33], product_squashed3[33];
12195     char keypath1[MAX_PATH], keypath2[MAX_PATH], keypath3[MAX_PATH];
12196     HKEY key1 = NULL, key2 = NULL, key3 = NULL;
12197     REGSAM access = KEY_ALL_ACCESS;
12198     char *usersid = get_user_sid();
12199
12200     if (!pMsiEnumProductsExA)
12201     {
12202         win_skip("MsiEnumProductsExA not implemented\n");
12203         return;
12204     }
12205
12206     create_test_guid( product0, NULL );
12207     create_test_guid( product1, product_squashed1 );
12208     create_test_guid( product2, product_squashed2 );
12209     create_test_guid( product3, product_squashed3 );
12210
12211     if (is_wow64) access |= KEY_WOW64_64KEY;
12212
12213     strcpy( keypath1, "Software\\Classes\\Installer\\Products\\" );
12214     strcat( keypath1, product_squashed1 );
12215
12216     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
12217     if (r == ERROR_ACCESS_DENIED)
12218     {
12219         skip( "insufficient rights\n" );
12220         goto done;
12221     }
12222     ok( r == ERROR_SUCCESS, "got %u\n", r );
12223
12224     strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\" );
12225     strcat( keypath2, usersid );
12226     strcat( keypath2, "\\Installer\\Products\\" );
12227     strcat( keypath2, product_squashed2 );
12228
12229     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
12230     ok( r == ERROR_SUCCESS, "got %u\n", r );
12231
12232     strcpy( keypath3, usersid );
12233     strcat( keypath3, "\\Software\\Microsoft\\Installer\\Products\\" );
12234     strcat( keypath3, product_squashed3 );
12235
12236     r = RegCreateKeyExA( HKEY_USERS, keypath3, 0, NULL, 0, access, NULL, &key3, NULL );
12237     ok( r == ERROR_SUCCESS, "got %u\n", r );
12238
12239     r = pMsiEnumProductsExA( NULL, NULL, 0, 0, NULL, NULL, NULL, NULL );
12240     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
12241
12242     len = sizeof(sid);
12243     r = pMsiEnumProductsExA( NULL, NULL, 0, 0, NULL, NULL, NULL, &len );
12244     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
12245     ok( len == sizeof(sid), "got %u\n", len );
12246
12247     r = pMsiEnumProductsExA( NULL, NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, NULL, NULL );
12248     ok( r == ERROR_SUCCESS, "got %u\n", r );
12249
12250     sid[0] = 0;
12251     len = sizeof(sid);
12252     r = pMsiEnumProductsExA( product0, NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, &len );
12253     ok( r == ERROR_NO_MORE_ITEMS, "got %u\n", r );
12254     ok( len == sizeof(sid), "got %u\n", len );
12255     ok( !sid[0], "got %s\n", sid );
12256
12257     sid[0] = 0;
12258     len = sizeof(sid);
12259     r = pMsiEnumProductsExA( product0, usersid, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, &len );
12260     ok( r == ERROR_NO_MORE_ITEMS, "got %u\n", r );
12261     ok( len == sizeof(sid), "got %u\n", len );
12262     ok( !sid[0], "got %s\n", sid );
12263
12264     sid[0] = 0;
12265     len = 0;
12266     r = pMsiEnumProductsExA( NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, 0, NULL, NULL, sid, &len );
12267     ok( r == ERROR_MORE_DATA, "got %u\n", r );
12268     ok( len, "length unchanged\n" );
12269     ok( !sid[0], "got %s\n", sid );
12270
12271     guid[0] = 0;
12272     context = 0xdeadbeef;
12273     sid[0] = 0;
12274     len = sizeof(sid);
12275     r = pMsiEnumProductsExA( NULL, NULL, MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
12276     ok( r == ERROR_SUCCESS, "got %u\n", r );
12277     ok( guid[0], "empty guid\n" );
12278     ok( context != 0xdeadbeef, "context unchanged\n" );
12279     ok( !len, "got %u\n", len );
12280     ok( !sid[0], "got %s\n", sid );
12281
12282     guid[0] = 0;
12283     context = 0xdeadbeef;
12284     sid[0] = 0;
12285     len = sizeof(sid);
12286     r = pMsiEnumProductsExA( NULL, usersid, MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
12287     ok( r == ERROR_SUCCESS, "got %u\n", r );
12288     ok( guid[0], "empty guid\n" );
12289     ok( context != 0xdeadbeef, "context unchanged\n" );
12290     ok( !len, "got %u\n", len );
12291     ok( !sid[0], "got %s\n", sid );
12292
12293     guid[0] = 0;
12294     context = 0xdeadbeef;
12295     sid[0] = 0;
12296     len = sizeof(sid);
12297     r = pMsiEnumProductsExA( NULL, "S-1-1-0", MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
12298     if (r == ERROR_ACCESS_DENIED)
12299     {
12300         skip( "insufficient rights\n" );
12301         goto done;
12302     }
12303     ok( r == ERROR_SUCCESS, "got %u\n", r );
12304     ok( guid[0], "empty guid\n" );
12305     ok( context != 0xdeadbeef, "context unchanged\n" );
12306     ok( !len, "got %u\n", len );
12307     ok( !sid[0], "got %s\n", sid );
12308
12309     index = 0;
12310     guid[0] = 0;
12311     context = 0xdeadbeef;
12312     sid[0] = 0;
12313     len = sizeof(sid);
12314     while (!pMsiEnumProductsExA( NULL, "S-1-1-0", MSIINSTALLCONTEXT_ALL, index, guid, &context, sid, &len ))
12315     {
12316         if (!strcmp( product1, guid ))
12317         {
12318             ok( context == MSIINSTALLCONTEXT_MACHINE, "got %u\n", context );
12319             ok( !sid[0], "got \"%s\"\n", sid );
12320             ok( !len, "unexpected length %u\n", len );
12321         }
12322         if (!strcmp( product2, guid ))
12323         {
12324             ok( context == MSIINSTALLCONTEXT_USERMANAGED, "got %u\n", context );
12325             ok( sid[0], "empty sid\n" );
12326             ok( len == strlen(sid), "unexpected length %u\n", len );
12327         }
12328         if (!strcmp( product3, guid ))
12329         {
12330             ok( context == MSIINSTALLCONTEXT_USERUNMANAGED, "got %u\n", context );
12331             ok( sid[0], "empty sid\n" );
12332             ok( len == strlen(sid), "unexpected length %u\n", len );
12333         }
12334         index++;
12335         guid[0] = 0;
12336         context = 0xdeadbeef;
12337         sid[0] = 0;
12338         len = sizeof(sid);
12339     }
12340
12341 done:
12342     delete_key( key1, "", access );
12343     delete_key( key2, "", access );
12344     delete_key( key3, "", access );
12345     RegCloseKey( key1 );
12346     RegCloseKey( key2 );
12347     RegCloseKey( key3 );
12348     LocalFree( usersid );
12349 }
12350
12351 static void test_MsiEnumComponents(void)
12352 {
12353     UINT r;
12354     int found1, found2;
12355     DWORD index;
12356     char comp1[39], comp2[39], guid[39];
12357     char comp_squashed1[33], comp_squashed2[33];
12358     char keypath1[MAX_PATH], keypath2[MAX_PATH];
12359     REGSAM access = KEY_ALL_ACCESS;
12360     char *usersid = get_user_sid();
12361     HKEY key1 = NULL, key2 = NULL;
12362
12363     create_test_guid( comp1, comp_squashed1 );
12364     create_test_guid( comp2, comp_squashed2 );
12365
12366     if (is_wow64) access |= KEY_WOW64_64KEY;
12367
12368     strcpy( keypath1, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
12369     strcat( keypath1, "S-1-5-18\\Components\\" );
12370     strcat( keypath1, comp_squashed1 );
12371
12372     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
12373     if (r == ERROR_ACCESS_DENIED)
12374     {
12375         skip( "insufficient rights\n" );
12376         goto done;
12377     }
12378     ok( r == ERROR_SUCCESS, "got %u\n", r );
12379
12380     strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
12381     strcat( keypath2, usersid );
12382     strcat( keypath2, "\\Components\\" );
12383     strcat( keypath2, comp_squashed2 );
12384
12385     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
12386     if (r == ERROR_ACCESS_DENIED)
12387     {
12388         skip( "insufficient rights\n" );
12389         goto done;
12390     }
12391
12392     r = MsiEnumComponentsA( 0, NULL );
12393     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
12394
12395     index = 0;
12396     guid[0] = 0;
12397     found1 = found2 = 0;
12398     while (!MsiEnumComponentsA( index, guid ))
12399     {
12400         if (!strcmp( guid, comp1 )) found1 = 1;
12401         if (!strcmp( guid, comp2 )) found2 = 1;
12402         ok( guid[0], "empty guid\n" );
12403         guid[0] = 0;
12404         index++;
12405     }
12406     ok( found1, "comp1 not found\n" );
12407     ok( found2, "comp2 not found\n" );
12408
12409 done:
12410     delete_key( key1, "", access );
12411     delete_key( key2, "", access );
12412     RegCloseKey( key1 );
12413     RegCloseKey( key2 );
12414     LocalFree( usersid );
12415 }
12416
12417 static void test_MsiEnumComponentsEx(void)
12418 {
12419     UINT r;
12420     int found1, found2;
12421     DWORD len, index;
12422     MSIINSTALLCONTEXT context;
12423     char comp1[39], comp2[39], guid[39], sid[128];
12424     char comp_squashed1[33], comp_squashed2[33];
12425     char keypath1[MAX_PATH], keypath2[MAX_PATH];
12426     HKEY key1 = NULL, key2 = NULL;
12427     REGSAM access = KEY_ALL_ACCESS;
12428     char *usersid = get_user_sid();
12429
12430     if (!pMsiEnumComponentsExA)
12431     {
12432         win_skip( "MsiEnumComponentsExA not implemented\n" );
12433         return;
12434     }
12435     create_test_guid( comp1, comp_squashed1 );
12436     create_test_guid( comp2, comp_squashed2 );
12437
12438     if (is_wow64) access |= KEY_WOW64_64KEY;
12439
12440     strcpy( keypath1, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
12441     strcat( keypath1, "S-1-5-18\\Components\\" );
12442     strcat( keypath1, comp_squashed1 );
12443
12444     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
12445     if (r == ERROR_ACCESS_DENIED)
12446     {
12447         skip( "insufficient rights\n" );
12448         goto done;
12449     }
12450     ok( r == ERROR_SUCCESS, "got %u\n", r );
12451
12452     strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
12453     strcat( keypath2, usersid );
12454     strcat( keypath2, "\\Components\\" );
12455     strcat( keypath2, comp_squashed2 );
12456
12457     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
12458     if (r == ERROR_ACCESS_DENIED)
12459     {
12460         skip( "insufficient rights\n" );
12461         goto done;
12462     }
12463     ok( r == ERROR_SUCCESS, "got %u\n", r );
12464     r = RegSetValueExA( key2, comp_squashed2, 0, REG_SZ, (const BYTE *)"c:\\doesnotexist",
12465                         sizeof("c:\\doesnotexist"));
12466     ok( r == ERROR_SUCCESS, "got %u\n", r );
12467
12468     index = 0;
12469     guid[0] = 0;
12470     context = 0xdeadbeef;
12471     sid[0] = 0;
12472     len = sizeof(sid);
12473     found1 = found2 = 0;
12474     while (!pMsiEnumComponentsExA( "S-1-1-0", MSIINSTALLCONTEXT_ALL, index, guid, &context, sid, &len ))
12475     {
12476         if (!strcmp( comp1, guid ))
12477         {
12478             ok( context == MSIINSTALLCONTEXT_MACHINE, "got %u\n", context );
12479             ok( !sid[0], "got \"%s\"\n", sid );
12480             ok( !len, "unexpected length %u\n", len );
12481             found1 = 1;
12482         }
12483         if (!strcmp( comp2, guid ))
12484         {
12485             ok( context == MSIINSTALLCONTEXT_USERUNMANAGED, "got %u\n", context );
12486             ok( sid[0], "empty sid\n" );
12487             ok( len == strlen(sid), "unexpected length %u\n", len );
12488             found2 = 1;
12489         }
12490         index++;
12491         guid[0] = 0;
12492         context = 0xdeadbeef;
12493         sid[0] = 0;
12494         len = sizeof(sid);
12495     }
12496     ok( found1, "comp1 not found\n" );
12497     ok( found2, "comp2 not found\n" );
12498
12499     r = pMsiEnumComponentsExA( NULL, 0, 0, NULL, NULL, NULL, NULL );
12500     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
12501
12502     r = pMsiEnumComponentsExA( NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, NULL );
12503     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
12504
12505 done:
12506     RegDeleteValueA( key2, comp_squashed2 );
12507     delete_key( key1, "", access );
12508     delete_key( key2, "", access );
12509     RegCloseKey( key1 );
12510     RegCloseKey( key2 );
12511     LocalFree( usersid );
12512 }
12513
12514 static void test_MsiConfigureProductEx(void)
12515 {
12516     UINT r;
12517     LONG res;
12518     DWORD type, size;
12519     HKEY props, source;
12520     CHAR keypath[MAX_PATH * 2], localpackage[MAX_PATH], packagename[MAX_PATH];
12521     REGSAM access = KEY_ALL_ACCESS;
12522
12523     if (is_process_limited())
12524     {
12525         skip("process is limited\n");
12526         return;
12527     }
12528
12529     CreateDirectoryA("msitest", NULL);
12530     create_file("msitest\\hydrogen", "hydrogen", 500);
12531     create_file("msitest\\helium", "helium", 500);
12532     create_file("msitest\\lithium", "lithium", 500);
12533
12534     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
12535
12536     if (is_wow64)
12537         access |= KEY_WOW64_64KEY;
12538
12539     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
12540
12541     /* NULL szProduct */
12542     r = MsiConfigureProductExA(NULL, INSTALLLEVEL_DEFAULT,
12543                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
12544     ok(r == ERROR_INVALID_PARAMETER,
12545        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12546
12547     /* empty szProduct */
12548     r = MsiConfigureProductExA("", INSTALLLEVEL_DEFAULT,
12549                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
12550     ok(r == ERROR_INVALID_PARAMETER,
12551        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12552
12553     /* garbage szProduct */
12554     r = MsiConfigureProductExA("garbage", INSTALLLEVEL_DEFAULT,
12555                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
12556     ok(r == ERROR_INVALID_PARAMETER,
12557        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12558
12559     /* guid without brackets */
12560     r = MsiConfigureProductExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
12561                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
12562                                "PROPVAR=42");
12563     ok(r == ERROR_INVALID_PARAMETER,
12564        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12565
12566     /* guid with brackets */
12567     r = MsiConfigureProductExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
12568                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
12569                                "PROPVAR=42");
12570     ok(r == ERROR_UNKNOWN_PRODUCT,
12571        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12572
12573     /* same length as guid, but random */
12574     r = MsiConfigureProductExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
12575                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
12576                                "PROPVAR=42");
12577     ok(r == ERROR_UNKNOWN_PRODUCT,
12578        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12579
12580     /* product not installed yet */
12581     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
12582                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
12583                                "PROPVAR=42");
12584     ok(r == ERROR_UNKNOWN_PRODUCT,
12585        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12586
12587     /* install the product, per-user unmanaged */
12588     r = MsiInstallProductA(msifile, "INSTALLLEVEL=10 PROPVAR=42");
12589     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
12590     {
12591         skip("Not enough rights to perform tests\n");
12592         goto error;
12593     }
12594     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
12595     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
12596     ok(pf_exists("msitest\\helium"), "File not installed\n");
12597     ok(pf_exists("msitest\\lithium"), "File not installed\n");
12598     ok(pf_exists("msitest"), "File not installed\n");
12599
12600     /* product is installed per-user managed, remove it */
12601     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12602                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
12603                                "PROPVAR=42");
12604     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12605     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
12606     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
12607     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
12608     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
12609
12610     /* product has been removed */
12611     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12612                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
12613                                "PROPVAR=42");
12614     ok(r == ERROR_UNKNOWN_PRODUCT,
12615        "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
12616
12617     /* install the product, machine */
12618     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
12619     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
12620     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
12621     ok(pf_exists("msitest\\helium"), "File not installed\n");
12622     ok(pf_exists("msitest\\lithium"), "File not installed\n");
12623     ok(pf_exists("msitest"), "File not installed\n");
12624
12625     /* product is installed machine, remove it */
12626     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12627                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
12628                                "PROPVAR=42");
12629     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12630     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
12631     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
12632     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
12633     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
12634
12635     /* product has been removed */
12636     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12637                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
12638                                "PROPVAR=42");
12639     ok(r == ERROR_UNKNOWN_PRODUCT,
12640        "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
12641
12642     /* install the product, machine */
12643     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
12644     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
12645     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
12646     ok(pf_exists("msitest\\helium"), "File not installed\n");
12647     ok(pf_exists("msitest\\lithium"), "File not installed\n");
12648     ok(pf_exists("msitest"), "File not installed\n");
12649
12650     DeleteFileA(msifile);
12651
12652     /* msifile is removed */
12653     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12654                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
12655                                "PROPVAR=42");
12656     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12657     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
12658     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
12659     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
12660     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
12661
12662     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
12663
12664     /* install the product, machine */
12665     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
12666     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
12667     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
12668     ok(pf_exists("msitest\\helium"), "File not installed\n");
12669     ok(pf_exists("msitest\\lithium"), "File not installed\n");
12670     ok(pf_exists("msitest"), "File not installed\n");
12671
12672     DeleteFileA(msifile);
12673
12674     lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
12675     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
12676     lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\InstallProperties");
12677
12678     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &props);
12679     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12680
12681     type = REG_SZ;
12682     size = MAX_PATH;
12683     res = RegQueryValueExA(props, "LocalPackage", NULL, &type,
12684                            (LPBYTE)localpackage, &size);
12685     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12686
12687     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
12688                          (const BYTE *)"C:\\idontexist.msi", 18);
12689     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12690
12691     /* LocalPackage is used to find the cached msi package */
12692     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12693                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
12694                                "PROPVAR=42");
12695     ok(r == ERROR_INSTALL_SOURCE_ABSENT,
12696        "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
12697     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
12698     ok(pf_exists("msitest\\helium"), "File not installed\n");
12699     ok(pf_exists("msitest\\lithium"), "File not installed\n");
12700     ok(pf_exists("msitest"), "File not installed\n");
12701
12702     RegCloseKey(props);
12703     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
12704
12705     /* LastUsedSource can be used as a last resort */
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     DeleteFileA( localpackage );
12715
12716     /* install the product, machine */
12717     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
12718     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
12719     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
12720     ok(pf_exists("msitest\\helium"), "File not installed\n");
12721     ok(pf_exists("msitest\\lithium"), "File not installed\n");
12722     ok(pf_exists("msitest"), "File not installed\n");
12723
12724     lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
12725     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
12726     lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\InstallProperties");
12727
12728     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &props);
12729     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12730
12731     type = REG_SZ;
12732     size = MAX_PATH;
12733     res = RegQueryValueExA(props, "LocalPackage", NULL, &type,
12734                            (LPBYTE)localpackage, &size);
12735     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12736
12737     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
12738                          (const BYTE *)"C:\\idontexist.msi", 18);
12739     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12740
12741     lstrcpyA(keypath, "SOFTWARE\\Classes\\Installer\\Products\\");
12742     lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\SourceList");
12743
12744     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &source);
12745     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12746
12747     type = REG_SZ;
12748     size = MAX_PATH;
12749     res = RegQueryValueExA(source, "PackageName", NULL, &type,
12750                            (LPBYTE)packagename, &size);
12751     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12752
12753     res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
12754                          (const BYTE *)"idontexist.msi", 15);
12755     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12756
12757     /* SourceList is altered */
12758     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12759                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
12760                                "PROPVAR=42");
12761     ok(r == ERROR_INSTALL_SOURCE_ABSENT,
12762        "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
12763     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
12764     ok(pf_exists("msitest\\helium"), "File not installed\n");
12765     ok(pf_exists("msitest\\lithium"), "File not installed\n");
12766     ok(pf_exists("msitest"), "File not installed\n");
12767
12768     /* restore PackageName */
12769     res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
12770                          (const BYTE *)packagename, lstrlenA(packagename) + 1);
12771     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12772
12773     /* restore LocalPackage */
12774     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
12775                          (const BYTE *)localpackage, lstrlenA(localpackage) + 1);
12776     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12777
12778     /* finally remove the product */
12779     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12780                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
12781                                "PROPVAR=42");
12782     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12783     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
12784     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
12785     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
12786     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
12787
12788     RegCloseKey(source);
12789     RegCloseKey(props);
12790
12791 error:
12792     DeleteFileA("msitest\\hydrogen");
12793     DeleteFileA("msitest\\helium");
12794     DeleteFileA("msitest\\lithium");
12795     RemoveDirectoryA("msitest");
12796     DeleteFileA(msifile);
12797 }
12798
12799 static void test_MsiSetFeatureAttributes(void)
12800 {
12801     UINT r;
12802     DWORD attrs;
12803     char path[MAX_PATH];
12804     MSIHANDLE package;
12805
12806     if (is_process_limited())
12807     {
12808         skip("process is limited\n");
12809         return;
12810     }
12811     create_database( msifile, tables, sizeof(tables) / sizeof(tables[0]) );
12812
12813     strcpy( path, CURR_DIR );
12814     strcat( path, "\\" );
12815     strcat( path, msifile );
12816
12817     r = MsiOpenPackage( path, &package );
12818     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
12819     {
12820         skip("Not enough rights to perform tests\n");
12821         DeleteFileA( msifile );
12822         return;
12823     }
12824     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12825
12826     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
12827     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %u\n", r);
12828
12829     r = MsiDoAction( package, "CostInitialize" );
12830     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12831
12832     r = MsiSetFeatureAttributesA( 0, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
12833     ok(r == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", r);
12834
12835     r = MsiSetFeatureAttributesA( package, "", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
12836     ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
12837
12838     r = MsiSetFeatureAttributesA( package, NULL, INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
12839     ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
12840
12841     r = MsiSetFeatureAttributesA( package, "One", 0 );
12842     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12843
12844     attrs = 0xdeadbeef;
12845     r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL );
12846     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12847     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL,
12848        "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got 0x%08x\n", attrs);
12849
12850     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
12851     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12852
12853     attrs = 0;
12854     r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL );
12855     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12856     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL,
12857        "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got 0x%08x\n", attrs);
12858
12859     r = MsiDoAction( package, "FileCost" );
12860     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12861
12862     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORSOURCE );
12863     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12864
12865     attrs = 0;
12866     r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL );
12867     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12868     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORSOURCE,
12869        "expected INSTALLFEATUREATTRIBUTE_FAVORSOURCE, got 0x%08x\n", attrs);
12870
12871     r = MsiDoAction( package, "CostFinalize" );
12872     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12873
12874     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
12875     ok(r == ERROR_FUNCTION_FAILED, "expected ERROR_FUNCTION_FAILED, got %u\n", r);
12876
12877     MsiCloseHandle( package );
12878     DeleteFileA( msifile );
12879 }
12880
12881 static void test_MsiGetFeatureInfo(void)
12882 {
12883     UINT r;
12884     MSIHANDLE package;
12885     char title[32], help[32], path[MAX_PATH];
12886     DWORD attrs, title_len, help_len;
12887
12888     if (is_process_limited())
12889     {
12890         skip("process is limited\n");
12891         return;
12892     }
12893     create_database( msifile, tables, sizeof(tables) / sizeof(tables[0]) );
12894
12895     strcpy( path, CURR_DIR );
12896     strcat( path, "\\" );
12897     strcat( path, msifile );
12898
12899     r = MsiOpenPackage( path, &package );
12900     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
12901     {
12902         skip("Not enough rights to perform tests\n");
12903         DeleteFileA( msifile );
12904         return;
12905     }
12906     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
12907
12908     r = MsiGetFeatureInfoA( 0, NULL, NULL, NULL, NULL, NULL, NULL );
12909     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
12910
12911     r = MsiGetFeatureInfoA( package, NULL, NULL, NULL, NULL, NULL, NULL );
12912     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
12913
12914     r = MsiGetFeatureInfoA( package, "", NULL, NULL, NULL, NULL, NULL );
12915     ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
12916
12917     r = MsiGetFeatureInfoA( package, "One", NULL, NULL, NULL, NULL, NULL );
12918     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12919
12920     r = MsiGetFeatureInfoA( 0, "One", NULL, NULL, NULL, NULL, NULL );
12921     ok(r == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", r);
12922
12923     title_len = help_len = 0;
12924     r = MsiGetFeatureInfoA( package, "One", NULL, NULL, &title_len, NULL, &help_len );
12925     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12926     ok(title_len == 3, "expected 3, got %u\n", title_len);
12927     ok(help_len == 3, "expected 3, got %u\n", help_len);
12928
12929     title[0] = help[0] = 0;
12930     title_len = help_len = 0;
12931     r = MsiGetFeatureInfoA( package, "One", NULL, title, &title_len, help, &help_len );
12932     ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %u\n", r);
12933     ok(title_len == 3, "expected 3, got %u\n", title_len);
12934     ok(help_len == 3, "expected 3, got %u\n", help_len);
12935
12936     attrs = 0;
12937     title[0] = help[0] = 0;
12938     title_len = sizeof(title);
12939     help_len = sizeof(help);
12940     r = MsiGetFeatureInfoA( package, "One", &attrs, title, &title_len, help, &help_len );
12941     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12942     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %u\n", attrs);
12943     ok(title_len == 3, "expected 3, got %u\n", title_len);
12944     ok(help_len == 3, "expected 3, got %u\n", help_len);
12945     ok(!strcmp(title, "One"), "expected \"One\", got \"%s\"\n", title);
12946     ok(!strcmp(help, "One"), "expected \"One\", got \"%s\"\n", help);
12947
12948     attrs = 0;
12949     title[0] = help[0] = 0;
12950     title_len = sizeof(title);
12951     help_len = sizeof(help);
12952     r = MsiGetFeatureInfoA( package, "Two", &attrs, title, &title_len, help, &help_len );
12953     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
12954     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %u\n", attrs);
12955     ok(!title_len, "expected 0, got %u\n", title_len);
12956     ok(!help_len, "expected 0, got %u\n", help_len);
12957     ok(!title[0], "expected \"\", got \"%s\"\n", title);
12958     ok(!help[0], "expected \"\", got \"%s\"\n", help);
12959
12960     MsiCloseHandle( package );
12961     DeleteFileA( msifile );
12962 }
12963
12964 static INT CALLBACK handler_a(LPVOID context, UINT type, LPCSTR msg)
12965 {
12966     return IDOK;
12967 }
12968
12969 static INT CALLBACK handler_w(LPVOID context, UINT type, LPCWSTR msg)
12970 {
12971     return IDOK;
12972 }
12973
12974 static INT CALLBACK handler_record(LPVOID context, UINT type, MSIHANDLE record)
12975 {
12976     return IDOK;
12977 }
12978
12979 static void test_MsiSetExternalUI(void)
12980 {
12981     INSTALLUI_HANDLERA ret_a;
12982     INSTALLUI_HANDLERW ret_w;
12983     INSTALLUI_HANDLER_RECORD prev;
12984     UINT error;
12985
12986     ret_a = MsiSetExternalUIA(handler_a, INSTALLLOGMODE_ERROR, NULL);
12987     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
12988
12989     ret_a = MsiSetExternalUIA(NULL, 0, NULL);
12990     ok(ret_a == handler_a, "expected %p, got %p\n", handler_a, ret_a);
12991
12992     /* Not present before Installer 3.1 */
12993     if (!pMsiSetExternalUIRecord) {
12994         win_skip("MsiSetExternalUIRecord is not available\n");
12995         return;
12996     }
12997
12998     error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, &prev);
12999     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
13000     ok(prev == NULL, "expected NULL, got %p\n", prev);
13001
13002     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
13003     error = pMsiSetExternalUIRecord(NULL, INSTALLLOGMODE_ERROR, NULL, &prev);
13004     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
13005     ok(prev == handler_record, "expected %p, got %p\n", handler_record, prev);
13006
13007     ret_w = MsiSetExternalUIW(handler_w, INSTALLLOGMODE_ERROR, NULL);
13008     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
13009
13010     ret_w = MsiSetExternalUIW(NULL, 0, NULL);
13011     ok(ret_w == handler_w, "expected %p, got %p\n", handler_w, ret_w);
13012
13013     ret_a = MsiSetExternalUIA(handler_a, INSTALLLOGMODE_ERROR, NULL);
13014     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
13015
13016     ret_w = MsiSetExternalUIW(handler_w, INSTALLLOGMODE_ERROR, NULL);
13017     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
13018
13019     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
13020     error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, &prev);
13021     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
13022     ok(prev == NULL, "expected NULL, got %p\n", prev);
13023
13024     ret_a = MsiSetExternalUIA(NULL, 0, NULL);
13025     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
13026
13027     ret_w = MsiSetExternalUIW(NULL, 0, NULL);
13028     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
13029
13030     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
13031     error = pMsiSetExternalUIRecord(NULL, 0, NULL, &prev);
13032     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
13033     ok(prev == handler_record, "expected %p, got %p\n", handler_record, prev);
13034
13035     error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, NULL);
13036     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
13037
13038     error = pMsiSetExternalUIRecord(NULL, 0, NULL, NULL);
13039     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
13040 }
13041
13042 START_TEST(msi)
13043 {
13044     DWORD len;
13045     char temp_path[MAX_PATH], prev_path[MAX_PATH];
13046
13047     init_functionpointers();
13048
13049     if (pIsWow64Process)
13050         pIsWow64Process(GetCurrentProcess(), &is_wow64);
13051
13052     GetCurrentDirectoryA(MAX_PATH, prev_path);
13053     GetTempPath(MAX_PATH, temp_path);
13054     SetCurrentDirectoryA(temp_path);
13055
13056     lstrcpyA(CURR_DIR, temp_path);
13057     len = lstrlenA(CURR_DIR);
13058
13059     if(len && (CURR_DIR[len - 1] == '\\'))
13060         CURR_DIR[len - 1] = 0;
13061
13062     ok(get_system_dirs(), "failed to retrieve system dirs\n");
13063
13064     test_usefeature();
13065     test_null();
13066     test_getcomponentpath();
13067     test_MsiGetFileHash();
13068
13069     if (!pConvertSidToStringSidA)
13070         win_skip("ConvertSidToStringSidA not implemented\n");
13071     else
13072     {
13073         /* These tests rely on get_user_sid that needs ConvertSidToStringSidA */
13074         test_MsiQueryProductState();
13075         test_MsiQueryFeatureState();
13076         test_MsiQueryComponentState();
13077         test_MsiGetComponentPath();
13078         test_MsiGetProductCode();
13079         test_MsiEnumClients();
13080         test_MsiGetProductInfo();
13081         test_MsiGetProductInfoEx();
13082         test_MsiGetUserInfo();
13083         test_MsiOpenProduct();
13084         test_MsiEnumPatchesEx();
13085         test_MsiEnumPatches();
13086         test_MsiGetPatchInfoEx();
13087         test_MsiGetPatchInfo();
13088         test_MsiEnumProducts();
13089         test_MsiEnumProductsEx();
13090         test_MsiEnumComponents();
13091         test_MsiEnumComponentsEx();
13092     }
13093     test_MsiGetFileVersion();
13094     test_MsiGetFileSignatureInformation();
13095     test_MsiConfigureProductEx();
13096     test_MsiSetFeatureAttributes();
13097     test_MsiGetFeatureInfo();
13098     test_MsiSetExternalUI();
13099
13100     SetCurrentDirectoryA(prev_path);
13101 }