xref: /reactos/modules/rostests/winetests/msi/msi.c (revision d09998df)
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 #include "precomp.h"
22 
23 static BOOL is_wow64;
24 static const char msifile[] = "winetest.msi";
25 static const WCHAR msifileW[] = {'w','i','n','e','t','e','s','t','.','m','s','i',0};
26 static char CURR_DIR[MAX_PATH];
27 static char PROG_FILES_DIR[MAX_PATH];
28 static char PROG_FILES_DIR_NATIVE[MAX_PATH];
29 static char COMMON_FILES_DIR[MAX_PATH];
30 static char WINDOWS_DIR[MAX_PATH];
31 
32 static BOOL (WINAPI *pCheckTokenMembership)(HANDLE,PSID,PBOOL);
33 static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
34 static BOOL (WINAPI *pOpenProcessToken)( HANDLE, DWORD, PHANDLE );
35 static LONG (WINAPI *pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD);
36 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
37 
38 static INSTALLSTATE (WINAPI *pMsiGetComponentPathA)
39     (LPCSTR, LPCSTR, LPSTR, DWORD*);
40 static INSTALLSTATE (WINAPI *pMsiGetComponentPathExA)
41     (LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPSTR, LPDWORD);
42 static INSTALLSTATE (WINAPI *pMsiProvideComponentA)
43     (LPCSTR, LPCSTR, LPCSTR, DWORD, LPSTR, LPDWORD);
44 static INSTALLSTATE (WINAPI *pMsiProvideComponentW)
45     (LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPWSTR, LPDWORD);
46 static UINT (WINAPI *pMsiGetFileHashA)
47     (LPCSTR, DWORD, PMSIFILEHASHINFO);
48 static UINT (WINAPI *pMsiGetProductInfoExA)
49     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, LPSTR, LPDWORD);
50 static UINT (WINAPI *pMsiOpenPackageExA)
51     (LPCSTR, DWORD, MSIHANDLE*);
52 static UINT (WINAPI *pMsiOpenPackageExW)
53     (LPCWSTR, DWORD, MSIHANDLE*);
54 static UINT (WINAPI *pMsiEnumPatchesExA)
55     (LPCSTR, LPCSTR, DWORD, DWORD, DWORD, LPSTR, LPSTR,
56     MSIINSTALLCONTEXT*, LPSTR, LPDWORD);
57 static UINT (WINAPI *pMsiQueryComponentStateA)
58     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, INSTALLSTATE*);
59 static INSTALLSTATE (WINAPI *pMsiUseFeatureExA)
60     (LPCSTR, LPCSTR ,DWORD, DWORD);
61 static UINT (WINAPI *pMsiGetPatchInfoExA)
62     (LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, LPSTR, DWORD *);
63 static UINT (WINAPI *pMsiEnumProductsExA)
64     (LPCSTR, LPCSTR, DWORD, DWORD, CHAR[39], MSIINSTALLCONTEXT *, LPSTR, LPDWORD);
65 static UINT (WINAPI *pMsiEnumComponentsExA)
66     (LPCSTR, DWORD, DWORD, CHAR[39], MSIINSTALLCONTEXT *, LPSTR, LPDWORD);
67 static UINT (WINAPI *pMsiSetExternalUIRecord)
68     (INSTALLUI_HANDLER_RECORD, DWORD, LPVOID, PINSTALLUI_HANDLER_RECORD);
69 static UINT (WINAPI *pMsiSourceListGetInfoA)
70     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, LPSTR, LPDWORD);
71 
72 static void init_functionpointers(void)
73 {
74     HMODULE hmsi = GetModuleHandleA("msi.dll");
75     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
76     HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
77 
78 #define GET_PROC(dll, func) \
79     p ## func = (void *)GetProcAddress(dll, #func); \
80     if(!p ## func) \
81       trace("GetProcAddress(%s) failed\n", #func);
82 
83     GET_PROC(hmsi, MsiGetComponentPathA)
84     GET_PROC(hmsi, MsiGetComponentPathExA);
85     GET_PROC(hmsi, MsiProvideComponentA)
86     GET_PROC(hmsi, MsiProvideComponentW)
87     GET_PROC(hmsi, MsiGetFileHashA)
88     GET_PROC(hmsi, MsiGetProductInfoExA)
89     GET_PROC(hmsi, MsiOpenPackageExA)
90     GET_PROC(hmsi, MsiOpenPackageExW)
91     GET_PROC(hmsi, MsiEnumPatchesExA)
92     GET_PROC(hmsi, MsiQueryComponentStateA)
93     GET_PROC(hmsi, MsiSetExternalUIRecord)
94     GET_PROC(hmsi, MsiUseFeatureExA)
95     GET_PROC(hmsi, MsiGetPatchInfoExA)
96     GET_PROC(hmsi, MsiEnumProductsExA)
97     GET_PROC(hmsi, MsiEnumComponentsExA)
98     GET_PROC(hmsi, MsiSourceListGetInfoA)
99 
100     GET_PROC(hadvapi32, CheckTokenMembership);
101     GET_PROC(hadvapi32, ConvertSidToStringSidA)
102     GET_PROC(hadvapi32, OpenProcessToken);
103     GET_PROC(hadvapi32, RegDeleteKeyExA)
104     GET_PROC(hkernel32, IsWow64Process)
105 
106 #undef GET_PROC
107 }
108 
109 static BOOL get_system_dirs(void)
110 {
111     HKEY hkey;
112     DWORD type, size;
113 
114     if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", &hkey))
115         return FALSE;
116 
117     size = MAX_PATH;
118     if (RegQueryValueExA(hkey, "ProgramFilesDir (x86)", 0, &type, (LPBYTE)PROG_FILES_DIR, &size) &&
119         RegQueryValueExA(hkey, "ProgramFilesDir", 0, &type, (LPBYTE)PROG_FILES_DIR, &size))
120     {
121         RegCloseKey(hkey);
122         return FALSE;
123     }
124     size = MAX_PATH;
125     if (RegQueryValueExA(hkey, "CommonFilesDir (x86)", 0, &type, (LPBYTE)COMMON_FILES_DIR, &size) &&
126         RegQueryValueExA(hkey, "CommonFilesDir", 0, &type, (LPBYTE)COMMON_FILES_DIR, &size))
127     {
128         RegCloseKey(hkey);
129         return FALSE;
130     }
131     size = MAX_PATH;
132     if (RegQueryValueExA(hkey, "ProgramFilesDir", 0, &type, (LPBYTE)PROG_FILES_DIR_NATIVE, &size))
133     {
134         RegCloseKey(hkey);
135         return FALSE;
136     }
137     RegCloseKey(hkey);
138     if (!GetWindowsDirectoryA(WINDOWS_DIR, MAX_PATH)) return FALSE;
139     return TRUE;
140 }
141 
142 static BOOL file_exists(const char *file)
143 {
144     return GetFileAttributesA(file) != INVALID_FILE_ATTRIBUTES;
145 }
146 
147 static BOOL pf_exists(const char *file)
148 {
149     char path[MAX_PATH];
150 
151     lstrcpyA(path, PROG_FILES_DIR);
152     lstrcatA(path, "\\");
153     lstrcatA(path, file);
154     return file_exists(path);
155 }
156 
157 static BOOL delete_pf(const char *rel_path, BOOL is_file)
158 {
159     char path[MAX_PATH];
160 
161     lstrcpyA(path, PROG_FILES_DIR);
162     lstrcatA(path, "\\");
163     lstrcatA(path, rel_path);
164 
165     if (is_file)
166         return DeleteFileA(path);
167     else
168         return RemoveDirectoryA(path);
169 }
170 
171 static BOOL is_process_limited(void)
172 {
173     SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
174     PSID Group = NULL;
175     BOOL IsInGroup;
176     HANDLE token;
177 
178     if (!pCheckTokenMembership || !pOpenProcessToken) return FALSE;
179 
180     if (!AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
181                                   DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &Group) ||
182         !pCheckTokenMembership(NULL, Group, &IsInGroup))
183     {
184         trace("Could not check if the current user is an administrator\n");
185         FreeSid(Group);
186         return FALSE;
187     }
188     FreeSid(Group);
189 
190     if (!IsInGroup)
191     {
192         /* Only administrators have enough privileges for these tests */
193         return TRUE;
194     }
195 
196     if (pOpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
197     {
198         BOOL ret;
199         TOKEN_ELEVATION_TYPE type = TokenElevationTypeDefault;
200         DWORD size;
201 
202         ret = GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &size);
203         CloseHandle(token);
204         return (ret && type == TokenElevationTypeLimited);
205     }
206     return FALSE;
207 }
208 
209 /* cabinet definitions */
210 
211 /* make the max size large so there is only one cab file */
212 #define MEDIA_SIZE          0x7FFFFFFF
213 #define FOLDER_THRESHOLD    900000
214 
215 /* the FCI callbacks */
216 
217 static void * CDECL mem_alloc(ULONG cb)
218 {
219     return HeapAlloc(GetProcessHeap(), 0, cb);
220 }
221 
222 static void CDECL mem_free(void *memory)
223 {
224     HeapFree(GetProcessHeap(), 0, memory);
225 }
226 
227 static BOOL CDECL get_next_cabinet(PCCAB pccab, ULONG  cbPrevCab, void *pv)
228 {
229     sprintf(pccab->szCab, pv, pccab->iCab);
230     return TRUE;
231 }
232 
233 static LONG CDECL progress(UINT typeStatus, ULONG cb1, ULONG cb2, void *pv)
234 {
235     return 0;
236 }
237 
238 static int CDECL file_placed(PCCAB pccab, char *pszFile, LONG cbFile,
239                              BOOL fContinuation, void *pv)
240 {
241     return 0;
242 }
243 
244 static INT_PTR CDECL fci_open(char *pszFile, int oflag, int pmode, int *err, void *pv)
245 {
246     HANDLE handle;
247     DWORD dwAccess = 0;
248     DWORD dwShareMode = 0;
249     DWORD dwCreateDisposition = OPEN_EXISTING;
250 
251     dwAccess = GENERIC_READ | GENERIC_WRITE;
252     /* FILE_SHARE_DELETE is not supported by Windows Me/98/95 */
253     dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
254 
255     if (GetFileAttributesA(pszFile) != INVALID_FILE_ATTRIBUTES)
256         dwCreateDisposition = OPEN_EXISTING;
257     else
258         dwCreateDisposition = CREATE_NEW;
259 
260     handle = CreateFileA(pszFile, dwAccess, dwShareMode, NULL,
261                          dwCreateDisposition, 0, NULL);
262 
263     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszFile);
264 
265     return (INT_PTR)handle;
266 }
267 
268 static UINT CDECL fci_read(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
269 {
270     HANDLE handle = (HANDLE)hf;
271     DWORD dwRead;
272     BOOL res;
273 
274     res = ReadFile(handle, memory, cb, &dwRead, NULL);
275     ok(res, "Failed to ReadFile\n");
276 
277     return dwRead;
278 }
279 
280 static UINT CDECL fci_write(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
281 {
282     HANDLE handle = (HANDLE)hf;
283     DWORD dwWritten;
284     BOOL res;
285 
286     res = WriteFile(handle, memory, cb, &dwWritten, NULL);
287     ok(res, "Failed to WriteFile\n");
288 
289     return dwWritten;
290 }
291 
292 static int CDECL fci_close(INT_PTR hf, int *err, void *pv)
293 {
294     HANDLE handle = (HANDLE)hf;
295     ok(CloseHandle(handle), "Failed to CloseHandle\n");
296 
297     return 0;
298 }
299 
300 static LONG CDECL fci_seek(INT_PTR hf, LONG dist, int seektype, int *err, void *pv)
301 {
302     HANDLE handle = (HANDLE)hf;
303     DWORD ret;
304 
305     ret = SetFilePointer(handle, dist, NULL, seektype);
306     ok(ret != INVALID_SET_FILE_POINTER, "Failed to SetFilePointer\n");
307 
308     return ret;
309 }
310 
311 static int CDECL fci_delete(char *pszFile, int *err, void *pv)
312 {
313     BOOL ret = DeleteFileA(pszFile);
314     ok(ret, "Failed to DeleteFile %s\n", pszFile);
315 
316     return 0;
317 }
318 
319 static BOOL CDECL get_temp_file(char *pszTempName, int cbTempName, void *pv)
320 {
321     LPSTR tempname;
322 
323     tempname = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
324     GetTempFileNameA(".", "xx", 0, tempname);
325 
326     if (tempname && (strlen(tempname) < (unsigned)cbTempName))
327     {
328         lstrcpyA(pszTempName, tempname);
329         HeapFree(GetProcessHeap(), 0, tempname);
330         return TRUE;
331     }
332 
333     HeapFree(GetProcessHeap(), 0, tempname);
334 
335     return FALSE;
336 }
337 
338 static INT_PTR CDECL get_open_info(char *pszName, USHORT *pdate, USHORT *ptime,
339                                    USHORT *pattribs, int *err, void *pv)
340 {
341     BY_HANDLE_FILE_INFORMATION finfo;
342     FILETIME filetime;
343     HANDLE handle;
344     DWORD attrs;
345     BOOL res;
346 
347     handle = CreateFileA(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
348                          OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
349     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszName);
350 
351     res = GetFileInformationByHandle(handle, &finfo);
352     ok(res, "Expected GetFileInformationByHandle to succeed\n");
353 
354     FileTimeToLocalFileTime(&finfo.ftLastWriteTime, &filetime);
355     FileTimeToDosDateTime(&filetime, pdate, ptime);
356 
357     attrs = GetFileAttributesA(pszName);
358     ok(attrs != INVALID_FILE_ATTRIBUTES, "Failed to GetFileAttributes\n");
359 
360     return (INT_PTR)handle;
361 }
362 
363 static BOOL add_file(HFCI hfci, const char *file, TCOMP compress)
364 {
365     char path[MAX_PATH];
366     char filename[MAX_PATH];
367 
368     lstrcpyA(path, CURR_DIR);
369     lstrcatA(path, "\\");
370     lstrcatA(path, file);
371 
372     lstrcpyA(filename, file);
373 
374     return FCIAddFile(hfci, path, filename, FALSE, get_next_cabinet,
375                       progress, get_open_info, compress);
376 }
377 
378 static void set_cab_parameters(PCCAB pCabParams, const CHAR *name, DWORD max_size)
379 {
380     ZeroMemory(pCabParams, sizeof(CCAB));
381 
382     pCabParams->cb = max_size;
383     pCabParams->cbFolderThresh = FOLDER_THRESHOLD;
384     pCabParams->setID = 0xbeef;
385     pCabParams->iCab = 1;
386     lstrcpyA(pCabParams->szCabPath, CURR_DIR);
387     lstrcatA(pCabParams->szCabPath, "\\");
388     lstrcpyA(pCabParams->szCab, name);
389 }
390 
391 static void create_cab_file(const CHAR *name, DWORD max_size, const CHAR *files)
392 {
393     CCAB cabParams;
394     LPCSTR ptr;
395     HFCI hfci;
396     ERF erf;
397     BOOL res;
398 
399     set_cab_parameters(&cabParams, name, max_size);
400 
401     hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
402                       fci_read, fci_write, fci_close, fci_seek, fci_delete,
403                       get_temp_file, &cabParams, NULL);
404 
405     ok(hfci != NULL, "Failed to create an FCI context\n");
406 
407     ptr = files;
408     while (*ptr)
409     {
410         res = add_file(hfci, ptr, tcompTYPE_MSZIP);
411         ok(res, "Failed to add file: %s\n", ptr);
412         ptr += lstrlenA(ptr) + 1;
413     }
414 
415     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
416     ok(res, "Failed to flush the cabinet\n");
417 
418     res = FCIDestroy(hfci);
419     ok(res, "Failed to destroy the cabinet\n");
420 }
421 
422 static BOOL add_cabinet_storage(LPCSTR db, LPCSTR cabinet)
423 {
424     WCHAR dbW[MAX_PATH], cabinetW[MAX_PATH];
425     IStorage *stg;
426     IStream *stm;
427     HRESULT hr;
428     HANDLE handle;
429 
430     MultiByteToWideChar(CP_ACP, 0, db, -1, dbW, MAX_PATH);
431     hr = StgOpenStorage(dbW, NULL, STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
432     if (FAILED(hr))
433         return FALSE;
434 
435     MultiByteToWideChar(CP_ACP, 0, cabinet, -1, cabinetW, MAX_PATH);
436     hr = IStorage_CreateStream(stg, cabinetW, STGM_WRITE|STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
437     if (FAILED(hr))
438     {
439         IStorage_Release(stg);
440         return FALSE;
441     }
442 
443     handle = CreateFileW(cabinetW, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
444     if (handle != INVALID_HANDLE_VALUE)
445     {
446         DWORD count;
447         char buffer[1024];
448         if (ReadFile(handle, buffer, sizeof(buffer), &count, NULL))
449             IStream_Write(stm, buffer, count, &count);
450         CloseHandle(handle);
451     }
452 
453     IStream_Release(stm);
454     IStorage_Release(stg);
455 
456     return TRUE;
457 }
458 
459 static void delete_cab_files(void)
460 {
461     SHFILEOPSTRUCTA shfl;
462     CHAR path[MAX_PATH+10];
463 
464     lstrcpyA(path, CURR_DIR);
465     lstrcatA(path, "\\*.cab");
466     path[strlen(path) + 1] = '\0';
467 
468     shfl.hwnd = NULL;
469     shfl.wFunc = FO_DELETE;
470     shfl.pFrom = path;
471     shfl.pTo = NULL;
472     shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
473 
474     SHFileOperationA(&shfl);
475 }
476 
477 /* msi database data */
478 
479 static const char directory_dat[] =
480     "Directory\tDirectory_Parent\tDefaultDir\n"
481     "s72\tS72\tl255\n"
482     "Directory\tDirectory\n"
483     "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
484     "ProgramFilesFolder\tTARGETDIR\t.\n"
485     "TARGETDIR\t\tSourceDir";
486 
487 static const char component_dat[] =
488     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
489     "s72\tS38\ts72\ti2\tS255\tS72\n"
490     "Component\tComponent\n"
491     "One\t{8F5BAEEF-DD92-40AC-9397-BE3CF9F97C81}\tMSITESTDIR\t2\tNOT REINSTALL\tone.txt\n";
492 
493 static const char feature_dat[] =
494     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
495     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
496     "Feature\tFeature\n"
497     "One\t\tOne\tOne\t1\t3\tMSITESTDIR\t0\n"
498     "Two\t\t\t\t2\t1\tTARGETDIR\t0\n";
499 
500 static const char feature_comp_dat[] =
501     "Feature_\tComponent_\n"
502     "s38\ts72\n"
503     "FeatureComponents\tFeature_\tComponent_\n"
504     "One\tOne\n";
505 
506 static const char file_dat[] =
507     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
508     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
509     "File\tFile\n"
510     "one.txt\tOne\tone.txt\t1000\t\t\t0\t1\n";
511 
512 static const char install_exec_seq_dat[] =
513     "Action\tCondition\tSequence\n"
514     "s72\tS255\tI2\n"
515     "InstallExecuteSequence\tAction\n"
516     "ValidateProductID\t\t700\n"
517     "CostInitialize\t\t800\n"
518     "FileCost\t\t900\n"
519     "CostFinalize\t\t1000\n"
520     "InstallValidate\t\t1400\n"
521     "InstallInitialize\t\t1500\n"
522     "ProcessComponents\t\t1600\n"
523     "UnpublishFeatures\t\t1800\n"
524     "RemoveFiles\t\t3500\n"
525     "InstallFiles\t\t4000\n"
526     "RegisterProduct\t\t6100\n"
527     "PublishFeatures\t\t6300\n"
528     "PublishProduct\t\t6400\n"
529     "InstallFinalize\t\t6600";
530 
531 static const char media_dat[] =
532     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
533     "i2\ti4\tL64\tS255\tS32\tS72\n"
534     "Media\tDiskId\n"
535     "1\t1\t\t\tDISK1\t\n";
536 
537 static const char property_dat[] =
538     "Property\tValue\n"
539     "s72\tl0\n"
540     "Property\tProperty\n"
541     "INSTALLLEVEL\t3\n"
542     "Manufacturer\tWine\n"
543     "ProductCode\t{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}\n"
544     "ProductName\tMSITEST\n"
545     "ProductVersion\t1.1.1\n"
546     "UpgradeCode\t{9574448F-9B86-4E07-B6F6-8D199DA12127}\n"
547     "MSIFASTINSTALL\t1\n";
548 
549 static const char ci2_property_dat[] =
550     "Property\tValue\n"
551     "s72\tl0\n"
552     "Property\tProperty\n"
553     "INSTALLLEVEL\t3\n"
554     "Manufacturer\tWine\n"
555     "ProductCode\t{FF4AFE9C-6AC2-44F9-A060-9EA6BD16C75E}\n"
556     "ProductName\tMSITEST2\n"
557     "ProductVersion\t1.1.1\n"
558     "UpgradeCode\t{6B60C3CA-B8CA-4FB7-A395-092D98FF5D2A}\n"
559     "MSIFASTINSTALL\t1\n";
560 
561 static const char mcp_component_dat[] =
562     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
563     "s72\tS38\ts72\ti2\tS255\tS72\n"
564     "Component\tComponent\n"
565     "hydrogen\t{C844BD1E-1907-4C00-8BC9-150BD70DF0A1}\tMSITESTDIR\t2\t\thydrogen\n"
566     "helium\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t2\t\thelium\n"
567     "lithium\t{4AF28FFC-71C7-4307-BDE4-B77C5338F56F}\tMSITESTDIR\t2\tPROPVAR=42\tlithium\n";
568 
569 static const char mcp_feature_dat[] =
570     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
571     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
572     "Feature\tFeature\n"
573     "hydroxyl\t\thydroxyl\thydroxyl\t2\t1\tTARGETDIR\t0\n"
574     "heliox\t\theliox\theliox\t2\t5\tTARGETDIR\t0\n"
575     "lithia\t\tlithia\tlithia\t2\t10\tTARGETDIR\t0";
576 
577 static const char mcp_feature_comp_dat[] =
578     "Feature_\tComponent_\n"
579     "s38\ts72\n"
580     "FeatureComponents\tFeature_\tComponent_\n"
581     "hydroxyl\thydrogen\n"
582     "heliox\thelium\n"
583     "lithia\tlithium";
584 
585 static const char mcp_file_dat[] =
586     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
587     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
588     "File\tFile\n"
589     "hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n"
590     "helium\thelium\thelium\t0\t\t\t8192\t1\n"
591     "lithium\tlithium\tlithium\t0\t\t\t8192\t1";
592 
593 static const char lus_component_dat[] =
594     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
595     "s72\tS38\ts72\ti2\tS255\tS72\n"
596     "Component\tComponent\n"
597     "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
598 
599 static const char lus_feature_dat[] =
600     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
601     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
602     "Feature\tFeature\n"
603     "feature\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0\n"
604     "montecristo\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0";
605 
606 static const char lus_file_dat[] =
607     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
608     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
609     "File\tFile\n"
610     "maximus\tmaximus\tmaximus\t500\t\t\t8192\t1";
611 
612 static const char lus_feature_comp_dat[] =
613     "Feature_\tComponent_\n"
614     "s38\ts72\n"
615     "FeatureComponents\tFeature_\tComponent_\n"
616     "feature\tmaximus\n"
617     "montecristo\tmaximus";
618 
619 static const char lus_install_exec_seq_dat[] =
620     "Action\tCondition\tSequence\n"
621     "s72\tS255\tI2\n"
622     "InstallExecuteSequence\tAction\n"
623     "ValidateProductID\t\t700\n"
624     "CostInitialize\t\t800\n"
625     "FileCost\t\t900\n"
626     "CostFinalize\t\t1000\n"
627     "InstallValidate\t\t1400\n"
628     "InstallInitialize\t\t1500\n"
629     "ProcessComponents\tPROCESS_COMPONENTS=1 Or FULL=1\t1600\n"
630     "UnpublishFeatures\tUNPUBLISH_FEATURES=1 Or FULL=1\t1800\n"
631     "RemoveFiles\t\t3500\n"
632     "InstallFiles\t\t4000\n"
633     "RegisterUser\tREGISTER_USER=1 Or FULL=1\t6000\n"
634     "RegisterProduct\tREGISTER_PRODUCT=1 Or FULL=1\t6100\n"
635     "PublishFeatures\tPUBLISH_FEATURES=1 Or FULL=1\t6300\n"
636     "PublishProduct\tPUBLISH_PRODUCT=1 Or FULL=1\t6400\n"
637     "InstallFinalize\t\t6600";
638 
639 static const char lus0_media_dat[] =
640     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
641     "i2\ti4\tL64\tS255\tS32\tS72\n"
642     "Media\tDiskId\n"
643     "1\t1\t\t\tDISK1\t\n";
644 
645 static const char lus1_media_dat[] =
646     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
647     "i2\ti4\tL64\tS255\tS32\tS72\n"
648     "Media\tDiskId\n"
649     "1\t1\t\ttest1.cab\tDISK1\t\n";
650 
651 static const char lus2_media_dat[] =
652     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
653     "i2\ti4\tL64\tS255\tS32\tS72\n"
654     "Media\tDiskId\n"
655     "1\t1\t\t#test1.cab\tDISK1\t\n";
656 
657 static const char spf_custom_action_dat[] =
658     "Action\tType\tSource\tTarget\tISComments\n"
659     "s72\ti2\tS64\tS0\tS255\n"
660     "CustomAction\tAction\n"
661     "SetFolderProp\t51\tMSITESTDIR\t[ProgramFilesFolder]\\msitest\\added\t\n";
662 
663 static const char spf_install_exec_seq_dat[] =
664     "Action\tCondition\tSequence\n"
665     "s72\tS255\tI2\n"
666     "InstallExecuteSequence\tAction\n"
667     "CostFinalize\t\t1000\n"
668     "CostInitialize\t\t800\n"
669     "FileCost\t\t900\n"
670     "SetFolderProp\t\t950\n"
671     "InstallFiles\t\t4000\n"
672     "InstallServices\t\t5000\n"
673     "InstallFinalize\t\t6600\n"
674     "InstallInitialize\t\t1500\n"
675     "InstallValidate\t\t1400\n"
676     "LaunchConditions\t\t100";
677 
678 static const char spf_install_ui_seq_dat[] =
679     "Action\tCondition\tSequence\n"
680     "s72\tS255\tI2\n"
681     "InstallUISequence\tAction\n"
682     "CostInitialize\t\t800\n"
683     "FileCost\t\t900\n"
684     "CostFinalize\t\t1000\n"
685     "ExecuteAction\t\t1100\n";
686 
687 static const char sd_file_dat[] =
688     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
689     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
690     "File\tFile\n"
691     "sourcedir.txt\tsourcedir\tsourcedir.txt\t1000\t\t\t8192\t1\n";
692 
693 static const char sd_feature_dat[] =
694     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
695     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
696     "Feature\tFeature\n"
697     "sourcedir\t\t\tsourcedir feature\t1\t2\tMSITESTDIR\t0\n";
698 
699 static const char sd_feature_comp_dat[] =
700     "Feature_\tComponent_\n"
701     "s38\ts72\n"
702     "FeatureComponents\tFeature_\tComponent_\n"
703     "sourcedir\tsourcedir\n";
704 
705 static const char sd_component_dat[] =
706     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
707     "s72\tS38\ts72\ti2\tS255\tS72\n"
708     "Component\tComponent\n"
709     "sourcedir\t{DD422F92-3ED8-49B5-A0B7-F266F98357DF}\tMSITESTDIR\t0\t\tsourcedir.txt\n";
710 
711 static const char sd_install_ui_seq_dat[] =
712     "Action\tCondition\tSequence\n"
713     "s72\tS255\tI2\n"
714     "InstallUISequence\tAction\n"
715     "TestSourceDirProp1\tnot SourceDir and not SOURCEDIR and not Installed\t99\n"
716     "AppSearch\t\t100\n"
717     "TestSourceDirProp2\tnot SourceDir and not SOURCEDIR and not Installed\t101\n"
718     "LaunchConditions\tnot Installed \t110\n"
719     "TestSourceDirProp3\tnot SourceDir and not SOURCEDIR and not Installed\t111\n"
720     "FindRelatedProducts\t\t120\n"
721     "TestSourceDirProp4\tnot SourceDir and not SOURCEDIR and not Installed\t121\n"
722     "CCPSearch\t\t130\n"
723     "TestSourceDirProp5\tnot SourceDir and not SOURCEDIR and not Installed\t131\n"
724     "RMCCPSearch\t\t140\n"
725     "TestSourceDirProp6\tnot SourceDir and not SOURCEDIR and not Installed\t141\n"
726     "ValidateProductID\t\t150\n"
727     "TestSourceDirProp7\tnot SourceDir and not SOURCEDIR and not Installed\t151\n"
728     "CostInitialize\t\t800\n"
729     "TestSourceDirProp8\tnot SourceDir and not SOURCEDIR and not Installed\t801\n"
730     "FileCost\t\t900\n"
731     "TestSourceDirProp9\tnot SourceDir and not SOURCEDIR and not Installed\t901\n"
732     "IsolateComponents\t\t1000\n"
733     "TestSourceDirProp10\tnot SourceDir and not SOURCEDIR and not Installed\t1001\n"
734     "CostFinalize\t\t1100\n"
735     "TestSourceDirProp11\tnot SourceDir and not SOURCEDIR and not Installed\t1101\n"
736     "MigrateFeatureStates\t\t1200\n"
737     "TestSourceDirProp12\tnot SourceDir and not SOURCEDIR and not Installed\t1201\n"
738     "ExecuteAction\t\t1300\n"
739     "TestSourceDirProp13\tnot SourceDir and not SOURCEDIR and not Installed\t1301\n";
740 
741 static const char sd_install_exec_seq_dat[] =
742     "Action\tCondition\tSequence\n"
743     "s72\tS255\tI2\n"
744     "InstallExecuteSequence\tAction\n"
745     "TestSourceDirProp14\tSourceDir and SOURCEDIR and not Installed\t99\n"
746     "LaunchConditions\t\t100\n"
747     "TestSourceDirProp15\tSourceDir and SOURCEDIR and not Installed\t101\n"
748     "ValidateProductID\t\t700\n"
749     "TestSourceDirProp16\tSourceDir and SOURCEDIR and not Installed\t701\n"
750     "CostInitialize\t\t800\n"
751     "TestSourceDirProp17\tSourceDir and SOURCEDIR and not Installed\t801\n"
752     "ResolveSource\tResolveSource and not Installed\t850\n"
753     "TestSourceDirProp18\tResolveSource and not SourceDir and not SOURCEDIR and not Installed\t851\n"
754     "TestSourceDirProp19\tnot ResolveSource and SourceDir and SOURCEDIR and not Installed\t852\n"
755     "FileCost\t\t900\n"
756     "TestSourceDirProp20\tSourceDir and SOURCEDIR and not Installed\t901\n"
757     "IsolateComponents\t\t1000\n"
758     "TestSourceDirProp21\tSourceDir and SOURCEDIR and not Installed\t1001\n"
759     "CostFinalize\t\t1100\n"
760     "TestSourceDirProp22\tSourceDir and SOURCEDIR and not Installed\t1101\n"
761     "MigrateFeatureStates\t\t1200\n"
762     "TestSourceDirProp23\tSourceDir and SOURCEDIR and not Installed\t1201\n"
763     "InstallValidate\t\t1400\n"
764     "TestSourceDirProp24\tSourceDir and SOURCEDIR and not Installed\t1401\n"
765     "InstallInitialize\t\t1500\n"
766     "TestSourceDirProp25\tSourceDir and SOURCEDIR and not Installed\t1501\n"
767     "ProcessComponents\t\t1600\n"
768     "TestSourceDirProp26\tnot SourceDir and not SOURCEDIR and not Installed\t1601\n"
769     "UnpublishFeatures\t\t1800\n"
770     "TestSourceDirProp27\tnot SourceDir and not SOURCEDIR and not Installed\t1801\n"
771     "RemoveFiles\t\t3500\n"
772     "TestSourceDirProp28\tnot SourceDir and not SOURCEDIR and not Installed\t3501\n"
773     "InstallFiles\t\t4000\n"
774     "TestSourceDirProp29\tnot SourceDir and not SOURCEDIR and not Installed\t4001\n"
775     "RegisterUser\t\t6000\n"
776     "TestSourceDirProp30\tnot SourceDir and not SOURCEDIR and not Installed\t6001\n"
777     "RegisterProduct\t\t6100\n"
778     "TestSourceDirProp31\tnot SourceDir and not SOURCEDIR and not Installed\t6101\n"
779     "PublishFeatures\t\t6300\n"
780     "TestSourceDirProp32\tnot SourceDir and not SOURCEDIR and not Installed\t6301\n"
781     "PublishProduct\t\t6400\n"
782     "TestSourceDirProp33\tnot SourceDir and not SOURCEDIR and not Installed\t6401\n"
783     "InstallExecute\t\t6500\n"
784     "TestSourceDirProp34\tnot SourceDir and not SOURCEDIR and not Installed\t6501\n"
785     "InstallFinalize\t\t6600\n"
786     "TestSourceDirProp35\tnot SourceDir and not SOURCEDIR and not Installed\t6601\n";
787 
788 static const char sd_custom_action_dat[] =
789     "Action\tType\tSource\tTarget\tISComments\n"
790     "s72\ti2\tS64\tS0\tS255\n"
791     "CustomAction\tAction\n"
792     "TestSourceDirProp1\t19\t\tTest 1 failed\t\n"
793     "TestSourceDirProp2\t19\t\tTest 2 failed\t\n"
794     "TestSourceDirProp3\t19\t\tTest 3 failed\t\n"
795     "TestSourceDirProp4\t19\t\tTest 4 failed\t\n"
796     "TestSourceDirProp5\t19\t\tTest 5 failed\t\n"
797     "TestSourceDirProp6\t19\t\tTest 6 failed\t\n"
798     "TestSourceDirProp7\t19\t\tTest 7 failed\t\n"
799     "TestSourceDirProp8\t19\t\tTest 8 failed\t\n"
800     "TestSourceDirProp9\t19\t\tTest 9 failed\t\n"
801     "TestSourceDirProp10\t19\t\tTest 10 failed\t\n"
802     "TestSourceDirProp11\t19\t\tTest 11 failed\t\n"
803     "TestSourceDirProp12\t19\t\tTest 12 failed\t\n"
804     "TestSourceDirProp13\t19\t\tTest 13 failed\t\n"
805     "TestSourceDirProp14\t19\t\tTest 14 failed\t\n"
806     "TestSourceDirProp15\t19\t\tTest 15 failed\t\n"
807     "TestSourceDirProp16\t19\t\tTest 16 failed\t\n"
808     "TestSourceDirProp17\t19\t\tTest 17 failed\t\n"
809     "TestSourceDirProp18\t19\t\tTest 18 failed\t\n"
810     "TestSourceDirProp19\t19\t\tTest 19 failed\t\n"
811     "TestSourceDirProp20\t19\t\tTest 20 failed\t\n"
812     "TestSourceDirProp21\t19\t\tTest 21 failed\t\n"
813     "TestSourceDirProp22\t19\t\tTest 22 failed\t\n"
814     "TestSourceDirProp23\t19\t\tTest 23 failed\t\n"
815     "TestSourceDirProp24\t19\t\tTest 24 failed\t\n"
816     "TestSourceDirProp25\t19\t\tTest 25 failed\t\n"
817     "TestSourceDirProp26\t19\t\tTest 26 failed\t\n"
818     "TestSourceDirProp27\t19\t\tTest 27 failed\t\n"
819     "TestSourceDirProp28\t19\t\tTest 28 failed\t\n"
820     "TestSourceDirProp29\t19\t\tTest 29 failed\t\n"
821     "TestSourceDirProp30\t19\t\tTest 30 failed\t\n"
822     "TestSourceDirProp31\t19\t\tTest 31 failed\t\n"
823     "TestSourceDirProp32\t19\t\tTest 32 failed\t\n"
824     "TestSourceDirProp33\t19\t\tTest 33 failed\t\n"
825     "TestSourceDirProp34\t19\t\tTest 34 failed\t\n"
826     "TestSourceDirProp35\t19\t\tTest 35 failed\t\n";
827 
828 static const char ci_install_exec_seq_dat[] =
829     "Action\tCondition\tSequence\n"
830     "s72\tS255\tI2\n"
831     "InstallExecuteSequence\tAction\n"
832     "CostInitialize\t\t800\n"
833     "FileCost\t\t900\n"
834     "CostFinalize\t\t1000\n"
835     "InstallValidate\t\t1400\n"
836     "InstallInitialize\t\t1500\n"
837     "RunInstall\tnot Installed\t1550\n"
838     "ProcessComponents\t\t1600\n"
839     "UnpublishFeatures\t\t1800\n"
840     "RemoveFiles\t\t3500\n"
841     "InstallFiles\t\t4000\n"
842     "RegisterProduct\t\t6100\n"
843     "PublishFeatures\t\t6300\n"
844     "PublishProduct\t\t6400\n"
845     "InstallFinalize\t\t6600\n";
846 
847 static const char ci_custom_action_dat[] =
848     "Action\tType\tSource\tTarget\tISComments\n"
849     "s72\ti2\tS64\tS0\tS255\n"
850     "CustomAction\tAction\n"
851     "RunInstall\t23\tmsitest\\concurrent.msi\tMYPROP=[UILevel]\t\n";
852 
853 static const char ci_component_dat[] =
854     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
855     "s72\tS38\ts72\ti2\tS255\tS72\n"
856     "Component\tComponent\n"
857     "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
858 
859 static const char ci2_component_dat[] =
860     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
861     "s72\tS38\ts72\ti2\tS255\tS72\n"
862     "Component\tComponent\n"
863     "augustus\t\tMSITESTDIR\t0\tUILevel=3 AND MYPROP=5\taugustus\n";
864 
865 static const char ci2_feature_comp_dat[] =
866     "Feature_\tComponent_\n"
867     "s38\ts72\n"
868     "FeatureComponents\tFeature_\tComponent_\n"
869     "feature\taugustus";
870 
871 static const char ci2_file_dat[] =
872     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
873     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
874     "File\tFile\n"
875     "augustus\taugustus\taugustus\t500\t\t\t8192\t1";
876 
877 static const char cl_custom_action_dat[] =
878     "Action\tType\tSource\tTarget\tISComments\n"
879     "s72\ti2\tS64\tS0\tS255\n"
880     "CustomAction\tAction\n"
881     "TestCommandlineProp\t19\t\tTest1\t\n";
882 
883 static const char cl_install_exec_seq_dat[] =
884     "Action\tCondition\tSequence\n"
885     "s72\tS255\tI2\n"
886     "InstallExecuteSequence\tAction\n"
887     "LaunchConditions\t\t100\n"
888     "ValidateProductID\t\t700\n"
889     "CostInitialize\t\t800\n"
890     "FileCost\t\t900\n"
891     "CostFinalize\t\t1000\n"
892     "TestCommandlineProp\tP=\"one\"\t1100\n"
893     "InstallInitialize\t\t1500\n"
894     "ProcessComponents\t\t1600\n"
895     "InstallValidate\t\t1400\n"
896     "InstallFinalize\t\t5000\n";
897 
898 typedef struct _msi_table
899 {
900     const CHAR *filename;
901     const CHAR *data;
902     int size;
903 } msi_table;
904 
905 #define ADD_TABLE(x) {#x".idt", x##_dat, sizeof(x##_dat)}
906 
907 static const msi_table tables[] =
908 {
909     ADD_TABLE(directory),
910     ADD_TABLE(component),
911     ADD_TABLE(feature),
912     ADD_TABLE(feature_comp),
913     ADD_TABLE(file),
914     ADD_TABLE(install_exec_seq),
915     ADD_TABLE(media),
916     ADD_TABLE(property),
917 };
918 
919 static const msi_table mcp_tables[] =
920 {
921     ADD_TABLE(directory),
922     ADD_TABLE(mcp_component),
923     ADD_TABLE(mcp_feature),
924     ADD_TABLE(mcp_feature_comp),
925     ADD_TABLE(mcp_file),
926     ADD_TABLE(install_exec_seq),
927     ADD_TABLE(media),
928     ADD_TABLE(property)
929 };
930 
931 static const msi_table lus0_tables[] =
932 {
933     ADD_TABLE(lus_component),
934     ADD_TABLE(directory),
935     ADD_TABLE(lus_feature),
936     ADD_TABLE(lus_feature_comp),
937     ADD_TABLE(lus_file),
938     ADD_TABLE(lus_install_exec_seq),
939     ADD_TABLE(lus0_media),
940     ADD_TABLE(property)
941 };
942 
943 static const msi_table lus1_tables[] =
944 {
945     ADD_TABLE(lus_component),
946     ADD_TABLE(directory),
947     ADD_TABLE(lus_feature),
948     ADD_TABLE(lus_feature_comp),
949     ADD_TABLE(lus_file),
950     ADD_TABLE(lus_install_exec_seq),
951     ADD_TABLE(lus1_media),
952     ADD_TABLE(property)
953 };
954 
955 static const msi_table lus2_tables[] =
956 {
957     ADD_TABLE(lus_component),
958     ADD_TABLE(directory),
959     ADD_TABLE(lus_feature),
960     ADD_TABLE(lus_feature_comp),
961     ADD_TABLE(lus_file),
962     ADD_TABLE(lus_install_exec_seq),
963     ADD_TABLE(lus2_media),
964     ADD_TABLE(property)
965 };
966 
967 static const msi_table spf_tables[] =
968 {
969     ADD_TABLE(lus_component),
970     ADD_TABLE(directory),
971     ADD_TABLE(lus_feature),
972     ADD_TABLE(lus_feature_comp),
973     ADD_TABLE(lus_file),
974     ADD_TABLE(lus0_media),
975     ADD_TABLE(property),
976     ADD_TABLE(spf_custom_action),
977     ADD_TABLE(spf_install_exec_seq),
978     ADD_TABLE(spf_install_ui_seq)
979 };
980 
981 static const msi_table sd_tables[] =
982 {
983     ADD_TABLE(directory),
984     ADD_TABLE(sd_component),
985     ADD_TABLE(sd_feature),
986     ADD_TABLE(sd_feature_comp),
987     ADD_TABLE(sd_file),
988     ADD_TABLE(sd_install_exec_seq),
989     ADD_TABLE(sd_install_ui_seq),
990     ADD_TABLE(sd_custom_action),
991     ADD_TABLE(media),
992     ADD_TABLE(property)
993 };
994 
995 static const msi_table ci_tables[] =
996 {
997     ADD_TABLE(ci_component),
998     ADD_TABLE(directory),
999     ADD_TABLE(lus_feature),
1000     ADD_TABLE(lus_feature_comp),
1001     ADD_TABLE(lus_file),
1002     ADD_TABLE(ci_install_exec_seq),
1003     ADD_TABLE(lus0_media),
1004     ADD_TABLE(property),
1005     ADD_TABLE(ci_custom_action),
1006 };
1007 
1008 static const msi_table ci2_tables[] =
1009 {
1010     ADD_TABLE(ci2_component),
1011     ADD_TABLE(directory),
1012     ADD_TABLE(lus_feature),
1013     ADD_TABLE(ci2_feature_comp),
1014     ADD_TABLE(ci2_file),
1015     ADD_TABLE(install_exec_seq),
1016     ADD_TABLE(lus0_media),
1017     ADD_TABLE(ci2_property),
1018 };
1019 
1020 static const msi_table cl_tables[] =
1021 {
1022     ADD_TABLE(component),
1023     ADD_TABLE(directory),
1024     ADD_TABLE(feature),
1025     ADD_TABLE(feature_comp),
1026     ADD_TABLE(file),
1027     ADD_TABLE(cl_custom_action),
1028     ADD_TABLE(cl_install_exec_seq),
1029     ADD_TABLE(media),
1030     ADD_TABLE(property)
1031 };
1032 
1033 static void write_file(const CHAR *filename, const char *data, int data_size)
1034 {
1035     DWORD size;
1036 
1037     HANDLE hf = CreateFileA(filename, GENERIC_WRITE, 0, NULL,
1038                             CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1039     WriteFile(hf, data, data_size, &size, NULL);
1040     CloseHandle(hf);
1041 }
1042 
1043 static void write_msi_summary_info(MSIHANDLE db, INT version, INT wordcount, const char *template)
1044 {
1045     MSIHANDLE summary;
1046     UINT r;
1047 
1048     r = MsiGetSummaryInformationA(db, NULL, 5, &summary);
1049     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1050 
1051     r = MsiSummaryInfoSetPropertyA(summary, PID_TEMPLATE, VT_LPSTR, 0, NULL, template);
1052     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1053 
1054     r = MsiSummaryInfoSetPropertyA(summary, PID_REVNUMBER, VT_LPSTR, 0, NULL,
1055                                    "{004757CA-5092-49C2-AD20-28E1CE0DF5F2}");
1056     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1057 
1058     r = MsiSummaryInfoSetPropertyA(summary, PID_PAGECOUNT, VT_I4, version, NULL, NULL);
1059     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1060 
1061     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, wordcount, NULL, NULL);
1062     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1063 
1064     r = MsiSummaryInfoSetPropertyA(summary, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
1065     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1066 
1067     /* write the summary changes back to the stream */
1068     r = MsiSummaryInfoPersist(summary);
1069     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1070 
1071     MsiCloseHandle(summary);
1072 }
1073 
1074 #define create_database(name, tables, num_tables) \
1075     create_database_wordcount(name, tables, num_tables, 100, 0, ";1033");
1076 
1077 #define create_database_template(name, tables, num_tables, version, template) \
1078     create_database_wordcount(name, tables, num_tables, version, 0, template);
1079 
1080 static void create_database_wordcount(const CHAR *name, const msi_table *tables,
1081                                       int num_tables, INT version, INT wordcount,
1082                                       const char *template)
1083 {
1084     MSIHANDLE db;
1085     UINT r;
1086     WCHAR *nameW;
1087     int j, len;
1088 
1089     len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 );
1090     if (!(nameW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return;
1091     MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, len );
1092 
1093     r = MsiOpenDatabaseW(nameW, MSIDBOPEN_CREATE, &db);
1094     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1095 
1096     /* import the tables into the database */
1097     for (j = 0; j < num_tables; j++)
1098     {
1099         const msi_table *table = &tables[j];
1100 
1101         write_file(table->filename, table->data, (table->size - 1) * sizeof(char));
1102 
1103         r = MsiDatabaseImportA(db, CURR_DIR, table->filename);
1104         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1105 
1106         DeleteFileA(table->filename);
1107     }
1108 
1109     write_msi_summary_info(db, version, wordcount, template);
1110 
1111     r = MsiDatabaseCommit(db);
1112     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1113 
1114     MsiCloseHandle(db);
1115     HeapFree( GetProcessHeap(), 0, nameW );
1116 }
1117 
1118 static UINT run_query(MSIHANDLE hdb, const char *query)
1119 {
1120     MSIHANDLE hview = 0;
1121     UINT r;
1122 
1123     r = MsiDatabaseOpenViewA(hdb, query, &hview);
1124     if (r != ERROR_SUCCESS)
1125         return r;
1126 
1127     r = MsiViewExecute(hview, 0);
1128     if (r == ERROR_SUCCESS)
1129         r = MsiViewClose(hview);
1130     MsiCloseHandle(hview);
1131     return r;
1132 }
1133 
1134 static UINT set_summary_info(MSIHANDLE hdb, LPSTR prodcode)
1135 {
1136     UINT res;
1137     MSIHANDLE suminfo;
1138 
1139     /* build summary info */
1140     res = MsiGetSummaryInformationA(hdb, NULL, 7, &suminfo);
1141     ok(res == ERROR_SUCCESS, "Failed to open summaryinfo\n");
1142 
1143     res = MsiSummaryInfoSetPropertyA(suminfo, 2, VT_LPSTR, 0, NULL,
1144                                     "Installation Database");
1145     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1146 
1147     res = MsiSummaryInfoSetPropertyA(suminfo, 3, VT_LPSTR, 0, NULL,
1148                                     "Installation Database");
1149     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1150 
1151     res = MsiSummaryInfoSetPropertyA(suminfo, 4, VT_LPSTR, 0, NULL,
1152                                     "Wine Hackers");
1153     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1154 
1155     res = MsiSummaryInfoSetPropertyA(suminfo, 7, VT_LPSTR, 0, NULL,
1156                                     ";1033");
1157     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1158 
1159     res = MsiSummaryInfoSetPropertyA(suminfo, PID_REVNUMBER, VT_LPSTR, 0, NULL,
1160                                     "{A2078D65-94D6-4205-8DEE-F68D6FD622AA}");
1161     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1162 
1163     res = MsiSummaryInfoSetPropertyA(suminfo, 14, VT_I4, 100, NULL, NULL);
1164     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1165 
1166     res = MsiSummaryInfoSetPropertyA(suminfo, 15, VT_I4, 0, NULL, NULL);
1167     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1168 
1169     res = MsiSummaryInfoPersist(suminfo);
1170     ok(res == ERROR_SUCCESS, "Failed to make summary info persist\n");
1171 
1172     res = MsiCloseHandle(suminfo);
1173     ok(res == ERROR_SUCCESS, "Failed to close suminfo\n");
1174 
1175     return res;
1176 }
1177 
1178 static MSIHANDLE create_package_db(LPSTR prodcode)
1179 {
1180     MSIHANDLE hdb = 0;
1181     CHAR query[MAX_PATH];
1182     UINT res;
1183 
1184     DeleteFileA(msifile);
1185 
1186     /* create an empty database */
1187     res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
1188     ok( res == ERROR_SUCCESS , "Failed to create database\n" );
1189     if (res != ERROR_SUCCESS)
1190         return hdb;
1191 
1192     res = MsiDatabaseCommit(hdb);
1193     ok(res == ERROR_SUCCESS, "Failed to commit database\n");
1194 
1195     set_summary_info(hdb, prodcode);
1196 
1197     res = run_query(hdb,
1198             "CREATE TABLE `Directory` ( "
1199             "`Directory` CHAR(255) NOT NULL, "
1200             "`Directory_Parent` CHAR(255), "
1201             "`DefaultDir` CHAR(255) NOT NULL "
1202             "PRIMARY KEY `Directory`)");
1203     ok(res == ERROR_SUCCESS , "Failed to create directory table\n");
1204 
1205     res = run_query(hdb,
1206             "CREATE TABLE `Property` ( "
1207             "`Property` CHAR(72) NOT NULL, "
1208             "`Value` CHAR(255) "
1209             "PRIMARY KEY `Property`)");
1210     ok(res == ERROR_SUCCESS , "Failed to create directory table\n");
1211 
1212     sprintf(query, "INSERT INTO `Property` "
1213             "(`Property`, `Value`) "
1214             "VALUES( 'ProductCode', '%s' )", prodcode);
1215     res = run_query(hdb, query);
1216     ok(res == ERROR_SUCCESS , "Failed\n");
1217 
1218     res = MsiDatabaseCommit(hdb);
1219     ok(res == ERROR_SUCCESS, "Failed to commit database\n");
1220 
1221     return hdb;
1222 }
1223 
1224 static void test_usefeature(void)
1225 {
1226     INSTALLSTATE r;
1227 
1228     if (!pMsiUseFeatureExA)
1229     {
1230         win_skip("MsiUseFeatureExA not implemented\n");
1231         return;
1232     }
1233 
1234     r = MsiQueryFeatureStateA(NULL, NULL);
1235     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1236 
1237     r = MsiQueryFeatureStateA("{9085040-6000-11d3-8cfe-0150048383c9}" ,NULL);
1238     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1239 
1240     r = pMsiUseFeatureExA(NULL,NULL,0,0);
1241     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1242 
1243     r = pMsiUseFeatureExA(NULL, "WORDVIEWFiles", -2, 1 );
1244     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1245 
1246     r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}",
1247                          NULL, -2, 0 );
1248     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1249 
1250     r = pMsiUseFeatureExA("{9085040-6000-11d3-8cfe-0150048383c9}",
1251                          "WORDVIEWFiles", -2, 0 );
1252     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1253 
1254     r = pMsiUseFeatureExA("{0085040-6000-11d3-8cfe-0150048383c9}",
1255                          "WORDVIEWFiles", -2, 0 );
1256     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1257 
1258     r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}",
1259                          "WORDVIEWFiles", -2, 1 );
1260     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1261 }
1262 
1263 static LONG delete_key( HKEY key, LPCSTR subkey, REGSAM access )
1264 {
1265     if (pRegDeleteKeyExA)
1266         return pRegDeleteKeyExA( key, subkey, access, 0 );
1267     return RegDeleteKeyA( key, subkey );
1268 }
1269 
1270 static void test_null(void)
1271 {
1272     MSIHANDLE hpkg;
1273     UINT r;
1274     HKEY hkey;
1275     DWORD dwType, cbData;
1276     LPBYTE lpData = NULL;
1277     INSTALLSTATE state;
1278     REGSAM access = KEY_ALL_ACCESS;
1279 
1280     if (is_wow64)
1281         access |= KEY_WOW64_64KEY;
1282 
1283     r = pMsiOpenPackageExW(NULL, 0, &hpkg);
1284     ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
1285 
1286     state = MsiQueryProductStateW(NULL);
1287     ok( state == INSTALLSTATE_INVALIDARG, "wrong return\n");
1288 
1289     r = MsiEnumFeaturesW(NULL,0,NULL,NULL);
1290     ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
1291 
1292     r = MsiConfigureFeatureW(NULL, NULL, 0);
1293     ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
1294 
1295     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", NULL, 0);
1296     ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
1297 
1298     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000001}", "foo", 0);
1299     ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
1300 
1301     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000002}", "foo", INSTALLSTATE_DEFAULT);
1302     ok( r == ERROR_UNKNOWN_PRODUCT, "wrong error %d\n", r);
1303 
1304     /* make sure empty string to MsiGetProductInfo is not a handle to default registry value, saving and restoring the
1305      * necessary registry values */
1306 
1307     /* empty product string */
1308     r = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", 0, access, &hkey);
1309     if (r == ERROR_ACCESS_DENIED)
1310     {
1311         skip("Not enough rights to perform tests\n");
1312         return;
1313     }
1314     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1315 
1316     r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
1317     ok ( r == ERROR_SUCCESS || r == ERROR_FILE_NOT_FOUND, "wrong error %d\n", r);
1318     if ( r == ERROR_SUCCESS )
1319     {
1320         lpData = HeapAlloc(GetProcessHeap(), 0, cbData);
1321         if (!lpData)
1322             skip("Out of memory\n");
1323         else
1324         {
1325             r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
1326             ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
1327         }
1328     }
1329 
1330     r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
1331     if (r == ERROR_ACCESS_DENIED)
1332     {
1333         skip("Not enough rights to perform tests\n");
1334         HeapFree(GetProcessHeap(), 0, lpData);
1335         RegCloseKey(hkey);
1336         return;
1337     }
1338     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1339 
1340     r = MsiGetProductInfoA("", "", NULL, NULL);
1341     ok ( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
1342 
1343     if (lpData)
1344     {
1345         r = RegSetValueExA(hkey, NULL, 0, dwType, lpData, cbData);
1346         ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
1347 
1348         HeapFree(GetProcessHeap(), 0, lpData);
1349     }
1350     else
1351     {
1352         r = RegDeleteValueA(hkey, NULL);
1353         ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
1354     }
1355 
1356     r = RegCloseKey(hkey);
1357     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1358 
1359     /* empty attribute */
1360     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}",
1361                         0, NULL, 0, access, NULL, &hkey, NULL);
1362     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1363 
1364     r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
1365     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1366 
1367     r = MsiGetProductInfoA("{F1C3AF50-8B56-4A69-A00C-00773FE42F30}", "", NULL, NULL);
1368     ok ( r == ERROR_UNKNOWN_PROPERTY, "wrong error %d\n", r);
1369 
1370     r = RegCloseKey(hkey);
1371     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1372 
1373     r = delete_key(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}",
1374                    access & KEY_WOW64_64KEY);
1375     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1376 }
1377 
1378 static void test_getcomponentpath(void)
1379 {
1380     INSTALLSTATE r;
1381     char buffer[0x100];
1382     DWORD sz;
1383 
1384     if(!pMsiGetComponentPathA)
1385         return;
1386 
1387     r = pMsiGetComponentPathA( NULL, NULL, NULL, NULL );
1388     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1389 
1390     r = pMsiGetComponentPathA( "bogus", "bogus", NULL, NULL );
1391     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1392 
1393     r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", NULL, NULL );
1394     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1395 
1396     sz = sizeof buffer;
1397     buffer[0]=0;
1398     r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", buffer, &sz );
1399     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1400 
1401     r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C998E7}",
1402         "{00000000-0000-0000-0000-000000000000}", buffer, &sz );
1403     ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
1404 
1405     r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
1406         "{00000000-0000-0000-0000-00000000}", buffer, &sz );
1407     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1408 
1409     r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
1410         "{029E403D-A86A-1D11-5B5B0006799C897E}", buffer, &sz );
1411     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1412 
1413     r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C9987e}",
1414                             "{00000000-A68A-11d1-5B5B-0006799C897E}", buffer, &sz );
1415     ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
1416 }
1417 
1418 static void create_file(LPCSTR name, LPCSTR data, DWORD size)
1419 {
1420     HANDLE file;
1421     DWORD written;
1422 
1423     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1424     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
1425     WriteFile(file, data, strlen(data), &written, NULL);
1426 
1427     if (size)
1428     {
1429         SetFilePointer(file, size, NULL, FILE_BEGIN);
1430         SetEndOfFile(file);
1431     }
1432 
1433     CloseHandle(file);
1434 }
1435 
1436 static void create_test_files(void)
1437 {
1438     CreateDirectoryA("msitest", NULL);
1439     create_file("msitest\\one.txt", "msitest\\one.txt", 100);
1440     CreateDirectoryA("msitest\\first", NULL);
1441     create_file("msitest\\first\\two.txt", "msitest\\first\\two.txt", 100);
1442     CreateDirectoryA("msitest\\second", NULL);
1443     create_file("msitest\\second\\three.txt", "msitest\\second\\three.txt", 100);
1444 
1445     create_file("four.txt", "four.txt", 100);
1446     create_file("five.txt", "five.txt", 100);
1447     create_cab_file("msitest.cab", MEDIA_SIZE, "four.txt\0five.txt\0");
1448 
1449     create_file("msitest\\filename", "msitest\\filename", 100);
1450     create_file("msitest\\service.exe", "msitest\\service.exe", 100);
1451 
1452     DeleteFileA("four.txt");
1453     DeleteFileA("five.txt");
1454 }
1455 
1456 static void delete_test_files(void)
1457 {
1458     DeleteFileA("msitest.msi");
1459     DeleteFileA("msitest.cab");
1460     DeleteFileA("msitest\\second\\three.txt");
1461     DeleteFileA("msitest\\first\\two.txt");
1462     DeleteFileA("msitest\\one.txt");
1463     DeleteFileA("msitest\\service.exe");
1464     DeleteFileA("msitest\\filename");
1465     RemoveDirectoryA("msitest\\second");
1466     RemoveDirectoryA("msitest\\first");
1467     RemoveDirectoryA("msitest");
1468 }
1469 
1470 #define HASHSIZE sizeof(MSIFILEHASHINFO)
1471 
1472 static const struct
1473 {
1474     LPCSTR data;
1475     DWORD size;
1476     MSIFILEHASHINFO hash;
1477 } hash_data[] =
1478 {
1479     { "", 0,
1480       { HASHSIZE,
1481         { 0, 0, 0, 0 },
1482       },
1483     },
1484 
1485     { "abc", 0,
1486       { HASHSIZE,
1487         { 0x98500190, 0xb04fd23c, 0x7d3f96d6, 0x727fe128 },
1488       },
1489     },
1490 
1491     { "C:\\Program Files\\msitest\\caesar\n", 0,
1492       { HASHSIZE,
1493         { 0x2b566794, 0xfd42181b, 0x2514d6e4, 0x5768b4e2 },
1494       },
1495     },
1496 
1497     { "C:\\Program Files\\msitest\\caesar\n", 500,
1498       { HASHSIZE,
1499         { 0x58095058, 0x805efeff, 0x10f3483e, 0x0147d653 },
1500       },
1501     },
1502 };
1503 
1504 static void test_MsiGetFileHash(void)
1505 {
1506     const char name[] = "msitest.bin";
1507     UINT r;
1508     MSIFILEHASHINFO hash;
1509     DWORD i;
1510 
1511     if (!pMsiGetFileHashA)
1512     {
1513         win_skip("MsiGetFileHash not implemented\n");
1514         return;
1515     }
1516 
1517     hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
1518 
1519     /* szFilePath is NULL */
1520     r = pMsiGetFileHashA(NULL, 0, &hash);
1521     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1522 
1523     /* szFilePath is empty */
1524     r = pMsiGetFileHashA("", 0, &hash);
1525     ok(r == ERROR_PATH_NOT_FOUND || r == ERROR_BAD_PATHNAME,
1526        "Expected ERROR_PATH_NOT_FOUND or ERROR_BAD_PATHNAME, got %d\n", r);
1527 
1528     /* szFilePath is nonexistent */
1529     r = pMsiGetFileHashA(name, 0, &hash);
1530     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
1531 
1532     /* dwOptions is non-zero */
1533     r = pMsiGetFileHashA(name, 1, &hash);
1534     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1535 
1536     /* pHash.dwFileHashInfoSize is not correct */
1537     hash.dwFileHashInfoSize = 0;
1538     r = pMsiGetFileHashA(name, 0, &hash);
1539     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1540 
1541     /* pHash is NULL */
1542     r = pMsiGetFileHashA(name, 0, NULL);
1543     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1544 
1545     for (i = 0; i < sizeof(hash_data) / sizeof(hash_data[0]); i++)
1546     {
1547         int ret;
1548 
1549         create_file(name, hash_data[i].data, hash_data[i].size);
1550 
1551         memset(&hash, 0, sizeof(MSIFILEHASHINFO));
1552         hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
1553 
1554         r = pMsiGetFileHashA(name, 0, &hash);
1555         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1556 
1557         ret = memcmp(&hash, &hash_data[i].hash, HASHSIZE);
1558         ok(!ret, "Hash incorrect\n");
1559 
1560         DeleteFileA(name);
1561     }
1562 }
1563 
1564 /* copied from dlls/msi/registry.c */
1565 static BOOL squash_guid(LPCWSTR in, LPWSTR out)
1566 {
1567     DWORD i,n=1;
1568     GUID guid;
1569 
1570     if (FAILED(CLSIDFromString((LPCOLESTR)in, &guid)))
1571         return FALSE;
1572 
1573     for(i=0; i<8; i++)
1574         out[7-i] = in[n++];
1575     n++;
1576     for(i=0; i<4; i++)
1577         out[11-i] = in[n++];
1578     n++;
1579     for(i=0; i<4; i++)
1580         out[15-i] = in[n++];
1581     n++;
1582     for(i=0; i<2; i++)
1583     {
1584         out[17+i*2] = in[n++];
1585         out[16+i*2] = in[n++];
1586     }
1587     n++;
1588     for( ; i<8; i++)
1589     {
1590         out[17+i*2] = in[n++];
1591         out[16+i*2] = in[n++];
1592     }
1593     out[32]=0;
1594     return TRUE;
1595 }
1596 
1597 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
1598 {
1599     WCHAR guidW[MAX_PATH];
1600     WCHAR squashedW[MAX_PATH];
1601     GUID guid;
1602     HRESULT hr;
1603     int size;
1604 
1605     hr = CoCreateGuid(&guid);
1606     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
1607 
1608     size = StringFromGUID2(&guid, guidW, MAX_PATH);
1609     ok(size == 39, "Expected 39, got %d\n", hr);
1610 
1611     WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
1612     if (squashed)
1613     {
1614         squash_guid(guidW, squashedW);
1615         WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
1616     }
1617 }
1618 
1619 static char *get_user_sid(void)
1620 {
1621     HANDLE token;
1622     DWORD size = 0;
1623     TOKEN_USER *user;
1624     char *usersid = NULL;
1625 
1626     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
1627     GetTokenInformation(token, TokenUser, NULL, size, &size);
1628 
1629     user = HeapAlloc(GetProcessHeap(), 0, size);
1630     GetTokenInformation(token, TokenUser, user, size, &size);
1631     pConvertSidToStringSidA(user->User.Sid, &usersid);
1632     HeapFree(GetProcessHeap(), 0, user);
1633 
1634     CloseHandle(token);
1635     return usersid;
1636 }
1637 
1638 static void test_MsiQueryProductState(void)
1639 {
1640     CHAR prodcode[MAX_PATH];
1641     CHAR prod_squashed[MAX_PATH];
1642     CHAR keypath[MAX_PATH*2];
1643     LPSTR usersid;
1644     INSTALLSTATE state;
1645     LONG res;
1646     HKEY userkey, localkey, props;
1647     HKEY prodkey;
1648     DWORD data, error;
1649     REGSAM access = KEY_ALL_ACCESS;
1650 
1651     create_test_guid(prodcode, prod_squashed);
1652     usersid = get_user_sid();
1653 
1654     if (is_wow64)
1655         access |= KEY_WOW64_64KEY;
1656 
1657     /* NULL prodcode */
1658     SetLastError(0xdeadbeef);
1659     state = MsiQueryProductStateA(NULL);
1660     error = GetLastError();
1661     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1662     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1663 
1664     /* empty prodcode */
1665     SetLastError(0xdeadbeef);
1666     state = MsiQueryProductStateA("");
1667     error = GetLastError();
1668     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1669     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1670 
1671     /* garbage prodcode */
1672     SetLastError(0xdeadbeef);
1673     state = MsiQueryProductStateA("garbage");
1674     error = GetLastError();
1675     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1676     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1677 
1678     /* guid without brackets */
1679     SetLastError(0xdeadbeef);
1680     state = MsiQueryProductStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D");
1681     error = GetLastError();
1682     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1683     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1684 
1685     /* guid with brackets */
1686     SetLastError(0xdeadbeef);
1687     state = MsiQueryProductStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}");
1688     error = GetLastError();
1689     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1690     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1691        "expected ERROR_SUCCESS, got %u\n", error);
1692 
1693     /* same length as guid, but random */
1694     SetLastError(0xdeadbeef);
1695     state = MsiQueryProductStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93");
1696     error = GetLastError();
1697     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1698     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1699 
1700     /* MSIINSTALLCONTEXT_USERUNMANAGED */
1701 
1702     SetLastError(0xdeadbeef);
1703     state = MsiQueryProductStateA(prodcode);
1704     error = GetLastError();
1705     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1706     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1707        "expected ERROR_SUCCESS, got %u\n", error);
1708 
1709     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
1710     lstrcatA(keypath, prod_squashed);
1711 
1712     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
1713     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1714 
1715     /* user product key exists */
1716     SetLastError(0xdeadbeef);
1717     state = MsiQueryProductStateA(prodcode);
1718     error = GetLastError();
1719     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1720     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1721        "expected ERROR_SUCCESS, got %u\n", error);
1722 
1723     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
1724     lstrcatA(keypath, prodcode);
1725 
1726     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1727     if (res == ERROR_ACCESS_DENIED)
1728     {
1729         skip("Not enough rights to perform tests\n");
1730         RegDeleteKeyA(userkey, "");
1731         RegCloseKey(userkey);
1732         LocalFree(usersid);
1733         return;
1734     }
1735     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1736 
1737     /* local uninstall key exists */
1738     SetLastError(0xdeadbeef);
1739     state = MsiQueryProductStateA(prodcode);
1740     error = GetLastError();
1741     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1742     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1743        "expected ERROR_SUCCESS, got %u\n", error);
1744 
1745     data = 1;
1746     res = RegSetValueExA(localkey, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1747     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1748 
1749     /* WindowsInstaller value exists */
1750     SetLastError(0xdeadbeef);
1751     state = MsiQueryProductStateA(prodcode);
1752     error = GetLastError();
1753     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1754     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1755        "expected ERROR_SUCCESS, got %u\n", error);
1756 
1757     RegDeleteValueA(localkey, "WindowsInstaller");
1758     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1759 
1760     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1761     lstrcatA(keypath, usersid);
1762     lstrcatA(keypath, "\\Products\\");
1763     lstrcatA(keypath, prod_squashed);
1764 
1765     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1766     if (res == ERROR_ACCESS_DENIED)
1767     {
1768         skip("Not enough rights to perform tests\n");
1769         RegDeleteKeyA(userkey, "");
1770         RegCloseKey(userkey);
1771         LocalFree(usersid);
1772         return;
1773     }
1774     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1775 
1776     /* local product key exists */
1777     SetLastError(0xdeadbeef);
1778     state = MsiQueryProductStateA(prodcode);
1779     error = GetLastError();
1780     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1781     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1782        "expected ERROR_SUCCESS, got %u\n", error);
1783 
1784     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1785     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1786 
1787     /* install properties key exists */
1788     SetLastError(0xdeadbeef);
1789     state = MsiQueryProductStateA(prodcode);
1790     error = GetLastError();
1791     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1792     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1793        "expected ERROR_SUCCESS, got %u\n", error);
1794 
1795     data = 1;
1796     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1797     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1798 
1799     /* WindowsInstaller value exists */
1800     SetLastError(0xdeadbeef);
1801     state = MsiQueryProductStateA(prodcode);
1802     error = GetLastError();
1803     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1804     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1805        "expected ERROR_SUCCESS, got %u\n", error);
1806 
1807     data = 2;
1808     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1809     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1810 
1811     /* WindowsInstaller value is not 1 */
1812     SetLastError(0xdeadbeef);
1813     state = MsiQueryProductStateA(prodcode);
1814     error = GetLastError();
1815     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1816     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1817        "expected ERROR_SUCCESS, got %u\n", error);
1818 
1819     RegDeleteKeyA(userkey, "");
1820 
1821     /* user product key does not exist */
1822     SetLastError(0xdeadbeef);
1823     state = MsiQueryProductStateA(prodcode);
1824     error = GetLastError();
1825     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1826     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1827        "expected ERROR_SUCCESS, got %u\n", error);
1828 
1829     RegDeleteValueA(props, "WindowsInstaller");
1830     delete_key(props, "", access & KEY_WOW64_64KEY);
1831     RegCloseKey(props);
1832     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1833     RegCloseKey(localkey);
1834     RegDeleteKeyA(userkey, "");
1835     RegCloseKey(userkey);
1836 
1837     /* MSIINSTALLCONTEXT_USERMANAGED */
1838 
1839     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
1840     lstrcatA(keypath, usersid);
1841     lstrcatA(keypath, "\\Installer\\Products\\");
1842     lstrcatA(keypath, prod_squashed);
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     state = MsiQueryProductStateA(prodcode);
1848     ok(state == INSTALLSTATE_ADVERTISED,
1849        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1850 
1851     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1852     lstrcatA(keypath, usersid);
1853     lstrcatA(keypath, "\\Products\\");
1854     lstrcatA(keypath, prod_squashed);
1855 
1856     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1857     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1858 
1859     state = MsiQueryProductStateA(prodcode);
1860     ok(state == INSTALLSTATE_ADVERTISED,
1861        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1862 
1863     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1864     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1865 
1866     state = MsiQueryProductStateA(prodcode);
1867     ok(state == INSTALLSTATE_ADVERTISED,
1868        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1869 
1870     data = 1;
1871     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1872     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1873 
1874     /* WindowsInstaller value exists */
1875     state = MsiQueryProductStateA(prodcode);
1876     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1877 
1878     RegDeleteValueA(props, "WindowsInstaller");
1879     delete_key(props, "", access & KEY_WOW64_64KEY);
1880     RegCloseKey(props);
1881     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1882     RegCloseKey(localkey);
1883     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
1884     RegCloseKey(prodkey);
1885 
1886     /* MSIINSTALLCONTEXT_MACHINE */
1887 
1888     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
1889     lstrcatA(keypath, prod_squashed);
1890 
1891     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
1892     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1893 
1894     state = MsiQueryProductStateA(prodcode);
1895     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1896 
1897     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1898     lstrcatA(keypath, "S-1-5-18\\Products\\");
1899     lstrcatA(keypath, prod_squashed);
1900 
1901     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1902     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1903 
1904     state = MsiQueryProductStateA(prodcode);
1905     ok(state == INSTALLSTATE_ADVERTISED,
1906        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1907 
1908     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1909     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1910 
1911     state = MsiQueryProductStateA(prodcode);
1912     ok(state == INSTALLSTATE_ADVERTISED,
1913        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1914 
1915     data = 1;
1916     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1917     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1918 
1919     /* WindowsInstaller value exists */
1920     state = MsiQueryProductStateA(prodcode);
1921     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1922 
1923     RegDeleteValueA(props, "WindowsInstaller");
1924     delete_key(props, "", access & KEY_WOW64_64KEY);
1925     RegCloseKey(props);
1926     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1927     RegCloseKey(localkey);
1928     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
1929     RegCloseKey(prodkey);
1930 
1931     LocalFree(usersid);
1932 }
1933 
1934 static const char table_enc85[] =
1935 "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
1936 "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
1937 "yz{}~";
1938 
1939 /*
1940  *  Encodes a base85 guid given a GUID pointer
1941  *  Caller should provide a 21 character buffer for the encoded string.
1942  */
1943 static void encode_base85_guid( GUID *guid, LPWSTR str )
1944 {
1945     unsigned int x, *p, i;
1946 
1947     p = (unsigned int*) guid;
1948     for( i=0; i<4; i++ )
1949     {
1950         x = p[i];
1951         *str++ = table_enc85[x%85];
1952         x = x/85;
1953         *str++ = table_enc85[x%85];
1954         x = x/85;
1955         *str++ = table_enc85[x%85];
1956         x = x/85;
1957         *str++ = table_enc85[x%85];
1958         x = x/85;
1959         *str++ = table_enc85[x%85];
1960     }
1961     *str = 0;
1962 }
1963 
1964 static void compose_base85_guid(LPSTR component, LPSTR comp_base85, LPSTR squashed)
1965 {
1966     WCHAR guidW[MAX_PATH];
1967     WCHAR base85W[MAX_PATH];
1968     WCHAR squashedW[MAX_PATH];
1969     GUID guid;
1970     HRESULT hr;
1971     int size;
1972 
1973     hr = CoCreateGuid(&guid);
1974     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
1975 
1976     size = StringFromGUID2(&guid, guidW, MAX_PATH);
1977     ok(size == 39, "Expected 39, got %d\n", hr);
1978 
1979     WideCharToMultiByte(CP_ACP, 0, guidW, size, component, MAX_PATH, NULL, NULL);
1980     encode_base85_guid(&guid, base85W);
1981     WideCharToMultiByte(CP_ACP, 0, base85W, -1, comp_base85, MAX_PATH, NULL, NULL);
1982     squash_guid(guidW, squashedW);
1983     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
1984 }
1985 
1986 static void test_MsiQueryFeatureState(void)
1987 {
1988     HKEY userkey, localkey, compkey, compkey2;
1989     CHAR prodcode[MAX_PATH];
1990     CHAR prod_squashed[MAX_PATH];
1991     CHAR component[MAX_PATH];
1992     CHAR comp_base85[MAX_PATH];
1993     CHAR comp_squashed[MAX_PATH], comp_squashed2[MAX_PATH];
1994     CHAR keypath[MAX_PATH*2];
1995     INSTALLSTATE state;
1996     LPSTR usersid;
1997     LONG res;
1998     REGSAM access = KEY_ALL_ACCESS;
1999     DWORD error;
2000 
2001     create_test_guid(prodcode, prod_squashed);
2002     compose_base85_guid(component, comp_base85, comp_squashed);
2003     compose_base85_guid(component, comp_base85 + 20, comp_squashed2);
2004     usersid = get_user_sid();
2005 
2006     if (is_wow64)
2007         access |= KEY_WOW64_64KEY;
2008 
2009     /* NULL prodcode */
2010     SetLastError(0xdeadbeef);
2011     state = MsiQueryFeatureStateA(NULL, "feature");
2012     error = GetLastError();
2013     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2014     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2015 
2016     /* empty prodcode */
2017     SetLastError(0xdeadbeef);
2018     state = MsiQueryFeatureStateA("", "feature");
2019     error = GetLastError();
2020     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2021     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2022 
2023     /* garbage prodcode */
2024     SetLastError(0xdeadbeef);
2025     state = MsiQueryFeatureStateA("garbage", "feature");
2026     error = GetLastError();
2027     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2028     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2029 
2030     /* guid without brackets */
2031     SetLastError(0xdeadbeef);
2032     state = MsiQueryFeatureStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", "feature");
2033     error = GetLastError();
2034     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2035     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2036 
2037     /* guid with brackets */
2038     SetLastError(0xdeadbeef);
2039     state = MsiQueryFeatureStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", "feature");
2040     error = GetLastError();
2041     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2042     ok(error == ERROR_SUCCESS || broken(error == ERROR_ALREADY_EXISTS) /* win2k */,
2043        "expected ERROR_SUCCESS, got %u\n", error);
2044 
2045     /* same length as guid, but random */
2046     SetLastError(0xdeadbeef);
2047     state = MsiQueryFeatureStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", "feature");
2048     error = GetLastError();
2049     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2050     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2051 
2052     /* NULL szFeature */
2053     SetLastError(0xdeadbeef);
2054     state = MsiQueryFeatureStateA(prodcode, NULL);
2055     error = GetLastError();
2056     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2057     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2058 
2059     /* empty szFeature */
2060     SetLastError(0xdeadbeef);
2061     state = MsiQueryFeatureStateA(prodcode, "");
2062     error = GetLastError();
2063     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2064     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2065        "expected ERROR_SUCCESS, got %u\n", error);
2066 
2067     /* feature key does not exist yet */
2068     SetLastError(0xdeadbeef);
2069     state = MsiQueryFeatureStateA(prodcode, "feature");
2070     error = GetLastError();
2071     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2072     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2073        "expected ERROR_SUCCESS, got %u\n", error);
2074 
2075     /* MSIINSTALLCONTEXT_USERUNMANAGED */
2076 
2077     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Features\\");
2078     lstrcatA(keypath, prod_squashed);
2079 
2080     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
2081     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2082 
2083     /* feature key exists */
2084     SetLastError(0xdeadbeef);
2085     state = MsiQueryFeatureStateA(prodcode, "feature");
2086     error = GetLastError();
2087     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2088     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2089        "expected ERROR_SUCCESS, got %u\n", error);
2090 
2091     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 2);
2092     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2093 
2094     /* feature value exists */
2095     SetLastError(0xdeadbeef);
2096     state = MsiQueryFeatureStateA(prodcode, "feature");
2097     error = GetLastError();
2098     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2099     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2100        "expected ERROR_SUCCESS, got %u\n", error);
2101 
2102     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2103     lstrcatA(keypath, usersid);
2104     lstrcatA(keypath, "\\Products\\");
2105     lstrcatA(keypath, prod_squashed);
2106     lstrcatA(keypath, "\\Features");
2107 
2108     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
2109     if (res == ERROR_ACCESS_DENIED)
2110     {
2111         skip("Not enough rights to perform tests\n");
2112         RegDeleteKeyA(userkey, "");
2113         RegCloseKey(userkey);
2114         LocalFree(usersid);
2115         return;
2116     }
2117     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2118 
2119     /* userdata features key exists */
2120     SetLastError(0xdeadbeef);
2121     state = MsiQueryFeatureStateA(prodcode, "feature");
2122     error = GetLastError();
2123     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2124     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2125        "expected ERROR_SUCCESS, got %u\n", error);
2126 
2127     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
2128     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2129 
2130     SetLastError(0xdeadbeef);
2131     state = MsiQueryFeatureStateA(prodcode, "feature");
2132     error = GetLastError();
2133     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
2134     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2135        "expected ERROR_SUCCESS, got %u\n", error);
2136 
2137     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
2138     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2139 
2140     SetLastError(0xdeadbeef);
2141     state = MsiQueryFeatureStateA(prodcode, "feature");
2142     error = GetLastError();
2143     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2144     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2145        "expected ERROR_SUCCESS, got %u\n", error);
2146 
2147     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
2148     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2149 
2150     SetLastError(0xdeadbeef);
2151     state = MsiQueryFeatureStateA(prodcode, "feature");
2152     error = GetLastError();
2153     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2154     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2155        "expected ERROR_SUCCESS, got %u\n", error);
2156 
2157     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
2158     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2159 
2160     SetLastError(0xdeadbeef);
2161     state = MsiQueryFeatureStateA(prodcode, "feature");
2162     error = GetLastError();
2163     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2164     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2165        "expected ERROR_SUCCESS, got %u\n", error);
2166 
2167     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2168     lstrcatA(keypath, usersid);
2169     lstrcatA(keypath, "\\Components\\");
2170     lstrcatA(keypath, comp_squashed);
2171 
2172     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2173     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2174 
2175     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2176     lstrcatA(keypath, usersid);
2177     lstrcatA(keypath, "\\Components\\");
2178     lstrcatA(keypath, comp_squashed2);
2179 
2180     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
2181     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2182 
2183     SetLastError(0xdeadbeef);
2184     state = MsiQueryFeatureStateA(prodcode, "feature");
2185     error = GetLastError();
2186     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2187     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2188        "expected ERROR_SUCCESS, got %u\n", error);
2189 
2190     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
2191     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2192 
2193     SetLastError(0xdeadbeef);
2194     state = MsiQueryFeatureStateA(prodcode, "feature");
2195     error = GetLastError();
2196     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2197     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2198        "expected ERROR_SUCCESS, got %u\n", error);
2199 
2200     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
2201     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2202 
2203     SetLastError(0xdeadbeef);
2204     state = MsiQueryFeatureStateA(prodcode, "feature");
2205     error = GetLastError();
2206     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2207     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2208        "expected ERROR_SUCCESS, got %u\n", error);
2209 
2210     res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
2211     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2212 
2213     /* INSTALLSTATE_LOCAL */
2214     SetLastError(0xdeadbeef);
2215     state = MsiQueryFeatureStateA(prodcode, "feature");
2216     error = GetLastError();
2217     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2218     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2219        "expected ERROR_SUCCESS, got %u\n", error);
2220 
2221     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01\\", 4);
2222     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2223 
2224     /* INSTALLSTATE_SOURCE */
2225     SetLastError(0xdeadbeef);
2226     state = MsiQueryFeatureStateA(prodcode, "feature");
2227     error = GetLastError();
2228     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2229     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2230        "expected ERROR_SUCCESS, got %u\n", error);
2231 
2232     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
2233     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2234 
2235     /* bad INSTALLSTATE_SOURCE */
2236     SetLastError(0xdeadbeef);
2237     state = MsiQueryFeatureStateA(prodcode, "feature");
2238     error = GetLastError();
2239     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2240     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2241        "expected ERROR_SUCCESS, got %u\n", error);
2242 
2243     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01a", 4);
2244     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2245 
2246     /* INSTALLSTATE_SOURCE */
2247     SetLastError(0xdeadbeef);
2248     state = MsiQueryFeatureStateA(prodcode, "feature");
2249     error = GetLastError();
2250     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2251     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2252        "expected ERROR_SUCCESS, got %u\n", error);
2253 
2254     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
2255     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2256 
2257     /* bad INSTALLSTATE_SOURCE */
2258     SetLastError(0xdeadbeef);
2259     state = MsiQueryFeatureStateA(prodcode, "feature");
2260     error = GetLastError();
2261     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2262     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2263        "expected ERROR_SUCCESS, got %u\n", error);
2264 
2265     RegDeleteValueA(compkey, prod_squashed);
2266     RegDeleteValueA(compkey2, prod_squashed);
2267     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2268     delete_key(compkey2, "", access & KEY_WOW64_64KEY);
2269     RegDeleteValueA(localkey, "feature");
2270     RegDeleteValueA(userkey, "feature");
2271     RegDeleteKeyA(userkey, "");
2272     RegCloseKey(compkey);
2273     RegCloseKey(compkey2);
2274     RegCloseKey(localkey);
2275     RegCloseKey(userkey);
2276 
2277     /* MSIINSTALLCONTEXT_USERMANAGED */
2278 
2279     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
2280     lstrcatA(keypath, usersid);
2281     lstrcatA(keypath, "\\Installer\\Features\\");
2282     lstrcatA(keypath, prod_squashed);
2283 
2284     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
2285     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2286 
2287     /* feature key exists */
2288     state = MsiQueryFeatureStateA(prodcode, "feature");
2289     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2290 
2291     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 1);
2292     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2293 
2294     /* feature value exists */
2295     state = MsiQueryFeatureStateA(prodcode, "feature");
2296     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2297 
2298     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2299     lstrcatA(keypath, usersid);
2300     lstrcatA(keypath, "\\Products\\");
2301     lstrcatA(keypath, prod_squashed);
2302     lstrcatA(keypath, "\\Features");
2303 
2304     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
2305     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2306 
2307     /* userdata features key exists */
2308     state = MsiQueryFeatureStateA(prodcode, "feature");
2309     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2310 
2311     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
2312     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2313 
2314     state = MsiQueryFeatureStateA(prodcode, "feature");
2315     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
2316 
2317     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
2318     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2319 
2320     state = MsiQueryFeatureStateA(prodcode, "feature");
2321     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2322 
2323     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
2324     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2325 
2326     state = MsiQueryFeatureStateA(prodcode, "feature");
2327     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2328 
2329     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
2330     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2331 
2332     state = MsiQueryFeatureStateA(prodcode, "feature");
2333     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2334 
2335     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2336     lstrcatA(keypath, usersid);
2337     lstrcatA(keypath, "\\Components\\");
2338     lstrcatA(keypath, comp_squashed);
2339 
2340     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2341     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2342 
2343     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2344     lstrcatA(keypath, usersid);
2345     lstrcatA(keypath, "\\Components\\");
2346     lstrcatA(keypath, comp_squashed2);
2347 
2348     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
2349     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2350 
2351     state = MsiQueryFeatureStateA(prodcode, "feature");
2352     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2353 
2354     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
2355     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2356 
2357     state = MsiQueryFeatureStateA(prodcode, "feature");
2358     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2359 
2360     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
2361     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2362 
2363     state = MsiQueryFeatureStateA(prodcode, "feature");
2364     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2365 
2366     res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
2367     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2368 
2369     state = MsiQueryFeatureStateA(prodcode, "feature");
2370     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2371 
2372     RegDeleteValueA(compkey, prod_squashed);
2373     RegDeleteValueA(compkey2, prod_squashed);
2374     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2375     delete_key(compkey2, "", access & KEY_WOW64_64KEY);
2376     RegDeleteValueA(localkey, "feature");
2377     RegDeleteValueA(userkey, "feature");
2378     delete_key(userkey, "", access & KEY_WOW64_64KEY);
2379     RegCloseKey(compkey);
2380     RegCloseKey(compkey2);
2381     RegCloseKey(localkey);
2382     RegCloseKey(userkey);
2383 
2384     /* MSIINSTALLCONTEXT_MACHINE */
2385 
2386     lstrcpyA(keypath, "Software\\Classes\\Installer\\Features\\");
2387     lstrcatA(keypath, prod_squashed);
2388 
2389     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
2390     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2391 
2392     /* feature key exists */
2393     state = MsiQueryFeatureStateA(prodcode, "feature");
2394     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2395 
2396     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 1);
2397     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2398 
2399     /* feature value exists */
2400     state = MsiQueryFeatureStateA(prodcode, "feature");
2401     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2402 
2403     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2404     lstrcatA(keypath, "S-1-5-18\\Products\\");
2405     lstrcatA(keypath, prod_squashed);
2406     lstrcatA(keypath, "\\Features");
2407 
2408     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
2409     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2410 
2411     /* userdata features key exists */
2412     state = MsiQueryFeatureStateA(prodcode, "feature");
2413     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2414 
2415     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
2416     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2417 
2418     state = MsiQueryFeatureStateA(prodcode, "feature");
2419     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
2420 
2421     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
2422     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2423 
2424     state = MsiQueryFeatureStateA(prodcode, "feature");
2425     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2426 
2427     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
2428     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2429 
2430     state = MsiQueryFeatureStateA(prodcode, "feature");
2431     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2432 
2433     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
2434     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2435 
2436     state = MsiQueryFeatureStateA(prodcode, "feature");
2437     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2438 
2439     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2440     lstrcatA(keypath, "S-1-5-18\\Components\\");
2441     lstrcatA(keypath, comp_squashed);
2442 
2443     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2444     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2445 
2446     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2447     lstrcatA(keypath, "S-1-5-18\\Components\\");
2448     lstrcatA(keypath, comp_squashed2);
2449 
2450     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
2451     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2452 
2453     state = MsiQueryFeatureStateA(prodcode, "feature");
2454     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2455 
2456     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
2457     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2458 
2459     state = MsiQueryFeatureStateA(prodcode, "feature");
2460     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2461 
2462     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
2463     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2464 
2465     state = MsiQueryFeatureStateA(prodcode, "feature");
2466     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2467 
2468     res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
2469     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2470 
2471     state = MsiQueryFeatureStateA(prodcode, "feature");
2472     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2473 
2474     RegDeleteValueA(compkey, prod_squashed);
2475     RegDeleteValueA(compkey2, prod_squashed);
2476     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2477     delete_key(compkey2, "", access & KEY_WOW64_64KEY);
2478     RegDeleteValueA(localkey, "feature");
2479     RegDeleteValueA(userkey, "feature");
2480     delete_key(userkey, "", access & KEY_WOW64_64KEY);
2481     RegCloseKey(compkey);
2482     RegCloseKey(compkey2);
2483     RegCloseKey(localkey);
2484     RegCloseKey(userkey);
2485     LocalFree(usersid);
2486 }
2487 
2488 static void test_MsiQueryComponentState(void)
2489 {
2490     HKEY compkey, prodkey;
2491     CHAR prodcode[MAX_PATH];
2492     CHAR prod_squashed[MAX_PATH];
2493     CHAR component[MAX_PATH];
2494     CHAR comp_base85[MAX_PATH];
2495     CHAR comp_squashed[MAX_PATH];
2496     CHAR keypath[MAX_PATH];
2497     INSTALLSTATE state;
2498     LPSTR usersid;
2499     LONG res;
2500     UINT r;
2501     REGSAM access = KEY_ALL_ACCESS;
2502     DWORD error;
2503 
2504     static const INSTALLSTATE MAGIC_ERROR = 0xdeadbeef;
2505 
2506     if (!pMsiQueryComponentStateA)
2507     {
2508         win_skip("MsiQueryComponentStateA not implemented\n");
2509         return;
2510     }
2511 
2512     create_test_guid(prodcode, prod_squashed);
2513     compose_base85_guid(component, comp_base85, comp_squashed);
2514     usersid = get_user_sid();
2515 
2516     if (is_wow64)
2517         access |= KEY_WOW64_64KEY;
2518 
2519     /* NULL szProductCode */
2520     state = MAGIC_ERROR;
2521     SetLastError(0xdeadbeef);
2522     r = pMsiQueryComponentStateA(NULL, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2523     error = GetLastError();
2524     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2525     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2526     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2527 
2528     /* empty szProductCode */
2529     state = MAGIC_ERROR;
2530     SetLastError(0xdeadbeef);
2531     r = pMsiQueryComponentStateA("", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2532     error = GetLastError();
2533     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2534     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2535     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2536 
2537     /* random szProductCode */
2538     state = MAGIC_ERROR;
2539     SetLastError(0xdeadbeef);
2540     r = pMsiQueryComponentStateA("random", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2541     error = GetLastError();
2542     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2543     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2544     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2545 
2546     /* GUID-length szProductCode */
2547     state = MAGIC_ERROR;
2548     SetLastError(0xdeadbeef);
2549     r = pMsiQueryComponentStateA("DJANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KDE", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2550     error = GetLastError();
2551     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2552     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2553     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2554 
2555     /* GUID-length with brackets */
2556     state = MAGIC_ERROR;
2557     SetLastError(0xdeadbeef);
2558     r = pMsiQueryComponentStateA("{JANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KD}", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2559     error = GetLastError();
2560     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2561     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2562     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2563 
2564     /* actual GUID */
2565     state = MAGIC_ERROR;
2566     SetLastError(0xdeadbeef);
2567     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2568     error = GetLastError();
2569     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2570     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2571     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2572 
2573     state = MAGIC_ERROR;
2574     SetLastError(0xdeadbeef);
2575     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2576     error = GetLastError();
2577     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2578     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2579     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2580 
2581     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
2582     lstrcatA(keypath, prod_squashed);
2583 
2584     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2585     if (res == ERROR_ACCESS_DENIED)
2586     {
2587         skip("Not enough rights to perform tests\n");
2588         LocalFree(usersid);
2589         return;
2590     }
2591     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2592 
2593     state = MAGIC_ERROR;
2594     SetLastError(0xdeadbeef);
2595     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2596     error = GetLastError();
2597     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2598     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2599     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2600 
2601     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2602     RegCloseKey(prodkey);
2603 
2604     /* create local system product key */
2605     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\");
2606     lstrcatA(keypath, prod_squashed);
2607     lstrcatA(keypath, "\\InstallProperties");
2608 
2609     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2610     if (res == ERROR_ACCESS_DENIED)
2611     {
2612         skip("Not enough rights to perform tests\n");
2613         LocalFree(usersid);
2614         return;
2615     }
2616     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2617 
2618     /* local system product key exists */
2619     state = MAGIC_ERROR;
2620     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2621     error = GetLastError();
2622     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2623     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2624     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2625 
2626     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2627     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2628 
2629     /* LocalPackage value exists */
2630     state = MAGIC_ERROR;
2631     SetLastError(0xdeadbeef);
2632     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2633     error = GetLastError();
2634     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2635     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2636     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2637 
2638     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\");
2639     lstrcatA(keypath, comp_squashed);
2640 
2641     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2642     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2643 
2644     /* component key exists */
2645     state = MAGIC_ERROR;
2646     SetLastError(0xdeadbeef);
2647     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2648     error = GetLastError();
2649     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2650     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2651     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2652 
2653     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
2654     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2655 
2656     /* component\product exists */
2657     state = MAGIC_ERROR;
2658     SetLastError(0xdeadbeef);
2659     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2660     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2661     error = GetLastError();
2662     ok(state == INSTALLSTATE_NOTUSED || state == INSTALLSTATE_LOCAL,
2663        "Expected INSTALLSTATE_NOTUSED or INSTALLSTATE_LOCAL, got %d\n", state);
2664     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2665 
2666     /* NULL component, product exists */
2667     state = MAGIC_ERROR;
2668     SetLastError(0xdeadbeef);
2669     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, NULL, &state);
2670     error = GetLastError();
2671     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2672     ok(state == MAGIC_ERROR, "Expected state not changed, got %d\n", state);
2673     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2674 
2675     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
2676     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2677 
2678     /* INSTALLSTATE_LOCAL */
2679     state = MAGIC_ERROR;
2680     SetLastError(0xdeadbeef);
2681     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2682     error = GetLastError();
2683     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2684     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2685     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2686 
2687     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01\\", 4);
2688     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2689 
2690     /* INSTALLSTATE_SOURCE */
2691     state = MAGIC_ERROR;
2692     SetLastError(0xdeadbeef);
2693     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2694     error = GetLastError();
2695     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2696     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2697     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2698 
2699     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
2700     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2701 
2702     /* bad INSTALLSTATE_SOURCE */
2703     state = MAGIC_ERROR;
2704     SetLastError(0xdeadbeef);
2705     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2706     error = GetLastError();
2707     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2708     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2709     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2710 
2711     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01a", 4);
2712     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2713 
2714     /* INSTALLSTATE_SOURCE */
2715     state = MAGIC_ERROR;
2716     SetLastError(0xdeadbeef);
2717     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2718     error = GetLastError();
2719     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2720     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2721     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2722 
2723     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01:", 4);
2724     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2725 
2726     /* registry component */
2727     state = MAGIC_ERROR;
2728     SetLastError(0xdeadbeef);
2729     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2730     error = GetLastError();
2731     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2732     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2733     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2734 
2735     RegDeleteValueA(prodkey, "LocalPackage");
2736     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2737     RegDeleteValueA(compkey, prod_squashed);
2738     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2739     RegCloseKey(prodkey);
2740     RegCloseKey(compkey);
2741 
2742     /* MSIINSTALLCONTEXT_USERUNMANAGED */
2743 
2744     state = MAGIC_ERROR;
2745     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2746     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2747     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2748 
2749     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2750     lstrcatA(keypath, prod_squashed);
2751 
2752     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
2753     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2754 
2755     state = MAGIC_ERROR;
2756     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2757     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2758     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2759 
2760     RegDeleteKeyA(prodkey, "");
2761     RegCloseKey(prodkey);
2762 
2763     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2764     lstrcatA(keypath, usersid);
2765     lstrcatA(keypath, "\\Products\\");
2766     lstrcatA(keypath, prod_squashed);
2767     lstrcatA(keypath, "\\InstallProperties");
2768 
2769     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2770     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2771 
2772     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2773     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2774 
2775     RegCloseKey(prodkey);
2776 
2777     state = MAGIC_ERROR;
2778     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2779     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2780     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2781 
2782     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2783     lstrcatA(keypath, usersid);
2784     lstrcatA(keypath, "\\Components\\");
2785     lstrcatA(keypath, comp_squashed);
2786 
2787     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2788     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2789 
2790     /* component key exists */
2791     state = MAGIC_ERROR;
2792     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2793     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2794     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2795 
2796     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
2797     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2798 
2799     /* component\product exists */
2800     state = MAGIC_ERROR;
2801     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2802     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2803     ok(state == INSTALLSTATE_NOTUSED || state == INSTALLSTATE_LOCAL,
2804        "Expected INSTALLSTATE_NOTUSED or INSTALLSTATE_LOCAL, got %d\n", state);
2805 
2806     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
2807     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2808 
2809     state = MAGIC_ERROR;
2810     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2811     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2812     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2813 
2814     /* MSIINSTALLCONTEXT_USERMANAGED */
2815 
2816     state = MAGIC_ERROR;
2817     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2818     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2819     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2820 
2821     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2822     lstrcatA(keypath, prod_squashed);
2823 
2824     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
2825     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2826 
2827     state = MAGIC_ERROR;
2828     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2829     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2830     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2831 
2832     RegDeleteKeyA(prodkey, "");
2833     RegCloseKey(prodkey);
2834 
2835     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
2836     lstrcatA(keypath, usersid);
2837     lstrcatA(keypath, "\\Installer\\Products\\");
2838     lstrcatA(keypath, prod_squashed);
2839 
2840     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2841     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2842 
2843     state = MAGIC_ERROR;
2844     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2845     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2846     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2847 
2848     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2849     RegCloseKey(prodkey);
2850 
2851     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2852     lstrcatA(keypath, usersid);
2853     lstrcatA(keypath, "\\Products\\");
2854     lstrcatA(keypath, prod_squashed);
2855     lstrcatA(keypath, "\\InstallProperties");
2856 
2857     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2858     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2859 
2860     res = RegSetValueExA(prodkey, "ManagedLocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2861     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2862 
2863     state = MAGIC_ERROR;
2864     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2865     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2866     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2867 
2868     RegDeleteValueA(prodkey, "LocalPackage");
2869     RegDeleteValueA(prodkey, "ManagedLocalPackage");
2870     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2871     RegDeleteValueA(compkey, prod_squashed);
2872     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2873     RegCloseKey(prodkey);
2874     RegCloseKey(compkey);
2875     LocalFree(usersid);
2876 }
2877 
2878 static void test_MsiGetComponentPath(void)
2879 {
2880     HKEY compkey, prodkey, installprop;
2881     CHAR prodcode[MAX_PATH];
2882     CHAR prod_squashed[MAX_PATH];
2883     CHAR component[MAX_PATH];
2884     CHAR comp_base85[MAX_PATH];
2885     CHAR comp_squashed[MAX_PATH];
2886     CHAR keypath[MAX_PATH];
2887     CHAR path[MAX_PATH];
2888     INSTALLSTATE state;
2889     LPSTR usersid;
2890     DWORD size, val;
2891     REGSAM access = KEY_ALL_ACCESS;
2892     LONG res;
2893 
2894     create_test_guid(prodcode, prod_squashed);
2895     compose_base85_guid(component, comp_base85, comp_squashed);
2896     usersid = get_user_sid();
2897 
2898     if (is_wow64)
2899         access |= KEY_WOW64_64KEY;
2900 
2901     /* NULL szProduct */
2902     size = MAX_PATH;
2903     state = MsiGetComponentPathA(NULL, component, path, &size);
2904     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2905     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2906 
2907     /* NULL szComponent */
2908     size = MAX_PATH;
2909     state = MsiGetComponentPathA(prodcode, NULL, path, &size);
2910     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2911     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2912 
2913     size = MAX_PATH;
2914     state = MsiLocateComponentA(NULL, path, &size);
2915     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2916     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2917 
2918     /* NULL lpPathBuf */
2919     size = MAX_PATH;
2920     state = MsiGetComponentPathA(prodcode, component, NULL, &size);
2921     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2922     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2923 
2924     size = MAX_PATH;
2925     state = MsiLocateComponentA(component, NULL, &size);
2926     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2927     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2928 
2929     /* NULL pcchBuf */
2930     size = MAX_PATH;
2931     state = MsiGetComponentPathA(prodcode, component, path, NULL);
2932     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2933     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2934 
2935     size = MAX_PATH;
2936     state = MsiLocateComponentA(component, path, NULL);
2937     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2938     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2939 
2940     /* all params valid */
2941     size = MAX_PATH;
2942     state = MsiGetComponentPathA(prodcode, component, path, &size);
2943     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2944     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2945 
2946     size = MAX_PATH;
2947     state = MsiLocateComponentA(component, path, &size);
2948     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2949     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2950 
2951     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2952     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
2953     lstrcatA(keypath, comp_squashed);
2954 
2955     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2956     if (res == ERROR_ACCESS_DENIED)
2957     {
2958         skip("Not enough rights to perform tests\n");
2959         LocalFree(usersid);
2960         return;
2961     }
2962     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2963 
2964     /* local system component key exists */
2965     size = MAX_PATH;
2966     state = MsiGetComponentPathA(prodcode, component, path, &size);
2967     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2968     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2969 
2970     size = MAX_PATH;
2971     state = MsiLocateComponentA(component, path, &size);
2972     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2973     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
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     path[0] = 0;
2980     size = MAX_PATH;
2981     state = MsiGetComponentPathA(prodcode, component, path, &size);
2982     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2983     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2984     ok(size == 10, "Expected 10, got %d\n", size);
2985 
2986     path[0] = 0;
2987     size = MAX_PATH;
2988     state = MsiLocateComponentA(component, path, &size);
2989     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2990     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2991     ok(size == 10, "Expected 10, got %d\n", size);
2992 
2993     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2994     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
2995     lstrcatA(keypath, prod_squashed);
2996     lstrcatA(keypath, "\\InstallProperties");
2997 
2998     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &installprop, NULL);
2999     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3000 
3001     val = 1;
3002     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
3003     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3004 
3005     /* install properties key exists */
3006     path[0] = 0;
3007     size = MAX_PATH;
3008     state = MsiGetComponentPathA(prodcode, component, path, &size);
3009     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3010     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3011     ok(size == 10, "Expected 10, got %d\n", size);
3012 
3013     path[0] = 0;
3014     size = MAX_PATH;
3015     state = MsiLocateComponentA(component, path, &size);
3016     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3017     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3018     ok(size == 10, "Expected 10, got %d\n", size);
3019 
3020     create_file("C:\\imapath", "C:\\imapath", 11);
3021 
3022     /* file exists */
3023     path[0] = 'a';
3024     size = 0;
3025     state = MsiGetComponentPathA(prodcode, component, path, &size);
3026     ok(state == INSTALLSTATE_MOREDATA, "Expected INSTALLSTATE_MOREDATA, got %d\n", state);
3027     ok(path[0] == 'a', "got %s\n", path);
3028     ok(size == 10, "Expected 10, got %d\n", size);
3029 
3030     path[0] = 0;
3031     size = MAX_PATH;
3032     state = MsiGetComponentPathA(prodcode, component, path, &size);
3033     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3034     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3035     ok(size == 10, "Expected 10, got %d\n", size);
3036 
3037     size = 0;
3038     path[0] = 'a';
3039     state = MsiLocateComponentA(component, path, &size);
3040     ok(state == INSTALLSTATE_MOREDATA, "Expected INSTALLSTATE_MOREDATA, got %d\n", state);
3041     ok(path[0] == 'a', "got %s\n", path);
3042     ok(size == 10, "Expected 10, got %d\n", size);
3043 
3044     path[0] = 0;
3045     size = MAX_PATH;
3046     state = MsiLocateComponentA(component, path, &size);
3047     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3048     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3049     ok(size == 10, "Expected 10, got %d\n", size);
3050 
3051     RegDeleteValueA(compkey, prod_squashed);
3052     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3053     RegDeleteValueA(installprop, "WindowsInstaller");
3054     delete_key(installprop, "", access & KEY_WOW64_64KEY);
3055     RegCloseKey(compkey);
3056     RegCloseKey(installprop);
3057     DeleteFileA("C:\\imapath");
3058 
3059     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3060     lstrcatA(keypath, "Installer\\UserData\\");
3061     lstrcatA(keypath, usersid);
3062     lstrcatA(keypath, "\\Components\\");
3063     lstrcatA(keypath, comp_squashed);
3064 
3065     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3066     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3067 
3068     /* user managed component key exists */
3069     size = MAX_PATH;
3070     state = MsiGetComponentPathA(prodcode, component, path, &size);
3071     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3072     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3073 
3074     size = MAX_PATH;
3075     state = MsiLocateComponentA(component, path, &size);
3076     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3077     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3078 
3079     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3080     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3081 
3082     /* product value exists */
3083     path[0] = 0;
3084     size = MAX_PATH;
3085     state = MsiGetComponentPathA(prodcode, component, path, &size);
3086     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3087     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3088     ok(size == 10, "Expected 10, got %d\n", size);
3089 
3090     path[0] = 0;
3091     size = MAX_PATH;
3092     state = MsiLocateComponentA(component, path, &size);
3093     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3094     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3095     ok(size == 10, "Expected 10, got %d\n", size);
3096 
3097     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3098     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
3099     lstrcatA(keypath, prod_squashed);
3100     lstrcatA(keypath, "\\InstallProperties");
3101 
3102     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &installprop, NULL);
3103     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3104 
3105     val = 1;
3106     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
3107     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3108 
3109     /* install properties key exists */
3110     path[0] = 0;
3111     size = MAX_PATH;
3112     state = MsiGetComponentPathA(prodcode, component, path, &size);
3113     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3114     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3115     ok(size == 10, "Expected 10, got %d\n", size);
3116 
3117     path[0] = 0;
3118     size = MAX_PATH;
3119     state = MsiLocateComponentA(component, path, &size);
3120     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3121     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3122     ok(size == 10, "Expected 10, got %d\n", size);
3123 
3124     create_file("C:\\imapath", "C:\\imapath", 11);
3125 
3126     /* file exists */
3127     path[0] = 0;
3128     size = MAX_PATH;
3129     state = MsiGetComponentPathA(prodcode, component, path, &size);
3130     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3131     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3132     ok(size == 10, "Expected 10, got %d\n", size);
3133 
3134     path[0] = 0;
3135     size = MAX_PATH;
3136     state = MsiLocateComponentA(component, path, &size);
3137     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3138     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3139     ok(size == 10, "Expected 10, got %d\n", size);
3140 
3141     RegDeleteValueA(compkey, prod_squashed);
3142     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3143     RegDeleteValueA(installprop, "WindowsInstaller");
3144     delete_key(installprop, "", access & KEY_WOW64_64KEY);
3145     RegCloseKey(compkey);
3146     RegCloseKey(installprop);
3147     DeleteFileA("C:\\imapath");
3148 
3149     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3150     lstrcatA(keypath, "Installer\\Managed\\");
3151     lstrcatA(keypath, usersid);
3152     lstrcatA(keypath, "\\Installer\\Products\\");
3153     lstrcatA(keypath, prod_squashed);
3154 
3155     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3156     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3157 
3158     /* user managed product key exists */
3159     size = MAX_PATH;
3160     state = MsiGetComponentPathA(prodcode, component, path, &size);
3161     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3162     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3163 
3164     size = MAX_PATH;
3165     state = MsiLocateComponentA(component, path, &size);
3166     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3167     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3168 
3169     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3170     lstrcatA(keypath, "Installer\\UserData\\");
3171     lstrcatA(keypath, usersid);
3172     lstrcatA(keypath, "\\Components\\");
3173     lstrcatA(keypath, comp_squashed);
3174 
3175     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3176     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3177 
3178     /* user managed component key exists */
3179     size = MAX_PATH;
3180     state = MsiGetComponentPathA(prodcode, component, path, &size);
3181     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3182     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3183 
3184     size = MAX_PATH;
3185     state = MsiLocateComponentA(component, path, &size);
3186     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3187     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3188 
3189     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3190     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3191 
3192     /* product value exists */
3193     path[0] = 0;
3194     size = MAX_PATH;
3195     state = MsiGetComponentPathA(prodcode, component, path, &size);
3196     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3197     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3198     ok(size == 10, "Expected 10, got %d\n", size);
3199 
3200     path[0] = 0;
3201     size = MAX_PATH;
3202     state = MsiLocateComponentA(component, path, &size);
3203     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3204     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3205     ok(size == 10, "Expected 10, got %d\n", size);
3206 
3207     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3208     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
3209     lstrcatA(keypath, prod_squashed);
3210     lstrcatA(keypath, "\\InstallProperties");
3211 
3212     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &installprop, NULL);
3213     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3214 
3215     val = 1;
3216     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
3217     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3218 
3219     /* install properties key exists */
3220     path[0] = 0;
3221     size = MAX_PATH;
3222     state = MsiGetComponentPathA(prodcode, component, path, &size);
3223     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3224     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3225     ok(size == 10, "Expected 10, got %d\n", size);
3226 
3227     path[0] = 0;
3228     size = MAX_PATH;
3229     state = MsiLocateComponentA(component, path, &size);
3230     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3231     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3232     ok(size == 10, "Expected 10, got %d\n", size);
3233 
3234     create_file("C:\\imapath", "C:\\imapath", 11);
3235 
3236     /* file exists */
3237     path[0] = 0;
3238     size = MAX_PATH;
3239     state = MsiGetComponentPathA(prodcode, component, path, &size);
3240     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3241     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3242     ok(size == 10, "Expected 10, got %d\n", size);
3243 
3244     path[0] = 0;
3245     size = MAX_PATH;
3246     state = MsiLocateComponentA(component, path, &size);
3247     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3248     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3249     ok(size == 10, "Expected 10, got %d\n", size);
3250 
3251     RegDeleteValueA(compkey, prod_squashed);
3252     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3253     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3254     RegDeleteValueA(installprop, "WindowsInstaller");
3255     delete_key(installprop, "", access & KEY_WOW64_64KEY);
3256     RegCloseKey(prodkey);
3257     RegCloseKey(compkey);
3258     RegCloseKey(installprop);
3259     DeleteFileA("C:\\imapath");
3260 
3261     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
3262     lstrcatA(keypath, prod_squashed);
3263 
3264     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
3265     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3266 
3267     /* user unmanaged product key exists */
3268     size = MAX_PATH;
3269     state = MsiGetComponentPathA(prodcode, component, path, &size);
3270     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3271     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3272 
3273     size = MAX_PATH;
3274     state = MsiLocateComponentA(component, path, &size);
3275     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3276     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3277 
3278     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3279     lstrcatA(keypath, "Installer\\UserData\\");
3280     lstrcatA(keypath, usersid);
3281     lstrcatA(keypath, "\\Components\\");
3282     lstrcatA(keypath, comp_squashed);
3283 
3284     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3285     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3286 
3287     /* user unmanaged component key exists */
3288     size = MAX_PATH;
3289     state = MsiGetComponentPathA(prodcode, component, path, &size);
3290     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3291     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3292 
3293     size = MAX_PATH;
3294     state = MsiLocateComponentA(component, path, &size);
3295     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3296     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3297 
3298     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3299     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3300 
3301     /* product value exists */
3302     path[0] = 0;
3303     size = MAX_PATH;
3304     state = MsiGetComponentPathA(prodcode, component, path, &size);
3305     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3306     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3307     ok(size == 10, "Expected 10, got %d\n", size);
3308 
3309     path[0] = 0;
3310     size = MAX_PATH;
3311     state = MsiLocateComponentA(component, path, &size);
3312     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3313     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3314     ok(size == 10, "Expected 10, got %d\n", size);
3315 
3316     create_file("C:\\imapath", "C:\\imapath", 11);
3317 
3318     /* file exists */
3319     path[0] = 0;
3320     size = MAX_PATH;
3321     state = MsiGetComponentPathA(prodcode, component, path, &size);
3322     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3323     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3324     ok(size == 10, "Expected 10, got %d\n", size);
3325 
3326     path[0] = 0;
3327     size = MAX_PATH;
3328     state = MsiLocateComponentA(component, path, &size);
3329     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3330     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3331     ok(size == 10, "Expected 10, got %d\n", size);
3332 
3333     RegDeleteValueA(compkey, prod_squashed);
3334     RegDeleteKeyA(prodkey, "");
3335     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3336     RegCloseKey(prodkey);
3337     RegCloseKey(compkey);
3338     DeleteFileA("C:\\imapath");
3339 
3340     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
3341     lstrcatA(keypath, prod_squashed);
3342 
3343     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3344     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3345 
3346     /* local classes product key exists */
3347     size = MAX_PATH;
3348     state = MsiGetComponentPathA(prodcode, component, path, &size);
3349     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3350     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3351 
3352     size = MAX_PATH;
3353     state = MsiLocateComponentA(component, path, &size);
3354     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3355     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3356 
3357     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3358     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
3359     lstrcatA(keypath, comp_squashed);
3360 
3361     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3362     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3363 
3364     /* local user component key exists */
3365     size = MAX_PATH;
3366     state = MsiGetComponentPathA(prodcode, component, path, &size);
3367     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3368     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3369 
3370     size = MAX_PATH;
3371     state = MsiLocateComponentA(component, path, &size);
3372     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3373     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3374 
3375     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3376     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3377 
3378     /* product value exists */
3379     path[0] = 0;
3380     size = MAX_PATH;
3381     state = MsiGetComponentPathA(prodcode, component, path, &size);
3382     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3383     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3384     ok(size == 10, "Expected 10, got %d\n", size);
3385 
3386     path[0] = 0;
3387     size = MAX_PATH;
3388     state = MsiLocateComponentA(component, path, &size);
3389     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3390     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3391     ok(size == 10, "Expected 10, got %d\n", size);
3392 
3393     create_file("C:\\imapath", "C:\\imapath", 11);
3394 
3395     /* file exists */
3396     path[0] = 0;
3397     size = MAX_PATH;
3398     state = MsiGetComponentPathA(prodcode, component, path, &size);
3399     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3400     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3401     ok(size == 10, "Expected 10, got %d\n", size);
3402 
3403     path[0] = 0;
3404     size = MAX_PATH;
3405     state = MsiLocateComponentA(component, path, &size);
3406     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3407     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3408     ok(size == 10, "Expected 10, got %d\n", size);
3409 
3410     RegDeleteValueA(compkey, prod_squashed);
3411     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3412     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3413     RegCloseKey(prodkey);
3414     RegCloseKey(compkey);
3415     DeleteFileA("C:\\imapath");
3416     LocalFree(usersid);
3417 }
3418 
3419 static void test_MsiGetComponentPathEx(void)
3420 {
3421     HKEY key_comp, key_installprop, key_prod;
3422     char prod[MAX_PATH], prod_squashed[MAX_PATH];
3423     char comp[MAX_PATH], comp_base85[MAX_PATH], comp_squashed[MAX_PATH];
3424     char path[MAX_PATH], path_key[MAX_PATH], *usersid;
3425     INSTALLSTATE state;
3426     DWORD size, val;
3427     REGSAM access = KEY_ALL_ACCESS;
3428     LONG res;
3429 
3430     if (!pMsiGetComponentPathExA)
3431     {
3432         win_skip( "MsiGetComponentPathExA not present\n" );
3433         return;
3434     }
3435 
3436     if (is_wow64) access |= KEY_WOW64_64KEY;
3437 
3438     create_test_guid( prod, prod_squashed );
3439     compose_base85_guid( comp, comp_base85, comp_squashed );
3440     usersid = get_user_sid();
3441 
3442     /* NULL product */
3443     size = MAX_PATH;
3444     state = pMsiGetComponentPathExA( NULL, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3445     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
3446     todo_wine ok( !size, "got %u\n", size );
3447 
3448     /* NULL component */
3449     size = MAX_PATH;
3450     state = pMsiGetComponentPathExA( prod, NULL, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3451     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
3452     todo_wine ok( !size, "got %u\n", size );
3453 
3454     /* non-NULL usersid, MSIINSTALLCONTEXT_MACHINE */
3455     size = MAX_PATH;
3456     state = pMsiGetComponentPathExA( prod, comp, usersid, MSIINSTALLCONTEXT_MACHINE, path, &size);
3457     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
3458     todo_wine ok( !size, "got %u\n", size );
3459 
3460     /* NULL buf */
3461     size = MAX_PATH;
3462     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, NULL, &size );
3463     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3464     todo_wine ok( size == MAX_PATH * 2, "got %u\n", size );
3465 
3466     /* NULL buflen */
3467     size = MAX_PATH;
3468     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, NULL );
3469     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
3470     ok( size == MAX_PATH, "got %u\n", size );
3471 
3472     /* all params valid */
3473     size = MAX_PATH;
3474     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3475     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3476     todo_wine ok( !size, "got %u\n", size );
3477 
3478     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3479     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Components\\" );
3480     lstrcatA( path_key, comp_squashed );
3481 
3482     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3483     if (res == ERROR_ACCESS_DENIED)
3484     {
3485         skip( "insufficient rights\n" );
3486         LocalFree( usersid );
3487         return;
3488     }
3489     ok( res == ERROR_SUCCESS, "got %d\n", res );
3490 
3491     /* local system component key exists */
3492     size = MAX_PATH;
3493     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3494     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3495 
3496     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3497     ok( res == ERROR_SUCCESS, "got %d\n", res );
3498 
3499     /* product value exists */
3500     path[0] = 0;
3501     size = MAX_PATH;
3502     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3503     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3504     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3505     ok( size == 20, "got %u\n", size );
3506 
3507     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3508     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Products\\" );
3509     lstrcatA( path_key, prod_squashed );
3510     lstrcatA( path_key, "\\InstallProperties" );
3511 
3512     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_installprop, NULL );
3513     ok( res == ERROR_SUCCESS, "got %d\n", res );
3514 
3515     val = 1;
3516     res = RegSetValueExA( key_installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(val) );
3517     ok( res == ERROR_SUCCESS, "got %d\n", res );
3518 
3519     /* install properties key exists */
3520     path[0] = 0;
3521     size = MAX_PATH;
3522     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3523     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3524     ok( !lstrcmpA( path, "c:\\testcomponentpath"), "got %s\n", path );
3525     ok( size == 20, "got %u\n", size );
3526 
3527     create_file( "c:\\testcomponentpath", "c:\\testcomponentpath", 21 );
3528 
3529     /* file exists */
3530     path[0] = 0;
3531     size = 0;
3532     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3533     ok( state == INSTALLSTATE_MOREDATA, "got %d\n", state );
3534     ok( !path[0], "got %s\n", path );
3535     todo_wine ok( size == 40, "got %u\n", size );
3536 
3537     path[0] = 0;
3538     size = MAX_PATH;
3539     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3540     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3541     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3542     ok( size == 20, "got %d\n", size );
3543 
3544     RegDeleteValueA( key_comp, prod_squashed );
3545     delete_key( key_comp, "", access & KEY_WOW64_64KEY );
3546     RegDeleteValueA( key_installprop, "WindowsInstaller" );
3547     delete_key( key_installprop, "", access & KEY_WOW64_64KEY );
3548     RegCloseKey( key_comp );
3549     RegCloseKey( key_installprop );
3550     DeleteFileA( "c:\\testcomponentpath" );
3551 
3552     lstrcpyA( path_key, "Software\\Microsoft\\Installer\\Products\\" );
3553     lstrcatA( path_key, prod_squashed );
3554 
3555     res = RegCreateKeyA( HKEY_CURRENT_USER, path_key, &key_prod );
3556     ok( res == ERROR_SUCCESS, "got %d\n", res );
3557 
3558     /* user unmanaged product key exists */
3559     size = MAX_PATH;
3560     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3561     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3562     todo_wine ok(!size, "got %u\n", size);
3563 
3564     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3565     lstrcatA( path_key, "Installer\\UserData\\" );
3566     lstrcatA( path_key, usersid );
3567     lstrcatA( path_key, "\\Components\\" );
3568     lstrcatA( path_key, comp_squashed );
3569 
3570     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3571     ok( res == ERROR_SUCCESS, "got %d\n", res );
3572 
3573     /* user unmanaged component key exists */
3574     size = MAX_PATH;
3575     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3576     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3577     todo_wine ok(!size, "got %u\n", size);
3578 
3579     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3580     ok( res == ERROR_SUCCESS, "got %d\n", res );
3581 
3582     /* product value exists */
3583     path[0] = 0;
3584     size = MAX_PATH;
3585     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3586     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3587     ok( !lstrcmpA( path, "c:\\testcomponentpath"), "got %s\n", path );
3588     ok( size == 20, "got %u\n", size );
3589 
3590     create_file( "c:\\testcomponentpath", "c:\\testcomponentpath", 21 );
3591 
3592     /* file exists */
3593     path[0] = 0;
3594     size = MAX_PATH;
3595     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3596     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3597     ok( !lstrcmpA( path, "c:\\testcomponentpath"), "got %s\n", path );
3598     ok( size == 20, "got %u\n", size );
3599 
3600     RegDeleteValueA( key_comp, prod_squashed );
3601     RegDeleteKeyA( key_prod, "" );
3602     delete_key( key_comp, "", access & KEY_WOW64_64KEY );
3603     RegCloseKey( key_prod );
3604     RegCloseKey( key_comp );
3605     DeleteFileA( "c:\\testcomponentpath" );
3606 
3607     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3608     lstrcatA( path_key, "Installer\\Managed\\" );
3609     lstrcatA( path_key, usersid );
3610     lstrcatA( path_key, "\\Installer\\Products\\" );
3611     lstrcatA( path_key, prod_squashed );
3612 
3613     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_prod, NULL );
3614     ok( res == ERROR_SUCCESS, "got %d\n", res );
3615 
3616     /* user managed product key exists */
3617     size = MAX_PATH;
3618     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3619     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3620 
3621     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3622     lstrcatA( path_key, "Installer\\UserData\\" );
3623     lstrcatA( path_key, usersid );
3624     lstrcatA( path_key, "\\Components\\" );
3625     lstrcatA( path_key, comp_squashed );
3626 
3627     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3628     ok( res == ERROR_SUCCESS, "got %d\n", res );
3629 
3630     /* user managed component key exists */
3631     size = MAX_PATH;
3632     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3633     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3634 
3635     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3636     ok( res == ERROR_SUCCESS, "got %d\n", res );
3637 
3638     /* product value exists */
3639     path[0] = 0;
3640     size = MAX_PATH;
3641     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3642     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3643     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3644     ok( size == 20, "got %u\n", size );
3645 
3646     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3647     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Products\\" );
3648     lstrcatA( path_key, prod_squashed );
3649     lstrcatA( path_key, "\\InstallProperties" );
3650 
3651     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_installprop, NULL );
3652     ok( res == ERROR_SUCCESS, "got %d\n", res );
3653 
3654     val = 1;
3655     res = RegSetValueExA( key_installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(val) );
3656     ok( res == ERROR_SUCCESS, "got %d\n", res );
3657 
3658     /* install properties key exists */
3659     path[0] = 0;
3660     size = MAX_PATH;
3661     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3662     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3663     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3664     ok( size == 20, "got %u\n", size );
3665 
3666     create_file( "c:\\testcomponentpath", "C:\\testcomponentpath", 21 );
3667 
3668     /* file exists */
3669     path[0] = 0;
3670     size = MAX_PATH;
3671     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3672     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3673     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3674     ok( size == 20, "got %u\n", size );
3675 
3676     RegDeleteValueA( key_comp, prod_squashed );
3677     delete_key( key_prod, "", access & KEY_WOW64_64KEY );
3678     delete_key( key_comp, "", access & KEY_WOW64_64KEY );
3679     RegDeleteValueA( key_installprop, "WindowsInstaller" );
3680     delete_key( key_installprop, "", access & KEY_WOW64_64KEY );
3681     RegCloseKey( key_prod );
3682     RegCloseKey( key_comp );
3683     RegCloseKey( key_installprop );
3684     DeleteFileA( "c:\\testcomponentpath" );
3685     lstrcpyA( path_key, "Software\\Classes\\Installer\\Products\\" );
3686     lstrcatA( path_key, prod_squashed );
3687 
3688     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_prod, NULL );
3689     ok( res == ERROR_SUCCESS, "got %d\n", res );
3690 
3691     /* local classes product key exists */
3692     size = MAX_PATH;
3693     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3694     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3695     todo_wine ok(!size, "got %u\n", size);
3696 
3697     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3698     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Components\\" );
3699     lstrcatA( path_key, comp_squashed );
3700 
3701     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE,  path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3702     ok( res == ERROR_SUCCESS, "got %d\n", res );
3703 
3704     /* local user component key exists */
3705     size = MAX_PATH;
3706     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3707     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3708     todo_wine ok(!size, "got %u\n", size);
3709 
3710     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3711     ok( res == ERROR_SUCCESS, "got %d\n", res );
3712 
3713     /* product value exists */
3714     path[0] = 0;
3715     size = MAX_PATH;
3716     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3717     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3718     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3719     ok( size == 20, "got %u\n", size );
3720 
3721     create_file( "c:\\testcomponentpath", "c:\\testcomponentpath", 21 );
3722 
3723     /* file exists */
3724     path[0] = 0;
3725     size = MAX_PATH;
3726     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3727     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3728     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3729     ok( size == 20, "got %u\n", size );
3730 
3731     RegDeleteValueA( key_comp, prod_squashed );
3732     delete_key( key_prod, "", access & KEY_WOW64_64KEY );
3733     delete_key( key_comp, "", access & KEY_WOW64_64KEY );
3734     RegCloseKey( key_prod );
3735     RegCloseKey( key_comp );
3736     DeleteFileA( "c:\\testcomponentpath" );
3737     LocalFree( usersid );
3738 }
3739 
3740 static void test_MsiProvideComponent(void)
3741 {
3742     static const WCHAR sourcedirW[] =
3743         {'s','o','u','r','c','e','d','i','r',0};
3744     static const WCHAR productW[] =
3745         {'{','3','8','8','4','7','3','3','8','-','1','B','B','C','-','4','1','0','4','-',
3746          '8','1','A','C','-','2','F','A','A','C','7','E','C','D','D','C','D','}',0};
3747     static const WCHAR componentW[] =
3748         {'{','D','D','4','2','2','F','9','2','-','3','E','D','8','-','4','9','B','5','-',
3749          'A','0','B','7','-','F','2','6','6','F','9','8','3','5','7','D','F','}',0};
3750     INSTALLSTATE state;
3751     char buf[0x100];
3752     WCHAR bufW[0x100];
3753     DWORD len, len2;
3754     UINT r;
3755 
3756     if (is_process_limited())
3757     {
3758         skip("process is limited\n");
3759         return;
3760     }
3761 
3762     create_test_files();
3763     create_file("msitest\\sourcedir.txt", "msitest\\sourcedir.txt", 1000);
3764     create_database(msifile, sd_tables, sizeof(sd_tables) / sizeof(msi_table));
3765 
3766     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3767 
3768     buf[0] = 0;
3769     len = sizeof(buf);
3770     r = pMsiProvideComponentA("{90120000-0070-0000-0000-4000000FF1CE}",
3771                               "{17961602-C4E2-482E-800A-DF6E627549CF}",
3772                               "ProductFiles", INSTALLMODE_NODETECTION, buf, &len);
3773     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
3774 
3775     r = MsiInstallProductA(msifile, NULL);
3776     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3777 
3778     state = MsiQueryFeatureStateA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir");
3779     ok(state == INSTALLSTATE_LOCAL, "got %d\n", state);
3780 
3781     buf[0] = 0;
3782     len = sizeof(buf);
3783     r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir",
3784                               "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
3785                               INSTALLMODE_NODETECTION, buf, &len);
3786     ok(r == ERROR_SUCCESS, "got %u\n", r);
3787     ok(buf[0], "empty path\n");
3788     ok(len == lstrlenA(buf), "got %u\n", len);
3789 
3790     len2 = 0;
3791     r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir",
3792                               "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
3793                               INSTALLMODE_NODETECTION, NULL, &len2);
3794     ok(r == ERROR_SUCCESS, "got %u\n", r);
3795     ok(len2 == len, "got %u\n", len2);
3796 
3797     len2 = 0;
3798     r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir",
3799                               "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
3800                               INSTALLMODE_NODETECTION, buf, &len2);
3801     ok(r == ERROR_MORE_DATA, "got %u\n", r);
3802     ok(len2 == len, "got %u\n", len2);
3803 
3804     /* wide version */
3805 
3806     bufW[0] = 0;
3807     len = sizeof(buf);
3808     r = pMsiProvideComponentW(productW, sourcedirW, componentW,
3809                               INSTALLMODE_NODETECTION, bufW, &len);
3810     ok(r == ERROR_SUCCESS, "got %u\n", r);
3811     ok(bufW[0], "empty path\n");
3812     ok(len == lstrlenW(bufW), "got %u\n", len);
3813 
3814     len2 = 0;
3815     r = pMsiProvideComponentW(productW, sourcedirW, componentW,
3816                               INSTALLMODE_NODETECTION, NULL, &len2);
3817     ok(r == ERROR_SUCCESS, "got %u\n", r);
3818     ok(len2 == len, "got %u\n", len2);
3819 
3820     len2 = 0;
3821     r = pMsiProvideComponentW(productW, sourcedirW, componentW,
3822                               INSTALLMODE_NODETECTION, bufW, &len2);
3823     ok(r == ERROR_MORE_DATA, "got %u\n", r);
3824     ok(len2 == len, "got %u\n", len2);
3825 
3826     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3827     ok(r == ERROR_SUCCESS, "got %u\n", r);
3828 
3829     DeleteFileA("msitest\\sourcedir.txt");
3830     delete_test_files();
3831     DeleteFileA(msifile);
3832 }
3833 
3834 static void test_MsiProvideQualifiedComponentEx(void)
3835 {
3836     UINT r;
3837     INSTALLSTATE state;
3838     char comp[39], comp_squashed[33], comp2[39], comp2_base85[21], comp2_squashed[33];
3839     char prod[39], prod_base85[21], prod_squashed[33];
3840     char desc[MAX_PATH], buf[MAX_PATH], keypath[MAX_PATH], path[MAX_PATH];
3841     DWORD len = sizeof(buf);
3842     REGSAM access = KEY_ALL_ACCESS;
3843     HKEY hkey, hkey2, hkey3, hkey4, hkey5;
3844     LONG res;
3845 
3846     if (is_process_limited())
3847     {
3848         skip( "process is limited\n" );
3849         return;
3850     }
3851 
3852     create_test_guid( comp, comp_squashed );
3853     compose_base85_guid( comp2, comp2_base85, comp2_squashed );
3854     compose_base85_guid( prod, prod_base85, prod_squashed );
3855 
3856     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3857     ok( r == ERROR_UNKNOWN_COMPONENT, "got %u\n", r );
3858 
3859     lstrcpyA( keypath, "Software\\Classes\\Installer\\Components\\" );
3860     lstrcatA( keypath, comp_squashed );
3861 
3862     if (is_wow64) access |= KEY_WOW64_64KEY;
3863     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey, NULL );
3864     ok( res == ERROR_SUCCESS, "got %d\n", res );
3865 
3866     lstrcpyA( desc, prod_base85 );
3867     memcpy( desc + lstrlenA(desc), "feature<\0", sizeof("feature<\0") );
3868     res = RegSetValueExA( hkey, "qualifier", 0, REG_MULTI_SZ, (const BYTE *)desc,
3869                           lstrlenA(prod_base85) + sizeof("feature<\0") );
3870     ok( res == ERROR_SUCCESS, "got %d\n", res );
3871 
3872     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3873     ok( r == ERROR_UNKNOWN_PRODUCT, "got %u\n", r );
3874 
3875     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, NULL, 0, 0, buf, &len );
3876     ok( r == ERROR_UNKNOWN_PRODUCT, "got %u\n", r );
3877 
3878     state = MsiQueryProductStateA( prod );
3879     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3880 
3881     lstrcpyA( keypath, "Software\\Classes\\Installer\\Products\\" );
3882     lstrcatA( keypath, prod_squashed );
3883 
3884     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey2, NULL );
3885     ok( res == ERROR_SUCCESS, "got %d\n", res );
3886 
3887     state = MsiQueryProductStateA( prod );
3888     ok( state == INSTALLSTATE_ADVERTISED, "got %d\n", state );
3889 
3890     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3891     todo_wine ok( r == ERROR_UNKNOWN_FEATURE, "got %u\n", r );
3892 
3893     lstrcpyA( keypath, "Software\\Classes\\Installer\\Features\\" );
3894     lstrcatA( keypath, prod_squashed );
3895 
3896     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey3, NULL );
3897     ok( res == ERROR_SUCCESS, "got %d\n", res );
3898 
3899     state = MsiQueryFeatureStateA( prod, "feature" );
3900     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3901 
3902     res = RegSetValueExA( hkey3, "feature", 0, REG_SZ, (const BYTE *)"", 1 );
3903     ok( res == ERROR_SUCCESS, "got %d\n", res );
3904 
3905     state = MsiQueryFeatureStateA( prod, "feature" );
3906     ok( state == INSTALLSTATE_ADVERTISED, "got %d\n", state );
3907 
3908     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3909     ok( r == ERROR_FILE_NOT_FOUND, "got %u\n", r );
3910 
3911     len = sizeof(buf);
3912     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, NULL, 0, 0, buf, &len );
3913     ok( r == ERROR_FILE_NOT_FOUND, "got %u\n", r );
3914 
3915     lstrcpyA( keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\" );
3916     lstrcatA( keypath, prod_squashed );
3917     lstrcatA( keypath, "\\Features" );
3918 
3919     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey4, NULL );
3920     ok( res == ERROR_SUCCESS, "got %d\n", res );
3921 
3922     res = RegSetValueExA( hkey4, "feature", 0, REG_SZ, (const BYTE *)comp2_base85, sizeof(comp2_base85) );
3923     ok( res == ERROR_SUCCESS, "got %d\n", res );
3924 
3925     state = MsiQueryFeatureStateA( prod, "feature" );
3926     ok( state == INSTALLSTATE_ADVERTISED, "got %d\n", state );
3927 
3928     lstrcpyA( keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\" );
3929     lstrcatA( keypath, comp2_squashed );
3930 
3931     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey5, NULL );
3932     ok( res == ERROR_SUCCESS, "got %d\n", res );
3933 
3934     res = RegSetValueExA( hkey5, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\nosuchfile", sizeof("c:\\nosuchfile") );
3935     ok( res == ERROR_SUCCESS, "got %d\n", res );
3936 
3937     state = MsiQueryFeatureStateA( prod, "feature" );
3938     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3939 
3940     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3941     ok( r == ERROR_FILE_NOT_FOUND, "got %u\n", r );
3942 
3943     GetCurrentDirectoryA( MAX_PATH, path );
3944     lstrcatA( path, "\\msitest" );
3945     CreateDirectoryA( path, NULL );
3946     lstrcatA( path, "\\test.txt" );
3947     create_file( path, "test", 100 );
3948 
3949     res = RegSetValueExA( hkey5, prod_squashed, 0, REG_SZ, (const BYTE *)path, lstrlenA(path) + 1 );
3950     ok( res == ERROR_SUCCESS, "got %d\n", res );
3951 
3952     buf[0] = 0;
3953     len = sizeof(buf);
3954     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3955     ok( r == ERROR_SUCCESS, "got %u\n", r );
3956     ok( len == lstrlenA(path), "got %u\n", len );
3957     ok( !lstrcmpA( path, buf ), "got '%s'\n", buf );
3958 
3959     DeleteFileA( "msitest\\text.txt" );
3960     RemoveDirectoryA( "msitest" );
3961 
3962     delete_key( hkey5, "", access & KEY_WOW64_64KEY );
3963     RegCloseKey( hkey5 );
3964     delete_key( hkey4, "", access & KEY_WOW64_64KEY );
3965     RegCloseKey( hkey4 );
3966     delete_key( hkey3, "", access & KEY_WOW64_64KEY );
3967     RegCloseKey( hkey3 );
3968     delete_key( hkey2, "", access & KEY_WOW64_64KEY );
3969     RegCloseKey( hkey2 );
3970     delete_key( hkey, "", access & KEY_WOW64_64KEY );
3971     RegCloseKey( hkey );
3972 }
3973 
3974 static void test_MsiGetProductCode(void)
3975 {
3976     HKEY compkey, prodkey;
3977     CHAR prodcode[MAX_PATH];
3978     CHAR prod_squashed[MAX_PATH];
3979     CHAR prodcode2[MAX_PATH];
3980     CHAR prod2_squashed[MAX_PATH];
3981     CHAR component[MAX_PATH];
3982     CHAR comp_base85[MAX_PATH];
3983     CHAR comp_squashed[MAX_PATH];
3984     CHAR keypath[MAX_PATH];
3985     CHAR product[MAX_PATH];
3986     LPSTR usersid;
3987     LONG res;
3988     UINT r;
3989     REGSAM access = KEY_ALL_ACCESS;
3990 
3991     create_test_guid(prodcode, prod_squashed);
3992     create_test_guid(prodcode2, prod2_squashed);
3993     compose_base85_guid(component, comp_base85, comp_squashed);
3994     usersid = get_user_sid();
3995 
3996     if (is_wow64)
3997         access |= KEY_WOW64_64KEY;
3998 
3999     /* szComponent is NULL */
4000     lstrcpyA(product, "prod");
4001     r = MsiGetProductCodeA(NULL, product);
4002     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4003     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4004 
4005     /* szComponent is empty */
4006     lstrcpyA(product, "prod");
4007     r = MsiGetProductCodeA("", product);
4008     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4009     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4010 
4011     /* garbage szComponent */
4012     lstrcpyA(product, "prod");
4013     r = MsiGetProductCodeA("garbage", product);
4014     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4015     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4016 
4017     /* guid without brackets */
4018     lstrcpyA(product, "prod");
4019     r = MsiGetProductCodeA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", product);
4020     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4021     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4022 
4023     /* guid with brackets */
4024     lstrcpyA(product, "prod");
4025     r = MsiGetProductCodeA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", product);
4026     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
4027     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4028 
4029     /* same length as guid, but random */
4030     lstrcpyA(product, "prod");
4031     r = MsiGetProductCodeA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", product);
4032     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4033     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4034 
4035     /* all params correct, szComponent not published */
4036     lstrcpyA(product, "prod");
4037     r = MsiGetProductCodeA(component, product);
4038     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
4039     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4040 
4041     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4042     lstrcatA(keypath, "Installer\\UserData\\");
4043     lstrcatA(keypath, usersid);
4044     lstrcatA(keypath, "\\Components\\");
4045     lstrcatA(keypath, comp_squashed);
4046 
4047     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
4048     if (res == ERROR_ACCESS_DENIED)
4049     {
4050         skip("Not enough rights to perform tests\n");
4051         LocalFree(usersid);
4052         return;
4053     }
4054     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4055 
4056     /* user unmanaged component key exists */
4057     lstrcpyA(product, "prod");
4058     r = MsiGetProductCodeA(component, product);
4059     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
4060     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4061 
4062     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
4063     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4064 
4065     /* product value exists */
4066     lstrcpyA(product, "prod");
4067     r = MsiGetProductCodeA(component, product);
4068     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4069     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4070 
4071     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
4072     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4073 
4074     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4075     lstrcatA(keypath, "Installer\\Managed\\");
4076     lstrcatA(keypath, usersid);
4077     lstrcatA(keypath, "\\Installer\\Products\\");
4078     lstrcatA(keypath, prod_squashed);
4079 
4080     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4081     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4082 
4083     /* user managed product key of first product exists */
4084     lstrcpyA(product, "prod");
4085     r = MsiGetProductCodeA(component, product);
4086     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4087     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4088 
4089     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4090     RegCloseKey(prodkey);
4091 
4092     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
4093     lstrcatA(keypath, prod_squashed);
4094 
4095     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
4096     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4097 
4098     /* user unmanaged product key exists */
4099     lstrcpyA(product, "prod");
4100     r = MsiGetProductCodeA(component, product);
4101     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4102     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4103 
4104     RegDeleteKeyA(prodkey, "");
4105     RegCloseKey(prodkey);
4106 
4107     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
4108     lstrcatA(keypath, prod_squashed);
4109 
4110     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4111     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4112 
4113     /* local classes product key exists */
4114     lstrcpyA(product, "prod");
4115     r = MsiGetProductCodeA(component, product);
4116     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4117     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4118 
4119     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4120     RegCloseKey(prodkey);
4121 
4122     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4123     lstrcatA(keypath, "Installer\\Managed\\");
4124     lstrcatA(keypath, usersid);
4125     lstrcatA(keypath, "\\Installer\\Products\\");
4126     lstrcatA(keypath, prod2_squashed);
4127 
4128     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4129     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4130 
4131     /* user managed product key of second product exists */
4132     lstrcpyA(product, "prod");
4133     r = MsiGetProductCodeA(component, product);
4134     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4135     ok(!lstrcmpA(product, prodcode2), "Expected %s, got %s\n", prodcode2, product);
4136 
4137     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4138     RegCloseKey(prodkey);
4139     RegDeleteValueA(compkey, prod_squashed);
4140     RegDeleteValueA(compkey, prod2_squashed);
4141     delete_key(compkey, "", access & KEY_WOW64_64KEY);
4142     RegCloseKey(compkey);
4143 
4144     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4145     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
4146     lstrcatA(keypath, comp_squashed);
4147 
4148     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
4149     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4150 
4151     /* local user component key exists */
4152     lstrcpyA(product, "prod");
4153     r = MsiGetProductCodeA(component, product);
4154     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
4155     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4156 
4157     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
4158     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4159 
4160     /* product value exists */
4161     lstrcpyA(product, "prod");
4162     r = MsiGetProductCodeA(component, product);
4163     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4164     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4165 
4166     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
4167     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4168 
4169     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4170     lstrcatA(keypath, "Installer\\Managed\\");
4171     lstrcatA(keypath, usersid);
4172     lstrcatA(keypath, "\\Installer\\Products\\");
4173     lstrcatA(keypath, prod_squashed);
4174 
4175     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4176     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4177 
4178     /* user managed product key of first product exists */
4179     lstrcpyA(product, "prod");
4180     r = MsiGetProductCodeA(component, product);
4181     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4182     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4183 
4184     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4185     RegCloseKey(prodkey);
4186 
4187     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
4188     lstrcatA(keypath, prod_squashed);
4189 
4190     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
4191     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4192 
4193     /* user unmanaged product key exists */
4194     lstrcpyA(product, "prod");
4195     r = MsiGetProductCodeA(component, product);
4196     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4197     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4198 
4199     RegDeleteKeyA(prodkey, "");
4200     RegCloseKey(prodkey);
4201 
4202     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
4203     lstrcatA(keypath, prod_squashed);
4204 
4205     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4206     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4207 
4208     /* local classes product key exists */
4209     lstrcpyA(product, "prod");
4210     r = MsiGetProductCodeA(component, product);
4211     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4212     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4213 
4214     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4215     RegCloseKey(prodkey);
4216 
4217     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4218     lstrcatA(keypath, "Installer\\Managed\\");
4219     lstrcatA(keypath, usersid);
4220     lstrcatA(keypath, "\\Installer\\Products\\");
4221     lstrcatA(keypath, prod2_squashed);
4222 
4223     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4224     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4225 
4226     /* user managed product key of second product exists */
4227     lstrcpyA(product, "prod");
4228     r = MsiGetProductCodeA(component, product);
4229     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4230     ok(!lstrcmpA(product, prodcode2), "Expected %s, got %s\n", prodcode2, product);
4231 
4232     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4233     RegCloseKey(prodkey);
4234     RegDeleteValueA(compkey, prod_squashed);
4235     RegDeleteValueA(compkey, prod2_squashed);
4236     delete_key(compkey, "", access & KEY_WOW64_64KEY);
4237     RegCloseKey(compkey);
4238     LocalFree(usersid);
4239 }
4240 
4241 static void test_MsiEnumClients(void)
4242 {
4243     HKEY compkey;
4244     CHAR prodcode[MAX_PATH];
4245     CHAR prod_squashed[MAX_PATH];
4246     CHAR prodcode2[MAX_PATH];
4247     CHAR prod2_squashed[MAX_PATH];
4248     CHAR component[MAX_PATH];
4249     CHAR comp_base85[MAX_PATH];
4250     CHAR comp_squashed[MAX_PATH];
4251     CHAR product[MAX_PATH];
4252     CHAR keypath[MAX_PATH];
4253     LPSTR usersid;
4254     LONG res;
4255     UINT r;
4256     REGSAM access = KEY_ALL_ACCESS;
4257 
4258     create_test_guid(prodcode, prod_squashed);
4259     create_test_guid(prodcode2, prod2_squashed);
4260     compose_base85_guid(component, comp_base85, comp_squashed);
4261     usersid = get_user_sid();
4262 
4263     if (is_wow64)
4264         access |= KEY_WOW64_64KEY;
4265 
4266     /* NULL szComponent */
4267     product[0] = '\0';
4268     r = MsiEnumClientsA(NULL, 0, product);
4269     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4270     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4271 
4272     /* empty szComponent */
4273     product[0] = '\0';
4274     r = MsiEnumClientsA("", 0, product);
4275     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4276     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4277 
4278     /* NULL lpProductBuf */
4279     r = MsiEnumClientsA(component, 0, NULL);
4280     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4281 
4282     /* all params correct, component missing */
4283     product[0] = '\0';
4284     r = MsiEnumClientsA(component, 0, product);
4285     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
4286     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4287 
4288     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4289     lstrcatA(keypath, "Installer\\UserData\\");
4290     lstrcatA(keypath, usersid);
4291     lstrcatA(keypath, "\\Components\\");
4292     lstrcatA(keypath, comp_squashed);
4293 
4294     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
4295     if (res == ERROR_ACCESS_DENIED)
4296     {
4297         skip("Not enough rights to perform tests\n");
4298         LocalFree(usersid);
4299         return;
4300     }
4301     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4302 
4303     /* user unmanaged component key exists */
4304     product[0] = '\0';
4305     r = MsiEnumClientsA(component, 0, product);
4306     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
4307     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4308 
4309     /* index > 0, no products exist */
4310     product[0] = '\0';
4311     r = MsiEnumClientsA(component, 1, product);
4312     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4313     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4314 
4315     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
4316     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4317 
4318     /* product value exists */
4319     r = MsiEnumClientsA(component, 0, product);
4320     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4321     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4322 
4323     /* try index 0 again */
4324     product[0] = '\0';
4325     r = MsiEnumClientsA(component, 0, product);
4326     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4327     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4328 
4329     /* try index 1, second product value does not exist */
4330     product[0] = '\0';
4331     r = MsiEnumClientsA(component, 1, product);
4332     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4333     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4334 
4335     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
4336     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4337 
4338     /* try index 1, second product value does exist */
4339     product[0] = '\0';
4340     r = MsiEnumClientsA(component, 1, product);
4341     todo_wine
4342     {
4343         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4344         ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4345     }
4346 
4347     /* start the enumeration over */
4348     product[0] = '\0';
4349     r = MsiEnumClientsA(component, 0, product);
4350     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4351     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
4352        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
4353 
4354     /* correctly query second product */
4355     product[0] = '\0';
4356     r = MsiEnumClientsA(component, 1, product);
4357     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4358     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
4359        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
4360 
4361     RegDeleteValueA(compkey, prod_squashed);
4362     RegDeleteValueA(compkey, prod2_squashed);
4363     delete_key(compkey, "", access & KEY_WOW64_64KEY);
4364     RegCloseKey(compkey);
4365 
4366     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4367     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
4368     lstrcatA(keypath, comp_squashed);
4369 
4370     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
4371     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4372 
4373     /* user local component key exists */
4374     product[0] = '\0';
4375     r = MsiEnumClientsA(component, 0, product);
4376     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
4377     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4378 
4379     /* index > 0, no products exist */
4380     product[0] = '\0';
4381     r = MsiEnumClientsA(component, 1, product);
4382     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4383     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4384 
4385     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
4386     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4387 
4388     /* product value exists */
4389     product[0] = '\0';
4390     r = MsiEnumClientsA(component, 0, product);
4391     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4392     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4393 
4394     /* try index 0 again */
4395     product[0] = '\0';
4396     r = MsiEnumClientsA(component, 0, product);
4397     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4398 
4399     /* try index 1, second product value does not exist */
4400     product[0] = '\0';
4401     r = MsiEnumClientsA(component, 1, product);
4402     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4403     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4404 
4405     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
4406     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4407 
4408     /* try index 1, second product value does exist */
4409     product[0] = '\0';
4410     r = MsiEnumClientsA(component, 1, product);
4411     todo_wine
4412     {
4413         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4414         ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4415     }
4416 
4417     /* start the enumeration over */
4418     product[0] = '\0';
4419     r = MsiEnumClientsA(component, 0, product);
4420     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4421     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
4422        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
4423 
4424     /* correctly query second product */
4425     product[0] = '\0';
4426     r = MsiEnumClientsA(component, 1, product);
4427     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4428     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
4429        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
4430 
4431     RegDeleteValueA(compkey, prod_squashed);
4432     RegDeleteValueA(compkey, prod2_squashed);
4433     delete_key(compkey, "", access & KEY_WOW64_64KEY);
4434     RegCloseKey(compkey);
4435     LocalFree(usersid);
4436 }
4437 
4438 static void get_version_info(LPSTR path, LPSTR *vercheck, LPDWORD verchecksz,
4439                              LPSTR *langcheck, LPDWORD langchecksz)
4440 {
4441     LPSTR version;
4442     VS_FIXEDFILEINFO *ffi;
4443     DWORD size = GetFileVersionInfoSizeA(path, NULL);
4444     USHORT *lang;
4445 
4446     version = HeapAlloc(GetProcessHeap(), 0, size);
4447     GetFileVersionInfoA(path, 0, size, version);
4448 
4449     VerQueryValueA(version, "\\", (LPVOID *)&ffi, &size);
4450     *vercheck = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
4451     sprintf(*vercheck, "%d.%d.%d.%d", HIWORD(ffi->dwFileVersionMS),
4452             LOWORD(ffi->dwFileVersionMS), HIWORD(ffi->dwFileVersionLS),
4453             LOWORD(ffi->dwFileVersionLS));
4454     *verchecksz = lstrlenA(*vercheck);
4455 
4456     VerQueryValueA(version, "\\VarFileInfo\\Translation", (void **)&lang, &size);
4457     *langcheck = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
4458     sprintf(*langcheck, "%d", *lang);
4459     *langchecksz = lstrlenA(*langcheck);
4460 
4461     HeapFree(GetProcessHeap(), 0, version);
4462 }
4463 
4464 static void test_MsiGetFileVersion(void)
4465 {
4466     UINT r;
4467     DWORD versz, langsz;
4468     char version[MAX_PATH];
4469     char lang[MAX_PATH];
4470     char path[MAX_PATH];
4471     LPSTR vercheck, langcheck;
4472     DWORD verchecksz, langchecksz;
4473 
4474     /* NULL szFilePath */
4475     r = MsiGetFileVersionA(NULL, NULL, NULL, NULL, NULL);
4476     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4477 
4478     versz = MAX_PATH;
4479     langsz = MAX_PATH;
4480     lstrcpyA(version, "version");
4481     lstrcpyA(lang, "lang");
4482     r = MsiGetFileVersionA(NULL, version, &versz, lang, &langsz);
4483     ok(r == ERROR_INVALID_PARAMETER,
4484        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4485     ok(!lstrcmpA(version, "version"),
4486        "Expected version to be unchanged, got %s\n", version);
4487     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4488     ok(!lstrcmpA(lang, "lang"),
4489        "Expected lang to be unchanged, got %s\n", lang);
4490     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4491 
4492     /* empty szFilePath */
4493     r = MsiGetFileVersionA("", NULL, NULL, NULL, NULL);
4494     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4495 
4496     versz = MAX_PATH;
4497     langsz = MAX_PATH;
4498     lstrcpyA(version, "version");
4499     lstrcpyA(lang, "lang");
4500     r = MsiGetFileVersionA("", version, &versz, lang, &langsz);
4501     ok(r == ERROR_FILE_NOT_FOUND,
4502        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4503     ok(!lstrcmpA(version, "version"),
4504        "Expected version to be unchanged, got %s\n", version);
4505     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4506     ok(!lstrcmpA(lang, "lang"),
4507        "Expected lang to be unchanged, got %s\n", lang);
4508     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4509 
4510     /* nonexistent szFilePath */
4511     versz = MAX_PATH;
4512     langsz = MAX_PATH;
4513     lstrcpyA(version, "version");
4514     lstrcpyA(lang, "lang");
4515     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
4516     ok(r == ERROR_FILE_NOT_FOUND,
4517        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4518     ok(!lstrcmpA(version, "version"),
4519        "Expected version to be unchanged, got %s\n", version);
4520     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4521     ok(!lstrcmpA(lang, "lang"),
4522        "Expected lang to be unchanged, got %s\n", lang);
4523     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4524 
4525     /* nonexistent szFilePath, valid lpVersionBuf, NULL pcchVersionBuf */
4526     versz = MAX_PATH;
4527     langsz = MAX_PATH;
4528     lstrcpyA(version, "version");
4529     lstrcpyA(lang, "lang");
4530     r = MsiGetFileVersionA("nonexistent", version, NULL, lang, &langsz);
4531     ok(r == ERROR_INVALID_PARAMETER,
4532        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4533     ok(!lstrcmpA(version, "version"),
4534        "Expected version to be unchanged, got %s\n", version);
4535     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4536     ok(!lstrcmpA(lang, "lang"),
4537        "Expected lang to be unchanged, got %s\n", lang);
4538     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4539 
4540     /* nonexistent szFilePath, valid lpLangBuf, NULL pcchLangBuf */
4541     versz = MAX_PATH;
4542     langsz = MAX_PATH;
4543     lstrcpyA(version, "version");
4544     lstrcpyA(lang, "lang");
4545     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, NULL);
4546     ok(r == ERROR_INVALID_PARAMETER,
4547        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4548     ok(!lstrcmpA(version, "version"),
4549        "Expected version to be unchanged, got %s\n", version);
4550     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4551     ok(!lstrcmpA(lang, "lang"),
4552        "Expected lang to be unchanged, got %s\n", lang);
4553     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4554 
4555     /* nonexistent szFilePath, valid lpVersionBuf, pcchVersionBuf is zero */
4556     versz = 0;
4557     langsz = MAX_PATH;
4558     lstrcpyA(version, "version");
4559     lstrcpyA(lang, "lang");
4560     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
4561     ok(r == ERROR_FILE_NOT_FOUND,
4562        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4563     ok(!lstrcmpA(version, "version"),
4564        "Expected version to be unchanged, got %s\n", version);
4565     ok(versz == 0, "Expected 0, got %d\n", versz);
4566     ok(!lstrcmpA(lang, "lang"),
4567        "Expected lang to be unchanged, got %s\n", lang);
4568     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4569 
4570     /* nonexistent szFilePath, valid lpLangBuf, pcchLangBuf is zero */
4571     versz = MAX_PATH;
4572     langsz = 0;
4573     lstrcpyA(version, "version");
4574     lstrcpyA(lang, "lang");
4575     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
4576     ok(r == ERROR_FILE_NOT_FOUND,
4577        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4578     ok(!lstrcmpA(version, "version"),
4579        "Expected version to be unchanged, got %s\n", version);
4580     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4581     ok(!lstrcmpA(lang, "lang"),
4582        "Expected lang to be unchanged, got %s\n", lang);
4583     ok(langsz == 0, "Expected 0, got %d\n", langsz);
4584 
4585     /* nonexistent szFilePath, rest NULL */
4586     r = MsiGetFileVersionA("nonexistent", NULL, NULL, NULL, NULL);
4587     ok(r == ERROR_FILE_NOT_FOUND,
4588        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4589 
4590     create_file("ver.txt", "ver.txt", 20);
4591 
4592     /* file exists, no version information */
4593     r = MsiGetFileVersionA("ver.txt", NULL, NULL, NULL, NULL);
4594     ok(r == ERROR_FILE_INVALID, "Expected ERROR_FILE_INVALID, got %d\n", r);
4595 
4596     versz = MAX_PATH;
4597     langsz = MAX_PATH;
4598     lstrcpyA(version, "version");
4599     lstrcpyA(lang, "lang");
4600     r = MsiGetFileVersionA("ver.txt", version, &versz, lang, &langsz);
4601     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4602     ok(!lstrcmpA(version, "version"),
4603        "Expected version to be unchanged, got %s\n", version);
4604     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4605     ok(!lstrcmpA(lang, "lang"),
4606        "Expected lang to be unchanged, got %s\n", lang);
4607     ok(r == ERROR_FILE_INVALID,
4608        "Expected ERROR_FILE_INVALID, got %d\n", r);
4609 
4610     DeleteFileA("ver.txt");
4611 
4612     /* relative path, has version information */
4613     versz = MAX_PATH;
4614     langsz = MAX_PATH;
4615     lstrcpyA(version, "version");
4616     lstrcpyA(lang, "lang");
4617     r = MsiGetFileVersionA("kernel32.dll", version, &versz, lang, &langsz);
4618     todo_wine
4619     {
4620         ok(r == ERROR_FILE_NOT_FOUND,
4621            "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4622         ok(!lstrcmpA(version, "version"),
4623            "Expected version to be unchanged, got %s\n", version);
4624         ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4625         ok(!lstrcmpA(lang, "lang"),
4626            "Expected lang to be unchanged, got %s\n", lang);
4627         ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4628     }
4629 
4630     GetSystemDirectoryA(path, MAX_PATH);
4631     lstrcatA(path, "\\kernel32.dll");
4632 
4633     get_version_info(path, &vercheck, &verchecksz, &langcheck, &langchecksz);
4634 
4635     /* absolute path, has version information */
4636     versz = MAX_PATH;
4637     langsz = MAX_PATH;
4638     lstrcpyA(version, "version");
4639     lstrcpyA(lang, "lang");
4640     r = MsiGetFileVersionA(path, version, &versz, lang, &langsz);
4641     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4642     if (langchecksz && !langsz)
4643     {
4644         win_skip("broken MsiGetFileVersionA detected\n");
4645         HeapFree(GetProcessHeap(), 0, vercheck);
4646         HeapFree(GetProcessHeap(), 0, langcheck);
4647         return;
4648     }
4649     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4650     ok(strstr(lang, langcheck) != NULL, "Expected \"%s\" in \"%s\"\n", langcheck, lang);
4651     ok(!lstrcmpA(version, vercheck),
4652         "Expected %s, got %s\n", vercheck, version);
4653 
4654     /* only check version */
4655     versz = MAX_PATH;
4656     lstrcpyA(version, "version");
4657     r = MsiGetFileVersionA(path, version, &versz, NULL, NULL);
4658     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4659     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4660     ok(!lstrcmpA(version, vercheck),
4661        "Expected %s, got %s\n", vercheck, version);
4662 
4663     /* only check language */
4664     langsz = MAX_PATH;
4665     lstrcpyA(lang, "lang");
4666     r = MsiGetFileVersionA(path, NULL, NULL, lang, &langsz);
4667     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4668     ok(strstr(lang, langcheck) != NULL, "Expected \"%s\" in \"%s\"\n", langcheck, lang);
4669 
4670     /* check neither version nor language */
4671     r = MsiGetFileVersionA(path, NULL, NULL, NULL, NULL);
4672     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4673 
4674     /* get pcchVersionBuf */
4675     versz = MAX_PATH;
4676     r = MsiGetFileVersionA(path, NULL, &versz, NULL, NULL);
4677     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4678     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4679 
4680     /* get pcchLangBuf */
4681     langsz = MAX_PATH;
4682     r = MsiGetFileVersionA(path, NULL, NULL, NULL, &langsz);
4683     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4684     ok(langsz >= langchecksz, "Expected %d >= %d\n", langsz, langchecksz);
4685 
4686     /* pcchVersionBuf not big enough */
4687     versz = 5;
4688     lstrcpyA(version, "version");
4689     r = MsiGetFileVersionA(path, version, &versz, NULL, NULL);
4690     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4691     ok(!strncmp(version, vercheck, 4),
4692        "Expected first 4 characters of \"%s\", got \"%s\"\n", vercheck, version);
4693     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4694 
4695     /* pcchLangBuf not big enough */
4696     langsz = 4;
4697     lstrcpyA(lang, "lang");
4698     r = MsiGetFileVersionA(path, NULL, NULL, lang, &langsz);
4699     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4700     ok(lstrcmpA(lang, "lang"), "lang not set\n");
4701     ok(langsz >= langchecksz, "Expected %d >= %d\n", langsz, langchecksz);
4702 
4703     /* pcchVersionBuf big enough, pcchLangBuf not big enough */
4704     versz = MAX_PATH;
4705     langsz = 0;
4706     lstrcpyA(version, "version");
4707     r = MsiGetFileVersionA(path, version, &versz, NULL, &langsz);
4708     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4709     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4710     ok(!lstrcmpA(version, vercheck), "Expected \"%s\", got \"%s\"\n", vercheck, version);
4711     ok(langsz >= langchecksz && langsz < MAX_PATH, "Expected %d >= %d\n", langsz, langchecksz);
4712 
4713     /* pcchVersionBuf not big enough, pcchLangBuf big enough */
4714     versz = 5;
4715     langsz = MAX_PATH;
4716     lstrcpyA(lang, "lang");
4717     r = MsiGetFileVersionA(path, NULL, &versz, lang, &langsz);
4718     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4719     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4720     ok(langsz >= langchecksz && langsz < MAX_PATH, "Expected %d >= %d\n", langsz, langchecksz);
4721     ok(strstr(lang, langcheck) != NULL, "expected %s in %s\n", langcheck, lang);
4722 
4723     /* NULL pcchVersionBuf and pcchLangBuf */
4724     r = MsiGetFileVersionA(path, version, NULL, lang, NULL);
4725     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4726 
4727     /* All NULL except szFilePath */
4728     r = MsiGetFileVersionA(path, NULL, NULL, NULL, NULL);
4729     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4730 
4731     HeapFree(GetProcessHeap(), 0, vercheck);
4732     HeapFree(GetProcessHeap(), 0, langcheck);
4733 }
4734 
4735 static void test_MsiGetProductInfo(void)
4736 {
4737     UINT r;
4738     LONG res;
4739     HKEY propkey, source;
4740     HKEY prodkey, localkey;
4741     CHAR prodcode[MAX_PATH];
4742     CHAR prod_squashed[MAX_PATH];
4743     CHAR packcode[MAX_PATH];
4744     CHAR pack_squashed[MAX_PATH];
4745     CHAR buf[MAX_PATH];
4746     CHAR keypath[MAX_PATH];
4747     LPSTR usersid;
4748     DWORD sz, val = 42;
4749     REGSAM access = KEY_ALL_ACCESS;
4750 
4751     create_test_guid(prodcode, prod_squashed);
4752     create_test_guid(packcode, pack_squashed);
4753     usersid = get_user_sid();
4754 
4755     if (is_wow64)
4756         access |= KEY_WOW64_64KEY;
4757 
4758     /* NULL szProduct */
4759     sz = MAX_PATH;
4760     lstrcpyA(buf, "apple");
4761     r = MsiGetProductInfoA(NULL, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4762     ok(r == ERROR_INVALID_PARAMETER,
4763        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4764     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4765     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4766 
4767     /* empty szProduct */
4768     sz = MAX_PATH;
4769     lstrcpyA(buf, "apple");
4770     r = MsiGetProductInfoA("", INSTALLPROPERTY_HELPLINKA, buf, &sz);
4771     ok(r == ERROR_INVALID_PARAMETER,
4772        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4773     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4774     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4775 
4776     /* garbage szProduct */
4777     sz = MAX_PATH;
4778     lstrcpyA(buf, "apple");
4779     r = MsiGetProductInfoA("garbage", INSTALLPROPERTY_HELPLINKA, buf, &sz);
4780     ok(r == ERROR_INVALID_PARAMETER,
4781        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4782     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4783     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4784 
4785     /* guid without brackets */
4786     sz = MAX_PATH;
4787     lstrcpyA(buf, "apple");
4788     r = MsiGetProductInfoA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
4789                            INSTALLPROPERTY_HELPLINKA, buf, &sz);
4790     ok(r == ERROR_INVALID_PARAMETER,
4791        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4792     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4793     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4794 
4795     /* guid with brackets */
4796     sz = MAX_PATH;
4797     lstrcpyA(buf, "apple");
4798     r = MsiGetProductInfoA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
4799                            INSTALLPROPERTY_HELPLINKA, buf, &sz);
4800     ok(r == ERROR_UNKNOWN_PRODUCT,
4801        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4802     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4803     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4804 
4805     /* same length as guid, but random */
4806     sz = MAX_PATH;
4807     lstrcpyA(buf, "apple");
4808     r = MsiGetProductInfoA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
4809                            INSTALLPROPERTY_HELPLINKA, buf, &sz);
4810     ok(r == ERROR_INVALID_PARAMETER,
4811        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4812     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4813     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4814 
4815     /* not installed, NULL szAttribute */
4816     sz = MAX_PATH;
4817     lstrcpyA(buf, "apple");
4818     r = MsiGetProductInfoA(prodcode, NULL, buf, &sz);
4819     ok(r == ERROR_INVALID_PARAMETER,
4820        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4821     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4822     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4823 
4824     /* not installed, NULL lpValueBuf */
4825     sz = MAX_PATH;
4826     lstrcpyA(buf, "apple");
4827     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, &sz);
4828     ok(r == ERROR_UNKNOWN_PRODUCT,
4829        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4830     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4831     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4832 
4833     /* not installed, NULL pcchValueBuf */
4834     sz = MAX_PATH;
4835     lstrcpyA(buf, "apple");
4836     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, NULL);
4837     ok(r == ERROR_INVALID_PARAMETER,
4838        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4839     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4840     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4841 
4842     /* created guid cannot possibly be an installed product code */
4843     sz = MAX_PATH;
4844     lstrcpyA(buf, "apple");
4845     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4846     ok(r == ERROR_UNKNOWN_PRODUCT,
4847        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4848     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4849     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4850 
4851     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
4852     lstrcatA(keypath, usersid);
4853     lstrcatA(keypath, "\\Installer\\Products\\");
4854     lstrcatA(keypath, prod_squashed);
4855 
4856     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4857     if (res == ERROR_ACCESS_DENIED)
4858     {
4859         skip("Not enough rights to perform tests\n");
4860         LocalFree(usersid);
4861         return;
4862     }
4863     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4864 
4865     /* managed product code exists */
4866     sz = MAX_PATH;
4867     lstrcpyA(buf, "apple");
4868     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4869     ok(r == ERROR_UNKNOWN_PROPERTY,
4870        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4871     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4872     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4873 
4874     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4875     RegCloseKey(prodkey);
4876 
4877     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
4878     lstrcatA(keypath, usersid);
4879     lstrcatA(keypath, "\\Products\\");
4880     lstrcatA(keypath, prod_squashed);
4881 
4882     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
4883     if (res == ERROR_ACCESS_DENIED)
4884     {
4885         skip("Not enough rights to perform tests\n");
4886         LocalFree(usersid);
4887         return;
4888     }
4889     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4890 
4891     /* local user product code exists */
4892     sz = MAX_PATH;
4893     lstrcpyA(buf, "apple");
4894     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4895     ok(r == ERROR_UNKNOWN_PRODUCT,
4896        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4897     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4898     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4899 
4900     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
4901     lstrcatA(keypath, usersid);
4902     lstrcatA(keypath, "\\Installer\\Products\\");
4903     lstrcatA(keypath, prod_squashed);
4904 
4905     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4906     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4907 
4908     /* both local and managed product code exist */
4909     sz = MAX_PATH;
4910     lstrcpyA(buf, "apple");
4911     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4912     ok(r == ERROR_UNKNOWN_PROPERTY,
4913        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4914     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4915     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4916 
4917     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
4918     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4919 
4920     /* InstallProperties key exists */
4921     sz = MAX_PATH;
4922     lstrcpyA(buf, "apple");
4923     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4924     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4925     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4926     ok(sz == 0, "Expected 0, got %d\n", sz);
4927 
4928     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
4929     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4930 
4931     /* HelpLink value exists */
4932     sz = MAX_PATH;
4933     lstrcpyA(buf, "apple");
4934     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4935     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4936     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
4937     ok(sz == 4, "Expected 4, got %d\n", sz);
4938 
4939     /* pcchBuf is NULL */
4940     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, NULL);
4941     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4942 
4943     /* lpValueBuf is NULL */
4944     sz = MAX_PATH;
4945     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, &sz);
4946     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4947     ok(sz == 4, "Expected 4, got %d\n", sz);
4948 
4949     /* lpValueBuf is NULL, pcchValueBuf is too small */
4950     sz = 2;
4951     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, &sz);
4952     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4953     ok(sz == 4, "Expected 4, got %d\n", sz);
4954 
4955     /* lpValueBuf is non-NULL, pcchValueBuf is too small */
4956     sz = 2;
4957     lstrcpyA(buf, "apple");
4958     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4959     ok(!lstrcmpA(buf, "apple"), "Expected buf to remain unchanged, got \"%s\"\n", buf);
4960     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4961     ok(sz == 4, "Expected 4, got %d\n", sz);
4962 
4963     /* lpValueBuf is non-NULL, pcchValueBuf is exactly 4 */
4964     sz = 4;
4965     lstrcpyA(buf, "apple");
4966     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4967     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4968     ok(!lstrcmpA(buf, "apple"),
4969        "Expected buf to remain unchanged, got \"%s\"\n", buf);
4970     ok(sz == 4, "Expected 4, got %d\n", sz);
4971 
4972     res = RegSetValueExA(propkey, "IMadeThis", 0, REG_SZ, (LPBYTE)"random", 7);
4973     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4974 
4975     /* random property not supported by MSI, value exists */
4976     sz = MAX_PATH;
4977     lstrcpyA(buf, "apple");
4978     r = MsiGetProductInfoA(prodcode, "IMadeThis", buf, &sz);
4979     ok(r == ERROR_UNKNOWN_PROPERTY,
4980        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4981     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4982     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4983 
4984     RegDeleteValueA(propkey, "IMadeThis");
4985     RegDeleteValueA(propkey, "HelpLink");
4986     delete_key(propkey, "", access & KEY_WOW64_64KEY);
4987     delete_key(localkey, "", access & KEY_WOW64_64KEY);
4988     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4989     RegCloseKey(propkey);
4990     RegCloseKey(localkey);
4991     RegCloseKey(prodkey);
4992 
4993     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
4994     lstrcatA(keypath, prod_squashed);
4995 
4996     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
4997     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4998 
4999     /* user product key exists */
5000     sz = MAX_PATH;
5001     lstrcpyA(buf, "apple");
5002     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5003     ok(r == ERROR_UNKNOWN_PROPERTY,
5004        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5005     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
5006     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5007 
5008     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
5009     lstrcatA(keypath, usersid);
5010     lstrcatA(keypath, "\\Products\\");
5011     lstrcatA(keypath, prod_squashed);
5012 
5013     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
5014     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5015 
5016     /* local user product key exists */
5017     sz = MAX_PATH;
5018     lstrcpyA(buf, "apple");
5019     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5020     ok(r == ERROR_UNKNOWN_PROPERTY,
5021        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5022     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
5023     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5024 
5025     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
5026     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5027 
5028     /* InstallProperties key exists */
5029     sz = MAX_PATH;
5030     lstrcpyA(buf, "apple");
5031     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5032     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5033     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5034     ok(sz == 0, "Expected 0, got %d\n", sz);
5035 
5036     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
5037     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5038 
5039     /* HelpLink value exists */
5040     sz = MAX_PATH;
5041     lstrcpyA(buf, "apple");
5042     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5043     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5044     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
5045     ok(sz == 4, "Expected 4, got %d\n", sz);
5046 
5047     RegDeleteValueA(propkey, "HelpLink");
5048     delete_key(propkey, "", access & KEY_WOW64_64KEY);
5049     delete_key(localkey, "", access & KEY_WOW64_64KEY);
5050     RegDeleteKeyA(prodkey, "");
5051     RegCloseKey(propkey);
5052     RegCloseKey(localkey);
5053     RegCloseKey(prodkey);
5054 
5055     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
5056     lstrcatA(keypath, prod_squashed);
5057 
5058     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
5059     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5060 
5061     /* classes product key exists */
5062     sz = MAX_PATH;
5063     lstrcpyA(buf, "apple");
5064     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5065     ok(r == ERROR_UNKNOWN_PROPERTY,
5066        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5067     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
5068     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5069 
5070     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
5071     lstrcatA(keypath, usersid);
5072     lstrcatA(keypath, "\\Products\\");
5073     lstrcatA(keypath, prod_squashed);
5074 
5075     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
5076     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5077 
5078     /* local user product key exists */
5079     sz = MAX_PATH;
5080     lstrcpyA(buf, "apple");
5081     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5082     ok(r == ERROR_UNKNOWN_PROPERTY,
5083        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5084     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
5085     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5086 
5087     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
5088     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5089 
5090     /* InstallProperties key exists */
5091     sz = MAX_PATH;
5092     lstrcpyA(buf, "apple");
5093     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5094     ok(r == ERROR_UNKNOWN_PROPERTY,
5095        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5096     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
5097     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5098 
5099     delete_key(propkey, "", access & KEY_WOW64_64KEY);
5100     delete_key(localkey, "", access & KEY_WOW64_64KEY);
5101     RegCloseKey(propkey);
5102     RegCloseKey(localkey);
5103 
5104     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
5105     lstrcatA(keypath, "S-1-5-18\\\\Products\\");
5106     lstrcatA(keypath, prod_squashed);
5107 
5108     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
5109     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5110 
5111     /* Local System product key exists */
5112     sz = MAX_PATH;
5113     lstrcpyA(buf, "apple");
5114     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5115     ok(r == ERROR_UNKNOWN_PROPERTY,
5116         "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5117     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
5118     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5119 
5120     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
5121     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5122 
5123     /* InstallProperties key exists */
5124     sz = MAX_PATH;
5125     lstrcpyA(buf, "apple");
5126     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5127     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5128     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5129     ok(sz == 0, "Expected 0, got %d\n", sz);
5130 
5131     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
5132     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5133 
5134     /* HelpLink value exists */
5135     sz = MAX_PATH;
5136     lstrcpyA(buf, "apple");
5137     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5138     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5139     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
5140     ok(sz == 4, "Expected 4, got %d\n", sz);
5141 
5142     res = RegSetValueExA(propkey, "HelpLink", 0, REG_DWORD,
5143                          (const BYTE *)&val, sizeof(DWORD));
5144     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5145 
5146     /* HelpLink type is REG_DWORD */
5147     sz = MAX_PATH;
5148     lstrcpyA(buf, "apple");
5149     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5150     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5151     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5152     ok(sz == 2, "Expected 2, got %d\n", sz);
5153 
5154     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
5155     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5156 
5157     /* DisplayName value exists */
5158     sz = MAX_PATH;
5159     lstrcpyA(buf, "apple");
5160     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
5161     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5162     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
5163     ok(sz == 4, "Expected 4, got %d\n", sz);
5164 
5165     res = RegSetValueExA(propkey, "DisplayName", 0, REG_DWORD,
5166                          (const BYTE *)&val, sizeof(DWORD));
5167     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5168 
5169     /* DisplayName type is REG_DWORD */
5170     sz = MAX_PATH;
5171     lstrcpyA(buf, "apple");
5172     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
5173     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5174     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5175     ok(sz == 2, "Expected 2, got %d\n", sz);
5176 
5177     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"1.1.1", 6);
5178     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5179 
5180     /* DisplayVersion value exists */
5181     sz = MAX_PATH;
5182     lstrcpyA(buf, "apple");
5183     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
5184     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5185     ok(!lstrcmpA(buf, "1.1.1"), "Expected \"1.1.1\", got \"%s\"\n", buf);
5186     ok(sz == 5, "Expected 5, got %d\n", sz);
5187 
5188     res = RegSetValueExA(propkey, "DisplayVersion", 0,
5189                          REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
5190     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5191 
5192     /* DisplayVersion type is REG_DWORD */
5193     sz = MAX_PATH;
5194     lstrcpyA(buf, "apple");
5195     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
5196     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5197     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5198     ok(sz == 2, "Expected 2, got %d\n", sz);
5199 
5200     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"tele", 5);
5201     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5202 
5203     /* HelpTelephone value exists */
5204     sz = MAX_PATH;
5205     lstrcpyA(buf, "apple");
5206     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
5207     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5208     ok(!lstrcmpA(buf, "tele"), "Expected \"tele\", got \"%s\"\n", buf);
5209     ok(sz == 4, "Expected 4, got %d\n", sz);
5210 
5211     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_DWORD,
5212                          (const BYTE *)&val, sizeof(DWORD));
5213     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5214 
5215     /* HelpTelephone type is REG_DWORD */
5216     sz = MAX_PATH;
5217     lstrcpyA(buf, "apple");
5218     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
5219     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5220     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5221     ok(sz == 2, "Expected 2, got %d\n", sz);
5222 
5223     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
5224     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5225 
5226     /* InstallLocation value exists */
5227     sz = MAX_PATH;
5228     lstrcpyA(buf, "apple");
5229     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
5230     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5231     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
5232     ok(sz == 3, "Expected 3, got %d\n", sz);
5233 
5234     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_DWORD,
5235                          (const BYTE *)&val, sizeof(DWORD));
5236     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5237 
5238     /* InstallLocation type is REG_DWORD */
5239     sz = MAX_PATH;
5240     lstrcpyA(buf, "apple");
5241     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
5242     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5243     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5244     ok(sz == 2, "Expected 2, got %d\n", sz);
5245 
5246     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
5247     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5248 
5249     /* InstallSource value exists */
5250     sz = MAX_PATH;
5251     lstrcpyA(buf, "apple");
5252     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
5253     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5254     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
5255     ok(sz == 6, "Expected 6, got %d\n", sz);
5256 
5257     res = RegSetValueExA(propkey, "InstallSource", 0, REG_DWORD,
5258                          (const BYTE *)&val, sizeof(DWORD));
5259     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5260 
5261     /* InstallSource type is REG_DWORD */
5262     sz = MAX_PATH;
5263     lstrcpyA(buf, "apple");
5264     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
5265     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5266     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5267     ok(sz == 2, "Expected 2, got %d\n", sz);
5268 
5269     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
5270     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5271 
5272     /* InstallDate value exists */
5273     sz = MAX_PATH;
5274     lstrcpyA(buf, "apple");
5275     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
5276     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5277     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
5278     ok(sz == 4, "Expected 4, got %d\n", sz);
5279 
5280     res = RegSetValueExA(propkey, "InstallDate", 0, REG_DWORD,
5281                          (const BYTE *)&val, sizeof(DWORD));
5282     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5283 
5284     /* InstallDate type is REG_DWORD */
5285     sz = MAX_PATH;
5286     lstrcpyA(buf, "apple");
5287     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
5288     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5289     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5290     ok(sz == 2, "Expected 2, got %d\n", sz);
5291 
5292     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
5293     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5294 
5295     /* Publisher value exists */
5296     sz = MAX_PATH;
5297     lstrcpyA(buf, "apple");
5298     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PUBLISHERA, buf, &sz);
5299     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5300     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
5301     ok(sz == 3, "Expected 3, got %d\n", sz);
5302 
5303     res = RegSetValueExA(propkey, "Publisher", 0, REG_DWORD,
5304                          (const BYTE *)&val, sizeof(DWORD));
5305     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5306 
5307     /* Publisher type is REG_DWORD */
5308     sz = MAX_PATH;
5309     lstrcpyA(buf, "apple");
5310     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PUBLISHERA, buf, &sz);
5311     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5312     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5313     ok(sz == 2, "Expected 2, got %d\n", sz);
5314 
5315     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"pack", 5);
5316     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5317 
5318     /* LocalPackage value exists */
5319     sz = MAX_PATH;
5320     lstrcpyA(buf, "apple");
5321     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
5322     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5323     ok(!lstrcmpA(buf, "pack"), "Expected \"pack\", got \"%s\"\n", buf);
5324     ok(sz == 4, "Expected 4, got %d\n", sz);
5325 
5326     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_DWORD,
5327                          (const BYTE *)&val, sizeof(DWORD));
5328     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5329 
5330     /* LocalPackage type is REG_DWORD */
5331     sz = MAX_PATH;
5332     lstrcpyA(buf, "apple");
5333     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
5334     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5335     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5336     ok(sz == 2, "Expected 2, got %d\n", sz);
5337 
5338     res = RegSetValueExA(propkey, "UrlInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
5339     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5340 
5341     /* UrlInfoAbout value exists */
5342     sz = MAX_PATH;
5343     lstrcpyA(buf, "apple");
5344     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
5345     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5346     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
5347     ok(sz == 5, "Expected 5, got %d\n", sz);
5348 
5349     res = RegSetValueExA(propkey, "UrlInfoAbout", 0, REG_DWORD,
5350                          (const BYTE *)&val, sizeof(DWORD));
5351     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5352 
5353     /* UrlInfoAbout type is REG_DWORD */
5354     sz = MAX_PATH;
5355     lstrcpyA(buf, "apple");
5356     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
5357     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5358     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5359     ok(sz == 2, "Expected 2, got %d\n", sz);
5360 
5361     res = RegSetValueExA(propkey, "UrlUpdateInfo", 0, REG_SZ, (LPBYTE)"info", 5);
5362     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5363 
5364     /* UrlUpdateInfo value exists */
5365     sz = MAX_PATH;
5366     lstrcpyA(buf, "apple");
5367     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
5368     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5369     ok(!lstrcmpA(buf, "info"), "Expected \"info\", got \"%s\"\n", buf);
5370     ok(sz == 4, "Expected 4, got %d\n", sz);
5371 
5372     res = RegSetValueExA(propkey, "UrlUpdateInfo", 0, REG_DWORD,
5373                          (const BYTE *)&val, sizeof(DWORD));
5374     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5375 
5376     /* UrlUpdateInfo type is REG_DWORD */
5377     sz = MAX_PATH;
5378     lstrcpyA(buf, "apple");
5379     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
5380     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5381     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5382     ok(sz == 2, "Expected 2, got %d\n", sz);
5383 
5384     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"1", 2);
5385     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5386 
5387     /* VersionMinor value exists */
5388     sz = MAX_PATH;
5389     lstrcpyA(buf, "apple");
5390     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
5391     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5392     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
5393     ok(sz == 1, "Expected 1, got %d\n", sz);
5394 
5395     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_DWORD,
5396                          (const BYTE *)&val, sizeof(DWORD));
5397     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5398 
5399     /* VersionMinor type is REG_DWORD */
5400     sz = MAX_PATH;
5401     lstrcpyA(buf, "apple");
5402     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
5403     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5404     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5405     ok(sz == 2, "Expected 2, got %d\n", sz);
5406 
5407     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"1", 2);
5408     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5409 
5410     /* VersionMajor value exists */
5411     sz = MAX_PATH;
5412     lstrcpyA(buf, "apple");
5413     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
5414     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5415     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
5416     ok(sz == 1, "Expected 1, got %d\n", sz);
5417 
5418     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_DWORD,
5419                          (const BYTE *)&val, sizeof(DWORD));
5420     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5421 
5422     /* VersionMajor type is REG_DWORD */
5423     sz = MAX_PATH;
5424     lstrcpyA(buf, "apple");
5425     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
5426     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5427     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5428     ok(sz == 2, "Expected 2, got %d\n", sz);
5429 
5430     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
5431     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5432 
5433     /* ProductID value exists */
5434     sz = MAX_PATH;
5435     lstrcpyA(buf, "apple");
5436     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
5437     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5438     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
5439     ok(sz == 2, "Expected 2, got %d\n", sz);
5440 
5441     res = RegSetValueExA(propkey, "ProductID", 0, REG_DWORD,
5442                          (const BYTE *)&val, sizeof(DWORD));
5443     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5444 
5445     /* ProductID type is REG_DWORD */
5446     sz = MAX_PATH;
5447     lstrcpyA(buf, "apple");
5448     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
5449     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5450     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5451     ok(sz == 2, "Expected 2, got %d\n", sz);
5452 
5453     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
5454     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5455 
5456     /* RegCompany value exists */
5457     sz = MAX_PATH;
5458     lstrcpyA(buf, "apple");
5459     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
5460     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5461     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
5462     ok(sz == 4, "Expected 4, got %d\n", sz);
5463 
5464     res = RegSetValueExA(propkey, "RegCompany", 0, REG_DWORD,
5465                          (const BYTE *)&val, sizeof(DWORD));
5466     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5467 
5468     /* RegCompany type is REG_DWORD */
5469     sz = MAX_PATH;
5470     lstrcpyA(buf, "apple");
5471     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
5472     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5473     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5474     ok(sz == 2, "Expected 2, got %d\n", sz);
5475 
5476     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"own", 4);
5477     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5478 
5479     /* RegOwner value exists */
5480     sz = MAX_PATH;
5481     lstrcpyA(buf, "apple");
5482     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGOWNERA, buf, &sz);
5483     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5484     ok(!lstrcmpA(buf, "own"), "Expected \"own\", got \"%s\"\n", buf);
5485     ok(sz == 3, "Expected 3, got %d\n", sz);
5486 
5487     res = RegSetValueExA(propkey, "RegOwner", 0, REG_DWORD,
5488                          (const BYTE *)&val, sizeof(DWORD));
5489     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5490 
5491     /* RegOwner type is REG_DWORD */
5492     sz = MAX_PATH;
5493     lstrcpyA(buf, "apple");
5494     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGOWNERA, buf, &sz);
5495     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5496     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5497     ok(sz == 2, "Expected 2, got %d\n", sz);
5498 
5499     res = RegSetValueExA(propkey, "InstanceType", 0, REG_SZ, (LPBYTE)"type", 5);
5500     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5501 
5502     /* InstanceType value exists */
5503     sz = MAX_PATH;
5504     lstrcpyA(buf, "apple");
5505     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5506     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5507     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5508     ok(sz == 0, "Expected 0, got %d\n", sz);
5509 
5510     res = RegSetValueExA(propkey, "InstanceType", 0, REG_DWORD,
5511                          (const BYTE *)&val, sizeof(DWORD));
5512     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5513 
5514     /* InstanceType type is REG_DWORD */
5515     sz = MAX_PATH;
5516     lstrcpyA(buf, "apple");
5517     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5518     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5519     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5520     ok(sz == 0, "Expected 0, got %d\n", sz);
5521 
5522     res = RegSetValueExA(prodkey, "InstanceType", 0, REG_SZ, (LPBYTE)"type", 5);
5523     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5524 
5525     /* InstanceType value exists */
5526     sz = MAX_PATH;
5527     lstrcpyA(buf, "apple");
5528     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5529     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5530     ok(!lstrcmpA(buf, "type"), "Expected \"type\", got \"%s\"\n", buf);
5531     ok(sz == 4, "Expected 4, got %d\n", sz);
5532 
5533     res = RegSetValueExA(prodkey, "InstanceType", 0, REG_DWORD,
5534                          (const BYTE *)&val, sizeof(DWORD));
5535     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5536 
5537     /* InstanceType type is REG_DWORD */
5538     sz = MAX_PATH;
5539     lstrcpyA(buf, "apple");
5540     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5541     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5542     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5543     ok(sz == 2, "Expected 2, got %d\n", sz);
5544 
5545     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"tforms", 7);
5546     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5547 
5548     /* Transforms value exists */
5549     sz = MAX_PATH;
5550     lstrcpyA(buf, "apple");
5551     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5552     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5553     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5554     ok(sz == 0, "Expected 0, got %d\n", sz);
5555 
5556     res = RegSetValueExA(propkey, "Transforms", 0, REG_DWORD,
5557                          (const BYTE *)&val, sizeof(DWORD));
5558     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5559 
5560     /* Transforms type is REG_DWORD */
5561     sz = MAX_PATH;
5562     lstrcpyA(buf, "apple");
5563     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5564     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5565     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5566     ok(sz == 0, "Expected 0, got %d\n", sz);
5567 
5568     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"tforms", 7);
5569     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5570 
5571     /* Transforms value exists */
5572     sz = MAX_PATH;
5573     lstrcpyA(buf, "apple");
5574     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5575     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5576     ok(!lstrcmpA(buf, "tforms"), "Expected \"tforms\", got \"%s\"\n", buf);
5577     ok(sz == 6, "Expected 6, got %d\n", sz);
5578 
5579     res = RegSetValueExA(prodkey, "Transforms", 0, REG_DWORD,
5580                          (const BYTE *)&val, sizeof(DWORD));
5581     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5582 
5583     /* Transforms type is REG_DWORD */
5584     sz = MAX_PATH;
5585     lstrcpyA(buf, "apple");
5586     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5587     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5588     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5589     ok(sz == 2, "Expected 2, got %d\n", sz);
5590 
5591     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
5592     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5593 
5594     /* Language value exists */
5595     sz = MAX_PATH;
5596     lstrcpyA(buf, "apple");
5597     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5598     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5599     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5600     ok(sz == 0, "Expected 0, got %d\n", sz);
5601 
5602     res = RegSetValueExA(propkey, "Language", 0, REG_DWORD,
5603                          (const BYTE *)&val, sizeof(DWORD));
5604     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5605 
5606     /* Language type is REG_DWORD */
5607     sz = MAX_PATH;
5608     lstrcpyA(buf, "apple");
5609     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5610     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5611     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5612     ok(sz == 0, "Expected 0, got %d\n", sz);
5613 
5614     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
5615     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5616 
5617     /* Language value exists */
5618     sz = MAX_PATH;
5619     lstrcpyA(buf, "apple");
5620     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5621     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5622     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
5623     ok(sz == 4, "Expected 4, got %d\n", sz);
5624 
5625     res = RegSetValueExA(prodkey, "Language", 0, REG_DWORD,
5626                          (const BYTE *)&val, sizeof(DWORD));
5627     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5628 
5629     /* Language type is REG_DWORD */
5630     sz = MAX_PATH;
5631     lstrcpyA(buf, "apple");
5632     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5633     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5634     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5635     ok(sz == 2, "Expected 2, got %d\n", sz);
5636 
5637     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
5638     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5639 
5640     /* ProductName value exists */
5641     sz = MAX_PATH;
5642     lstrcpyA(buf, "apple");
5643     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5644     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5645     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5646     ok(sz == 0, "Expected 0, got %d\n", sz);
5647 
5648     res = RegSetValueExA(propkey, "ProductName", 0, REG_DWORD,
5649                          (const BYTE *)&val, sizeof(DWORD));
5650     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5651 
5652     /* ProductName type is REG_DWORD */
5653     sz = MAX_PATH;
5654     lstrcpyA(buf, "apple");
5655     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5656     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5657     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5658     ok(sz == 0, "Expected 0, got %d\n", sz);
5659 
5660     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
5661     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5662 
5663     /* ProductName value exists */
5664     sz = MAX_PATH;
5665     lstrcpyA(buf, "apple");
5666     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5667     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5668     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
5669     ok(sz == 4, "Expected 4, got %d\n", sz);
5670 
5671     res = RegSetValueExA(prodkey, "ProductName", 0, REG_DWORD,
5672                          (const BYTE *)&val, sizeof(DWORD));
5673     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5674 
5675     /* ProductName type is REG_DWORD */
5676     sz = MAX_PATH;
5677     lstrcpyA(buf, "apple");
5678     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5679     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5680     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5681     ok(sz == 2, "Expected 2, got %d\n", sz);
5682 
5683     res = RegSetValueExA(propkey, "Assignment", 0, REG_SZ, (LPBYTE)"at", 3);
5684     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5685 
5686     /* Assignment value exists */
5687     sz = MAX_PATH;
5688     lstrcpyA(buf, "apple");
5689     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5690     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5691     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5692     ok(sz == 0, "Expected 0, got %d\n", sz);
5693 
5694     res = RegSetValueExA(propkey, "Assignment", 0, REG_DWORD,
5695                          (const BYTE *)&val, sizeof(DWORD));
5696     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5697 
5698     /* Assignment type is REG_DWORD */
5699     sz = MAX_PATH;
5700     lstrcpyA(buf, "apple");
5701     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5702     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5703     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5704     ok(sz == 0, "Expected 0, got %d\n", sz);
5705 
5706     res = RegSetValueExA(prodkey, "Assignment", 0, REG_SZ, (LPBYTE)"at", 3);
5707     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5708 
5709     /* Assignment value exists */
5710     sz = MAX_PATH;
5711     lstrcpyA(buf, "apple");
5712     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5713     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5714     ok(!lstrcmpA(buf, "at"), "Expected \"at\", got \"%s\"\n", buf);
5715     ok(sz == 2, "Expected 2, got %d\n", sz);
5716 
5717     res = RegSetValueExA(prodkey, "Assignment", 0, REG_DWORD,
5718                          (const BYTE *)&val, sizeof(DWORD));
5719     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5720 
5721     /* Assignment type is REG_DWORD */
5722     sz = MAX_PATH;
5723     lstrcpyA(buf, "apple");
5724     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5725     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5726     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5727     ok(sz == 2, "Expected 2, got %d\n", sz);
5728 
5729     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
5730     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5731 
5732     /* PackageCode value exists */
5733     sz = MAX_PATH;
5734     lstrcpyA(buf, "apple");
5735     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5736     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5737     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5738     ok(sz == 0, "Expected 0, got %d\n", sz);
5739 
5740     res = RegSetValueExA(propkey, "PackageCode", 0, REG_DWORD,
5741                          (const BYTE *)&val, sizeof(DWORD));
5742     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5743 
5744     /* PackageCode type is REG_DWORD */
5745     sz = MAX_PATH;
5746     lstrcpyA(buf, "apple");
5747     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5748     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5749     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5750     ok(sz == 0, "Expected 0, got %d\n", sz);
5751 
5752     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
5753     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5754 
5755     /* PackageCode value exists */
5756     sz = MAX_PATH;
5757     lstrcpyA(buf, "apple");
5758     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5759     ok(r == ERROR_BAD_CONFIGURATION,
5760        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
5761     ok(!lstrcmpA(buf, "code"), "Expected \"code\", got \"%s\"\n", buf);
5762     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5763 
5764     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_DWORD,
5765                          (const BYTE *)&val, sizeof(DWORD));
5766     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5767 
5768     /* PackageCode type is REG_DWORD */
5769     sz = MAX_PATH;
5770     lstrcpyA(buf, "apple");
5771     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5772     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5773     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5774     ok(sz == 2, "Expected 2, got %d\n", sz);
5775 
5776     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)pack_squashed, 33);
5777     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5778 
5779     /* PackageCode value exists */
5780     sz = MAX_PATH;
5781     lstrcpyA(buf, "apple");
5782     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5783     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5784     ok(!lstrcmpA(buf, packcode), "Expected \"%s\", got \"%s\"\n", packcode, buf);
5785     ok(sz == 38, "Expected 38, got %d\n", sz);
5786 
5787     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
5788     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5789 
5790     /* Version value exists */
5791     sz = MAX_PATH;
5792     lstrcpyA(buf, "apple");
5793     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5794     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5795     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5796     ok(sz == 0, "Expected 0, got %d\n", sz);
5797 
5798     res = RegSetValueExA(propkey, "Version", 0, REG_DWORD,
5799                          (const BYTE *)&val, sizeof(DWORD));
5800     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5801 
5802     /* Version type is REG_DWORD */
5803     sz = MAX_PATH;
5804     lstrcpyA(buf, "apple");
5805     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5806     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5807     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5808     ok(sz == 0, "Expected 0, got %d\n", sz);
5809 
5810     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
5811     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5812 
5813     /* Version value exists */
5814     sz = MAX_PATH;
5815     lstrcpyA(buf, "apple");
5816     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5817     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5818     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
5819     ok(sz == 3, "Expected 3, got %d\n", sz);
5820 
5821     res = RegSetValueExA(prodkey, "Version", 0, REG_DWORD,
5822                          (const BYTE *)&val, sizeof(DWORD));
5823     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5824 
5825     /* Version type is REG_DWORD */
5826     sz = MAX_PATH;
5827     lstrcpyA(buf, "apple");
5828     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5829     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5830     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5831     ok(sz == 2, "Expected 2, got %d\n", sz);
5832 
5833     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"ico", 4);
5834     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5835 
5836     /* ProductIcon value exists */
5837     sz = MAX_PATH;
5838     lstrcpyA(buf, "apple");
5839     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5840     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5841     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5842     ok(sz == 0, "Expected 0, got %d\n", sz);
5843 
5844     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_DWORD,
5845                          (const BYTE *)&val, sizeof(DWORD));
5846     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5847 
5848     /* ProductIcon type is REG_DWORD */
5849     sz = MAX_PATH;
5850     lstrcpyA(buf, "apple");
5851     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5852     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5853     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5854     ok(sz == 0, "Expected 0, got %d\n", sz);
5855 
5856     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"ico", 4);
5857     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5858 
5859     /* ProductIcon value exists */
5860     sz = MAX_PATH;
5861     lstrcpyA(buf, "apple");
5862     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5863     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5864     ok(!lstrcmpA(buf, "ico"), "Expected \"ico\", got \"%s\"\n", buf);
5865     ok(sz == 3, "Expected 3, got %d\n", sz);
5866 
5867     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_DWORD,
5868                          (const BYTE *)&val, sizeof(DWORD));
5869     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5870 
5871     /* ProductIcon type is REG_DWORD */
5872     sz = MAX_PATH;
5873     lstrcpyA(buf, "apple");
5874     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5875     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5876     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5877     ok(sz == 2, "Expected 2, got %d\n", sz);
5878 
5879     /* SourceList key does not exist */
5880     sz = MAX_PATH;
5881     lstrcpyA(buf, "apple");
5882     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5883     ok(r == ERROR_UNKNOWN_PRODUCT,
5884        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5885     ok(!lstrcmpA(buf, "apple"),
5886        "Expected buf to be unchanged, got \"%s\"\n", buf);
5887     ok(sz == MAX_PATH, "Expected sz to be unchanged, got %d\n", sz);
5888 
5889     res = RegCreateKeyExA(prodkey, "SourceList", 0, NULL, 0, access, NULL, &source, NULL);
5890     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5891 
5892     /* SourceList key exists, but PackageName val does not exist */
5893     sz = MAX_PATH;
5894     lstrcpyA(buf, "apple");
5895     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5896     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5897     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5898     ok(sz == 0, "Expected 0, got %d\n", sz);
5899 
5900     res = RegSetValueExA(source, "PackageName", 0, REG_SZ, (LPBYTE)"packname", 9);
5901     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5902 
5903     /* PackageName val exists */
5904     sz = MAX_PATH;
5905     lstrcpyA(buf, "apple");
5906     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5907     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5908     ok(!lstrcmpA(buf, "packname"), "Expected \"packname\", got \"%s\"\n", buf);
5909     ok(sz == 8, "Expected 8, got %d\n", sz);
5910 
5911     res = RegSetValueExA(source, "PackageName", 0, REG_DWORD,
5912                          (const BYTE *)&val, sizeof(DWORD));
5913     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5914 
5915     /* PackageName type is REG_DWORD */
5916     sz = MAX_PATH;
5917     lstrcpyA(buf, "apple");
5918     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5919     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5920     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5921     ok(sz == 2, "Expected 2, got %d\n", sz);
5922 
5923     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
5924     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5925 
5926     /* Authorized value exists */
5927     sz = MAX_PATH;
5928     lstrcpyA(buf, "apple");
5929     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5930     if (r != ERROR_UNKNOWN_PROPERTY)
5931     {
5932         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5933         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5934         ok(sz == 0, "Expected 0, got %d\n", sz);
5935     }
5936 
5937     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_DWORD,
5938                          (const BYTE *)&val, sizeof(DWORD));
5939     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5940 
5941     /* AuthorizedLUAApp type is REG_DWORD */
5942     sz = MAX_PATH;
5943     lstrcpyA(buf, "apple");
5944     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5945     if (r != ERROR_UNKNOWN_PROPERTY)
5946     {
5947         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5948         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5949         ok(sz == 0, "Expected 0, got %d\n", sz);
5950     }
5951 
5952     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
5953     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5954 
5955     /* Authorized value exists */
5956     sz = MAX_PATH;
5957     lstrcpyA(buf, "apple");
5958     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5959     if (r != ERROR_UNKNOWN_PROPERTY)
5960     {
5961         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5962         ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
5963         ok(sz == 4, "Expected 4, got %d\n", sz);
5964     }
5965 
5966     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_DWORD,
5967                          (const BYTE *)&val, sizeof(DWORD));
5968     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5969 
5970     /* AuthorizedLUAApp type is REG_DWORD */
5971     sz = MAX_PATH;
5972     lstrcpyA(buf, "apple");
5973     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5974     if (r != ERROR_UNKNOWN_PROPERTY)
5975     {
5976         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5977         ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5978         ok(sz == 2, "Expected 2, got %d\n", sz);
5979     }
5980 
5981     RegDeleteValueA(propkey, "HelpLink");
5982     RegDeleteValueA(propkey, "DisplayName");
5983     RegDeleteValueA(propkey, "DisplayVersion");
5984     RegDeleteValueA(propkey, "HelpTelephone");
5985     RegDeleteValueA(propkey, "InstallLocation");
5986     RegDeleteValueA(propkey, "InstallSource");
5987     RegDeleteValueA(propkey, "InstallDate");
5988     RegDeleteValueA(propkey, "Publisher");
5989     RegDeleteValueA(propkey, "LocalPackage");
5990     RegDeleteValueA(propkey, "UrlInfoAbout");
5991     RegDeleteValueA(propkey, "UrlUpdateInfo");
5992     RegDeleteValueA(propkey, "VersionMinor");
5993     RegDeleteValueA(propkey, "VersionMajor");
5994     RegDeleteValueA(propkey, "ProductID");
5995     RegDeleteValueA(propkey, "RegCompany");
5996     RegDeleteValueA(propkey, "RegOwner");
5997     RegDeleteValueA(propkey, "InstanceType");
5998     RegDeleteValueA(propkey, "Transforms");
5999     RegDeleteValueA(propkey, "Language");
6000     RegDeleteValueA(propkey, "ProductName");
6001     RegDeleteValueA(propkey, "Assignment");
6002     RegDeleteValueA(propkey, "PackageCode");
6003     RegDeleteValueA(propkey, "Version");
6004     RegDeleteValueA(propkey, "ProductIcon");
6005     RegDeleteValueA(propkey, "AuthorizedLUAApp");
6006     delete_key(propkey, "", access & KEY_WOW64_64KEY);
6007     delete_key(localkey, "", access & KEY_WOW64_64KEY);
6008     RegDeleteValueA(prodkey, "InstanceType");
6009     RegDeleteValueA(prodkey, "Transforms");
6010     RegDeleteValueA(prodkey, "Language");
6011     RegDeleteValueA(prodkey, "ProductName");
6012     RegDeleteValueA(prodkey, "Assignment");
6013     RegDeleteValueA(prodkey, "PackageCode");
6014     RegDeleteValueA(prodkey, "Version");
6015     RegDeleteValueA(prodkey, "ProductIcon");
6016     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
6017     RegDeleteValueA(source, "PackageName");
6018     delete_key(source, "", access & KEY_WOW64_64KEY);
6019     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
6020     RegCloseKey(propkey);
6021     RegCloseKey(localkey);
6022     RegCloseKey(source);
6023     RegCloseKey(prodkey);
6024     LocalFree(usersid);
6025 }
6026 
6027 static void test_MsiGetProductInfoEx(void)
6028 {
6029     UINT r;
6030     LONG res;
6031     HKEY propkey, userkey;
6032     HKEY prodkey, localkey;
6033     CHAR prodcode[MAX_PATH];
6034     CHAR prod_squashed[MAX_PATH];
6035     CHAR packcode[MAX_PATH];
6036     CHAR pack_squashed[MAX_PATH];
6037     CHAR buf[MAX_PATH];
6038     CHAR keypath[MAX_PATH];
6039     LPSTR usersid;
6040     DWORD sz;
6041     REGSAM access = KEY_ALL_ACCESS;
6042 
6043     if (!pMsiGetProductInfoExA)
6044     {
6045         win_skip("MsiGetProductInfoExA is not available\n");
6046         return;
6047     }
6048 
6049     create_test_guid(prodcode, prod_squashed);
6050     create_test_guid(packcode, pack_squashed);
6051     usersid = get_user_sid();
6052 
6053     if (is_wow64)
6054         access |= KEY_WOW64_64KEY;
6055 
6056     /* NULL szProductCode */
6057     sz = MAX_PATH;
6058     lstrcpyA(buf, "apple");
6059     r = pMsiGetProductInfoExA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
6060                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6061     ok(r == ERROR_INVALID_PARAMETER,
6062        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6063     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6064     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6065 
6066     /* empty szProductCode */
6067     sz = MAX_PATH;
6068     lstrcpyA(buf, "apple");
6069     r = pMsiGetProductInfoExA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
6070                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6071     ok(r == ERROR_INVALID_PARAMETER,
6072        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6073     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6074     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6075 
6076     /* garbage szProductCode */
6077     sz = MAX_PATH;
6078     lstrcpyA(buf, "apple");
6079     r = pMsiGetProductInfoExA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
6080                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6081     ok(r == ERROR_INVALID_PARAMETER,
6082        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6083     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6084     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6085 
6086     /* guid without brackets */
6087     sz = MAX_PATH;
6088     lstrcpyA(buf, "apple");
6089     r = pMsiGetProductInfoExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", usersid,
6090                               MSIINSTALLCONTEXT_USERUNMANAGED,
6091                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6092     ok(r == ERROR_INVALID_PARAMETER,
6093        "Expected ERROR_INVALID_PARAMETER, 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     /* guid with brackets */
6098     sz = MAX_PATH;
6099     lstrcpyA(buf, "apple");
6100     r = pMsiGetProductInfoExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", usersid,
6101                               MSIINSTALLCONTEXT_USERUNMANAGED,
6102                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6103     ok(r == ERROR_UNKNOWN_PRODUCT,
6104        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6105     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6106     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6107 
6108     /* szValue is non-NULL while pcchValue is NULL */
6109     lstrcpyA(buf, "apple");
6110     r = pMsiGetProductInfoExA(prodcode, usersid,
6111                               MSIINSTALLCONTEXT_USERUNMANAGED,
6112                               INSTALLPROPERTY_PRODUCTSTATEA, buf, NULL);
6113     ok(r == ERROR_INVALID_PARAMETER,
6114        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6115     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6116 
6117     /* dwContext is out of range */
6118     sz = MAX_PATH;
6119     lstrcpyA(buf, "apple");
6120     r = pMsiGetProductInfoExA(prodcode, usersid, 42,
6121                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6122     ok(r == ERROR_INVALID_PARAMETER,
6123        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6124     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6125     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6126 
6127     /* szProperty is NULL */
6128     sz = MAX_PATH;
6129     lstrcpyA(buf, "apple");
6130     r = pMsiGetProductInfoExA(prodcode, usersid,
6131                               MSIINSTALLCONTEXT_USERUNMANAGED,
6132                               NULL, buf, &sz);
6133     ok(r == ERROR_INVALID_PARAMETER,
6134        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6135     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6136     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6137 
6138     /* szProperty is empty */
6139     sz = MAX_PATH;
6140     lstrcpyA(buf, "apple");
6141     r = pMsiGetProductInfoExA(prodcode, usersid,
6142                               MSIINSTALLCONTEXT_USERUNMANAGED,
6143                               "", buf, &sz);
6144     ok(r == ERROR_INVALID_PARAMETER,
6145        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6146     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6147     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6148 
6149     /* szProperty is not a valid property */
6150     sz = MAX_PATH;
6151     lstrcpyA(buf, "apple");
6152     r = pMsiGetProductInfoExA(prodcode, usersid,
6153                               MSIINSTALLCONTEXT_USERUNMANAGED,
6154                               "notvalid", buf, &sz);
6155     ok(r == ERROR_UNKNOWN_PRODUCT,
6156        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6157     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6158     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6159 
6160     /* same length as guid, but random */
6161     sz = MAX_PATH;
6162     lstrcpyA(buf, "apple");
6163     r = pMsiGetProductInfoExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", usersid,
6164                               MSIINSTALLCONTEXT_USERUNMANAGED,
6165                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6166     ok(r == ERROR_INVALID_PARAMETER,
6167        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6168     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6169     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6170 
6171     /* MSIINSTALLCONTEXT_USERUNMANAGED */
6172 
6173     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
6174     lstrcatA(keypath, usersid);
6175     lstrcatA(keypath, "\\Products\\");
6176     lstrcatA(keypath, prod_squashed);
6177 
6178     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
6179     if (res == ERROR_ACCESS_DENIED)
6180     {
6181         skip("Not enough rights to perform tests\n");
6182         LocalFree(usersid);
6183         return;
6184     }
6185     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6186 
6187     /* local user product key exists */
6188     sz = MAX_PATH;
6189     lstrcpyA(buf, "apple");
6190     r = pMsiGetProductInfoExA(prodcode, usersid,
6191                               MSIINSTALLCONTEXT_USERUNMANAGED,
6192                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6193     ok(r == ERROR_UNKNOWN_PRODUCT,
6194        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6195     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6196     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6197 
6198     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
6199     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6200 
6201     /* InstallProperties key exists */
6202     sz = MAX_PATH;
6203     lstrcpyA(buf, "apple");
6204     r = pMsiGetProductInfoExA(prodcode, usersid,
6205                               MSIINSTALLCONTEXT_USERUNMANAGED,
6206                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6207     ok(r == ERROR_UNKNOWN_PRODUCT,
6208        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6209     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6210     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6211 
6212     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6213     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6214 
6215     /* LocalPackage value exists */
6216     sz = MAX_PATH;
6217     lstrcpyA(buf, "apple");
6218     r = pMsiGetProductInfoExA(prodcode, usersid,
6219                               MSIINSTALLCONTEXT_USERUNMANAGED,
6220                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6221     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6222     ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
6223     ok(sz == 1, "Expected 1, got %d\n", sz);
6224 
6225     RegDeleteValueA(propkey, "LocalPackage");
6226 
6227     /* LocalPackage value must exist */
6228     sz = MAX_PATH;
6229     lstrcpyA(buf, "apple");
6230     r = pMsiGetProductInfoExA(prodcode, usersid,
6231                               MSIINSTALLCONTEXT_USERUNMANAGED,
6232                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
6233     ok(r == ERROR_UNKNOWN_PRODUCT,
6234        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6235     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6236     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6237 
6238     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6239     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6240 
6241     /* LocalPackage exists, but HelpLink does not exist */
6242     sz = MAX_PATH;
6243     lstrcpyA(buf, "apple");
6244     r = pMsiGetProductInfoExA(prodcode, usersid,
6245                               MSIINSTALLCONTEXT_USERUNMANAGED,
6246                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
6247     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6248     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
6249     ok(sz == 0, "Expected 0, got %d\n", sz);
6250 
6251     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
6252     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6253 
6254     /* HelpLink value exists */
6255     sz = MAX_PATH;
6256     lstrcpyA(buf, "apple");
6257     r = pMsiGetProductInfoExA(prodcode, usersid,
6258                               MSIINSTALLCONTEXT_USERUNMANAGED,
6259                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
6260     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6261     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
6262     ok(sz == 4, "Expected 4, got %d\n", sz);
6263 
6264     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
6265     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6266 
6267     /* HelpTelephone value exists */
6268     sz = MAX_PATH;
6269     lstrcpyA(buf, "apple");
6270     r = pMsiGetProductInfoExA(prodcode, usersid,
6271                               MSIINSTALLCONTEXT_USERUNMANAGED,
6272                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
6273     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6274     ok(!lstrcmpA(buf, "phone"), "Expected \"phone\", got \"%s\"\n", buf);
6275     ok(sz == 5, "Expected 5, got %d\n", sz);
6276 
6277     /* szValue and pcchValue are NULL */
6278     r = pMsiGetProductInfoExA(prodcode, usersid,
6279                               MSIINSTALLCONTEXT_USERUNMANAGED,
6280                               INSTALLPROPERTY_HELPTELEPHONEA, NULL, NULL);
6281     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6282 
6283     /* pcchValue is exactly 5 */
6284     sz = 5;
6285     lstrcpyA(buf, "apple");
6286     r = pMsiGetProductInfoExA(prodcode, usersid,
6287                               MSIINSTALLCONTEXT_USERUNMANAGED,
6288                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
6289     ok(r == ERROR_MORE_DATA,
6290        "Expected ERROR_MORE_DATA, got %d\n", r);
6291     ok(sz == 10, "Expected 10, got %d\n", sz);
6292 
6293     /* szValue is NULL, pcchValue is exactly 5 */
6294     sz = 5;
6295     r = pMsiGetProductInfoExA(prodcode, usersid,
6296                               MSIINSTALLCONTEXT_USERUNMANAGED,
6297                               INSTALLPROPERTY_HELPTELEPHONEA, NULL, &sz);
6298     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6299     ok(sz == 10, "Expected 10, got %d\n", sz);
6300 
6301     /* szValue is NULL, pcchValue is MAX_PATH */
6302     sz = MAX_PATH;
6303     r = pMsiGetProductInfoExA(prodcode, usersid,
6304                               MSIINSTALLCONTEXT_USERUNMANAGED,
6305                               INSTALLPROPERTY_HELPTELEPHONEA, NULL, &sz);
6306     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6307     ok(sz == 10, "Expected 10, got %d\n", sz);
6308 
6309     /* pcchValue is exactly 0 */
6310     sz = 0;
6311     lstrcpyA(buf, "apple");
6312     r = pMsiGetProductInfoExA(prodcode, usersid,
6313                               MSIINSTALLCONTEXT_USERUNMANAGED,
6314                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
6315     ok(r == ERROR_MORE_DATA,
6316        "Expected ERROR_MORE_DATA, got %d\n", r);
6317     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
6318     ok(sz == 10, "Expected 10, got %d\n", sz);
6319 
6320     res = RegSetValueExA(propkey, "notvalid", 0, REG_SZ, (LPBYTE)"invalid", 8);
6321     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6322 
6323     /* szProperty is not a valid property */
6324     sz = MAX_PATH;
6325     lstrcpyA(buf, "apple");
6326     r = pMsiGetProductInfoExA(prodcode, usersid,
6327                               MSIINSTALLCONTEXT_USERUNMANAGED,
6328                               "notvalid", buf, &sz);
6329     ok(r == ERROR_UNKNOWN_PROPERTY,
6330        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6331     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6332     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6333 
6334     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
6335     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6336 
6337     /* InstallDate value exists */
6338     sz = MAX_PATH;
6339     lstrcpyA(buf, "apple");
6340     r = pMsiGetProductInfoExA(prodcode, usersid,
6341                               MSIINSTALLCONTEXT_USERUNMANAGED,
6342                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
6343     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6344     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
6345     ok(sz == 4, "Expected 4, got %d\n", sz);
6346 
6347     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
6348     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6349 
6350     /* DisplayName value exists */
6351     sz = MAX_PATH;
6352     lstrcpyA(buf, "apple");
6353     r = pMsiGetProductInfoExA(prodcode, usersid,
6354                               MSIINSTALLCONTEXT_USERUNMANAGED,
6355                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
6356     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6357     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
6358     ok(sz == 4, "Expected 4, got %d\n", sz);
6359 
6360     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
6361     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6362 
6363     /* InstallLocation value exists */
6364     sz = MAX_PATH;
6365     lstrcpyA(buf, "apple");
6366     r = pMsiGetProductInfoExA(prodcode, usersid,
6367                               MSIINSTALLCONTEXT_USERUNMANAGED,
6368                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
6369     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6370     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
6371     ok(sz == 3, "Expected 3, got %d\n", sz);
6372 
6373     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
6374     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6375 
6376     /* InstallSource value exists */
6377     sz = MAX_PATH;
6378     lstrcpyA(buf, "apple");
6379     r = pMsiGetProductInfoExA(prodcode, usersid,
6380                               MSIINSTALLCONTEXT_USERUNMANAGED,
6381                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
6382     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6383     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
6384     ok(sz == 6, "Expected 6, got %d\n", sz);
6385 
6386     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6387     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6388 
6389     /* LocalPackage value exists */
6390     sz = MAX_PATH;
6391     lstrcpyA(buf, "apple");
6392     r = pMsiGetProductInfoExA(prodcode, usersid,
6393                               MSIINSTALLCONTEXT_USERUNMANAGED,
6394                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
6395     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6396     ok(!lstrcmpA(buf, "local"), "Expected \"local\", got \"%s\"\n", buf);
6397     ok(sz == 5, "Expected 5, got %d\n", sz);
6398 
6399     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
6400     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6401 
6402     /* Publisher value exists */
6403     sz = MAX_PATH;
6404     lstrcpyA(buf, "apple");
6405     r = pMsiGetProductInfoExA(prodcode, usersid,
6406                               MSIINSTALLCONTEXT_USERUNMANAGED,
6407                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
6408     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6409     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
6410     ok(sz == 3, "Expected 3, got %d\n", sz);
6411 
6412     res = RegSetValueExA(propkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
6413     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6414 
6415     /* URLInfoAbout value exists */
6416     sz = MAX_PATH;
6417     lstrcpyA(buf, "apple");
6418     r = pMsiGetProductInfoExA(prodcode, usersid,
6419                               MSIINSTALLCONTEXT_USERUNMANAGED,
6420                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
6421     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6422     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
6423     ok(sz == 5, "Expected 5, got %d\n", sz);
6424 
6425     res = RegSetValueExA(propkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
6426     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6427 
6428     /* URLUpdateInfo value exists */
6429     sz = MAX_PATH;
6430     lstrcpyA(buf, "apple");
6431     r = pMsiGetProductInfoExA(prodcode, usersid,
6432                               MSIINSTALLCONTEXT_USERUNMANAGED,
6433                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
6434     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6435     ok(!lstrcmpA(buf, "update"), "Expected \"update\", got \"%s\"\n", buf);
6436     ok(sz == 6, "Expected 6, got %d\n", sz);
6437 
6438     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
6439     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6440 
6441     /* VersionMinor value exists */
6442     sz = MAX_PATH;
6443     lstrcpyA(buf, "apple");
6444     r = pMsiGetProductInfoExA(prodcode, usersid,
6445                               MSIINSTALLCONTEXT_USERUNMANAGED,
6446                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
6447     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6448     ok(!lstrcmpA(buf, "2"), "Expected \"2\", got \"%s\"\n", buf);
6449     ok(sz == 1, "Expected 1, got %d\n", sz);
6450 
6451     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
6452     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6453 
6454     /* VersionMajor value exists */
6455     sz = MAX_PATH;
6456     lstrcpyA(buf, "apple");
6457     r = pMsiGetProductInfoExA(prodcode, usersid,
6458                               MSIINSTALLCONTEXT_USERUNMANAGED,
6459                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
6460     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6461     ok(!lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
6462     ok(sz == 1, "Expected 1, got %d\n", sz);
6463 
6464     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
6465     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6466 
6467     /* DisplayVersion value exists */
6468     sz = MAX_PATH;
6469     lstrcpyA(buf, "apple");
6470     r = pMsiGetProductInfoExA(prodcode, usersid,
6471                               MSIINSTALLCONTEXT_USERUNMANAGED,
6472                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
6473     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6474     ok(!lstrcmpA(buf, "3.2.1"), "Expected \"3.2.1\", got \"%s\"\n", buf);
6475     ok(sz == 5, "Expected 5, got %d\n", sz);
6476 
6477     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
6478     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6479 
6480     /* ProductID value exists */
6481     sz = MAX_PATH;
6482     lstrcpyA(buf, "apple");
6483     r = pMsiGetProductInfoExA(prodcode, usersid,
6484                               MSIINSTALLCONTEXT_USERUNMANAGED,
6485                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
6486     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6487     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
6488     ok(sz == 2, "Expected 2, got %d\n", sz);
6489 
6490     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
6491     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6492 
6493     /* RegCompany value exists */
6494     sz = MAX_PATH;
6495     lstrcpyA(buf, "apple");
6496     r = pMsiGetProductInfoExA(prodcode, usersid,
6497                               MSIINSTALLCONTEXT_USERUNMANAGED,
6498                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
6499     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6500     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
6501     ok(sz == 4, "Expected 4, got %d\n", sz);
6502 
6503     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
6504     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6505 
6506     /* RegOwner value exists */
6507     sz = MAX_PATH;
6508     lstrcpyA(buf, "apple");
6509     r = pMsiGetProductInfoExA(prodcode, usersid,
6510                               MSIINSTALLCONTEXT_USERUNMANAGED,
6511                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
6512     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6513     ok(!lstrcmpA(buf, "owner"), "Expected \"owner\", got \"%s\"\n", buf);
6514     ok(sz == 5, "Expected 5, got %d\n", sz);
6515 
6516     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
6517     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6518 
6519     /* Transforms value exists */
6520     sz = MAX_PATH;
6521     lstrcpyA(buf, "apple");
6522     r = pMsiGetProductInfoExA(prodcode, usersid,
6523                               MSIINSTALLCONTEXT_USERUNMANAGED,
6524                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
6525     ok(r == ERROR_UNKNOWN_PRODUCT,
6526        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6527     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6528     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6529 
6530     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
6531     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6532 
6533     /* Language value exists */
6534     sz = MAX_PATH;
6535     lstrcpyA(buf, "apple");
6536     r = pMsiGetProductInfoExA(prodcode, usersid,
6537                               MSIINSTALLCONTEXT_USERUNMANAGED,
6538                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
6539     ok(r == ERROR_UNKNOWN_PRODUCT,
6540        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6541     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6542     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6543 
6544     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
6545     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6546 
6547     /* ProductName value exists */
6548     sz = MAX_PATH;
6549     lstrcpyA(buf, "apple");
6550     r = pMsiGetProductInfoExA(prodcode, usersid,
6551                               MSIINSTALLCONTEXT_USERUNMANAGED,
6552                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
6553     ok(r == ERROR_UNKNOWN_PRODUCT,
6554        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6555     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6556     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6557 
6558     res = RegSetValueExA(propkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
6559     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6560 
6561     /* FIXME */
6562 
6563     /* AssignmentType value exists */
6564     sz = MAX_PATH;
6565     lstrcpyA(buf, "apple");
6566     r = pMsiGetProductInfoExA(prodcode, usersid,
6567                               MSIINSTALLCONTEXT_USERUNMANAGED,
6568                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
6569     ok(r == ERROR_UNKNOWN_PRODUCT,
6570        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6571     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6572     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6573 
6574     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
6575     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6576 
6577     /* PackageCode value exists */
6578     sz = MAX_PATH;
6579     lstrcpyA(buf, "apple");
6580     r = pMsiGetProductInfoExA(prodcode, usersid,
6581                               MSIINSTALLCONTEXT_USERUNMANAGED,
6582                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
6583     ok(r == ERROR_UNKNOWN_PRODUCT,
6584        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6585     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6586     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6587 
6588     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
6589     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6590 
6591     /* Version value exists */
6592     sz = MAX_PATH;
6593     lstrcpyA(buf, "apple");
6594     r = pMsiGetProductInfoExA(prodcode, usersid,
6595                               MSIINSTALLCONTEXT_USERUNMANAGED,
6596                               INSTALLPROPERTY_VERSIONA, buf, &sz);
6597     ok(r == ERROR_UNKNOWN_PRODUCT,
6598        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6599     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6600     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6601 
6602     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
6603     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6604 
6605     /* ProductIcon value exists */
6606     sz = MAX_PATH;
6607     lstrcpyA(buf, "apple");
6608     r = pMsiGetProductInfoExA(prodcode, usersid,
6609                               MSIINSTALLCONTEXT_USERUNMANAGED,
6610                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
6611     ok(r == ERROR_UNKNOWN_PRODUCT,
6612        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6613     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6614     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6615 
6616     res = RegSetValueExA(propkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
6617     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6618 
6619     /* PackageName value exists */
6620     sz = MAX_PATH;
6621     lstrcpyA(buf, "apple");
6622     r = pMsiGetProductInfoExA(prodcode, usersid,
6623                               MSIINSTALLCONTEXT_USERUNMANAGED,
6624                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
6625     ok(r == ERROR_UNKNOWN_PRODUCT,
6626        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6627     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6628     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6629 
6630     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
6631     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6632 
6633     /* AuthorizedLUAApp value exists */
6634     sz = MAX_PATH;
6635     lstrcpyA(buf, "apple");
6636     r = pMsiGetProductInfoExA(prodcode, usersid,
6637                               MSIINSTALLCONTEXT_USERUNMANAGED,
6638                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
6639     ok(r == ERROR_UNKNOWN_PRODUCT,
6640        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6641     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6642     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6643 
6644     RegDeleteValueA(propkey, "AuthorizedLUAApp");
6645     RegDeleteValueA(propkey, "PackageName");
6646     RegDeleteValueA(propkey, "ProductIcon");
6647     RegDeleteValueA(propkey, "Version");
6648     RegDeleteValueA(propkey, "PackageCode");
6649     RegDeleteValueA(propkey, "AssignmentType");
6650     RegDeleteValueA(propkey, "ProductName");
6651     RegDeleteValueA(propkey, "Language");
6652     RegDeleteValueA(propkey, "Transforms");
6653     RegDeleteValueA(propkey, "RegOwner");
6654     RegDeleteValueA(propkey, "RegCompany");
6655     RegDeleteValueA(propkey, "ProductID");
6656     RegDeleteValueA(propkey, "DisplayVersion");
6657     RegDeleteValueA(propkey, "VersionMajor");
6658     RegDeleteValueA(propkey, "VersionMinor");
6659     RegDeleteValueA(propkey, "URLUpdateInfo");
6660     RegDeleteValueA(propkey, "URLInfoAbout");
6661     RegDeleteValueA(propkey, "Publisher");
6662     RegDeleteValueA(propkey, "LocalPackage");
6663     RegDeleteValueA(propkey, "InstallSource");
6664     RegDeleteValueA(propkey, "InstallLocation");
6665     RegDeleteValueA(propkey, "DisplayName");
6666     RegDeleteValueA(propkey, "InstallDate");
6667     RegDeleteValueA(propkey, "HelpTelephone");
6668     RegDeleteValueA(propkey, "HelpLink");
6669     RegDeleteValueA(propkey, "LocalPackage");
6670     RegDeleteKeyA(propkey, "");
6671     RegCloseKey(propkey);
6672     RegDeleteKeyA(localkey, "");
6673     RegCloseKey(localkey);
6674 
6675     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
6676     lstrcatA(keypath, usersid);
6677     lstrcatA(keypath, "\\Installer\\Products\\");
6678     lstrcatA(keypath, prod_squashed);
6679 
6680     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
6681     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6682 
6683     /* user product key exists */
6684     sz = MAX_PATH;
6685     lstrcpyA(buf, "apple");
6686     r = pMsiGetProductInfoExA(prodcode, usersid,
6687                               MSIINSTALLCONTEXT_USERUNMANAGED,
6688                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6689     ok(r == ERROR_UNKNOWN_PRODUCT,
6690        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6691     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6692     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6693 
6694     RegDeleteKeyA(userkey, "");
6695     RegCloseKey(userkey);
6696 
6697     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
6698     lstrcatA(keypath, prod_squashed);
6699 
6700     res = RegCreateKeyExA(HKEY_CURRENT_USER, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
6701     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6702 
6703     sz = MAX_PATH;
6704     lstrcpyA(buf, "apple");
6705     r = pMsiGetProductInfoExA(prodcode, usersid,
6706                               MSIINSTALLCONTEXT_USERUNMANAGED,
6707                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6708     ok(r == ERROR_SUCCESS || broken(r == ERROR_UNKNOWN_PRODUCT), "Expected ERROR_SUCCESS, got %d\n", r);
6709     if (r == ERROR_UNKNOWN_PRODUCT)
6710     {
6711         win_skip("skipping remaining tests for MsiGetProductInfoEx\n");
6712         delete_key(prodkey, "", access);
6713         RegCloseKey(prodkey);
6714         return;
6715     }
6716     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
6717     ok(sz == 1, "Expected 1, got %d\n", sz);
6718 
6719     res = RegSetValueExA(prodkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
6720     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6721 
6722     /* HelpLink value exists */
6723     sz = MAX_PATH;
6724     lstrcpyA(buf, "apple");
6725     r = pMsiGetProductInfoExA(prodcode, usersid,
6726                               MSIINSTALLCONTEXT_USERUNMANAGED,
6727                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
6728     ok(r == ERROR_UNKNOWN_PROPERTY,
6729        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6730     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6731     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6732 
6733     res = RegSetValueExA(prodkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
6734     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6735 
6736     /* HelpTelephone value exists */
6737     sz = MAX_PATH;
6738     lstrcpyA(buf, "apple");
6739     r = pMsiGetProductInfoExA(prodcode, usersid,
6740                               MSIINSTALLCONTEXT_USERUNMANAGED,
6741                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
6742     ok(r == ERROR_UNKNOWN_PROPERTY,
6743        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6744     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6745     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6746 
6747     res = RegSetValueExA(prodkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
6748     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6749 
6750     /* InstallDate value exists */
6751     sz = MAX_PATH;
6752     lstrcpyA(buf, "apple");
6753     r = pMsiGetProductInfoExA(prodcode, usersid,
6754                               MSIINSTALLCONTEXT_USERUNMANAGED,
6755                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
6756     ok(r == ERROR_UNKNOWN_PROPERTY,
6757        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6758     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6759     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6760 
6761     res = RegSetValueExA(prodkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
6762     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6763 
6764     /* DisplayName value exists */
6765     sz = MAX_PATH;
6766     lstrcpyA(buf, "apple");
6767     r = pMsiGetProductInfoExA(prodcode, usersid,
6768                               MSIINSTALLCONTEXT_USERUNMANAGED,
6769                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
6770     ok(r == ERROR_UNKNOWN_PROPERTY,
6771        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6772     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6773     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6774 
6775     res = RegSetValueExA(prodkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
6776     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6777 
6778     /* InstallLocation value exists */
6779     sz = MAX_PATH;
6780     lstrcpyA(buf, "apple");
6781     r = pMsiGetProductInfoExA(prodcode, usersid,
6782                               MSIINSTALLCONTEXT_USERUNMANAGED,
6783                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
6784     ok(r == ERROR_UNKNOWN_PROPERTY,
6785        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6786     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6787     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6788 
6789     res = RegSetValueExA(prodkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
6790     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6791 
6792     /* InstallSource value exists */
6793     sz = MAX_PATH;
6794     lstrcpyA(buf, "apple");
6795     r = pMsiGetProductInfoExA(prodcode, usersid,
6796                               MSIINSTALLCONTEXT_USERUNMANAGED,
6797                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
6798     ok(r == ERROR_UNKNOWN_PROPERTY,
6799        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6800     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6801     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6802 
6803     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6804     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6805 
6806     /* LocalPackage value exists */
6807     sz = MAX_PATH;
6808     lstrcpyA(buf, "apple");
6809     r = pMsiGetProductInfoExA(prodcode, usersid,
6810                               MSIINSTALLCONTEXT_USERUNMANAGED,
6811                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
6812     ok(r == ERROR_UNKNOWN_PROPERTY,
6813        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6814     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6815     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6816 
6817     res = RegSetValueExA(prodkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
6818     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6819 
6820     /* Publisher value exists */
6821     sz = MAX_PATH;
6822     lstrcpyA(buf, "apple");
6823     r = pMsiGetProductInfoExA(prodcode, usersid,
6824                               MSIINSTALLCONTEXT_USERUNMANAGED,
6825                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
6826     ok(r == ERROR_UNKNOWN_PROPERTY,
6827        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6828     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6829     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6830 
6831     res = RegSetValueExA(prodkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
6832     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6833 
6834     /* URLInfoAbout value exists */
6835     sz = MAX_PATH;
6836     lstrcpyA(buf, "apple");
6837     r = pMsiGetProductInfoExA(prodcode, usersid,
6838                               MSIINSTALLCONTEXT_USERUNMANAGED,
6839                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
6840     ok(r == ERROR_UNKNOWN_PROPERTY,
6841        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6842     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6843     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6844 
6845     res = RegSetValueExA(prodkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
6846     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6847 
6848     /* URLUpdateInfo value exists */
6849     sz = MAX_PATH;
6850     lstrcpyA(buf, "apple");
6851     r = pMsiGetProductInfoExA(prodcode, usersid,
6852                               MSIINSTALLCONTEXT_USERUNMANAGED,
6853                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
6854     ok(r == ERROR_UNKNOWN_PROPERTY,
6855        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6856     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6857     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6858 
6859     res = RegSetValueExA(prodkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
6860     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6861 
6862     /* VersionMinor value exists */
6863     sz = MAX_PATH;
6864     lstrcpyA(buf, "apple");
6865     r = pMsiGetProductInfoExA(prodcode, usersid,
6866                               MSIINSTALLCONTEXT_USERUNMANAGED,
6867                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
6868     ok(r == ERROR_UNKNOWN_PROPERTY,
6869        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6870     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6871     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6872 
6873     res = RegSetValueExA(prodkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
6874     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6875 
6876     /* VersionMajor value exists */
6877     sz = MAX_PATH;
6878     lstrcpyA(buf, "apple");
6879     r = pMsiGetProductInfoExA(prodcode, usersid,
6880                               MSIINSTALLCONTEXT_USERUNMANAGED,
6881                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
6882     ok(r == ERROR_UNKNOWN_PROPERTY,
6883        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6884     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6885     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6886 
6887     res = RegSetValueExA(prodkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
6888     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6889 
6890     /* DisplayVersion value exists */
6891     sz = MAX_PATH;
6892     lstrcpyA(buf, "apple");
6893     r = pMsiGetProductInfoExA(prodcode, usersid,
6894                               MSIINSTALLCONTEXT_USERUNMANAGED,
6895                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
6896     ok(r == ERROR_UNKNOWN_PROPERTY,
6897        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6898     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6899     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6900 
6901     res = RegSetValueExA(prodkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
6902     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6903 
6904     /* ProductID value exists */
6905     sz = MAX_PATH;
6906     lstrcpyA(buf, "apple");
6907     r = pMsiGetProductInfoExA(prodcode, usersid,
6908                               MSIINSTALLCONTEXT_USERUNMANAGED,
6909                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
6910     ok(r == ERROR_UNKNOWN_PROPERTY,
6911        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6912     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6913     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6914 
6915     res = RegSetValueExA(prodkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
6916     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6917 
6918     /* RegCompany value exists */
6919     sz = MAX_PATH;
6920     lstrcpyA(buf, "apple");
6921     r = pMsiGetProductInfoExA(prodcode, usersid,
6922                               MSIINSTALLCONTEXT_USERUNMANAGED,
6923                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
6924     ok(r == ERROR_UNKNOWN_PROPERTY,
6925        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6926     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6927     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6928 
6929     res = RegSetValueExA(prodkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
6930     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6931 
6932     /* RegOwner value exists */
6933     sz = MAX_PATH;
6934     lstrcpyA(buf, "apple");
6935     r = pMsiGetProductInfoExA(prodcode, usersid,
6936                               MSIINSTALLCONTEXT_USERUNMANAGED,
6937                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
6938     ok(r == ERROR_UNKNOWN_PROPERTY,
6939        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6940     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6941     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6942 
6943     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
6944     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6945 
6946     /* Transforms value exists */
6947     sz = MAX_PATH;
6948     lstrcpyA(buf, "apple");
6949     r = pMsiGetProductInfoExA(prodcode, usersid,
6950                               MSIINSTALLCONTEXT_USERUNMANAGED,
6951                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
6952     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6953     ok(!lstrcmpA(buf, "trans"), "Expected \"trans\", got \"%s\"\n", buf);
6954     ok(sz == 5, "Expected 5, got %d\n", sz);
6955 
6956     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
6957     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6958 
6959     /* Language value exists */
6960     sz = MAX_PATH;
6961     lstrcpyA(buf, "apple");
6962     r = pMsiGetProductInfoExA(prodcode, usersid,
6963                               MSIINSTALLCONTEXT_USERUNMANAGED,
6964                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
6965     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6966     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
6967     ok(sz == 4, "Expected 4, got %d\n", sz);
6968 
6969     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
6970     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6971 
6972     /* ProductName value exists */
6973     sz = MAX_PATH;
6974     lstrcpyA(buf, "apple");
6975     r = pMsiGetProductInfoExA(prodcode, usersid,
6976                               MSIINSTALLCONTEXT_USERUNMANAGED,
6977                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
6978     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6979     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
6980     ok(sz == 4, "Expected 4, got %d\n", sz);
6981 
6982     res = RegSetValueExA(prodkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
6983     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6984 
6985     /* FIXME */
6986 
6987     /* AssignmentType value exists */
6988     sz = MAX_PATH;
6989     lstrcpyA(buf, "apple");
6990     r = pMsiGetProductInfoExA(prodcode, usersid,
6991                               MSIINSTALLCONTEXT_USERUNMANAGED,
6992                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
6993     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6994     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
6995     ok(sz == 0, "Expected 0, got %d\n", sz);
6996 
6997     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
6998     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6999 
7000     /* FIXME */
7001 
7002     /* PackageCode value exists */
7003     sz = MAX_PATH;
7004     lstrcpyA(buf, "apple");
7005     r = pMsiGetProductInfoExA(prodcode, usersid,
7006                               MSIINSTALLCONTEXT_USERUNMANAGED,
7007                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
7008     todo_wine
7009     {
7010         ok(r == ERROR_BAD_CONFIGURATION,
7011            "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
7012         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7013         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7014     }
7015 
7016     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
7017     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7018 
7019     /* Version value exists */
7020     sz = MAX_PATH;
7021     lstrcpyA(buf, "apple");
7022     r = pMsiGetProductInfoExA(prodcode, usersid,
7023                               MSIINSTALLCONTEXT_USERUNMANAGED,
7024                               INSTALLPROPERTY_VERSIONA, buf, &sz);
7025     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7026     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
7027     ok(sz == 3, "Expected 3, got %d\n", sz);
7028 
7029     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
7030     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7031 
7032     /* ProductIcon value exists */
7033     sz = MAX_PATH;
7034     lstrcpyA(buf, "apple");
7035     r = pMsiGetProductInfoExA(prodcode, usersid,
7036                               MSIINSTALLCONTEXT_USERUNMANAGED,
7037                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
7038     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7039     ok(!lstrcmpA(buf, "icon"), "Expected \"icon\", got \"%s\"\n", buf);
7040     ok(sz == 4, "Expected 4, got %d\n", sz);
7041 
7042     res = RegSetValueExA(prodkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
7043     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7044 
7045     /* PackageName value exists */
7046     sz = MAX_PATH;
7047     lstrcpyA(buf, "apple");
7048     r = pMsiGetProductInfoExA(prodcode, usersid,
7049                               MSIINSTALLCONTEXT_USERUNMANAGED,
7050                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
7051     todo_wine
7052     {
7053         ok(r == ERROR_UNKNOWN_PRODUCT,
7054            "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7055         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7056         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7057     }
7058 
7059     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
7060     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7061 
7062     /* AuthorizedLUAApp value exists */
7063     sz = MAX_PATH;
7064     lstrcpyA(buf, "apple");
7065     r = pMsiGetProductInfoExA(prodcode, usersid,
7066                               MSIINSTALLCONTEXT_USERUNMANAGED,
7067                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
7068     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7069     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
7070     ok(sz == 4, "Expected 4, got %d\n", sz);
7071 
7072     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
7073     RegDeleteValueA(prodkey, "PackageName");
7074     RegDeleteValueA(prodkey, "ProductIcon");
7075     RegDeleteValueA(prodkey, "Version");
7076     RegDeleteValueA(prodkey, "PackageCode");
7077     RegDeleteValueA(prodkey, "AssignmentType");
7078     RegDeleteValueA(prodkey, "ProductName");
7079     RegDeleteValueA(prodkey, "Language");
7080     RegDeleteValueA(prodkey, "Transforms");
7081     RegDeleteValueA(prodkey, "RegOwner");
7082     RegDeleteValueA(prodkey, "RegCompany");
7083     RegDeleteValueA(prodkey, "ProductID");
7084     RegDeleteValueA(prodkey, "DisplayVersion");
7085     RegDeleteValueA(prodkey, "VersionMajor");
7086     RegDeleteValueA(prodkey, "VersionMinor");
7087     RegDeleteValueA(prodkey, "URLUpdateInfo");
7088     RegDeleteValueA(prodkey, "URLInfoAbout");
7089     RegDeleteValueA(prodkey, "Publisher");
7090     RegDeleteValueA(prodkey, "LocalPackage");
7091     RegDeleteValueA(prodkey, "InstallSource");
7092     RegDeleteValueA(prodkey, "InstallLocation");
7093     RegDeleteValueA(prodkey, "DisplayName");
7094     RegDeleteValueA(prodkey, "InstallDate");
7095     RegDeleteValueA(prodkey, "HelpTelephone");
7096     RegDeleteValueA(prodkey, "HelpLink");
7097     RegDeleteValueA(prodkey, "LocalPackage");
7098     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
7099     RegCloseKey(prodkey);
7100 
7101     /* MSIINSTALLCONTEXT_USERMANAGED */
7102 
7103     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
7104     lstrcatA(keypath, usersid);
7105     lstrcatA(keypath, "\\Products\\");
7106     lstrcatA(keypath, prod_squashed);
7107 
7108     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
7109     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7110 
7111     /* local user product key exists */
7112     sz = MAX_PATH;
7113     lstrcpyA(buf, "apple");
7114     r = pMsiGetProductInfoExA(prodcode, usersid,
7115                               MSIINSTALLCONTEXT_USERMANAGED,
7116                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7117     ok(r == ERROR_UNKNOWN_PRODUCT,
7118        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7119     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7120     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7121 
7122     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
7123     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7124 
7125     /* InstallProperties key exists */
7126     sz = MAX_PATH;
7127     lstrcpyA(buf, "apple");
7128     r = pMsiGetProductInfoExA(prodcode, usersid,
7129                               MSIINSTALLCONTEXT_USERMANAGED,
7130                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7131     ok(r == ERROR_UNKNOWN_PRODUCT,
7132        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7133     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7134     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7135 
7136     res = RegSetValueExA(propkey, "ManagedLocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
7137     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7138 
7139     /* ManagedLocalPackage value exists */
7140     sz = MAX_PATH;
7141     lstrcpyA(buf, "apple");
7142     r = pMsiGetProductInfoExA(prodcode, usersid,
7143                               MSIINSTALLCONTEXT_USERMANAGED,
7144                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7145     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7146     ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
7147     ok(sz == 1, "Expected 1, got %d\n", sz);
7148 
7149     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
7150     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7151 
7152     /* HelpLink value exists */
7153     sz = MAX_PATH;
7154     lstrcpyA(buf, "apple");
7155     r = pMsiGetProductInfoExA(prodcode, usersid,
7156                               MSIINSTALLCONTEXT_USERMANAGED,
7157                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
7158     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7159     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
7160     ok(sz == 4, "Expected 4, got %d\n", sz);
7161 
7162     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
7163     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7164 
7165     /* HelpTelephone value exists */
7166     sz = MAX_PATH;
7167     lstrcpyA(buf, "apple");
7168     r = pMsiGetProductInfoExA(prodcode, usersid,
7169                               MSIINSTALLCONTEXT_USERMANAGED,
7170                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
7171     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7172     ok(!lstrcmpA(buf, "phone"), "Expected \"phone\", got \"%s\"\n", buf);
7173     ok(sz == 5, "Expected 5, got %d\n", sz);
7174 
7175     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
7176     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7177 
7178     /* InstallDate value exists */
7179     sz = MAX_PATH;
7180     lstrcpyA(buf, "apple");
7181     r = pMsiGetProductInfoExA(prodcode, usersid,
7182                               MSIINSTALLCONTEXT_USERMANAGED,
7183                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
7184     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7185     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
7186     ok(sz == 4, "Expected 4, got %d\n", sz);
7187 
7188     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
7189     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7190 
7191     /* DisplayName value exists */
7192     sz = MAX_PATH;
7193     lstrcpyA(buf, "apple");
7194     r = pMsiGetProductInfoExA(prodcode, usersid,
7195                               MSIINSTALLCONTEXT_USERMANAGED,
7196                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
7197     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7198     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
7199     ok(sz == 4, "Expected 4, got %d\n", sz);
7200 
7201     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
7202     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7203 
7204     /* InstallLocation value exists */
7205     sz = MAX_PATH;
7206     lstrcpyA(buf, "apple");
7207     r = pMsiGetProductInfoExA(prodcode, usersid,
7208                               MSIINSTALLCONTEXT_USERMANAGED,
7209                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
7210     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7211     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
7212     ok(sz == 3, "Expected 3, got %d\n", sz);
7213 
7214     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
7215     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7216 
7217     /* InstallSource value exists */
7218     sz = MAX_PATH;
7219     lstrcpyA(buf, "apple");
7220     r = pMsiGetProductInfoExA(prodcode, usersid,
7221                               MSIINSTALLCONTEXT_USERMANAGED,
7222                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
7223     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7224     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
7225     ok(sz == 6, "Expected 6, got %d\n", sz);
7226 
7227     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
7228     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7229 
7230     /* LocalPackage value exists */
7231     sz = MAX_PATH;
7232     lstrcpyA(buf, "apple");
7233     r = pMsiGetProductInfoExA(prodcode, usersid,
7234                               MSIINSTALLCONTEXT_USERMANAGED,
7235                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
7236     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7237     ok(!lstrcmpA(buf, "local"), "Expected \"local\", got \"%s\"\n", buf);
7238     ok(sz == 5, "Expected 5, got %d\n", sz);
7239 
7240     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
7241     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7242 
7243     /* Publisher value exists */
7244     sz = MAX_PATH;
7245     lstrcpyA(buf, "apple");
7246     r = pMsiGetProductInfoExA(prodcode, usersid,
7247                               MSIINSTALLCONTEXT_USERMANAGED,
7248                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
7249     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7250     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
7251     ok(sz == 3, "Expected 3, got %d\n", sz);
7252 
7253     res = RegSetValueExA(propkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
7254     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7255 
7256     /* URLInfoAbout value exists */
7257     sz = MAX_PATH;
7258     lstrcpyA(buf, "apple");
7259     r = pMsiGetProductInfoExA(prodcode, usersid,
7260                               MSIINSTALLCONTEXT_USERMANAGED,
7261                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
7262     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7263     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
7264     ok(sz == 5, "Expected 5, got %d\n", sz);
7265 
7266     res = RegSetValueExA(propkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
7267     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7268 
7269     /* URLUpdateInfo value exists */
7270     sz = MAX_PATH;
7271     lstrcpyA(buf, "apple");
7272     r = pMsiGetProductInfoExA(prodcode, usersid,
7273                               MSIINSTALLCONTEXT_USERMANAGED,
7274                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
7275     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7276     ok(!lstrcmpA(buf, "update"), "Expected \"update\", got \"%s\"\n", buf);
7277     ok(sz == 6, "Expected 6, got %d\n", sz);
7278 
7279     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
7280     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7281 
7282     /* VersionMinor value exists */
7283     sz = MAX_PATH;
7284     lstrcpyA(buf, "apple");
7285     r = pMsiGetProductInfoExA(prodcode, usersid,
7286                               MSIINSTALLCONTEXT_USERMANAGED,
7287                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
7288     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7289     ok(!lstrcmpA(buf, "2"), "Expected \"2\", got \"%s\"\n", buf);
7290     ok(sz == 1, "Expected 1, got %d\n", sz);
7291 
7292     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
7293     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7294 
7295     /* VersionMajor value exists */
7296     sz = MAX_PATH;
7297     lstrcpyA(buf, "apple");
7298     r = pMsiGetProductInfoExA(prodcode, usersid,
7299                               MSIINSTALLCONTEXT_USERMANAGED,
7300                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
7301     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7302     ok(!lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
7303     ok(sz == 1, "Expected 1, got %d\n", sz);
7304 
7305     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
7306     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7307 
7308     /* DisplayVersion value exists */
7309     sz = MAX_PATH;
7310     lstrcpyA(buf, "apple");
7311     r = pMsiGetProductInfoExA(prodcode, usersid,
7312                               MSIINSTALLCONTEXT_USERMANAGED,
7313                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
7314     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7315     ok(!lstrcmpA(buf, "3.2.1"), "Expected \"3.2.1\", got \"%s\"\n", buf);
7316     ok(sz == 5, "Expected 5, got %d\n", sz);
7317 
7318     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
7319     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7320 
7321     /* ProductID value exists */
7322     sz = MAX_PATH;
7323     lstrcpyA(buf, "apple");
7324     r = pMsiGetProductInfoExA(prodcode, usersid,
7325                               MSIINSTALLCONTEXT_USERMANAGED,
7326                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
7327     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7328     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
7329     ok(sz == 2, "Expected 2, got %d\n", sz);
7330 
7331     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
7332     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7333 
7334     /* RegCompany value exists */
7335     sz = MAX_PATH;
7336     lstrcpyA(buf, "apple");
7337     r = pMsiGetProductInfoExA(prodcode, usersid,
7338                               MSIINSTALLCONTEXT_USERMANAGED,
7339                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
7340     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7341     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
7342     ok(sz == 4, "Expected 4, got %d\n", sz);
7343 
7344     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
7345     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7346 
7347     /* RegOwner value exists */
7348     sz = MAX_PATH;
7349     lstrcpyA(buf, "apple");
7350     r = pMsiGetProductInfoExA(prodcode, usersid,
7351                               MSIINSTALLCONTEXT_USERMANAGED,
7352                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
7353     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7354     ok(!lstrcmpA(buf, "owner"), "Expected \"owner\", got \"%s\"\n", buf);
7355     ok(sz == 5, "Expected 5, got %d\n", sz);
7356 
7357     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
7358     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7359 
7360     /* Transforms value exists */
7361     sz = MAX_PATH;
7362     lstrcpyA(buf, "apple");
7363     r = pMsiGetProductInfoExA(prodcode, usersid,
7364                               MSIINSTALLCONTEXT_USERMANAGED,
7365                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
7366     ok(r == ERROR_UNKNOWN_PRODUCT,
7367        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7368     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7369     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7370 
7371     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
7372     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7373 
7374     /* Language value exists */
7375     sz = MAX_PATH;
7376     lstrcpyA(buf, "apple");
7377     r = pMsiGetProductInfoExA(prodcode, usersid,
7378                               MSIINSTALLCONTEXT_USERMANAGED,
7379                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
7380     ok(r == ERROR_UNKNOWN_PRODUCT,
7381        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7382     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7383     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7384 
7385     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
7386     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7387 
7388     /* ProductName value exists */
7389     sz = MAX_PATH;
7390     lstrcpyA(buf, "apple");
7391     r = pMsiGetProductInfoExA(prodcode, usersid,
7392                               MSIINSTALLCONTEXT_USERMANAGED,
7393                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
7394     ok(r == ERROR_UNKNOWN_PRODUCT,
7395        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7396     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7397     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7398 
7399     res = RegSetValueExA(propkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
7400     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7401 
7402     /* FIXME */
7403 
7404     /* AssignmentType value exists */
7405     sz = MAX_PATH;
7406     lstrcpyA(buf, "apple");
7407     r = pMsiGetProductInfoExA(prodcode, usersid,
7408                               MSIINSTALLCONTEXT_USERMANAGED,
7409                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
7410     ok(r == ERROR_UNKNOWN_PRODUCT,
7411        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7412     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7413     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7414 
7415     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
7416     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7417 
7418     /* PackageCode value exists */
7419     sz = MAX_PATH;
7420     lstrcpyA(buf, "apple");
7421     r = pMsiGetProductInfoExA(prodcode, usersid,
7422                               MSIINSTALLCONTEXT_USERMANAGED,
7423                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
7424     ok(r == ERROR_UNKNOWN_PRODUCT,
7425        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7426     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7427     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7428 
7429     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
7430     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7431 
7432     /* Version value exists */
7433     sz = MAX_PATH;
7434     lstrcpyA(buf, "apple");
7435     r = pMsiGetProductInfoExA(prodcode, usersid,
7436                               MSIINSTALLCONTEXT_USERMANAGED,
7437                               INSTALLPROPERTY_VERSIONA, buf, &sz);
7438     ok(r == ERROR_UNKNOWN_PRODUCT,
7439        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7440     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7441     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7442 
7443     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
7444     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7445 
7446     /* ProductIcon value exists */
7447     sz = MAX_PATH;
7448     lstrcpyA(buf, "apple");
7449     r = pMsiGetProductInfoExA(prodcode, usersid,
7450                               MSIINSTALLCONTEXT_USERMANAGED,
7451                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
7452     ok(r == ERROR_UNKNOWN_PRODUCT,
7453        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7454     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7455     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7456 
7457     res = RegSetValueExA(propkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
7458     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7459 
7460     /* PackageName value exists */
7461     sz = MAX_PATH;
7462     lstrcpyA(buf, "apple");
7463     r = pMsiGetProductInfoExA(prodcode, usersid,
7464                               MSIINSTALLCONTEXT_USERMANAGED,
7465                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
7466     ok(r == ERROR_UNKNOWN_PRODUCT,
7467        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7468     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7469     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7470 
7471     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
7472     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7473 
7474     /* AuthorizedLUAApp value exists */
7475     sz = MAX_PATH;
7476     lstrcpyA(buf, "apple");
7477     r = pMsiGetProductInfoExA(prodcode, usersid,
7478                               MSIINSTALLCONTEXT_USERMANAGED,
7479                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
7480     ok(r == ERROR_UNKNOWN_PRODUCT,
7481        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7482     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7483     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7484 
7485     RegDeleteValueA(propkey, "AuthorizedLUAApp");
7486     RegDeleteValueA(propkey, "PackageName");
7487     RegDeleteValueA(propkey, "ProductIcon");
7488     RegDeleteValueA(propkey, "Version");
7489     RegDeleteValueA(propkey, "PackageCode");
7490     RegDeleteValueA(propkey, "AssignmentType");
7491     RegDeleteValueA(propkey, "ProductName");
7492     RegDeleteValueA(propkey, "Language");
7493     RegDeleteValueA(propkey, "Transforms");
7494     RegDeleteValueA(propkey, "RegOwner");
7495     RegDeleteValueA(propkey, "RegCompany");
7496     RegDeleteValueA(propkey, "ProductID");
7497     RegDeleteValueA(propkey, "DisplayVersion");
7498     RegDeleteValueA(propkey, "VersionMajor");
7499     RegDeleteValueA(propkey, "VersionMinor");
7500     RegDeleteValueA(propkey, "URLUpdateInfo");
7501     RegDeleteValueA(propkey, "URLInfoAbout");
7502     RegDeleteValueA(propkey, "Publisher");
7503     RegDeleteValueA(propkey, "LocalPackage");
7504     RegDeleteValueA(propkey, "InstallSource");
7505     RegDeleteValueA(propkey, "InstallLocation");
7506     RegDeleteValueA(propkey, "DisplayName");
7507     RegDeleteValueA(propkey, "InstallDate");
7508     RegDeleteValueA(propkey, "HelpTelephone");
7509     RegDeleteValueA(propkey, "HelpLink");
7510     RegDeleteValueA(propkey, "ManagedLocalPackage");
7511     delete_key(propkey, "", access & KEY_WOW64_64KEY);
7512     RegCloseKey(propkey);
7513     delete_key(localkey, "", access & KEY_WOW64_64KEY);
7514     RegCloseKey(localkey);
7515 
7516     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
7517     lstrcatA(keypath, usersid);
7518     lstrcatA(keypath, "\\Installer\\Products\\");
7519     lstrcatA(keypath, prod_squashed);
7520 
7521     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
7522     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7523 
7524     /* user product key exists */
7525     sz = MAX_PATH;
7526     lstrcpyA(buf, "apple");
7527     r = pMsiGetProductInfoExA(prodcode, usersid,
7528                               MSIINSTALLCONTEXT_USERMANAGED,
7529                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7530     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7531     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
7532     ok(sz == 1, "Expected 1, got %d\n", sz);
7533 
7534     delete_key(userkey, "", access & KEY_WOW64_64KEY);
7535     RegCloseKey(userkey);
7536 
7537     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
7538     lstrcatA(keypath, prod_squashed);
7539 
7540     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
7541     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7542 
7543     /* current user product key exists */
7544     sz = MAX_PATH;
7545     lstrcpyA(buf, "apple");
7546     r = pMsiGetProductInfoExA(prodcode, usersid,
7547                               MSIINSTALLCONTEXT_USERMANAGED,
7548                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7549     ok(r == ERROR_UNKNOWN_PRODUCT,
7550        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7551     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7552     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7553 
7554     res = RegSetValueExA(prodkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
7555     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7556 
7557     /* HelpLink value exists, user product key does not exist */
7558     sz = MAX_PATH;
7559     lstrcpyA(buf, "apple");
7560     r = pMsiGetProductInfoExA(prodcode, usersid,
7561                               MSIINSTALLCONTEXT_USERMANAGED,
7562                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
7563     ok(r == ERROR_UNKNOWN_PRODUCT,
7564        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7565     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7566     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7567 
7568     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
7569     lstrcatA(keypath, usersid);
7570     lstrcatA(keypath, "\\Installer\\Products\\");
7571     lstrcatA(keypath, prod_squashed);
7572 
7573     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
7574     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7575 
7576     res = RegSetValueExA(userkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
7577     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7578 
7579     /* HelpLink value exists, user product key does exist */
7580     sz = MAX_PATH;
7581     lstrcpyA(buf, "apple");
7582     r = pMsiGetProductInfoExA(prodcode, usersid,
7583                               MSIINSTALLCONTEXT_USERMANAGED,
7584                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
7585     ok(r == ERROR_UNKNOWN_PROPERTY,
7586        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7587     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7588     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7589 
7590     res = RegSetValueExA(userkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
7591     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7592 
7593     /* HelpTelephone value exists */
7594     sz = MAX_PATH;
7595     lstrcpyA(buf, "apple");
7596     r = pMsiGetProductInfoExA(prodcode, usersid,
7597                               MSIINSTALLCONTEXT_USERMANAGED,
7598                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
7599     ok(r == ERROR_UNKNOWN_PROPERTY,
7600        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7601     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7602     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7603 
7604     res = RegSetValueExA(userkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
7605     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7606 
7607     /* InstallDate value exists */
7608     sz = MAX_PATH;
7609     lstrcpyA(buf, "apple");
7610     r = pMsiGetProductInfoExA(prodcode, usersid,
7611                               MSIINSTALLCONTEXT_USERMANAGED,
7612                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
7613     ok(r == ERROR_UNKNOWN_PROPERTY,
7614        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7615     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7616     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7617 
7618     res = RegSetValueExA(userkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
7619     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7620 
7621     /* DisplayName value exists */
7622     sz = MAX_PATH;
7623     lstrcpyA(buf, "apple");
7624     r = pMsiGetProductInfoExA(prodcode, usersid,
7625                               MSIINSTALLCONTEXT_USERMANAGED,
7626                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
7627     ok(r == ERROR_UNKNOWN_PROPERTY,
7628        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7629     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7630     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7631 
7632     res = RegSetValueExA(userkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
7633     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7634 
7635     /* InstallLocation value exists */
7636     sz = MAX_PATH;
7637     lstrcpyA(buf, "apple");
7638     r = pMsiGetProductInfoExA(prodcode, usersid,
7639                               MSIINSTALLCONTEXT_USERMANAGED,
7640                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
7641     ok(r == ERROR_UNKNOWN_PROPERTY,
7642        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7643     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7644     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7645 
7646     res = RegSetValueExA(userkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
7647     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7648 
7649     /* InstallSource value exists */
7650     sz = MAX_PATH;
7651     lstrcpyA(buf, "apple");
7652     r = pMsiGetProductInfoExA(prodcode, usersid,
7653                               MSIINSTALLCONTEXT_USERMANAGED,
7654                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
7655     ok(r == ERROR_UNKNOWN_PROPERTY,
7656        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7657     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7658     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7659 
7660     res = RegSetValueExA(userkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
7661     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7662 
7663     /* LocalPackage value exists */
7664     sz = MAX_PATH;
7665     lstrcpyA(buf, "apple");
7666     r = pMsiGetProductInfoExA(prodcode, usersid,
7667                               MSIINSTALLCONTEXT_USERMANAGED,
7668                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
7669     ok(r == ERROR_UNKNOWN_PROPERTY,
7670        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7671     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7672     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7673 
7674     res = RegSetValueExA(userkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
7675     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7676 
7677     /* Publisher value exists */
7678     sz = MAX_PATH;
7679     lstrcpyA(buf, "apple");
7680     r = pMsiGetProductInfoExA(prodcode, usersid,
7681                               MSIINSTALLCONTEXT_USERMANAGED,
7682                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
7683     ok(r == ERROR_UNKNOWN_PROPERTY,
7684        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7685     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7686     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7687 
7688     res = RegSetValueExA(userkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
7689     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7690 
7691     /* URLInfoAbout value exists */
7692     sz = MAX_PATH;
7693     lstrcpyA(buf, "apple");
7694     r = pMsiGetProductInfoExA(prodcode, usersid,
7695                               MSIINSTALLCONTEXT_USERMANAGED,
7696                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
7697     ok(r == ERROR_UNKNOWN_PROPERTY,
7698        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7699     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7700     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7701 
7702     res = RegSetValueExA(userkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
7703     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7704 
7705     /* URLUpdateInfo value exists */
7706     sz = MAX_PATH;
7707     lstrcpyA(buf, "apple");
7708     r = pMsiGetProductInfoExA(prodcode, usersid,
7709                               MSIINSTALLCONTEXT_USERMANAGED,
7710                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
7711     ok(r == ERROR_UNKNOWN_PROPERTY,
7712        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7713     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7714     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7715 
7716     res = RegSetValueExA(userkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
7717     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7718 
7719     /* VersionMinor value exists */
7720     sz = MAX_PATH;
7721     lstrcpyA(buf, "apple");
7722     r = pMsiGetProductInfoExA(prodcode, usersid,
7723                               MSIINSTALLCONTEXT_USERMANAGED,
7724                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
7725     ok(r == ERROR_UNKNOWN_PROPERTY,
7726        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7727     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7728     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7729 
7730     res = RegSetValueExA(userkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
7731     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7732 
7733     /* VersionMajor value exists */
7734     sz = MAX_PATH;
7735     lstrcpyA(buf, "apple");
7736     r = pMsiGetProductInfoExA(prodcode, usersid,
7737                               MSIINSTALLCONTEXT_USERMANAGED,
7738                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
7739     ok(r == ERROR_UNKNOWN_PROPERTY,
7740        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7741     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7742     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7743 
7744     res = RegSetValueExA(userkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
7745     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7746 
7747     /* DisplayVersion value exists */
7748     sz = MAX_PATH;
7749     lstrcpyA(buf, "apple");
7750     r = pMsiGetProductInfoExA(prodcode, usersid,
7751                               MSIINSTALLCONTEXT_USERMANAGED,
7752                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
7753     ok(r == ERROR_UNKNOWN_PROPERTY,
7754        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7755     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7756     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7757 
7758     res = RegSetValueExA(userkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
7759     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7760 
7761     /* ProductID value exists */
7762     sz = MAX_PATH;
7763     lstrcpyA(buf, "apple");
7764     r = pMsiGetProductInfoExA(prodcode, usersid,
7765                               MSIINSTALLCONTEXT_USERMANAGED,
7766                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
7767     ok(r == ERROR_UNKNOWN_PROPERTY,
7768        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7769     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7770     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7771 
7772     res = RegSetValueExA(userkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
7773     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7774 
7775     /* RegCompany value exists */
7776     sz = MAX_PATH;
7777     lstrcpyA(buf, "apple");
7778     r = pMsiGetProductInfoExA(prodcode, usersid,
7779                               MSIINSTALLCONTEXT_USERMANAGED,
7780                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
7781     ok(r == ERROR_UNKNOWN_PROPERTY,
7782        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7783     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7784     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7785 
7786     res = RegSetValueExA(userkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
7787     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7788 
7789     /* RegOwner value exists */
7790     sz = MAX_PATH;
7791     lstrcpyA(buf, "apple");
7792     r = pMsiGetProductInfoExA(prodcode, usersid,
7793                               MSIINSTALLCONTEXT_USERMANAGED,
7794                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
7795     ok(r == ERROR_UNKNOWN_PROPERTY,
7796        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7797     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7798     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7799 
7800     res = RegSetValueExA(userkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
7801     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7802 
7803     /* Transforms value exists */
7804     sz = MAX_PATH;
7805     lstrcpyA(buf, "apple");
7806     r = pMsiGetProductInfoExA(prodcode, usersid,
7807                               MSIINSTALLCONTEXT_USERMANAGED,
7808                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
7809     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7810     ok(!lstrcmpA(buf, "trans"), "Expected \"trans\", got \"%s\"\n", buf);
7811     ok(sz == 5, "Expected 5, got %d\n", sz);
7812 
7813     res = RegSetValueExA(userkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
7814     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7815 
7816     /* Language value exists */
7817     sz = MAX_PATH;
7818     lstrcpyA(buf, "apple");
7819     r = pMsiGetProductInfoExA(prodcode, usersid,
7820                               MSIINSTALLCONTEXT_USERMANAGED,
7821                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
7822     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7823     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
7824     ok(sz == 4, "Expected 4, got %d\n", sz);
7825 
7826     res = RegSetValueExA(userkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
7827     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7828 
7829     /* ProductName value exists */
7830     sz = MAX_PATH;
7831     lstrcpyA(buf, "apple");
7832     r = pMsiGetProductInfoExA(prodcode, usersid,
7833                               MSIINSTALLCONTEXT_USERMANAGED,
7834                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
7835     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7836     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
7837     ok(sz == 4, "Expected 4, got %d\n", sz);
7838 
7839     res = RegSetValueExA(userkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
7840     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7841 
7842     /* FIXME */
7843 
7844     /* AssignmentType value exists */
7845     sz = MAX_PATH;
7846     lstrcpyA(buf, "apple");
7847     r = pMsiGetProductInfoExA(prodcode, usersid,
7848                               MSIINSTALLCONTEXT_USERMANAGED,
7849                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
7850     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7851     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7852     ok(sz == 0, "Expected 0, got %d\n", sz);
7853 
7854     res = RegSetValueExA(userkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
7855     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7856 
7857     /* FIXME */
7858 
7859     /* PackageCode value exists */
7860     sz = MAX_PATH;
7861     lstrcpyA(buf, "apple");
7862     r = pMsiGetProductInfoExA(prodcode, usersid,
7863                               MSIINSTALLCONTEXT_USERMANAGED,
7864                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
7865     todo_wine
7866     {
7867         ok(r == ERROR_BAD_CONFIGURATION,
7868            "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
7869         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7870         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7871     }
7872 
7873     res = RegSetValueExA(userkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
7874     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7875 
7876     /* Version value exists */
7877     sz = MAX_PATH;
7878     lstrcpyA(buf, "apple");
7879     r = pMsiGetProductInfoExA(prodcode, usersid,
7880                               MSIINSTALLCONTEXT_USERMANAGED,
7881                               INSTALLPROPERTY_VERSIONA, buf, &sz);
7882     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7883     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
7884     ok(sz == 3, "Expected 3, got %d\n", sz);
7885 
7886     res = RegSetValueExA(userkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
7887     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7888 
7889     /* ProductIcon value exists */
7890     sz = MAX_PATH;
7891     lstrcpyA(buf, "apple");
7892     r = pMsiGetProductInfoExA(prodcode, usersid,
7893                               MSIINSTALLCONTEXT_USERMANAGED,
7894                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
7895     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7896     ok(!lstrcmpA(buf, "icon"), "Expected \"icon\", got \"%s\"\n", buf);
7897     ok(sz == 4, "Expected 4, got %d\n", sz);
7898 
7899     res = RegSetValueExA(userkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
7900     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7901 
7902     /* PackageName value exists */
7903     sz = MAX_PATH;
7904     lstrcpyA(buf, "apple");
7905     r = pMsiGetProductInfoExA(prodcode, usersid,
7906                               MSIINSTALLCONTEXT_USERMANAGED,
7907                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
7908     todo_wine
7909     {
7910         ok(r == ERROR_UNKNOWN_PRODUCT,
7911            "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7912         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7913         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7914     }
7915 
7916     res = RegSetValueExA(userkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
7917     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7918 
7919     /* AuthorizedLUAApp value exists */
7920     sz = MAX_PATH;
7921     lstrcpyA(buf, "apple");
7922     r = pMsiGetProductInfoExA(prodcode, usersid,
7923                               MSIINSTALLCONTEXT_USERMANAGED,
7924                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
7925     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7926     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
7927     ok(sz == 4, "Expected 4, got %d\n", sz);
7928 
7929     RegDeleteValueA(userkey, "AuthorizedLUAApp");
7930     RegDeleteValueA(userkey, "PackageName");
7931     RegDeleteValueA(userkey, "ProductIcon");
7932     RegDeleteValueA(userkey, "Version");
7933     RegDeleteValueA(userkey, "PackageCode");
7934     RegDeleteValueA(userkey, "AssignmentType");
7935     RegDeleteValueA(userkey, "ProductName");
7936     RegDeleteValueA(userkey, "Language");
7937     RegDeleteValueA(userkey, "Transforms");
7938     RegDeleteValueA(userkey, "RegOwner");
7939     RegDeleteValueA(userkey, "RegCompany");
7940     RegDeleteValueA(userkey, "ProductID");
7941     RegDeleteValueA(userkey, "DisplayVersion");
7942     RegDeleteValueA(userkey, "VersionMajor");
7943     RegDeleteValueA(userkey, "VersionMinor");
7944     RegDeleteValueA(userkey, "URLUpdateInfo");
7945     RegDeleteValueA(userkey, "URLInfoAbout");
7946     RegDeleteValueA(userkey, "Publisher");
7947     RegDeleteValueA(userkey, "LocalPackage");
7948     RegDeleteValueA(userkey, "InstallSource");
7949     RegDeleteValueA(userkey, "InstallLocation");
7950     RegDeleteValueA(userkey, "DisplayName");
7951     RegDeleteValueA(userkey, "InstallDate");
7952     RegDeleteValueA(userkey, "HelpTelephone");
7953     RegDeleteValueA(userkey, "HelpLink");
7954     delete_key(userkey, "", access & KEY_WOW64_64KEY);
7955     RegCloseKey(userkey);
7956     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
7957     RegCloseKey(prodkey);
7958 
7959     /* MSIINSTALLCONTEXT_MACHINE */
7960 
7961     /* szUserSid is non-NULL */
7962     sz = MAX_PATH;
7963     lstrcpyA(buf, "apple");
7964     r = pMsiGetProductInfoExA(prodcode, usersid,
7965                               MSIINSTALLCONTEXT_MACHINE,
7966                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7967     ok(r == ERROR_INVALID_PARAMETER,
7968        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
7969     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7970     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7971 
7972     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\");
7973     lstrcatA(keypath, prod_squashed);
7974 
7975     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
7976     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7977 
7978     /* local system product key exists */
7979     sz = MAX_PATH;
7980     lstrcpyA(buf, "apple");
7981     r = pMsiGetProductInfoExA(prodcode, NULL,
7982                               MSIINSTALLCONTEXT_MACHINE,
7983                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7984     ok(r == ERROR_UNKNOWN_PRODUCT,
7985        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7986     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7987     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7988 
7989     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
7990     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7991 
7992     /* InstallProperties key exists */
7993     sz = MAX_PATH;
7994     lstrcpyA(buf, "apple");
7995     r = pMsiGetProductInfoExA(prodcode, NULL,
7996                               MSIINSTALLCONTEXT_MACHINE,
7997                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7998     ok(r == ERROR_UNKNOWN_PRODUCT,
7999        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8000     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8001     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8002 
8003     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
8004     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8005 
8006     /* LocalPackage value exists */
8007     sz = MAX_PATH;
8008     lstrcpyA(buf, "apple");
8009     r = pMsiGetProductInfoExA(prodcode, NULL,
8010                               MSIINSTALLCONTEXT_MACHINE,
8011                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
8012     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8013     ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
8014     ok(sz == 1, "Expected 1, got %d\n", sz);
8015 
8016     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
8017     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8018 
8019     /* HelpLink value exists */
8020     sz = MAX_PATH;
8021     lstrcpyA(buf, "apple");
8022     r = pMsiGetProductInfoExA(prodcode, NULL,
8023                               MSIINSTALLCONTEXT_MACHINE,
8024                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
8025     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8026     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
8027     ok(sz == 4, "Expected 4, got %d\n", sz);
8028 
8029     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
8030     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8031 
8032     /* HelpTelephone value exists */
8033     sz = MAX_PATH;
8034     lstrcpyA(buf, "apple");
8035     r = pMsiGetProductInfoExA(prodcode, NULL,
8036                               MSIINSTALLCONTEXT_MACHINE,
8037                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
8038     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8039     ok(!lstrcmpA(buf, "phone"), "Expected \"phone\", got \"%s\"\n", buf);
8040     ok(sz == 5, "Expected 5, got %d\n", sz);
8041 
8042     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
8043     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8044 
8045     /* InstallDate value exists */
8046     sz = MAX_PATH;
8047     lstrcpyA(buf, "apple");
8048     r = pMsiGetProductInfoExA(prodcode, NULL,
8049                               MSIINSTALLCONTEXT_MACHINE,
8050                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
8051     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8052     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
8053     ok(sz == 4, "Expected 4, got %d\n", sz);
8054 
8055     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
8056     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8057 
8058     /* DisplayName value exists */
8059     sz = MAX_PATH;
8060     lstrcpyA(buf, "apple");
8061     r = pMsiGetProductInfoExA(prodcode, NULL,
8062                               MSIINSTALLCONTEXT_MACHINE,
8063                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
8064     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8065     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
8066     ok(sz == 4, "Expected 4, got %d\n", sz);
8067 
8068     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
8069     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8070 
8071     /* InstallLocation value exists */
8072     sz = MAX_PATH;
8073     lstrcpyA(buf, "apple");
8074     r = pMsiGetProductInfoExA(prodcode, NULL,
8075                               MSIINSTALLCONTEXT_MACHINE,
8076                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
8077     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8078     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
8079     ok(sz == 3, "Expected 3, got %d\n", sz);
8080 
8081     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
8082     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8083 
8084     /* InstallSource value exists */
8085     sz = MAX_PATH;
8086     lstrcpyA(buf, "apple");
8087     r = pMsiGetProductInfoExA(prodcode, NULL,
8088                               MSIINSTALLCONTEXT_MACHINE,
8089                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
8090     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8091     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
8092     ok(sz == 6, "Expected 6, got %d\n", sz);
8093 
8094     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
8095     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8096 
8097     /* LocalPackage value exists */
8098     sz = MAX_PATH;
8099     lstrcpyA(buf, "apple");
8100     r = pMsiGetProductInfoExA(prodcode, NULL,
8101                               MSIINSTALLCONTEXT_MACHINE,
8102                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
8103     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8104     ok(!lstrcmpA(buf, "local"), "Expected \"local\", got \"%s\"\n", buf);
8105     ok(sz == 5, "Expected 5, got %d\n", sz);
8106 
8107     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
8108     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8109 
8110     /* Publisher value exists */
8111     sz = MAX_PATH;
8112     lstrcpyA(buf, "apple");
8113     r = pMsiGetProductInfoExA(prodcode, NULL,
8114                               MSIINSTALLCONTEXT_MACHINE,
8115                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
8116     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8117     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
8118     ok(sz == 3, "Expected 3, got %d\n", sz);
8119 
8120     res = RegSetValueExA(propkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
8121     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8122 
8123     /* URLInfoAbout value exists */
8124     sz = MAX_PATH;
8125     lstrcpyA(buf, "apple");
8126     r = pMsiGetProductInfoExA(prodcode, NULL,
8127                               MSIINSTALLCONTEXT_MACHINE,
8128                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
8129     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8130     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
8131     ok(sz == 5, "Expected 5, got %d\n", sz);
8132 
8133     res = RegSetValueExA(propkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
8134     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8135 
8136     /* URLUpdateInfo value exists */
8137     sz = MAX_PATH;
8138     lstrcpyA(buf, "apple");
8139     r = pMsiGetProductInfoExA(prodcode, NULL,
8140                               MSIINSTALLCONTEXT_MACHINE,
8141                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
8142     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8143     ok(!lstrcmpA(buf, "update"), "Expected \"update\", got \"%s\"\n", buf);
8144     ok(sz == 6, "Expected 6, got %d\n", sz);
8145 
8146     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
8147     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8148 
8149     /* VersionMinor value exists */
8150     sz = MAX_PATH;
8151     lstrcpyA(buf, "apple");
8152     r = pMsiGetProductInfoExA(prodcode, NULL,
8153                               MSIINSTALLCONTEXT_MACHINE,
8154                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
8155     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8156     ok(!lstrcmpA(buf, "2"), "Expected \"2\", got \"%s\"\n", buf);
8157     ok(sz == 1, "Expected 1, got %d\n", sz);
8158 
8159     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
8160     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8161 
8162     /* VersionMajor value exists */
8163     sz = MAX_PATH;
8164     lstrcpyA(buf, "apple");
8165     r = pMsiGetProductInfoExA(prodcode, NULL,
8166                               MSIINSTALLCONTEXT_MACHINE,
8167                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
8168     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8169     ok(!lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
8170     ok(sz == 1, "Expected 1, got %d\n", sz);
8171 
8172     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
8173     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8174 
8175     /* DisplayVersion value exists */
8176     sz = MAX_PATH;
8177     lstrcpyA(buf, "apple");
8178     r = pMsiGetProductInfoExA(prodcode, NULL,
8179                               MSIINSTALLCONTEXT_MACHINE,
8180                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
8181     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8182     ok(!lstrcmpA(buf, "3.2.1"), "Expected \"3.2.1\", got \"%s\"\n", buf);
8183     ok(sz == 5, "Expected 5, got %d\n", sz);
8184 
8185     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
8186     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8187 
8188     /* ProductID value exists */
8189     sz = MAX_PATH;
8190     lstrcpyA(buf, "apple");
8191     r = pMsiGetProductInfoExA(prodcode, NULL,
8192                               MSIINSTALLCONTEXT_MACHINE,
8193                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
8194     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8195     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
8196     ok(sz == 2, "Expected 2, got %d\n", sz);
8197 
8198     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
8199     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8200 
8201     /* RegCompany value exists */
8202     sz = MAX_PATH;
8203     lstrcpyA(buf, "apple");
8204     r = pMsiGetProductInfoExA(prodcode, NULL,
8205                               MSIINSTALLCONTEXT_MACHINE,
8206                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
8207     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8208     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
8209     ok(sz == 4, "Expected 4, got %d\n", sz);
8210 
8211     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
8212     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8213 
8214     /* RegOwner value exists */
8215     sz = MAX_PATH;
8216     lstrcpyA(buf, "apple");
8217     r = pMsiGetProductInfoExA(prodcode, NULL,
8218                               MSIINSTALLCONTEXT_MACHINE,
8219                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
8220     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8221     ok(!lstrcmpA(buf, "owner"), "Expected \"owner\", got \"%s\"\n", buf);
8222     ok(sz == 5, "Expected 5, got %d\n", sz);
8223 
8224     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
8225     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8226 
8227     /* Transforms value exists */
8228     sz = MAX_PATH;
8229     lstrcpyA(buf, "apple");
8230     r = pMsiGetProductInfoExA(prodcode, NULL,
8231                               MSIINSTALLCONTEXT_MACHINE,
8232                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
8233     ok(r == ERROR_UNKNOWN_PRODUCT,
8234        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8235     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8236     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8237 
8238     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
8239     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8240 
8241     /* Language value exists */
8242     sz = MAX_PATH;
8243     lstrcpyA(buf, "apple");
8244     r = pMsiGetProductInfoExA(prodcode, NULL,
8245                               MSIINSTALLCONTEXT_MACHINE,
8246                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
8247     ok(r == ERROR_UNKNOWN_PRODUCT,
8248        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8249     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8250     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8251 
8252     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
8253     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8254 
8255     /* ProductName value exists */
8256     sz = MAX_PATH;
8257     lstrcpyA(buf, "apple");
8258     r = pMsiGetProductInfoExA(prodcode, NULL,
8259                               MSIINSTALLCONTEXT_MACHINE,
8260                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
8261     ok(r == ERROR_UNKNOWN_PRODUCT,
8262        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8263     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8264     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8265 
8266     res = RegSetValueExA(propkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
8267     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8268 
8269     /* FIXME */
8270 
8271     /* AssignmentType value exists */
8272     sz = MAX_PATH;
8273     lstrcpyA(buf, "apple");
8274     r = pMsiGetProductInfoExA(prodcode, NULL,
8275                               MSIINSTALLCONTEXT_MACHINE,
8276                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
8277     ok(r == ERROR_UNKNOWN_PRODUCT,
8278        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8279     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8280     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8281 
8282     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
8283     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8284 
8285     /* PackageCode value exists */
8286     sz = MAX_PATH;
8287     lstrcpyA(buf, "apple");
8288     r = pMsiGetProductInfoExA(prodcode, NULL,
8289                               MSIINSTALLCONTEXT_MACHINE,
8290                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
8291     ok(r == ERROR_UNKNOWN_PRODUCT,
8292        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8293     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8294     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8295 
8296     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
8297     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8298 
8299     /* Version value exists */
8300     sz = MAX_PATH;
8301     lstrcpyA(buf, "apple");
8302     r = pMsiGetProductInfoExA(prodcode, NULL,
8303                               MSIINSTALLCONTEXT_MACHINE,
8304                               INSTALLPROPERTY_VERSIONA, buf, &sz);
8305     ok(r == ERROR_UNKNOWN_PRODUCT,
8306        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8307     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8308     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8309 
8310     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
8311     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8312 
8313     /* ProductIcon value exists */
8314     sz = MAX_PATH;
8315     lstrcpyA(buf, "apple");
8316     r = pMsiGetProductInfoExA(prodcode, NULL,
8317                               MSIINSTALLCONTEXT_MACHINE,
8318                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
8319     ok(r == ERROR_UNKNOWN_PRODUCT,
8320        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8321     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8322     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8323 
8324     res = RegSetValueExA(propkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
8325     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8326 
8327     /* PackageName value exists */
8328     sz = MAX_PATH;
8329     lstrcpyA(buf, "apple");
8330     r = pMsiGetProductInfoExA(prodcode, NULL,
8331                               MSIINSTALLCONTEXT_MACHINE,
8332                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
8333     ok(r == ERROR_UNKNOWN_PRODUCT,
8334        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8335     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8336     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8337 
8338     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
8339     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8340 
8341     /* AuthorizedLUAApp value exists */
8342     sz = MAX_PATH;
8343     lstrcpyA(buf, "apple");
8344     r = pMsiGetProductInfoExA(prodcode, NULL,
8345                               MSIINSTALLCONTEXT_MACHINE,
8346                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
8347     ok(r == ERROR_UNKNOWN_PRODUCT,
8348        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8349     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8350     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8351 
8352     RegDeleteValueA(propkey, "AuthorizedLUAApp");
8353     RegDeleteValueA(propkey, "PackageName");
8354     RegDeleteValueA(propkey, "ProductIcon");
8355     RegDeleteValueA(propkey, "Version");
8356     RegDeleteValueA(propkey, "PackageCode");
8357     RegDeleteValueA(propkey, "AssignmentType");
8358     RegDeleteValueA(propkey, "ProductName");
8359     RegDeleteValueA(propkey, "Language");
8360     RegDeleteValueA(propkey, "Transforms");
8361     RegDeleteValueA(propkey, "RegOwner");
8362     RegDeleteValueA(propkey, "RegCompany");
8363     RegDeleteValueA(propkey, "ProductID");
8364     RegDeleteValueA(propkey, "DisplayVersion");
8365     RegDeleteValueA(propkey, "VersionMajor");
8366     RegDeleteValueA(propkey, "VersionMinor");
8367     RegDeleteValueA(propkey, "URLUpdateInfo");
8368     RegDeleteValueA(propkey, "URLInfoAbout");
8369     RegDeleteValueA(propkey, "Publisher");
8370     RegDeleteValueA(propkey, "LocalPackage");
8371     RegDeleteValueA(propkey, "InstallSource");
8372     RegDeleteValueA(propkey, "InstallLocation");
8373     RegDeleteValueA(propkey, "DisplayName");
8374     RegDeleteValueA(propkey, "InstallDate");
8375     RegDeleteValueA(propkey, "HelpTelephone");
8376     RegDeleteValueA(propkey, "HelpLink");
8377     RegDeleteValueA(propkey, "LocalPackage");
8378     delete_key(propkey, "", access & KEY_WOW64_64KEY);
8379     RegCloseKey(propkey);
8380     delete_key(localkey, "", access & KEY_WOW64_64KEY);
8381     RegCloseKey(localkey);
8382 
8383     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
8384     lstrcatA(keypath, prod_squashed);
8385 
8386     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8387     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8388 
8389     /* local classes product key exists */
8390     sz = MAX_PATH;
8391     lstrcpyA(buf, "apple");
8392     r = pMsiGetProductInfoExA(prodcode, NULL,
8393                               MSIINSTALLCONTEXT_MACHINE,
8394                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
8395     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8396     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
8397     ok(sz == 1, "Expected 1, got %d\n", sz);
8398 
8399     res = RegSetValueExA(prodkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
8400     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8401 
8402     /* HelpLink value exists */
8403     sz = MAX_PATH;
8404     lstrcpyA(buf, "apple");
8405     r = pMsiGetProductInfoExA(prodcode, NULL,
8406                               MSIINSTALLCONTEXT_MACHINE,
8407                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
8408     ok(r == ERROR_UNKNOWN_PROPERTY,
8409        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8410     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8411     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8412 
8413     res = RegSetValueExA(prodkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
8414     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8415 
8416     /* HelpTelephone value exists */
8417     sz = MAX_PATH;
8418     lstrcpyA(buf, "apple");
8419     r = pMsiGetProductInfoExA(prodcode, NULL,
8420                               MSIINSTALLCONTEXT_MACHINE,
8421                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
8422     ok(r == ERROR_UNKNOWN_PROPERTY,
8423        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8424     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8425     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8426 
8427     res = RegSetValueExA(prodkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
8428     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8429 
8430     /* InstallDate value exists */
8431     sz = MAX_PATH;
8432     lstrcpyA(buf, "apple");
8433     r = pMsiGetProductInfoExA(prodcode, NULL,
8434                               MSIINSTALLCONTEXT_MACHINE,
8435                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
8436     ok(r == ERROR_UNKNOWN_PROPERTY,
8437        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8438     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8439     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8440 
8441     res = RegSetValueExA(prodkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
8442     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8443 
8444     /* DisplayName value exists */
8445     sz = MAX_PATH;
8446     lstrcpyA(buf, "apple");
8447     r = pMsiGetProductInfoExA(prodcode, NULL,
8448                               MSIINSTALLCONTEXT_MACHINE,
8449                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
8450     ok(r == ERROR_UNKNOWN_PROPERTY,
8451        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8452     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8453     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8454 
8455     res = RegSetValueExA(prodkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
8456     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8457 
8458     /* InstallLocation value exists */
8459     sz = MAX_PATH;
8460     lstrcpyA(buf, "apple");
8461     r = pMsiGetProductInfoExA(prodcode, NULL,
8462                               MSIINSTALLCONTEXT_MACHINE,
8463                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
8464     ok(r == ERROR_UNKNOWN_PROPERTY,
8465        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8466     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8467     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8468 
8469     res = RegSetValueExA(prodkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
8470     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8471 
8472     /* InstallSource value exists */
8473     sz = MAX_PATH;
8474     lstrcpyA(buf, "apple");
8475     r = pMsiGetProductInfoExA(prodcode, NULL,
8476                               MSIINSTALLCONTEXT_MACHINE,
8477                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
8478     ok(r == ERROR_UNKNOWN_PROPERTY,
8479        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8480     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8481     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8482 
8483     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
8484     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8485 
8486     /* LocalPackage value exists */
8487     sz = MAX_PATH;
8488     lstrcpyA(buf, "apple");
8489     r = pMsiGetProductInfoExA(prodcode, NULL,
8490                               MSIINSTALLCONTEXT_MACHINE,
8491                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
8492     ok(r == ERROR_UNKNOWN_PROPERTY,
8493        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8494     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8495     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8496 
8497     res = RegSetValueExA(prodkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
8498     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8499 
8500     /* Publisher value exists */
8501     sz = MAX_PATH;
8502     lstrcpyA(buf, "apple");
8503     r = pMsiGetProductInfoExA(prodcode, NULL,
8504                               MSIINSTALLCONTEXT_MACHINE,
8505                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
8506     ok(r == ERROR_UNKNOWN_PROPERTY,
8507        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8508     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8509     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8510 
8511     res = RegSetValueExA(prodkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
8512     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8513 
8514     /* URLInfoAbout value exists */
8515     sz = MAX_PATH;
8516     lstrcpyA(buf, "apple");
8517     r = pMsiGetProductInfoExA(prodcode, NULL,
8518                               MSIINSTALLCONTEXT_MACHINE,
8519                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
8520     ok(r == ERROR_UNKNOWN_PROPERTY,
8521        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8522     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8523     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8524 
8525     res = RegSetValueExA(prodkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
8526     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8527 
8528     /* URLUpdateInfo value exists */
8529     sz = MAX_PATH;
8530     lstrcpyA(buf, "apple");
8531     r = pMsiGetProductInfoExA(prodcode, NULL,
8532                               MSIINSTALLCONTEXT_MACHINE,
8533                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
8534     ok(r == ERROR_UNKNOWN_PROPERTY,
8535        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8536     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8537     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8538 
8539     res = RegSetValueExA(prodkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
8540     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8541 
8542     /* VersionMinor value exists */
8543     sz = MAX_PATH;
8544     lstrcpyA(buf, "apple");
8545     r = pMsiGetProductInfoExA(prodcode, NULL,
8546                               MSIINSTALLCONTEXT_MACHINE,
8547                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
8548     ok(r == ERROR_UNKNOWN_PROPERTY,
8549        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8550     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8551     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8552 
8553     res = RegSetValueExA(prodkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
8554     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8555 
8556     /* VersionMajor value exists */
8557     sz = MAX_PATH;
8558     lstrcpyA(buf, "apple");
8559     r = pMsiGetProductInfoExA(prodcode, NULL,
8560                               MSIINSTALLCONTEXT_MACHINE,
8561                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
8562     ok(r == ERROR_UNKNOWN_PROPERTY,
8563        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8564     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8565     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8566 
8567     res = RegSetValueExA(prodkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
8568     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8569 
8570     /* DisplayVersion value exists */
8571     sz = MAX_PATH;
8572     lstrcpyA(buf, "apple");
8573     r = pMsiGetProductInfoExA(prodcode, NULL,
8574                               MSIINSTALLCONTEXT_MACHINE,
8575                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
8576     ok(r == ERROR_UNKNOWN_PROPERTY,
8577        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8578     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8579     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8580 
8581     res = RegSetValueExA(prodkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
8582     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8583 
8584     /* ProductID value exists */
8585     sz = MAX_PATH;
8586     lstrcpyA(buf, "apple");
8587     r = pMsiGetProductInfoExA(prodcode, NULL,
8588                               MSIINSTALLCONTEXT_MACHINE,
8589                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
8590     ok(r == ERROR_UNKNOWN_PROPERTY,
8591        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8592     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8593     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8594 
8595     res = RegSetValueExA(prodkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
8596     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8597 
8598     /* RegCompany value exists */
8599     sz = MAX_PATH;
8600     lstrcpyA(buf, "apple");
8601     r = pMsiGetProductInfoExA(prodcode, NULL,
8602                               MSIINSTALLCONTEXT_MACHINE,
8603                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
8604     ok(r == ERROR_UNKNOWN_PROPERTY,
8605        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8606     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8607     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8608 
8609     res = RegSetValueExA(prodkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
8610     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8611 
8612     /* RegOwner value exists */
8613     sz = MAX_PATH;
8614     lstrcpyA(buf, "apple");
8615     r = pMsiGetProductInfoExA(prodcode, NULL,
8616                               MSIINSTALLCONTEXT_MACHINE,
8617                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
8618     ok(r == ERROR_UNKNOWN_PROPERTY,
8619        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8620     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8621     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8622 
8623     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
8624     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8625 
8626     /* Transforms value exists */
8627     sz = MAX_PATH;
8628     lstrcpyA(buf, "apple");
8629     r = pMsiGetProductInfoExA(prodcode, NULL,
8630                               MSIINSTALLCONTEXT_MACHINE,
8631                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
8632     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8633     ok(!lstrcmpA(buf, "trans"), "Expected \"trans\", got \"%s\"\n", buf);
8634     ok(sz == 5, "Expected 5, got %d\n", sz);
8635 
8636     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
8637     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8638 
8639     /* Language value exists */
8640     sz = MAX_PATH;
8641     lstrcpyA(buf, "apple");
8642     r = pMsiGetProductInfoExA(prodcode, NULL,
8643                               MSIINSTALLCONTEXT_MACHINE,
8644                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
8645     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8646     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
8647     ok(sz == 4, "Expected 4, got %d\n", sz);
8648 
8649     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
8650     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8651 
8652     /* ProductName value exists */
8653     sz = MAX_PATH;
8654     lstrcpyA(buf, "apple");
8655     r = pMsiGetProductInfoExA(prodcode, NULL,
8656                               MSIINSTALLCONTEXT_MACHINE,
8657                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
8658     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8659     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
8660     ok(sz == 4, "Expected 4, got %d\n", sz);
8661 
8662     res = RegSetValueExA(prodkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
8663     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8664 
8665     /* FIXME */
8666 
8667     /* AssignmentType value exists */
8668     sz = MAX_PATH;
8669     lstrcpyA(buf, "apple");
8670     r = pMsiGetProductInfoExA(prodcode, NULL,
8671                               MSIINSTALLCONTEXT_MACHINE,
8672                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
8673     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8674     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
8675     ok(sz == 0, "Expected 0, got %d\n", sz);
8676 
8677     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
8678     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8679 
8680     /* FIXME */
8681 
8682     /* PackageCode value exists */
8683     sz = MAX_PATH;
8684     lstrcpyA(buf, "apple");
8685     r = pMsiGetProductInfoExA(prodcode, NULL,
8686                               MSIINSTALLCONTEXT_MACHINE,
8687                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
8688     todo_wine
8689     {
8690         ok(r == ERROR_BAD_CONFIGURATION,
8691            "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
8692         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8693         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8694     }
8695 
8696     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
8697     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8698 
8699     /* Version value exists */
8700     sz = MAX_PATH;
8701     lstrcpyA(buf, "apple");
8702     r = pMsiGetProductInfoExA(prodcode, NULL,
8703                               MSIINSTALLCONTEXT_MACHINE,
8704                               INSTALLPROPERTY_VERSIONA, buf, &sz);
8705     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8706     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
8707     ok(sz == 3, "Expected 3, got %d\n", sz);
8708 
8709     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
8710     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8711 
8712     /* ProductIcon value exists */
8713     sz = MAX_PATH;
8714     lstrcpyA(buf, "apple");
8715     r = pMsiGetProductInfoExA(prodcode, NULL,
8716                               MSIINSTALLCONTEXT_MACHINE,
8717                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
8718     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8719     ok(!lstrcmpA(buf, "icon"), "Expected \"icon\", got \"%s\"\n", buf);
8720     ok(sz == 4, "Expected 4, got %d\n", sz);
8721 
8722     res = RegSetValueExA(prodkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
8723     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8724 
8725     /* PackageName value exists */
8726     sz = MAX_PATH;
8727     lstrcpyA(buf, "apple");
8728     r = pMsiGetProductInfoExA(prodcode, NULL,
8729                               MSIINSTALLCONTEXT_MACHINE,
8730                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
8731     todo_wine
8732     {
8733         ok(r == ERROR_UNKNOWN_PRODUCT,
8734            "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8735         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8736         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8737     }
8738 
8739     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
8740     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8741 
8742     /* AuthorizedLUAApp value exists */
8743     sz = MAX_PATH;
8744     lstrcpyA(buf, "apple");
8745     r = pMsiGetProductInfoExA(prodcode, NULL,
8746                               MSIINSTALLCONTEXT_MACHINE,
8747                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
8748     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8749     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
8750     ok(sz == 4, "Expected 4, got %d\n", sz);
8751 
8752     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
8753     RegDeleteValueA(prodkey, "PackageName");
8754     RegDeleteValueA(prodkey, "ProductIcon");
8755     RegDeleteValueA(prodkey, "Version");
8756     RegDeleteValueA(prodkey, "PackageCode");
8757     RegDeleteValueA(prodkey, "AssignmentType");
8758     RegDeleteValueA(prodkey, "ProductName");
8759     RegDeleteValueA(prodkey, "Language");
8760     RegDeleteValueA(prodkey, "Transforms");
8761     RegDeleteValueA(prodkey, "RegOwner");
8762     RegDeleteValueA(prodkey, "RegCompany");
8763     RegDeleteValueA(prodkey, "ProductID");
8764     RegDeleteValueA(prodkey, "DisplayVersion");
8765     RegDeleteValueA(prodkey, "VersionMajor");
8766     RegDeleteValueA(prodkey, "VersionMinor");
8767     RegDeleteValueA(prodkey, "URLUpdateInfo");
8768     RegDeleteValueA(prodkey, "URLInfoAbout");
8769     RegDeleteValueA(prodkey, "Publisher");
8770     RegDeleteValueA(prodkey, "LocalPackage");
8771     RegDeleteValueA(prodkey, "InstallSource");
8772     RegDeleteValueA(prodkey, "InstallLocation");
8773     RegDeleteValueA(prodkey, "DisplayName");
8774     RegDeleteValueA(prodkey, "InstallDate");
8775     RegDeleteValueA(prodkey, "HelpTelephone");
8776     RegDeleteValueA(prodkey, "HelpLink");
8777     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
8778     RegCloseKey(prodkey);
8779     LocalFree(usersid);
8780 }
8781 
8782 #define INIT_USERINFO() \
8783     lstrcpyA(user, "apple"); \
8784     lstrcpyA(org, "orange"); \
8785     lstrcpyA(serial, "banana"); \
8786     usersz = orgsz = serialsz = MAX_PATH;
8787 
8788 static void test_MsiGetUserInfo(void)
8789 {
8790     USERINFOSTATE state;
8791     CHAR user[MAX_PATH];
8792     CHAR org[MAX_PATH];
8793     CHAR serial[MAX_PATH];
8794     DWORD usersz, orgsz, serialsz;
8795     CHAR keypath[MAX_PATH * 2];
8796     CHAR prodcode[MAX_PATH];
8797     CHAR prod_squashed[MAX_PATH];
8798     HKEY prodkey, userprod, props;
8799     LPSTR usersid;
8800     LONG res;
8801     REGSAM access = KEY_ALL_ACCESS;
8802 
8803     create_test_guid(prodcode, prod_squashed);
8804     usersid = get_user_sid();
8805 
8806     if (is_wow64)
8807         access |= KEY_WOW64_64KEY;
8808 
8809     /* NULL szProduct */
8810     INIT_USERINFO();
8811     state = MsiGetUserInfoA(NULL, user, &usersz, org, &orgsz, serial, &serialsz);
8812     ok(state == USERINFOSTATE_INVALIDARG,
8813        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8814     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8815     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8816     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8817     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8818     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8819     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8820 
8821     /* empty szProductCode */
8822     INIT_USERINFO();
8823     state = MsiGetUserInfoA("", user, &usersz, org, &orgsz, serial, &serialsz);
8824     ok(state == USERINFOSTATE_INVALIDARG,
8825        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8826     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8827     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8828     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8829     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8830     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8831     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8832 
8833     /* garbage szProductCode */
8834     INIT_USERINFO();
8835     state = MsiGetUserInfoA("garbage", user, &usersz, org, &orgsz, serial, &serialsz);
8836     ok(state == USERINFOSTATE_INVALIDARG,
8837        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8838     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8839     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8840     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8841     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8842     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8843     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8844 
8845     /* guid without brackets */
8846     INIT_USERINFO();
8847     state = MsiGetUserInfoA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
8848                             user, &usersz, org, &orgsz, serial, &serialsz);
8849     ok(state == USERINFOSTATE_INVALIDARG,
8850        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8851     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8852     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8853     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8854     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8855     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8856     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8857 
8858     /* guid with brackets */
8859     INIT_USERINFO();
8860     state = MsiGetUserInfoA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
8861                             user, &usersz, org, &orgsz, serial, &serialsz);
8862     ok(state == USERINFOSTATE_UNKNOWN,
8863        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8864     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8865     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8866     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8867     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8868     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8869     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8870 
8871     /* NULL lpUserNameBuf */
8872     INIT_USERINFO();
8873     state = MsiGetUserInfoA(prodcode, NULL, &usersz, org, &orgsz, serial, &serialsz);
8874     ok(state == USERINFOSTATE_UNKNOWN,
8875        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8876     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8877     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8878     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8879     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8880     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8881 
8882     /* NULL pcchUserNameBuf */
8883     INIT_USERINFO();
8884     state = MsiGetUserInfoA(prodcode, user, NULL, org, &orgsz, serial, &serialsz);
8885     ok(state == USERINFOSTATE_INVALIDARG,
8886        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8887     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8888     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8889     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8890     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8891     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8892 
8893     /* both lpUserNameBuf and pcchUserNameBuf NULL */
8894     INIT_USERINFO();
8895     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
8896     ok(state == USERINFOSTATE_UNKNOWN,
8897        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8898     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8899     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8900     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8901     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8902 
8903     /* NULL lpOrgNameBuf */
8904     INIT_USERINFO();
8905     state = MsiGetUserInfoA(prodcode, user, &usersz, NULL, &orgsz, serial, &serialsz);
8906     ok(state == USERINFOSTATE_UNKNOWN,
8907        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8908     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8909     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8910     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8911     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8912     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8913 
8914     /* NULL pcchOrgNameBuf */
8915     INIT_USERINFO();
8916     state = MsiGetUserInfoA(prodcode, user, &usersz, org, NULL, serial, &serialsz);
8917     ok(state == USERINFOSTATE_INVALIDARG,
8918        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8919     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8920     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8921     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8922     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8923     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8924 
8925     /* both lpOrgNameBuf and pcchOrgNameBuf NULL */
8926     INIT_USERINFO();
8927     state = MsiGetUserInfoA(prodcode, user, &usersz, NULL, NULL, serial, &serialsz);
8928     ok(state == USERINFOSTATE_UNKNOWN,
8929        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8930     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8931     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8932     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8933     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8934 
8935     /* NULL lpSerialBuf */
8936     INIT_USERINFO();
8937     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, NULL, &serialsz);
8938     ok(state == USERINFOSTATE_UNKNOWN,
8939        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8940     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8941     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8942     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8943     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8944     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8945 
8946     /* NULL pcchSerialBuf */
8947     INIT_USERINFO();
8948     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, NULL);
8949     ok(state == USERINFOSTATE_INVALIDARG,
8950        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8951     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8952     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8953     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8954     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8955     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8956 
8957     /* both lpSerialBuf and pcchSerialBuf NULL */
8958     INIT_USERINFO();
8959     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, NULL, NULL);
8960     ok(state == USERINFOSTATE_UNKNOWN,
8961        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8962     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8963     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8964     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8965     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8966 
8967     /* MSIINSTALLCONTEXT_USERMANAGED */
8968 
8969     /* create local system product key */
8970     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
8971     lstrcatA(keypath, usersid);
8972     lstrcatA(keypath, "\\Installer\\Products\\");
8973     lstrcatA(keypath, prod_squashed);
8974 
8975     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8976     if (res == ERROR_ACCESS_DENIED)
8977     {
8978         skip("Not enough rights to perform tests\n");
8979         LocalFree(usersid);
8980         return;
8981     }
8982     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8983 
8984     /* managed product key exists */
8985     INIT_USERINFO();
8986     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8987     ok(state == USERINFOSTATE_ABSENT,
8988        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
8989     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8990     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8991     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8992     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8993     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8994     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8995 
8996     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8997     lstrcatA(keypath, "Installer\\UserData\\");
8998     lstrcatA(keypath, usersid);
8999     lstrcatA(keypath, "\\Products\\");
9000     lstrcatA(keypath, prod_squashed);
9001 
9002     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL);
9003     if (res == ERROR_ACCESS_DENIED)
9004     {
9005         skip("Not enough rights to perform tests\n");
9006         LocalFree(usersid);
9007         return;
9008     }
9009     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9010 
9011     res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9012     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9013 
9014     /* InstallProperties key exists */
9015     INIT_USERINFO();
9016     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9017     ok(state == USERINFOSTATE_ABSENT,
9018        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9019     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9020     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
9021     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9022     ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", usersz);
9023     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
9024     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
9025 
9026     /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */
9027     INIT_USERINFO();
9028     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
9029     ok(state == USERINFOSTATE_ABSENT,
9030        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9031     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
9032     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9033     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
9034     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9035 
9036     /* RegOwner, RegCompany don't exist, out params are NULL */
9037     INIT_USERINFO();
9038     state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz);
9039     ok(state == USERINFOSTATE_ABSENT,
9040        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9041     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9042     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9043 
9044     res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
9045     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9046 
9047     /* RegOwner value exists */
9048     INIT_USERINFO();
9049     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9050     ok(state == USERINFOSTATE_ABSENT,
9051        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9052     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9053     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
9054     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9055     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9056     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
9057     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9058 
9059     res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8);
9060     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9061 
9062     /* RegCompany value exists */
9063     INIT_USERINFO();
9064     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9065     ok(state == USERINFOSTATE_ABSENT,
9066        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9067     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9068     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9069     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9070     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9071     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
9072     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9073 
9074     res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3);
9075     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9076 
9077     /* ProductID value exists */
9078     INIT_USERINFO();
9079     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9080     ok(state == USERINFOSTATE_PRESENT,
9081        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
9082     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9083     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9084     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
9085     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9086     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
9087     ok(serialsz == 2, "Expected 2, got %d\n", serialsz);
9088 
9089     /* pcchUserNameBuf is too small */
9090     INIT_USERINFO();
9091     usersz = 0;
9092     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9093     ok(state == USERINFOSTATE_MOREDATA,
9094        "Expected USERINFOSTATE_MOREDATA, got %d\n", state);
9095     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9096     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
9097     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9098     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9099     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
9100     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
9101 
9102     /* pcchUserNameBuf has no room for NULL terminator */
9103     INIT_USERINFO();
9104     usersz = 5;
9105     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9106     ok(state == USERINFOSTATE_MOREDATA,
9107        "Expected USERINFOSTATE_MOREDATA, got %d\n", state);
9108     todo_wine
9109     {
9110         ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9111     }
9112     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
9113     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9114     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9115     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
9116     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
9117 
9118     /* pcchUserNameBuf is too small, lpUserNameBuf is NULL */
9119     INIT_USERINFO();
9120     usersz = 0;
9121     state = MsiGetUserInfoA(prodcode, NULL, &usersz, org, &orgsz, serial, &serialsz);
9122     ok(state == USERINFOSTATE_PRESENT,
9123        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
9124     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9125     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9126     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
9127     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9128     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
9129     ok(serialsz == 2, "Expected 2, got %d\n", serialsz);
9130 
9131     RegDeleteValueA(props, "ProductID");
9132     RegDeleteValueA(props, "RegCompany");
9133     RegDeleteValueA(props, "RegOwner");
9134     delete_key(props, "", access & KEY_WOW64_64KEY);
9135     RegCloseKey(props);
9136     delete_key(userprod, "", access & KEY_WOW64_64KEY);
9137     RegCloseKey(userprod);
9138     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
9139     RegCloseKey(prodkey);
9140 
9141     /* MSIINSTALLCONTEXT_USERUNMANAGED */
9142 
9143     /* create local system product key */
9144     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
9145     lstrcatA(keypath, prod_squashed);
9146 
9147     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
9148     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9149 
9150     /* product key exists */
9151     INIT_USERINFO();
9152     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9153     ok(state == USERINFOSTATE_ABSENT,
9154        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9155     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9156     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
9157     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9158     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
9159     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
9160     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
9161 
9162     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9163     lstrcatA(keypath, "Installer\\UserData\\");
9164     lstrcatA(keypath, usersid);
9165     lstrcatA(keypath, "\\Products\\");
9166     lstrcatA(keypath, prod_squashed);
9167 
9168     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL);
9169     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9170 
9171     res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9172     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9173 
9174     /* InstallProperties key exists */
9175     INIT_USERINFO();
9176     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9177     ok(state == USERINFOSTATE_ABSENT,
9178        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9179     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9180     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
9181     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9182     ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", usersz);
9183     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
9184     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
9185 
9186     /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */
9187     INIT_USERINFO();
9188     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
9189     ok(state == USERINFOSTATE_ABSENT,
9190        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9191     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
9192     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9193     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
9194     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9195 
9196     /* RegOwner, RegCompany don't exist, out params are NULL */
9197     INIT_USERINFO();
9198     state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz);
9199     ok(state == USERINFOSTATE_ABSENT,
9200        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9201     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9202     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9203 
9204     res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
9205     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9206 
9207     /* RegOwner value exists */
9208     INIT_USERINFO();
9209     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9210     ok(state == USERINFOSTATE_ABSENT,
9211        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9212     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9213     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
9214     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9215     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9216     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
9217     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9218 
9219     res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8);
9220     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9221 
9222     /* RegCompany value exists */
9223     INIT_USERINFO();
9224     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9225     ok(state == USERINFOSTATE_ABSENT,
9226        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9227     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9228     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9229     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9230     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9231     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
9232     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9233 
9234     res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3);
9235     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9236 
9237     /* ProductID value exists */
9238     INIT_USERINFO();
9239     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9240     ok(state == USERINFOSTATE_PRESENT,
9241        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
9242     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9243     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9244     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
9245     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9246     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
9247     ok(serialsz == 2, "Expected 2, got %d\n", serialsz);
9248 
9249     RegDeleteValueA(props, "ProductID");
9250     RegDeleteValueA(props, "RegCompany");
9251     RegDeleteValueA(props, "RegOwner");
9252     delete_key(props, "", access & KEY_WOW64_64KEY);
9253     RegCloseKey(props);
9254     delete_key(userprod, "", access & KEY_WOW64_64KEY);
9255     RegCloseKey(userprod);
9256     RegDeleteKeyA(prodkey, "");
9257     RegCloseKey(prodkey);
9258 
9259     /* MSIINSTALLCONTEXT_MACHINE */
9260 
9261     /* create local system product key */
9262     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
9263     lstrcatA(keypath, prod_squashed);
9264 
9265     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
9266     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9267 
9268     /* product key exists */
9269     INIT_USERINFO();
9270     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9271     ok(state == USERINFOSTATE_ABSENT,
9272        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9273     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9274     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
9275     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9276     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
9277     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
9278     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
9279 
9280     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9281     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18");
9282     lstrcatA(keypath, "\\Products\\");
9283     lstrcatA(keypath, prod_squashed);
9284 
9285     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL);
9286     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9287 
9288     res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9289     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9290 
9291     /* InstallProperties key exists */
9292     INIT_USERINFO();
9293     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9294     ok(state == USERINFOSTATE_ABSENT,
9295        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9296     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9297     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
9298     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9299     ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", usersz);
9300     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
9301     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
9302 
9303     /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */
9304     INIT_USERINFO();
9305     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
9306     ok(state == USERINFOSTATE_ABSENT,
9307        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9308     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
9309     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9310     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
9311     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9312 
9313     /* RegOwner, RegCompany don't exist, out params are NULL */
9314     INIT_USERINFO();
9315     state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz);
9316     ok(state == USERINFOSTATE_ABSENT,
9317        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9318     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9319     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9320 
9321     res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
9322     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9323 
9324     /* RegOwner value exists */
9325     INIT_USERINFO();
9326     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9327     ok(state == USERINFOSTATE_ABSENT,
9328        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9329     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9330     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
9331     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9332     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9333     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
9334     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9335 
9336     res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8);
9337     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9338 
9339     /* RegCompany value exists */
9340     INIT_USERINFO();
9341     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9342     ok(state == USERINFOSTATE_ABSENT,
9343        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9344     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9345     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9346     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9347     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9348     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
9349     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9350 
9351     res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3);
9352     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9353 
9354     /* ProductID value exists */
9355     INIT_USERINFO();
9356     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9357     ok(state == USERINFOSTATE_PRESENT,
9358        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
9359     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9360     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9361     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
9362     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9363     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
9364     ok(serialsz == 2, "Expected 2, got %d\n", serialsz);
9365 
9366     RegDeleteValueA(props, "ProductID");
9367     RegDeleteValueA(props, "RegCompany");
9368     RegDeleteValueA(props, "RegOwner");
9369     delete_key(props, "", access & KEY_WOW64_64KEY);
9370     RegCloseKey(props);
9371     delete_key(userprod, "", access & KEY_WOW64_64KEY);
9372     RegCloseKey(userprod);
9373     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
9374     RegCloseKey(prodkey);
9375     LocalFree(usersid);
9376 }
9377 
9378 static void test_MsiOpenProduct(void)
9379 {
9380     MSIHANDLE hprod, hdb;
9381     CHAR val[MAX_PATH];
9382     CHAR path[MAX_PATH];
9383     CHAR keypath[MAX_PATH*2];
9384     CHAR prodcode[MAX_PATH];
9385     CHAR prod_squashed[MAX_PATH];
9386     HKEY prodkey, userkey, props;
9387     LPSTR usersid;
9388     DWORD size;
9389     LONG res;
9390     UINT r;
9391     REGSAM access = KEY_ALL_ACCESS;
9392 
9393     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
9394 
9395     GetCurrentDirectoryA(MAX_PATH, path);
9396     lstrcatA(path, "\\");
9397 
9398     create_test_guid(prodcode, prod_squashed);
9399     usersid = get_user_sid();
9400 
9401     if (is_wow64)
9402         access |= KEY_WOW64_64KEY;
9403 
9404     hdb = create_package_db(prodcode);
9405     MsiCloseHandle(hdb);
9406 
9407     /* NULL szProduct */
9408     hprod = 0xdeadbeef;
9409     r = MsiOpenProductA(NULL, &hprod);
9410     ok(r == ERROR_INVALID_PARAMETER,
9411        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9412     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9413 
9414     /* empty szProduct */
9415     hprod = 0xdeadbeef;
9416     r = MsiOpenProductA("", &hprod);
9417     ok(r == ERROR_INVALID_PARAMETER,
9418        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9419     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9420 
9421     /* garbage szProduct */
9422     hprod = 0xdeadbeef;
9423     r = MsiOpenProductA("garbage", &hprod);
9424     ok(r == ERROR_INVALID_PARAMETER,
9425        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9426     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9427 
9428     /* guid without brackets */
9429     hprod = 0xdeadbeef;
9430     r = MsiOpenProductA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", &hprod);
9431     ok(r == ERROR_INVALID_PARAMETER,
9432        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9433     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9434 
9435     /* guid with brackets */
9436     hprod = 0xdeadbeef;
9437     r = MsiOpenProductA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", &hprod);
9438     ok(r == ERROR_UNKNOWN_PRODUCT,
9439        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9440     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9441 
9442     /* same length as guid, but random */
9443     hprod = 0xdeadbeef;
9444     r = MsiOpenProductA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", &hprod);
9445     ok(r == ERROR_INVALID_PARAMETER,
9446        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9447     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9448 
9449     /* hProduct is NULL */
9450     hprod = 0xdeadbeef;
9451     r = MsiOpenProductA(prodcode, NULL);
9452     ok(r == ERROR_INVALID_PARAMETER,
9453        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9454     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9455 
9456     /* MSIINSTALLCONTEXT_USERMANAGED */
9457 
9458     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9459     lstrcatA(keypath, "Installer\\Managed\\");
9460     lstrcatA(keypath, usersid);
9461     lstrcatA(keypath, "\\Installer\\Products\\");
9462     lstrcatA(keypath, prod_squashed);
9463 
9464     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
9465     if (res == ERROR_ACCESS_DENIED)
9466     {
9467         skip("Not enough rights to perform tests\n");
9468         LocalFree(usersid);
9469         return;
9470     }
9471     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9472 
9473     /* managed product key exists */
9474     hprod = 0xdeadbeef;
9475     r = MsiOpenProductA(prodcode, &hprod);
9476     ok(r == ERROR_UNKNOWN_PRODUCT,
9477        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9478     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9479 
9480     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9481     lstrcatA(keypath, "Installer\\UserData\\");
9482     lstrcatA(keypath, usersid);
9483     lstrcatA(keypath, "\\Products\\");
9484     lstrcatA(keypath, prod_squashed);
9485 
9486     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
9487     if (res == ERROR_ACCESS_DENIED)
9488     {
9489         skip("Not enough rights to perform tests\n");
9490         LocalFree(usersid);
9491         return;
9492     }
9493     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9494 
9495     /* user product key exists */
9496     hprod = 0xdeadbeef;
9497     r = MsiOpenProductA(prodcode, &hprod);
9498     ok(r == ERROR_UNKNOWN_PRODUCT,
9499        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9500     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9501 
9502     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9503     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9504 
9505     /* InstallProperties key exists */
9506     hprod = 0xdeadbeef;
9507     r = MsiOpenProductA(prodcode, &hprod);
9508     ok(r == ERROR_UNKNOWN_PRODUCT,
9509        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9510     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9511 
9512     lstrcpyA(val, path);
9513     lstrcatA(val, "\\winetest.msi");
9514     res = RegSetValueExA(props, "ManagedLocalPackage", 0, REG_SZ,
9515                          (const BYTE *)val, lstrlenA(val) + 1);
9516     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9517 
9518     /* ManagedLocalPackage value exists */
9519     hprod = 0xdeadbeef;
9520     r = MsiOpenProductA(prodcode, &hprod);
9521     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9522     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
9523 
9524     size = MAX_PATH;
9525     r = MsiGetPropertyA(hprod, "ProductCode", val, &size);
9526     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9527     ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val);
9528     ok(size == lstrlenA(prodcode), "Expected %d, got %d\n", lstrlenA(prodcode), size);
9529 
9530     MsiCloseHandle(hprod);
9531 
9532     RegDeleteValueA(props, "ManagedLocalPackage");
9533     delete_key(props, "", access & KEY_WOW64_64KEY);
9534     RegCloseKey(props);
9535     delete_key(userkey, "", access & KEY_WOW64_64KEY);
9536     RegCloseKey(userkey);
9537     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
9538     RegCloseKey(prodkey);
9539 
9540     /* MSIINSTALLCONTEXT_USERUNMANAGED */
9541 
9542     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
9543     lstrcatA(keypath, prod_squashed);
9544 
9545     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
9546     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9547 
9548     /* unmanaged product key exists */
9549     hprod = 0xdeadbeef;
9550     r = MsiOpenProductA(prodcode, &hprod);
9551     ok(r == ERROR_UNKNOWN_PRODUCT,
9552        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9553     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9554 
9555     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9556     lstrcatA(keypath, "Installer\\UserData\\");
9557     lstrcatA(keypath, usersid);
9558     lstrcatA(keypath, "\\Products\\");
9559     lstrcatA(keypath, prod_squashed);
9560 
9561     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
9562     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9563 
9564     /* user product key exists */
9565     hprod = 0xdeadbeef;
9566     r = MsiOpenProductA(prodcode, &hprod);
9567     ok(r == ERROR_UNKNOWN_PRODUCT,
9568        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9569     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9570 
9571     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9572     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9573 
9574     /* InstallProperties key exists */
9575     hprod = 0xdeadbeef;
9576     r = MsiOpenProductA(prodcode, &hprod);
9577     ok(r == ERROR_UNKNOWN_PRODUCT,
9578        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9579     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9580 
9581     lstrcpyA(val, path);
9582     lstrcatA(val, "\\winetest.msi");
9583     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
9584                          (const BYTE *)val, lstrlenA(val) + 1);
9585     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9586 
9587     /* LocalPackage value exists */
9588     hprod = 0xdeadbeef;
9589     r = MsiOpenProductA(prodcode, &hprod);
9590     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9591     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
9592 
9593     size = MAX_PATH;
9594     r = MsiGetPropertyA(hprod, "ProductCode", val, &size);
9595     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9596     ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val);
9597     ok(size == lstrlenA(prodcode), "Expected %d, got %d\n", lstrlenA(prodcode), size);
9598 
9599     MsiCloseHandle(hprod);
9600 
9601     RegDeleteValueA(props, "LocalPackage");
9602     delete_key(props, "", access & KEY_WOW64_64KEY);
9603     RegCloseKey(props);
9604     delete_key(userkey, "", access & KEY_WOW64_64KEY);
9605     RegCloseKey(userkey);
9606     RegDeleteKeyA(prodkey, "");
9607     RegCloseKey(prodkey);
9608 
9609     /* MSIINSTALLCONTEXT_MACHINE */
9610 
9611     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
9612     lstrcatA(keypath, prod_squashed);
9613 
9614     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
9615     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9616 
9617     /* managed product key exists */
9618     hprod = 0xdeadbeef;
9619     r = MsiOpenProductA(prodcode, &hprod);
9620     ok(r == ERROR_UNKNOWN_PRODUCT,
9621        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9622     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9623 
9624     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9625     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
9626     lstrcatA(keypath, prod_squashed);
9627 
9628     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
9629     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9630 
9631     /* user product key exists */
9632     hprod = 0xdeadbeef;
9633     r = MsiOpenProductA(prodcode, &hprod);
9634     ok(r == ERROR_UNKNOWN_PRODUCT,
9635        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9636     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9637 
9638     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9639     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9640 
9641     /* InstallProperties key exists */
9642     hprod = 0xdeadbeef;
9643     r = MsiOpenProductA(prodcode, &hprod);
9644     ok(r == ERROR_UNKNOWN_PRODUCT,
9645        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9646     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9647 
9648     lstrcpyA(val, path);
9649     lstrcatA(val, "\\winetest.msi");
9650     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
9651                          (const BYTE *)val, lstrlenA(val) + 1);
9652     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9653 
9654     /* LocalPackage value exists */
9655     hprod = 0xdeadbeef;
9656     r = MsiOpenProductA(prodcode, &hprod);
9657     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9658     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
9659 
9660     size = MAX_PATH;
9661     r = MsiGetPropertyA(hprod, "ProductCode", val, &size);
9662     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9663     ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val);
9664     ok(size == lstrlenA(prodcode), "Expected %d, got %d\n", lstrlenA(prodcode), size);
9665 
9666     MsiCloseHandle(hprod);
9667 
9668     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
9669                          (const BYTE *)"winetest.msi", 13);
9670     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9671 
9672     lstrcpyA(val, path);
9673     lstrcatA(val, "\\winetest.msi");
9674     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
9675                          (const BYTE *)val, lstrlenA(val) + 1);
9676     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9677 
9678     DeleteFileA(msifile);
9679 
9680     /* local package does not exist */
9681     hprod = 0xdeadbeef;
9682     r = MsiOpenProductA(prodcode, &hprod);
9683     ok(r == ERROR_UNKNOWN_PRODUCT,
9684        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9685     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9686 
9687     RegDeleteValueA(props, "LocalPackage");
9688     delete_key(props, "", access & KEY_WOW64_64KEY);
9689     RegCloseKey(props);
9690     delete_key(userkey, "", access & KEY_WOW64_64KEY);
9691     RegCloseKey(userkey);
9692     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
9693     RegCloseKey(prodkey);
9694 
9695     DeleteFileA(msifile);
9696     LocalFree(usersid);
9697 }
9698 
9699 static void test_MsiEnumPatchesEx_usermanaged(LPCSTR usersid, LPCSTR expectedsid)
9700 {
9701     MSIINSTALLCONTEXT context;
9702     CHAR keypath[MAX_PATH], patch[MAX_PATH];
9703     CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
9704     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
9705     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
9706     HKEY prodkey, patches, udprod, udpatch, hpatch;
9707     DWORD size, data;
9708     LONG res;
9709     UINT r;
9710     REGSAM access = KEY_ALL_ACCESS;
9711 
9712     create_test_guid(prodcode, prod_squashed);
9713     create_test_guid(patch, patch_squashed);
9714 
9715     if (is_wow64)
9716         access |= KEY_WOW64_64KEY;
9717 
9718     /* MSIPATCHSTATE_APPLIED */
9719 
9720     lstrcpyA(patchcode, "apple");
9721     lstrcpyA(targetprod, "banana");
9722     context = 0xdeadbeef;
9723     lstrcpyA(targetsid, "kiwi");
9724     size = MAX_PATH;
9725     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9726                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9727                            &context, targetsid, &size);
9728     if (r == ERROR_ACCESS_DENIED)
9729     {
9730         skip("Not enough rights to perform tests\n");
9731         return;
9732     }
9733     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9734     ok(!lstrcmpA(patchcode, "apple"),
9735        "Expected patchcode to be unchanged, got %s\n", patchcode);
9736     ok(!lstrcmpA(targetprod, "banana"),
9737        "Expected targetprod to be unchanged, got %s\n", targetprod);
9738     ok(context == 0xdeadbeef,
9739        "Expected context to be unchanged, got %d\n", context);
9740     ok(!lstrcmpA(targetsid, "kiwi"),
9741        "Expected targetsid to be unchanged, got %s\n", targetsid);
9742     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9743 
9744     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
9745     lstrcatA(keypath, expectedsid);
9746     lstrcatA(keypath, "\\Installer\\Products\\");
9747     lstrcatA(keypath, prod_squashed);
9748 
9749     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
9750     if (res == ERROR_ACCESS_DENIED)
9751     {
9752         skip("Not enough rights to perform tests\n");
9753         return;
9754     }
9755     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9756 
9757     /* managed product key exists */
9758     lstrcpyA(patchcode, "apple");
9759     lstrcpyA(targetprod, "banana");
9760     context = 0xdeadbeef;
9761     lstrcpyA(targetsid, "kiwi");
9762     size = MAX_PATH;
9763     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9764                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9765                            &context, targetsid, &size);
9766     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9767     ok(!lstrcmpA(patchcode, "apple"),
9768        "Expected patchcode to be unchanged, got %s\n", patchcode);
9769     ok(!lstrcmpA(targetprod, "banana"),
9770        "Expected targetprod to be unchanged, got %s\n", targetprod);
9771     ok(context == 0xdeadbeef,
9772        "Expected context to be unchanged, got %d\n", context);
9773     ok(!lstrcmpA(targetsid, "kiwi"),
9774        "Expected targetsid to be unchanged, got %s\n", targetsid);
9775     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9776 
9777     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
9778     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9779 
9780     /* patches key exists */
9781     lstrcpyA(patchcode, "apple");
9782     lstrcpyA(targetprod, "banana");
9783     context = 0xdeadbeef;
9784     lstrcpyA(targetsid, "kiwi");
9785     size = MAX_PATH;
9786     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9787                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9788                            &context, targetsid, &size);
9789     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9790     ok(!lstrcmpA(patchcode, "apple"),
9791        "Expected patchcode to be unchanged, got %s\n", patchcode);
9792     ok(!lstrcmpA(targetprod, "banana"),
9793        "Expected targetprod to be unchanged, got %s\n", targetprod);
9794     ok(context == 0xdeadbeef,
9795        "Expected context to be unchanged, got %d\n", context);
9796     ok(!lstrcmpA(targetsid, "kiwi"),
9797        "Expected targetsid to be unchanged, got %s\n", targetsid);
9798     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9799 
9800     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
9801                          (const BYTE *)patch_squashed,
9802                          lstrlenA(patch_squashed) + 1);
9803     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9804 
9805     /* Patches value exists, is not REG_MULTI_SZ */
9806     lstrcpyA(patchcode, "apple");
9807     lstrcpyA(targetprod, "banana");
9808     context = 0xdeadbeef;
9809     lstrcpyA(targetsid, "kiwi");
9810     size = MAX_PATH;
9811     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9812                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9813                            &context, targetsid, &size);
9814     ok(r == ERROR_BAD_CONFIGURATION,
9815        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9816     ok(!lstrcmpA(patchcode, "apple"),
9817        "Expected patchcode to be unchanged, got %s\n", patchcode);
9818     ok(!lstrcmpA(targetprod, "banana"),
9819        "Expected targetprod to be unchanged, got %s\n", targetprod);
9820     ok(context == 0xdeadbeef,
9821        "Expected context to be unchanged, got %d\n", context);
9822     ok(!lstrcmpA(targetsid, "kiwi"),
9823        "Expected targetsid to be unchanged, got %s\n", targetsid);
9824     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9825 
9826     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
9827                          (const BYTE *)"a\0b\0c\0\0", 7);
9828     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9829 
9830     /* Patches value exists, is not a squashed guid */
9831     lstrcpyA(patchcode, "apple");
9832     lstrcpyA(targetprod, "banana");
9833     context = 0xdeadbeef;
9834     lstrcpyA(targetsid, "kiwi");
9835     size = MAX_PATH;
9836     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9837                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9838                            &context, targetsid, &size);
9839     ok(r == ERROR_BAD_CONFIGURATION,
9840        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9841     ok(!lstrcmpA(patchcode, "apple"),
9842        "Expected patchcode to be unchanged, got %s\n", patchcode);
9843     ok(!lstrcmpA(targetprod, "banana"),
9844        "Expected targetprod to be unchanged, got %s\n", targetprod);
9845     ok(context == 0xdeadbeef,
9846        "Expected context to be unchanged, got %d\n", context);
9847     ok(!lstrcmpA(targetsid, "kiwi"),
9848        "Expected targetsid to be unchanged, got %s\n", targetsid);
9849     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9850 
9851     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
9852     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
9853                          (const BYTE *)patch_squashed,
9854                          lstrlenA(patch_squashed) + 2);
9855     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9856 
9857     /* Patches value exists */
9858     lstrcpyA(patchcode, "apple");
9859     lstrcpyA(targetprod, "banana");
9860     context = 0xdeadbeef;
9861     lstrcpyA(targetsid, "kiwi");
9862     size = MAX_PATH;
9863     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9864                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9865                            &context, targetsid, &size);
9866     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9867     ok(!lstrcmpA(patchcode, "apple"),
9868        "Expected patchcode to be unchanged, got %s\n", patchcode);
9869     ok(!lstrcmpA(targetprod, "banana"),
9870        "Expected targetprod to be unchanged, got %s\n", targetprod);
9871     ok(context == 0xdeadbeef,
9872        "Expected context to be unchanged, got %d\n", context);
9873     ok(!lstrcmpA(targetsid, "kiwi"),
9874        "Expected targetsid to be unchanged, got %s\n", targetsid);
9875     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9876 
9877     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
9878                          (const BYTE *)"whatever", 9);
9879     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9880 
9881     /* patch squashed value exists */
9882     lstrcpyA(patchcode, "apple");
9883     lstrcpyA(targetprod, "banana");
9884     context = 0xdeadbeef;
9885     lstrcpyA(targetsid, "kiwi");
9886     size = MAX_PATH;
9887     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9888                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9889                            &context, targetsid, &size);
9890     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9891     ok(!lstrcmpA(patchcode, patch),
9892        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9893     ok(!lstrcmpA(targetprod, prodcode),
9894        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9895     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9896        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9897     ok(!lstrcmpA(targetsid, expectedsid),
9898        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9899     ok(size == lstrlenA(expectedsid),
9900        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9901 
9902     /* increase the index */
9903     lstrcpyA(patchcode, "apple");
9904     lstrcpyA(targetprod, "banana");
9905     context = 0xdeadbeef;
9906     lstrcpyA(targetsid, "kiwi");
9907     size = MAX_PATH;
9908     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9909                            MSIPATCHSTATE_APPLIED, 1, patchcode, targetprod,
9910                            &context, targetsid, &size);
9911     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9912     ok(!lstrcmpA(patchcode, "apple"),
9913        "Expected patchcode to be unchanged, got %s\n", patchcode);
9914     ok(!lstrcmpA(targetprod, "banana"),
9915        "Expected targetprod to be unchanged, got %s\n", targetprod);
9916     ok(context == 0xdeadbeef,
9917        "Expected context to be unchanged, got %d\n", context);
9918     ok(!lstrcmpA(targetsid, "kiwi"),
9919        "Expected targetsid to be unchanged, got %s\n", targetsid);
9920     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9921 
9922     /* increase again */
9923     lstrcpyA(patchcode, "apple");
9924     lstrcpyA(targetprod, "banana");
9925     context = 0xdeadbeef;
9926     lstrcpyA(targetsid, "kiwi");
9927     size = MAX_PATH;
9928     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9929                            MSIPATCHSTATE_APPLIED, 2, patchcode, targetprod,
9930                            &context, targetsid, &size);
9931     ok(r == ERROR_INVALID_PARAMETER,
9932        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9933     ok(!lstrcmpA(patchcode, "apple"),
9934        "Expected patchcode to be unchanged, got %s\n", patchcode);
9935     ok(!lstrcmpA(targetprod, "banana"),
9936        "Expected targetprod to be unchanged, got %s\n", targetprod);
9937     ok(context == 0xdeadbeef,
9938        "Expected context to be unchanged, got %d\n", context);
9939     ok(!lstrcmpA(targetsid, "kiwi"),
9940        "Expected targetsid to be unchanged, got %s\n", targetsid);
9941     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9942 
9943     /* szPatchCode is NULL */
9944     lstrcpyA(targetprod, "banana");
9945     context = 0xdeadbeef;
9946     lstrcpyA(targetsid, "kiwi");
9947     size = MAX_PATH;
9948     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9949                            MSIPATCHSTATE_APPLIED, 0, NULL, targetprod,
9950                            &context, targetsid, &size);
9951     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9952     ok(!lstrcmpA(targetprod, prodcode),
9953        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9954     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9955        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9956     ok(!lstrcmpA(targetsid, expectedsid),
9957        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9958     ok(size == lstrlenA(expectedsid),
9959        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9960 
9961     /* szTargetProductCode is NULL */
9962     lstrcpyA(patchcode, "apple");
9963     context = 0xdeadbeef;
9964     lstrcpyA(targetsid, "kiwi");
9965     size = MAX_PATH;
9966     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9967                            MSIPATCHSTATE_APPLIED, 0, patchcode, NULL,
9968                            &context, targetsid, &size);
9969     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9970     ok(!lstrcmpA(patchcode, patch),
9971        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9972     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9973        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9974     ok(!lstrcmpA(targetsid, expectedsid),
9975        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9976     ok(size == lstrlenA(expectedsid),
9977        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9978 
9979     /* pdwTargetProductContext is NULL */
9980     lstrcpyA(patchcode, "apple");
9981     lstrcpyA(targetprod, "banana");
9982     lstrcpyA(targetsid, "kiwi");
9983     size = MAX_PATH;
9984     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9985                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9986                            NULL, targetsid, &size);
9987     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9988     ok(!lstrcmpA(patchcode, patch),
9989        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9990     ok(!lstrcmpA(targetprod, prodcode),
9991        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9992     ok(!lstrcmpA(targetsid, expectedsid),
9993        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9994     ok(size == lstrlenA(expectedsid),
9995        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9996 
9997     /* szTargetUserSid is NULL */
9998     lstrcpyA(patchcode, "apple");
9999     lstrcpyA(targetprod, "banana");
10000     context = 0xdeadbeef;
10001     size = MAX_PATH;
10002     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10003                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10004                            &context, NULL, &size);
10005     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10006     ok(!lstrcmpA(patchcode, patch),
10007        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10008     ok(!lstrcmpA(targetprod, prodcode),
10009        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10010     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
10011        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
10012     ok(size == lstrlenA(expectedsid) * sizeof(WCHAR),
10013        "Expected %d*sizeof(WCHAR), got %d\n", lstrlenA(expectedsid), size);
10014 
10015     /* pcchTargetUserSid is exactly the length of szTargetUserSid */
10016     lstrcpyA(patchcode, "apple");
10017     lstrcpyA(targetprod, "banana");
10018     context = 0xdeadbeef;
10019     lstrcpyA(targetsid, "kiwi");
10020     size = lstrlenA(expectedsid);
10021     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10022                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10023                            &context, targetsid, &size);
10024     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
10025     ok(!lstrcmpA(patchcode, patch),
10026        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10027     ok(!lstrcmpA(targetprod, prodcode),
10028        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10029     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
10030        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
10031     ok(!strncmp(targetsid, expectedsid, lstrlenA(expectedsid) - 1),
10032        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10033     ok(size == lstrlenA(expectedsid) * sizeof(WCHAR),
10034        "Expected %d*sizeof(WCHAR), got %d\n", lstrlenA(expectedsid), size);
10035 
10036     /* pcchTargetUserSid has enough room for NULL terminator */
10037     lstrcpyA(patchcode, "apple");
10038     lstrcpyA(targetprod, "banana");
10039     context = 0xdeadbeef;
10040     lstrcpyA(targetsid, "kiwi");
10041     size = lstrlenA(expectedsid) + 1;
10042     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10043                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10044                            &context, targetsid, &size);
10045     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10046     ok(!lstrcmpA(patchcode, patch),
10047        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10048     ok(!lstrcmpA(targetprod, prodcode),
10049        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10050     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
10051        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
10052     ok(!lstrcmpA(targetsid, expectedsid),
10053        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10054     ok(size == lstrlenA(expectedsid),
10055        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10056 
10057     /* both szTargetuserSid and pcchTargetUserSid are NULL */
10058     lstrcpyA(patchcode, "apple");
10059     lstrcpyA(targetprod, "banana");
10060     context = 0xdeadbeef;
10061     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10062                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10063                            &context, NULL, NULL);
10064     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10065     ok(!lstrcmpA(patchcode, patch),
10066        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10067     ok(!lstrcmpA(targetprod, prodcode),
10068        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10069     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
10070        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
10071 
10072     /* MSIPATCHSTATE_SUPERSEDED */
10073 
10074     lstrcpyA(patchcode, "apple");
10075     lstrcpyA(targetprod, "banana");
10076     context = 0xdeadbeef;
10077     lstrcpyA(targetsid, "kiwi");
10078     size = MAX_PATH;
10079     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10080                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10081                            &context, targetsid, &size);
10082     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10083     ok(!lstrcmpA(patchcode, "apple"),
10084        "Expected patchcode to be unchanged, got %s\n", patchcode);
10085     ok(!lstrcmpA(targetprod, "banana"),
10086        "Expected targetprod to be unchanged, got %s\n", targetprod);
10087     ok(context == 0xdeadbeef,
10088        "Expected context to be unchanged, got %d\n", context);
10089     ok(!lstrcmpA(targetsid, "kiwi"),
10090        "Expected targetsid to be unchanged, got %s\n", targetsid);
10091     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10092 
10093     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
10094     lstrcatA(keypath, expectedsid);
10095     lstrcatA(keypath, "\\Products\\");
10096     lstrcatA(keypath, prod_squashed);
10097 
10098     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
10099     if (res == ERROR_ACCESS_DENIED)
10100     {
10101         skip("Not enough rights to perform tests\n");
10102         return;
10103     }
10104     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10105 
10106     /* UserData product key exists */
10107     lstrcpyA(patchcode, "apple");
10108     lstrcpyA(targetprod, "banana");
10109     context = 0xdeadbeef;
10110     lstrcpyA(targetsid, "kiwi");
10111     size = MAX_PATH;
10112     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10113                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10114                            &context, targetsid, &size);
10115     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10116     ok(!lstrcmpA(patchcode, "apple"),
10117        "Expected patchcode to be unchanged, got %s\n", patchcode);
10118     ok(!lstrcmpA(targetprod, "banana"),
10119        "Expected targetprod to be unchanged, got %s\n", targetprod);
10120     ok(context == 0xdeadbeef,
10121        "Expected context to be unchanged, got %d\n", context);
10122     ok(!lstrcmpA(targetsid, "kiwi"),
10123        "Expected targetsid to be unchanged, got %s\n", targetsid);
10124     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10125 
10126     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
10127     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10128 
10129     /* UserData patches key exists */
10130     lstrcpyA(patchcode, "apple");
10131     lstrcpyA(targetprod, "banana");
10132     context = 0xdeadbeef;
10133     lstrcpyA(targetsid, "kiwi");
10134     size = MAX_PATH;
10135     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10136                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10137                            &context, targetsid, &size);
10138     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10139     ok(!lstrcmpA(patchcode, "apple"),
10140        "Expected patchcode to be unchanged, got %s\n", patchcode);
10141     ok(!lstrcmpA(targetprod, "banana"),
10142        "Expected targetprod to be unchanged, got %s\n", targetprod);
10143     ok(context == 0xdeadbeef,
10144        "Expected context to be unchanged, got %d\n", context);
10145     ok(!lstrcmpA(targetsid, "kiwi"),
10146        "Expected targetsid to be unchanged, got %s\n", targetsid);
10147     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10148 
10149     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
10150     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10151 
10152     /* specific UserData patch key exists */
10153     lstrcpyA(patchcode, "apple");
10154     lstrcpyA(targetprod, "banana");
10155     context = 0xdeadbeef;
10156     lstrcpyA(targetsid, "kiwi");
10157     size = MAX_PATH;
10158     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10159                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10160                            &context, targetsid, &size);
10161     ok(r == ERROR_BAD_CONFIGURATION,
10162        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10163     ok(!lstrcmpA(patchcode, "apple"),
10164        "Expected patchcode to be unchanged, got %s\n", patchcode);
10165     ok(!lstrcmpA(targetprod, "banana"),
10166        "Expected targetprod to be unchanged, got %s\n", targetprod);
10167     ok(context == 0xdeadbeef,
10168        "Expected context to be unchanged, got %d\n", context);
10169     ok(!lstrcmpA(targetsid, "kiwi"),
10170        "Expected targetsid to be unchanged, got %s\n", targetsid);
10171     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10172 
10173     data = MSIPATCHSTATE_SUPERSEDED;
10174     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10175                          (const BYTE *)&data, sizeof(DWORD));
10176     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10177 
10178     /* State value exists */
10179     lstrcpyA(patchcode, "apple");
10180     lstrcpyA(targetprod, "banana");
10181     context = 0xdeadbeef;
10182     lstrcpyA(targetsid, "kiwi");
10183     size = MAX_PATH;
10184     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10185                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10186                            &context, targetsid, &size);
10187     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10188     ok(!lstrcmpA(patchcode, patch),
10189        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10190     ok(!lstrcmpA(targetprod, prodcode),
10191        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10192     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
10193        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
10194     ok(!lstrcmpA(targetsid, expectedsid),
10195        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10196     ok(size == lstrlenA(expectedsid),
10197        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10198 
10199     /* MSIPATCHSTATE_OBSOLETED */
10200 
10201     lstrcpyA(patchcode, "apple");
10202     lstrcpyA(targetprod, "banana");
10203     context = 0xdeadbeef;
10204     lstrcpyA(targetsid, "kiwi");
10205     size = MAX_PATH;
10206     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10207                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
10208                            &context, targetsid, &size);
10209     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10210     ok(!lstrcmpA(patchcode, "apple"),
10211        "Expected patchcode to be unchanged, got %s\n", patchcode);
10212     ok(!lstrcmpA(targetprod, "banana"),
10213        "Expected targetprod to be unchanged, got %s\n", targetprod);
10214     ok(context == 0xdeadbeef,
10215        "Expected context to be unchanged, got %d\n", context);
10216     ok(!lstrcmpA(targetsid, "kiwi"),
10217        "Expected targetsid to be unchanged, got %s\n", targetsid);
10218     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10219 
10220     data = MSIPATCHSTATE_OBSOLETED;
10221     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10222                          (const BYTE *)&data, sizeof(DWORD));
10223     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10224 
10225     /* State value is obsoleted */
10226     lstrcpyA(patchcode, "apple");
10227     lstrcpyA(targetprod, "banana");
10228     context = 0xdeadbeef;
10229     lstrcpyA(targetsid, "kiwi");
10230     size = MAX_PATH;
10231     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10232                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
10233                            &context, targetsid, &size);
10234     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10235     ok(!lstrcmpA(patchcode, patch),
10236        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10237     ok(!lstrcmpA(targetprod, prodcode),
10238        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10239     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
10240        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
10241     ok(!lstrcmpA(targetsid, expectedsid),
10242        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10243     ok(size == lstrlenA(expectedsid),
10244        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10245 
10246     /* MSIPATCHSTATE_REGISTERED */
10247     /* FIXME */
10248 
10249     /* MSIPATCHSTATE_ALL */
10250 
10251     /* 1st */
10252     lstrcpyA(patchcode, "apple");
10253     lstrcpyA(targetprod, "banana");
10254     context = 0xdeadbeef;
10255     lstrcpyA(targetsid, "kiwi");
10256     size = MAX_PATH;
10257     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10258                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
10259                            &context, targetsid, &size);
10260     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10261     ok(!lstrcmpA(patchcode, patch),
10262        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10263     ok(!lstrcmpA(targetprod, prodcode),
10264        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10265     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
10266        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
10267     ok(!lstrcmpA(targetsid, expectedsid),
10268        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10269     ok(size == lstrlenA(expectedsid),
10270        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10271 
10272     /* same patch in multiple places, only one is enumerated */
10273     lstrcpyA(patchcode, "apple");
10274     lstrcpyA(targetprod, "banana");
10275     context = 0xdeadbeef;
10276     lstrcpyA(targetsid, "kiwi");
10277     size = MAX_PATH;
10278     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10279                            MSIPATCHSTATE_ALL, 1, patchcode, targetprod,
10280                            &context, targetsid, &size);
10281     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10282     ok(!lstrcmpA(patchcode, "apple"),
10283        "Expected patchcode to be unchanged, got %s\n", patchcode);
10284     ok(!lstrcmpA(targetprod, "banana"),
10285        "Expected targetprod to be unchanged, got %s\n", targetprod);
10286     ok(context == 0xdeadbeef,
10287        "Expected context to be unchanged, got %d\n", context);
10288     ok(!lstrcmpA(targetsid, "kiwi"),
10289        "Expected targetsid to be unchanged, got %s\n", targetsid);
10290     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10291 
10292     RegDeleteValueA(hpatch, "State");
10293     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
10294     RegCloseKey(hpatch);
10295     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
10296     RegCloseKey(udpatch);
10297     delete_key(udprod, "", access & KEY_WOW64_64KEY);
10298     RegCloseKey(udprod);
10299     RegDeleteValueA(patches, "Patches");
10300     delete_key(patches, "", access & KEY_WOW64_64KEY);
10301     RegCloseKey(patches);
10302     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
10303     RegCloseKey(prodkey);
10304 }
10305 
10306 static void test_MsiEnumPatchesEx_userunmanaged(LPCSTR usersid, LPCSTR expectedsid)
10307 {
10308     MSIINSTALLCONTEXT context;
10309     CHAR keypath[MAX_PATH], patch[MAX_PATH];
10310     CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
10311     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
10312     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
10313     HKEY prodkey, patches, udprod, udpatch;
10314     HKEY userkey, hpatch;
10315     DWORD size, data;
10316     LONG res;
10317     UINT r;
10318     REGSAM access = KEY_ALL_ACCESS;
10319 
10320     create_test_guid(prodcode, prod_squashed);
10321     create_test_guid(patch, patch_squashed);
10322 
10323     if (is_wow64)
10324         access |= KEY_WOW64_64KEY;
10325 
10326     /* MSIPATCHSTATE_APPLIED */
10327 
10328     lstrcpyA(patchcode, "apple");
10329     lstrcpyA(targetprod, "banana");
10330     context = 0xdeadbeef;
10331     lstrcpyA(targetsid, "kiwi");
10332     size = MAX_PATH;
10333     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10334                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10335                            &context, targetsid, &size);
10336     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10337     ok(!lstrcmpA(patchcode, "apple"),
10338        "Expected patchcode to be unchanged, got %s\n", patchcode);
10339     ok(!lstrcmpA(targetprod, "banana"),
10340        "Expected targetprod to be unchanged, got %s\n", targetprod);
10341     ok(context == 0xdeadbeef,
10342        "Expected context to be unchanged, got %d\n", context);
10343     ok(!lstrcmpA(targetsid, "kiwi"),
10344        "Expected targetsid to be unchanged, got %s\n", targetsid);
10345     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10346 
10347     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
10348     lstrcatA(keypath, prod_squashed);
10349 
10350     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
10351     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10352 
10353     /* current user product key exists */
10354     lstrcpyA(patchcode, "apple");
10355     lstrcpyA(targetprod, "banana");
10356     context = 0xdeadbeef;
10357     lstrcpyA(targetsid, "kiwi");
10358     size = MAX_PATH;
10359     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10360                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10361                            &context, targetsid, &size);
10362     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10363     ok(!lstrcmpA(patchcode, "apple"),
10364        "Expected patchcode to be unchanged, got %s\n", patchcode);
10365     ok(!lstrcmpA(targetprod, "banana"),
10366        "Expected targetprod to be unchanged, got %s\n", targetprod);
10367     ok(context == 0xdeadbeef,
10368        "Expected context to be unchanged, got %d\n", context);
10369     ok(!lstrcmpA(targetsid, "kiwi"),
10370        "Expected targetsid to be unchanged, got %s\n", targetsid);
10371     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10372 
10373     res = RegCreateKeyA(prodkey, "Patches", &patches);
10374     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10375 
10376     /* Patches key exists */
10377     lstrcpyA(patchcode, "apple");
10378     lstrcpyA(targetprod, "banana");
10379     context = 0xdeadbeef;
10380     lstrcpyA(targetsid, "kiwi");
10381     size = MAX_PATH;
10382     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10383                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10384                            &context, targetsid, &size);
10385     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10386     ok(!lstrcmpA(patchcode, "apple"),
10387        "Expected patchcode to be unchanged, got %s\n", patchcode);
10388     ok(!lstrcmpA(targetprod, "banana"),
10389        "Expected targetprod to be unchanged, got %s\n", targetprod);
10390     ok(context == 0xdeadbeef,
10391        "Expected context to be unchanged, got %d\n", context);
10392     ok(!lstrcmpA(targetsid, "kiwi"),
10393        "Expected targetsid to be unchanged, got %s\n", targetsid);
10394     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10395 
10396     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
10397                          (const BYTE *)patch_squashed,
10398                          lstrlenA(patch_squashed) + 1);
10399     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10400 
10401     /* Patches value exists, is not REG_MULTI_SZ */
10402     lstrcpyA(patchcode, "apple");
10403     lstrcpyA(targetprod, "banana");
10404     context = 0xdeadbeef;
10405     lstrcpyA(targetsid, "kiwi");
10406     size = MAX_PATH;
10407     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10408                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10409                            &context, targetsid, &size);
10410     ok(r == ERROR_BAD_CONFIGURATION,
10411        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10412     ok(!lstrcmpA(patchcode, "apple"),
10413        "Expected patchcode to be unchanged, got %s\n", patchcode);
10414     ok(!lstrcmpA(targetprod, "banana"),
10415        "Expected targetprod to be unchanged, got %s\n", targetprod);
10416     ok(context == 0xdeadbeef,
10417        "Expected context to be unchanged, got %d\n", context);
10418     ok(!lstrcmpA(targetsid, "kiwi"),
10419        "Expected targetsid to be unchanged, got %s\n", targetsid);
10420     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10421 
10422     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10423                          (const BYTE *)"a\0b\0c\0\0", 7);
10424     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10425 
10426     /* Patches value exists, is not a squashed guid */
10427     lstrcpyA(patchcode, "apple");
10428     lstrcpyA(targetprod, "banana");
10429     context = 0xdeadbeef;
10430     lstrcpyA(targetsid, "kiwi");
10431     size = MAX_PATH;
10432     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10433                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10434                            &context, targetsid, &size);
10435     ok(r == ERROR_BAD_CONFIGURATION,
10436        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10437     ok(!lstrcmpA(patchcode, "apple"),
10438        "Expected patchcode to be unchanged, got %s\n", patchcode);
10439     ok(!lstrcmpA(targetprod, "banana"),
10440        "Expected targetprod to be unchanged, got %s\n", targetprod);
10441     ok(context == 0xdeadbeef,
10442        "Expected context to be unchanged, got %d\n", context);
10443     ok(!lstrcmpA(targetsid, "kiwi"),
10444        "Expected targetsid to be unchanged, got %s\n", targetsid);
10445     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10446 
10447     patch_squashed[lstrlenA(patch_squashed) + 1] = 0;
10448     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10449                          (const BYTE *)patch_squashed,
10450                          lstrlenA(patch_squashed) + 2);
10451     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10452 
10453     /* Patches value exists */
10454     lstrcpyA(patchcode, "apple");
10455     lstrcpyA(targetprod, "banana");
10456     context = 0xdeadbeef;
10457     lstrcpyA(targetsid, "kiwi");
10458     size = MAX_PATH;
10459     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10460                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10461                            &context, targetsid, &size);
10462     ok(r == ERROR_NO_MORE_ITEMS ||
10463        broken(r == ERROR_BAD_CONFIGURATION), /* Windows Installer 3.0 */
10464        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10465     ok(!lstrcmpA(patchcode, "apple"),
10466        "Expected patchcode to be unchanged, got %s\n", patchcode);
10467     ok(!lstrcmpA(targetprod, "banana"),
10468        "Expected targetprod to be unchanged, got %s\n", targetprod);
10469     ok(context == 0xdeadbeef,
10470        "Expected context to be unchanged, got %d\n", context);
10471     ok(!lstrcmpA(targetsid, "kiwi"),
10472        "Expected targetsid to be unchanged, got %s\n", targetsid);
10473     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10474 
10475     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
10476                          (const BYTE *)"whatever", 9);
10477     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10478 
10479     /* patch code value exists */
10480     lstrcpyA(patchcode, "apple");
10481     lstrcpyA(targetprod, "banana");
10482     context = 0xdeadbeef;
10483     lstrcpyA(targetsid, "kiwi");
10484     size = MAX_PATH;
10485     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10486                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10487                            &context, targetsid, &size);
10488     ok(r == ERROR_NO_MORE_ITEMS ||
10489        broken(r == ERROR_BAD_CONFIGURATION), /* Windows Installer 3.0 */
10490        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10491     ok(!lstrcmpA(patchcode, "apple"),
10492        "Expected patchcode to be unchanged, got %s\n", patchcode);
10493     ok(!lstrcmpA(targetprod, "banana"),
10494        "Expected targetprod to be unchanged, got %s\n", targetprod);
10495     ok(context == 0xdeadbeef,
10496        "Expected context to be unchanged, got %d\n", context);
10497     ok(!lstrcmpA(targetsid, "kiwi"),
10498        "Expected targetsid to be unchanged, got %s\n", targetsid);
10499     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10500 
10501     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
10502     lstrcatA(keypath, expectedsid);
10503     lstrcatA(keypath, "\\Patches\\");
10504     lstrcatA(keypath, patch_squashed);
10505 
10506     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
10507     if (res == ERROR_ACCESS_DENIED)
10508     {
10509         skip("Not enough rights to perform tests\n");
10510         goto error;
10511     }
10512     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10513 
10514     /* userdata patch key exists */
10515     lstrcpyA(patchcode, "apple");
10516     lstrcpyA(targetprod, "banana");
10517     context = 0xdeadbeef;
10518     lstrcpyA(targetsid, "kiwi");
10519     size = MAX_PATH;
10520     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10521                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10522                            &context, targetsid, &size);
10523     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10524     ok(!lstrcmpA(patchcode, patch),
10525        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10526     ok(!lstrcmpA(targetprod, prodcode),
10527        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10528     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
10529        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
10530     ok(!lstrcmpA(targetsid, expectedsid),
10531        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10532     ok(size == lstrlenA(expectedsid),
10533        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10534 
10535     /* MSIPATCHSTATE_SUPERSEDED */
10536 
10537     lstrcpyA(patchcode, "apple");
10538     lstrcpyA(targetprod, "banana");
10539     context = 0xdeadbeef;
10540     lstrcpyA(targetsid, "kiwi");
10541     size = MAX_PATH;
10542     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10543                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10544                            &context, targetsid, &size);
10545     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10546     ok(!lstrcmpA(patchcode, "apple"),
10547        "Expected patchcode to be unchanged, got %s\n", patchcode);
10548     ok(!lstrcmpA(targetprod, "banana"),
10549        "Expected targetprod to be unchanged, got %s\n", targetprod);
10550     ok(context == 0xdeadbeef,
10551        "Expected context to be unchanged, got %d\n", context);
10552     ok(!lstrcmpA(targetsid, "kiwi"),
10553        "Expected targetsid to be unchanged, got %s\n", targetsid);
10554     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10555 
10556     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
10557     lstrcatA(keypath, expectedsid);
10558     lstrcatA(keypath, "\\Products\\");
10559     lstrcatA(keypath, prod_squashed);
10560 
10561     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
10562     if (res == ERROR_ACCESS_DENIED)
10563     {
10564         skip("Not enough rights to perform tests\n");
10565         goto error;
10566     }
10567     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10568 
10569     /* UserData product key exists */
10570     lstrcpyA(patchcode, "apple");
10571     lstrcpyA(targetprod, "banana");
10572     context = 0xdeadbeef;
10573     lstrcpyA(targetsid, "kiwi");
10574     size = MAX_PATH;
10575     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10576                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10577                            &context, targetsid, &size);
10578     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10579     ok(!lstrcmpA(patchcode, "apple"),
10580        "Expected patchcode to be unchanged, got %s\n", patchcode);
10581     ok(!lstrcmpA(targetprod, "banana"),
10582        "Expected targetprod to be unchanged, got %s\n", targetprod);
10583     ok(context == 0xdeadbeef,
10584        "Expected context to be unchanged, got %d\n", context);
10585     ok(!lstrcmpA(targetsid, "kiwi"),
10586        "Expected targetsid to be unchanged, got %s\n", targetsid);
10587     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10588 
10589     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
10590     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10591 
10592     /* UserData patches key exists */
10593     lstrcpyA(patchcode, "apple");
10594     lstrcpyA(targetprod, "banana");
10595     context = 0xdeadbeef;
10596     lstrcpyA(targetsid, "kiwi");
10597     size = MAX_PATH;
10598     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10599                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10600                            &context, targetsid, &size);
10601     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10602     ok(!lstrcmpA(patchcode, "apple"),
10603        "Expected patchcode to be unchanged, got %s\n", patchcode);
10604     ok(!lstrcmpA(targetprod, "banana"),
10605        "Expected targetprod to be unchanged, got %s\n", targetprod);
10606     ok(context == 0xdeadbeef,
10607        "Expected context to be unchanged, got %d\n", context);
10608     ok(!lstrcmpA(targetsid, "kiwi"),
10609        "Expected targetsid to be unchanged, got %s\n", targetsid);
10610     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10611 
10612     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
10613     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10614 
10615     /* specific UserData patch key exists */
10616     lstrcpyA(patchcode, "apple");
10617     lstrcpyA(targetprod, "banana");
10618     context = 0xdeadbeef;
10619     lstrcpyA(targetsid, "kiwi");
10620     size = MAX_PATH;
10621     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10622                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10623                            &context, targetsid, &size);
10624     ok(r == ERROR_BAD_CONFIGURATION,
10625        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10626     ok(!lstrcmpA(patchcode, "apple"),
10627        "Expected patchcode to be unchanged, got %s\n", patchcode);
10628     ok(!lstrcmpA(targetprod, "banana"),
10629        "Expected targetprod to be unchanged, got %s\n", targetprod);
10630     ok(context == 0xdeadbeef,
10631        "Expected context to be unchanged, got %d\n", context);
10632     ok(!lstrcmpA(targetsid, "kiwi"),
10633        "Expected targetsid to be unchanged, got %s\n", targetsid);
10634     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10635 
10636     data = MSIPATCHSTATE_SUPERSEDED;
10637     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10638                          (const BYTE *)&data, sizeof(DWORD));
10639     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10640 
10641     /* State value exists */
10642     lstrcpyA(patchcode, "apple");
10643     lstrcpyA(targetprod, "banana");
10644     context = 0xdeadbeef;
10645     lstrcpyA(targetsid, "kiwi");
10646     size = MAX_PATH;
10647     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10648                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10649                            &context, targetsid, &size);
10650     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10651     ok(!lstrcmpA(patchcode, patch),
10652        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10653     ok(!lstrcmpA(targetprod, prodcode),
10654        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10655     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
10656        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
10657     ok(!lstrcmpA(targetsid, expectedsid),
10658        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10659     ok(size == lstrlenA(expectedsid),
10660        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10661 
10662     /* MSIPATCHSTATE_OBSOLETED */
10663 
10664     lstrcpyA(patchcode, "apple");
10665     lstrcpyA(targetprod, "banana");
10666     context = 0xdeadbeef;
10667     lstrcpyA(targetsid, "kiwi");
10668     size = MAX_PATH;
10669     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10670                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
10671                            &context, targetsid, &size);
10672     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10673     ok(!lstrcmpA(patchcode, "apple"),
10674        "Expected patchcode to be unchanged, got %s\n", patchcode);
10675     ok(!lstrcmpA(targetprod, "banana"),
10676        "Expected targetprod to be unchanged, got %s\n", targetprod);
10677     ok(context == 0xdeadbeef,
10678        "Expected context to be unchanged, got %d\n", context);
10679     ok(!lstrcmpA(targetsid, "kiwi"),
10680        "Expected targetsid to be unchanged, got %s\n", targetsid);
10681     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10682 
10683     data = MSIPATCHSTATE_OBSOLETED;
10684     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10685                          (const BYTE *)&data, sizeof(DWORD));
10686     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10687 
10688     /* State value is obsoleted */
10689     lstrcpyA(patchcode, "apple");
10690     lstrcpyA(targetprod, "banana");
10691     context = 0xdeadbeef;
10692     lstrcpyA(targetsid, "kiwi");
10693     size = MAX_PATH;
10694     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10695                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
10696                            &context, targetsid, &size);
10697     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10698     ok(!lstrcmpA(patchcode, patch),
10699        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10700     ok(!lstrcmpA(targetprod, prodcode),
10701        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10702     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
10703        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
10704     ok(!lstrcmpA(targetsid, expectedsid),
10705        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10706     ok(size == lstrlenA(expectedsid),
10707        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10708 
10709     /* MSIPATCHSTATE_REGISTERED */
10710     /* FIXME */
10711 
10712     /* MSIPATCHSTATE_ALL */
10713 
10714     /* 1st */
10715     lstrcpyA(patchcode, "apple");
10716     lstrcpyA(targetprod, "banana");
10717     context = 0xdeadbeef;
10718     lstrcpyA(targetsid, "kiwi");
10719     size = MAX_PATH;
10720     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10721                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
10722                            &context, targetsid, &size);
10723     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10724     ok(!lstrcmpA(patchcode, patch),
10725        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10726     ok(!lstrcmpA(targetprod, prodcode),
10727        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10728     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
10729        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
10730     ok(!lstrcmpA(targetsid, expectedsid),
10731        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10732     ok(size == lstrlenA(expectedsid),
10733        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10734 
10735     /* same patch in multiple places, only one is enumerated */
10736     lstrcpyA(patchcode, "apple");
10737     lstrcpyA(targetprod, "banana");
10738     context = 0xdeadbeef;
10739     lstrcpyA(targetsid, "kiwi");
10740     size = MAX_PATH;
10741     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10742                            MSIPATCHSTATE_ALL, 1, patchcode, targetprod,
10743                            &context, targetsid, &size);
10744     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10745     ok(!lstrcmpA(patchcode, "apple"),
10746        "Expected patchcode to be unchanged, got %s\n", patchcode);
10747     ok(!lstrcmpA(targetprod, "banana"),
10748        "Expected targetprod to be unchanged, got %s\n", targetprod);
10749     ok(context == 0xdeadbeef,
10750        "Expected context to be unchanged, got %d\n", context);
10751     ok(!lstrcmpA(targetsid, "kiwi"),
10752        "Expected targetsid to be unchanged, got %s\n", targetsid);
10753     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10754 
10755     RegDeleteValueA(hpatch, "State");
10756     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
10757     RegCloseKey(hpatch);
10758     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
10759     RegCloseKey(udpatch);
10760     delete_key(udprod, "", access & KEY_WOW64_64KEY);
10761     RegCloseKey(udprod);
10762     delete_key(userkey, "", access & KEY_WOW64_64KEY);
10763     RegCloseKey(userkey);
10764     RegDeleteValueA(patches, patch_squashed);
10765     RegDeleteValueA(patches, "Patches");
10766 
10767 error:
10768     RegDeleteKeyA(patches, "");
10769     RegCloseKey(patches);
10770     RegDeleteKeyA(prodkey, "");
10771     RegCloseKey(prodkey);
10772 }
10773 
10774 static void test_MsiEnumPatchesEx_machine(void)
10775 {
10776     CHAR keypath[MAX_PATH], patch[MAX_PATH];
10777     CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
10778     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
10779     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
10780     HKEY prodkey, patches, udprod, udpatch;
10781     HKEY hpatch;
10782     MSIINSTALLCONTEXT context;
10783     DWORD size, data;
10784     LONG res;
10785     UINT r;
10786     REGSAM access = KEY_ALL_ACCESS;
10787 
10788     create_test_guid(prodcode, prod_squashed);
10789     create_test_guid(patch, patch_squashed);
10790 
10791     if (is_wow64)
10792         access |= KEY_WOW64_64KEY;
10793 
10794     /* MSIPATCHSTATE_APPLIED */
10795 
10796     lstrcpyA(patchcode, "apple");
10797     lstrcpyA(targetprod, "banana");
10798     context = 0xdeadbeef;
10799     lstrcpyA(targetsid, "kiwi");
10800     size = MAX_PATH;
10801     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10802                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10803                            &context, targetsid, &size);
10804     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10805     ok(!lstrcmpA(patchcode, "apple"),
10806        "Expected patchcode to be unchanged, got %s\n", patchcode);
10807     ok(!lstrcmpA(targetprod, "banana"),
10808        "Expected targetprod to be unchanged, got %s\n", targetprod);
10809     ok(context == 0xdeadbeef,
10810        "Expected context to be unchanged, got %d\n", context);
10811     ok(!lstrcmpA(targetsid, "kiwi"),
10812        "Expected targetsid to be unchanged, got %s\n", targetsid);
10813     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10814 
10815     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
10816     lstrcatA(keypath, prod_squashed);
10817 
10818     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
10819     if (res == ERROR_ACCESS_DENIED)
10820     {
10821         skip("Not enough rights to perform tests\n");
10822         return;
10823     }
10824     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10825 
10826     /* local product key exists */
10827     lstrcpyA(patchcode, "apple");
10828     lstrcpyA(targetprod, "banana");
10829     context = 0xdeadbeef;
10830     lstrcpyA(targetsid, "kiwi");
10831     size = MAX_PATH;
10832     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10833                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10834                            &context, targetsid, &size);
10835     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10836     ok(!lstrcmpA(patchcode, "apple"),
10837        "Expected patchcode to be unchanged, got %s\n", patchcode);
10838     ok(!lstrcmpA(targetprod, "banana"),
10839        "Expected targetprod to be unchanged, got %s\n", targetprod);
10840     ok(context == 0xdeadbeef,
10841        "Expected context to be unchanged, got %d\n", context);
10842     ok(!lstrcmpA(targetsid, "kiwi"),
10843        "Expected targetsid to be unchanged, got %s\n", targetsid);
10844     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10845 
10846     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
10847     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10848 
10849     /* Patches key exists */
10850     lstrcpyA(patchcode, "apple");
10851     lstrcpyA(targetprod, "banana");
10852     context = 0xdeadbeef;
10853     lstrcpyA(targetsid, "kiwi");
10854     size = MAX_PATH;
10855     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10856                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10857                            &context, targetsid, &size);
10858     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10859     ok(!lstrcmpA(patchcode, "apple"),
10860        "Expected patchcode to be unchanged, got %s\n", patchcode);
10861     ok(!lstrcmpA(targetprod, "banana"),
10862        "Expected targetprod to be unchanged, got %s\n", targetprod);
10863     ok(context == 0xdeadbeef,
10864        "Expected context to be unchanged, got %d\n", context);
10865     ok(!lstrcmpA(targetsid, "kiwi"),
10866        "Expected targetsid to be unchanged, got %s\n", targetsid);
10867     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10868 
10869     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
10870                          (const BYTE *)patch_squashed,
10871                          lstrlenA(patch_squashed) + 1);
10872     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10873 
10874     /* Patches value exists, is not REG_MULTI_SZ */
10875     lstrcpyA(patchcode, "apple");
10876     lstrcpyA(targetprod, "banana");
10877     context = 0xdeadbeef;
10878     lstrcpyA(targetsid, "kiwi");
10879     size = MAX_PATH;
10880     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10881                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10882                            &context, targetsid, &size);
10883     ok(r == ERROR_BAD_CONFIGURATION,
10884        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10885     ok(!lstrcmpA(patchcode, "apple"),
10886        "Expected patchcode to be unchanged, got %s\n", patchcode);
10887     ok(!lstrcmpA(targetprod, "banana"),
10888        "Expected targetprod to be unchanged, got %s\n", targetprod);
10889     ok(context == 0xdeadbeef,
10890        "Expected context to be unchanged, got %d\n", context);
10891     ok(!lstrcmpA(targetsid, "kiwi"),
10892        "Expected targetsid to be unchanged, got %s\n", targetsid);
10893     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10894 
10895     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10896                          (const BYTE *)"a\0b\0c\0\0", 7);
10897     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10898 
10899     /* Patches value exists, is not a squashed guid */
10900     lstrcpyA(patchcode, "apple");
10901     lstrcpyA(targetprod, "banana");
10902     context = 0xdeadbeef;
10903     lstrcpyA(targetsid, "kiwi");
10904     size = MAX_PATH;
10905     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10906                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10907                            &context, targetsid, &size);
10908     ok(r == ERROR_BAD_CONFIGURATION,
10909        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10910     ok(!lstrcmpA(patchcode, "apple"),
10911        "Expected patchcode to be unchanged, got %s\n", patchcode);
10912     ok(!lstrcmpA(targetprod, "banana"),
10913        "Expected targetprod to be unchanged, got %s\n", targetprod);
10914     ok(context == 0xdeadbeef,
10915        "Expected context to be unchanged, got %d\n", context);
10916     ok(!lstrcmpA(targetsid, "kiwi"),
10917        "Expected targetsid to be unchanged, got %s\n", targetsid);
10918     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10919 
10920     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
10921     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10922                          (const BYTE *)patch_squashed,
10923                          lstrlenA(patch_squashed) + 2);
10924     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10925 
10926     /* Patches value exists */
10927     lstrcpyA(patchcode, "apple");
10928     lstrcpyA(targetprod, "banana");
10929     context = 0xdeadbeef;
10930     lstrcpyA(targetsid, "kiwi");
10931     size = MAX_PATH;
10932     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10933                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10934                            &context, targetsid, &size);
10935     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10936     ok(!lstrcmpA(patchcode, "apple"),
10937        "Expected patchcode to be unchanged, got %s\n", patchcode);
10938     ok(!lstrcmpA(targetprod, "banana"),
10939        "Expected targetprod to be unchanged, got %s\n", targetprod);
10940     ok(context == 0xdeadbeef,
10941        "Expected context to be unchanged, got %d\n", context);
10942     ok(!lstrcmpA(targetsid, "kiwi"),
10943        "Expected targetsid to be unchanged, got %s\n", targetsid);
10944     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10945 
10946     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
10947                          (const BYTE *)"whatever", 9);
10948     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10949 
10950     /* patch code value exists */
10951     lstrcpyA(patchcode, "apple");
10952     lstrcpyA(targetprod, "banana");
10953     context = 0xdeadbeef;
10954     lstrcpyA(targetsid, "kiwi");
10955     size = MAX_PATH;
10956     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10957                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10958                            &context, targetsid, &size);
10959     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10960     ok(!lstrcmpA(patchcode, patch),
10961        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10962     ok(!lstrcmpA(targetprod, prodcode),
10963        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10964     ok(context == MSIINSTALLCONTEXT_MACHINE,
10965        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10966     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
10967     ok(size == 0, "Expected 0, got %d\n", size);
10968 
10969     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
10970     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
10971     lstrcatA(keypath, prod_squashed);
10972 
10973     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
10974     if (res == ERROR_ACCESS_DENIED)
10975     {
10976         skip("Not enough rights to perform tests\n");
10977         goto done;
10978     }
10979     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10980 
10981     /* local UserData product key exists */
10982     lstrcpyA(patchcode, "apple");
10983     lstrcpyA(targetprod, "banana");
10984     context = 0xdeadbeef;
10985     lstrcpyA(targetsid, "kiwi");
10986     size = MAX_PATH;
10987     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10988                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10989                            &context, targetsid, &size);
10990     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10991     ok(!lstrcmpA(patchcode, patch),
10992        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10993     ok(!lstrcmpA(targetprod, prodcode),
10994        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10995     ok(context == MSIINSTALLCONTEXT_MACHINE,
10996        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10997     ok(!lstrcmpA(targetsid, ""),
10998        "Expected \"\", got \"%s\"\n", targetsid);
10999     ok(size == 0, "Expected 0, got %d\n", size);
11000 
11001     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
11002     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11003 
11004     /* local UserData Patches key exists */
11005     lstrcpyA(patchcode, "apple");
11006     lstrcpyA(targetprod, "banana");
11007     context = 0xdeadbeef;
11008     lstrcpyA(targetsid, "kiwi");
11009     size = MAX_PATH;
11010     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11011                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
11012                            &context, targetsid, &size);
11013     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11014     ok(!lstrcmpA(patchcode, patch),
11015        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
11016     ok(!lstrcmpA(targetprod, prodcode),
11017        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
11018     ok(context == MSIINSTALLCONTEXT_MACHINE,
11019        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
11020     ok(!lstrcmpA(targetsid, ""),
11021        "Expected \"\", got \"%s\"\n", targetsid);
11022     ok(size == 0, "Expected 0, got %d\n", size);
11023 
11024     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
11025     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11026 
11027     /* local UserData Product patch key exists */
11028     lstrcpyA(patchcode, "apple");
11029     lstrcpyA(targetprod, "banana");
11030     context = 0xdeadbeef;
11031     lstrcpyA(targetsid, "kiwi");
11032     size = MAX_PATH;
11033     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11034                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
11035                            &context, targetsid, &size);
11036     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11037     ok(!lstrcmpA(patchcode, "apple"),
11038        "Expected patchcode to be unchanged, got %s\n", patchcode);
11039     ok(!lstrcmpA(targetprod, "banana"),
11040        "Expected targetprod to be unchanged, got %s\n", targetprod);
11041     ok(context == 0xdeadbeef,
11042        "Expected context to be unchanged, got %d\n", context);
11043     ok(!lstrcmpA(targetsid, "kiwi"),
11044        "Expected targetsid to be unchanged, got %s\n", targetsid);
11045     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11046 
11047     data = MSIPATCHSTATE_APPLIED;
11048     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
11049                          (const BYTE *)&data, sizeof(DWORD));
11050     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11051 
11052     /* State value exists */
11053     lstrcpyA(patchcode, "apple");
11054     lstrcpyA(targetprod, "banana");
11055     context = 0xdeadbeef;
11056     lstrcpyA(targetsid, "kiwi");
11057     size = MAX_PATH;
11058     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11059                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
11060                            &context, targetsid, &size);
11061     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11062     ok(!lstrcmpA(patchcode, patch),
11063        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
11064     ok(!lstrcmpA(targetprod, prodcode),
11065        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
11066     ok(context == MSIINSTALLCONTEXT_MACHINE,
11067        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
11068     ok(!lstrcmpA(targetsid, ""),
11069        "Expected \"\", got \"%s\"\n", targetsid);
11070     ok(size == 0, "Expected 0, got %d\n", size);
11071 
11072     /* MSIPATCHSTATE_SUPERSEDED */
11073 
11074     lstrcpyA(patchcode, "apple");
11075     lstrcpyA(targetprod, "banana");
11076     context = 0xdeadbeef;
11077     lstrcpyA(targetsid, "kiwi");
11078     size = MAX_PATH;
11079     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11080                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
11081                            &context, targetsid, &size);
11082     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11083     ok(!lstrcmpA(patchcode, "apple"),
11084        "Expected patchcode to be unchanged, got %s\n", patchcode);
11085     ok(!lstrcmpA(targetprod, "banana"),
11086        "Expected targetprod to be unchanged, got %s\n", targetprod);
11087     ok(context == 0xdeadbeef,
11088        "Expected context to be unchanged, got %d\n", context);
11089     ok(!lstrcmpA(targetsid, "kiwi"),
11090        "Expected targetsid to be unchanged, got %s\n", targetsid);
11091     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11092 
11093     data = MSIPATCHSTATE_SUPERSEDED;
11094     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
11095                          (const BYTE *)&data, sizeof(DWORD));
11096     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11097 
11098     /* State value is MSIPATCHSTATE_SUPERSEDED */
11099     lstrcpyA(patchcode, "apple");
11100     lstrcpyA(targetprod, "banana");
11101     context = 0xdeadbeef;
11102     lstrcpyA(targetsid, "kiwi");
11103     size = MAX_PATH;
11104     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11105                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
11106                            &context, targetsid, &size);
11107     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11108     ok(!lstrcmpA(patchcode, patch),
11109        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
11110     ok(!lstrcmpA(targetprod, prodcode),
11111        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
11112     ok(context == MSIINSTALLCONTEXT_MACHINE,
11113        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
11114     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
11115     ok(size == 0, "Expected 0, got %d\n", size);
11116 
11117     /* MSIPATCHSTATE_OBSOLETED */
11118 
11119     lstrcpyA(patchcode, "apple");
11120     lstrcpyA(targetprod, "banana");
11121     context = 0xdeadbeef;
11122     lstrcpyA(targetsid, "kiwi");
11123     size = MAX_PATH;
11124     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11125                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
11126                            &context, targetsid, &size);
11127     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11128     ok(!lstrcmpA(patchcode, "apple"),
11129        "Expected patchcode to be unchanged, got %s\n", patchcode);
11130     ok(!lstrcmpA(targetprod, "banana"),
11131        "Expected targetprod to be unchanged, got %s\n", targetprod);
11132     ok(context == 0xdeadbeef,
11133        "Expected context to be unchanged, got %d\n", context);
11134     ok(!lstrcmpA(targetsid, "kiwi"),
11135        "Expected targetsid to be unchanged, got %s\n", targetsid);
11136     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11137 
11138     data = MSIPATCHSTATE_OBSOLETED;
11139     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
11140                          (const BYTE *)&data, sizeof(DWORD));
11141     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11142 
11143     /* State value is obsoleted */
11144     lstrcpyA(patchcode, "apple");
11145     lstrcpyA(targetprod, "banana");
11146     context = 0xdeadbeef;
11147     lstrcpyA(targetsid, "kiwi");
11148     size = MAX_PATH;
11149     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11150                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
11151                            &context, targetsid, &size);
11152     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11153     ok(!lstrcmpA(patchcode, patch),
11154        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
11155     ok(!lstrcmpA(targetprod, prodcode),
11156        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
11157     ok(context == MSIINSTALLCONTEXT_MACHINE,
11158        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
11159     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
11160     ok(size == 0, "Expected 0, got %d\n", size);
11161 
11162     /* MSIPATCHSTATE_REGISTERED */
11163     /* FIXME */
11164 
11165     /* MSIPATCHSTATE_ALL */
11166 
11167     /* 1st */
11168     lstrcpyA(patchcode, "apple");
11169     lstrcpyA(targetprod, "banana");
11170     context = 0xdeadbeef;
11171     lstrcpyA(targetsid, "kiwi");
11172     size = MAX_PATH;
11173     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11174                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
11175                            &context, targetsid, &size);
11176     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11177     ok(!lstrcmpA(patchcode, patch),
11178        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
11179     ok(!lstrcmpA(targetprod, prodcode),
11180        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
11181     ok(context == MSIINSTALLCONTEXT_MACHINE,
11182        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
11183     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
11184     ok(size == 0, "Expected 0, got %d\n", size);
11185 
11186     /* same patch in multiple places, only one is enumerated */
11187     lstrcpyA(patchcode, "apple");
11188     lstrcpyA(targetprod, "banana");
11189     context = 0xdeadbeef;
11190     lstrcpyA(targetsid, "kiwi");
11191     size = MAX_PATH;
11192     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11193                            MSIPATCHSTATE_ALL, 1, patchcode, targetprod,
11194                            &context, targetsid, &size);
11195     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11196     ok(!lstrcmpA(patchcode, "apple"),
11197        "Expected patchcode to be unchanged, got %s\n", patchcode);
11198     ok(!lstrcmpA(targetprod, "banana"),
11199        "Expected targetprod to be unchanged, got %s\n", targetprod);
11200     ok(context == 0xdeadbeef,
11201        "Expected context to be unchanged, got %d\n", context);
11202     ok(!lstrcmpA(targetsid, "kiwi"),
11203        "Expected targetsid to be unchanged, got %s\n", targetsid);
11204     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11205 
11206     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
11207     RegDeleteValueA(hpatch, "State");
11208     RegCloseKey(hpatch);
11209     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
11210     RegCloseKey(udpatch);
11211     delete_key(udprod, "", access & KEY_WOW64_64KEY);
11212     RegCloseKey(udprod);
11213 
11214 done:
11215     RegDeleteValueA(patches, patch_squashed);
11216     RegDeleteValueA(patches, "Patches");
11217     delete_key(patches, "", access & KEY_WOW64_64KEY);
11218     RegCloseKey(patches);
11219     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
11220     RegCloseKey(prodkey);
11221 }
11222 
11223 static void test_MsiEnumPatchesEx(void)
11224 {
11225     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
11226     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
11227     CHAR patchcode[MAX_PATH];
11228     MSIINSTALLCONTEXT context;
11229     LPSTR usersid;
11230     DWORD size;
11231     UINT r;
11232 
11233     if (!pMsiEnumPatchesExA)
11234     {
11235         win_skip("MsiEnumPatchesExA not implemented\n");
11236         return;
11237     }
11238 
11239     create_test_guid(prodcode, prod_squashed);
11240     usersid = get_user_sid();
11241 
11242     /* empty szProductCode */
11243     lstrcpyA(patchcode, "apple");
11244     lstrcpyA(targetprod, "banana");
11245     context = 0xdeadbeef;
11246     lstrcpyA(targetsid, "kiwi");
11247     size = MAX_PATH;
11248     r = pMsiEnumPatchesExA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
11249                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod, &context,
11250                            targetsid, &size);
11251     ok(r == ERROR_INVALID_PARAMETER,
11252        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11253     ok(!lstrcmpA(patchcode, "apple"),
11254        "Expected patchcode to be unchanged, got %s\n", patchcode);
11255     ok(!lstrcmpA(targetprod, "banana"),
11256        "Expected targetprod to be unchanged, got %s\n", targetprod);
11257     ok(context == 0xdeadbeef,
11258        "Expected context to be unchanged, got %d\n", context);
11259     ok(!lstrcmpA(targetsid, "kiwi"),
11260        "Expected targetsid to be unchanged, got %s\n", targetsid);
11261     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11262 
11263     /* garbage szProductCode */
11264     lstrcpyA(patchcode, "apple");
11265     lstrcpyA(targetprod, "banana");
11266     context = 0xdeadbeef;
11267     lstrcpyA(targetsid, "kiwi");
11268     size = MAX_PATH;
11269     r = pMsiEnumPatchesExA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
11270                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod, &context,
11271                            targetsid, &size);
11272     ok(r == ERROR_INVALID_PARAMETER,
11273        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11274     ok(!lstrcmpA(patchcode, "apple"),
11275        "Expected patchcode to be unchanged, got %s\n", patchcode);
11276     ok(!lstrcmpA(targetprod, "banana"),
11277        "Expected targetprod to be unchanged, got %s\n", targetprod);
11278     ok(context == 0xdeadbeef,
11279        "Expected context to be unchanged, got %d\n", context);
11280     ok(!lstrcmpA(targetsid, "kiwi"),
11281        "Expected targetsid to be unchanged, got %s\n", targetsid);
11282     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11283 
11284     /* guid without brackets */
11285     lstrcpyA(patchcode, "apple");
11286     lstrcpyA(targetprod, "banana");
11287     context = 0xdeadbeef;
11288     lstrcpyA(targetsid, "kiwi");
11289     size = MAX_PATH;
11290     r = pMsiEnumPatchesExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", usersid,
11291                            MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
11292                            0, patchcode, targetprod, &context,
11293                            targetsid, &size);
11294     ok(r == ERROR_INVALID_PARAMETER,
11295        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11296     ok(!lstrcmpA(patchcode, "apple"),
11297        "Expected patchcode to be unchanged, got %s\n", patchcode);
11298     ok(!lstrcmpA(targetprod, "banana"),
11299        "Expected targetprod to be unchanged, got %s\n", targetprod);
11300     ok(context == 0xdeadbeef,
11301        "Expected context to be unchanged, got %d\n", context);
11302     ok(!lstrcmpA(targetsid, "kiwi"),
11303        "Expected targetsid to be unchanged, got %s\n", targetsid);
11304     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11305 
11306     /* guid with brackets */
11307     lstrcpyA(patchcode, "apple");
11308     lstrcpyA(targetprod, "banana");
11309     context = 0xdeadbeef;
11310     lstrcpyA(targetsid, "kiwi");
11311     size = MAX_PATH;
11312     r = pMsiEnumPatchesExA("{6700E8CF-95AB-4D9C-BC2C-15840DDA7A5D}", usersid,
11313                            MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
11314                            0, patchcode, targetprod, &context,
11315                            targetsid, &size);
11316     ok(r == ERROR_NO_MORE_ITEMS,
11317        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11318     ok(!lstrcmpA(patchcode, "apple"),
11319        "Expected patchcode to be unchanged, got %s\n", patchcode);
11320     ok(!lstrcmpA(targetprod, "banana"),
11321        "Expected targetprod to be unchanged, got %s\n", targetprod);
11322     ok(context == 0xdeadbeef,
11323        "Expected context to be unchanged, got %d\n", context);
11324     ok(!lstrcmpA(targetsid, "kiwi"),
11325        "Expected targetsid to be unchanged, got %s\n", targetsid);
11326     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11327 
11328     /* szUserSid is S-1-5-18 */
11329     lstrcpyA(patchcode, "apple");
11330     lstrcpyA(targetprod, "banana");
11331     context = 0xdeadbeef;
11332     lstrcpyA(targetsid, "kiwi");
11333     size = MAX_PATH;
11334     r = pMsiEnumPatchesExA(prodcode, "S-1-5-18",
11335                            MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
11336                            0, patchcode, targetprod, &context,
11337                            targetsid, &size);
11338     ok(r == ERROR_INVALID_PARAMETER,
11339        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11340     ok(!lstrcmpA(patchcode, "apple"),
11341        "Expected patchcode to be unchanged, got %s\n", patchcode);
11342     ok(!lstrcmpA(targetprod, "banana"),
11343        "Expected targetprod to be unchanged, got %s\n", targetprod);
11344     ok(context == 0xdeadbeef,
11345        "Expected context to be unchanged, got %d\n", context);
11346     ok(!lstrcmpA(targetsid, "kiwi"),
11347        "Expected targetsid to be unchanged, got %s\n", targetsid);
11348     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11349 
11350     /* dwContext is MSIINSTALLCONTEXT_MACHINE, but szUserSid is non-NULL */
11351     lstrcpyA(patchcode, "apple");
11352     lstrcpyA(targetprod, "banana");
11353     context = 0xdeadbeef;
11354     lstrcpyA(targetsid, "kiwi");
11355     size = MAX_PATH;
11356     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_MACHINE,
11357                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
11358                            &context, targetsid, &size);
11359     ok(r == ERROR_INVALID_PARAMETER,
11360        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11361     ok(!lstrcmpA(patchcode, "apple"),
11362        "Expected patchcode to be unchanged, got %s\n", patchcode);
11363     ok(!lstrcmpA(targetprod, "banana"),
11364        "Expected targetprod to be unchanged, got %s\n", targetprod);
11365     ok(context == 0xdeadbeef,
11366        "Expected context to be unchanged, got %d\n", context);
11367     ok(!lstrcmpA(targetsid, "kiwi"),
11368        "Expected targetsid to be unchanged, got %s\n", targetsid);
11369     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11370 
11371     /* dwContext is out of bounds */
11372     lstrcpyA(patchcode, "apple");
11373     lstrcpyA(targetprod, "banana");
11374     context = 0xdeadbeef;
11375     lstrcpyA(targetsid, "kiwi");
11376     size = MAX_PATH;
11377     r = pMsiEnumPatchesExA(prodcode, usersid, 0,
11378                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
11379                            &context, targetsid, &size);
11380     ok(r == ERROR_INVALID_PARAMETER,
11381        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11382     ok(!lstrcmpA(patchcode, "apple"),
11383        "Expected patchcode to be unchanged, got %s\n", patchcode);
11384     ok(!lstrcmpA(targetprod, "banana"),
11385        "Expected targetprod to be unchanged, got %s\n", targetprod);
11386     ok(context == 0xdeadbeef,
11387        "Expected context to be unchanged, got %d\n", context);
11388     ok(!lstrcmpA(targetsid, "kiwi"),
11389        "Expected targetsid to be unchanged, got %s\n", targetsid);
11390     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11391 
11392     /* dwContext is out of bounds */
11393     lstrcpyA(patchcode, "apple");
11394     lstrcpyA(targetprod, "banana");
11395     context = 0xdeadbeef;
11396     lstrcpyA(targetsid, "kiwi");
11397     size = MAX_PATH;
11398     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_ALL + 1,
11399                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
11400                            &context, targetsid, &size);
11401     ok(r == ERROR_INVALID_PARAMETER,
11402        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11403     ok(!lstrcmpA(patchcode, "apple"),
11404        "Expected patchcode to be unchanged, got %s\n", patchcode);
11405     ok(!lstrcmpA(targetprod, "banana"),
11406        "Expected targetprod to be unchanged, got %s\n", targetprod);
11407     ok(context == 0xdeadbeef,
11408        "Expected context to be unchanged, got %d\n", context);
11409     ok(!lstrcmpA(targetsid, "kiwi"),
11410        "Expected targetsid to be unchanged, got %s\n", targetsid);
11411     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11412 
11413     /* dwFilter is out of bounds */
11414     lstrcpyA(patchcode, "apple");
11415     lstrcpyA(targetprod, "banana");
11416     context = 0xdeadbeef;
11417     lstrcpyA(targetsid, "kiwi");
11418     size = MAX_PATH;
11419     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
11420                            MSIPATCHSTATE_INVALID, 0, patchcode, targetprod,
11421                            &context, targetsid, &size);
11422     ok(r == ERROR_INVALID_PARAMETER,
11423        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11424     ok(!lstrcmpA(patchcode, "apple"),
11425        "Expected patchcode to be unchanged, got %s\n", patchcode);
11426     ok(!lstrcmpA(targetprod, "banana"),
11427        "Expected targetprod to be unchanged, got %s\n", targetprod);
11428     ok(context == 0xdeadbeef,
11429        "Expected context to be unchanged, got %d\n", context);
11430     ok(!lstrcmpA(targetsid, "kiwi"),
11431        "Expected targetsid to be unchanged, got %s\n", targetsid);
11432     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11433 
11434     /* dwFilter is out of bounds */
11435     lstrcpyA(patchcode, "apple");
11436     lstrcpyA(targetprod, "banana");
11437     context = 0xdeadbeef;
11438     lstrcpyA(targetsid, "kiwi");
11439     size = MAX_PATH;
11440     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
11441                            MSIPATCHSTATE_ALL + 1, 0, patchcode, targetprod,
11442                            &context, targetsid, &size);
11443     ok(r == ERROR_INVALID_PARAMETER,
11444        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11445     ok(!lstrcmpA(patchcode, "apple"),
11446        "Expected patchcode to be unchanged, got %s\n", patchcode);
11447     ok(!lstrcmpA(targetprod, "banana"),
11448        "Expected targetprod to be unchanged, got %s\n", targetprod);
11449     ok(context == 0xdeadbeef,
11450        "Expected context to be unchanged, got %d\n", context);
11451     ok(!lstrcmpA(targetsid, "kiwi"),
11452        "Expected targetsid to be unchanged, got %s\n", targetsid);
11453     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11454 
11455     /* pcchTargetUserSid is NULL while szTargetUserSid is non-NULL */
11456     lstrcpyA(patchcode, "apple");
11457     lstrcpyA(targetprod, "banana");
11458     context = 0xdeadbeef;
11459     lstrcpyA(targetsid, "kiwi");
11460     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
11461                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
11462                            &context, targetsid, NULL);
11463     ok(r == ERROR_INVALID_PARAMETER,
11464        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11465     ok(!lstrcmpA(patchcode, "apple"),
11466        "Expected patchcode to be unchanged, got %s\n", patchcode);
11467     ok(!lstrcmpA(targetprod, "banana"),
11468        "Expected targetprod to be unchanged, got %s\n", targetprod);
11469     ok(context == 0xdeadbeef,
11470        "Expected context to be unchanged, got %d\n", context);
11471     ok(!lstrcmpA(targetsid, "kiwi"),
11472        "Expected targetsid to be unchanged, got %s\n", targetsid);
11473 
11474     test_MsiEnumPatchesEx_usermanaged(usersid, usersid);
11475     test_MsiEnumPatchesEx_usermanaged(NULL, usersid);
11476     test_MsiEnumPatchesEx_usermanaged("S-1-2-34", "S-1-2-34");
11477     test_MsiEnumPatchesEx_userunmanaged(usersid, usersid);
11478     test_MsiEnumPatchesEx_userunmanaged(NULL, usersid);
11479     /* FIXME: Successfully test userunmanaged with a different user */
11480     test_MsiEnumPatchesEx_machine();
11481     LocalFree(usersid);
11482 }
11483 
11484 static void test_MsiEnumPatches(void)
11485 {
11486     CHAR keypath[MAX_PATH], patch[MAX_PATH];
11487     CHAR patchcode[MAX_PATH], patch_squashed[MAX_PATH];
11488     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
11489     CHAR transforms[MAX_PATH];
11490     WCHAR patchW[MAX_PATH], prodcodeW[MAX_PATH], transformsW[MAX_PATH];
11491     HKEY prodkey, patches, udprod;
11492     HKEY userkey, hpatch, udpatch;
11493     DWORD size, data;
11494     LPSTR usersid;
11495     LONG res;
11496     UINT r;
11497     REGSAM access = KEY_ALL_ACCESS;
11498 
11499     create_test_guid(prodcode, prod_squashed);
11500     create_test_guid(patchcode, patch_squashed);
11501     usersid = get_user_sid();
11502 
11503     if (is_wow64)
11504         access |= KEY_WOW64_64KEY;
11505 
11506     /* NULL szProduct */
11507     size = MAX_PATH;
11508     lstrcpyA(patch, "apple");
11509     lstrcpyA(transforms, "banana");
11510     r = MsiEnumPatchesA(NULL, 0, patch, transforms, &size);
11511     ok(r == ERROR_INVALID_PARAMETER,
11512        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11513     ok(!lstrcmpA(patch, "apple"),
11514        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11515     ok(!lstrcmpA(transforms, "banana"),
11516        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11517     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11518 
11519     /* empty szProduct */
11520     size = MAX_PATH;
11521     lstrcpyA(patch, "apple");
11522     lstrcpyA(transforms, "banana");
11523     r = MsiEnumPatchesA("", 0, patch, transforms, &size);
11524     ok(r == ERROR_INVALID_PARAMETER,
11525        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11526     ok(!lstrcmpA(patch, "apple"),
11527        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11528     ok(!lstrcmpA(transforms, "banana"),
11529        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11530     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11531 
11532     /* garbage szProduct */
11533     size = MAX_PATH;
11534     lstrcpyA(patch, "apple");
11535     lstrcpyA(transforms, "banana");
11536     r = MsiEnumPatchesA("garbage", 0, patch, transforms, &size);
11537     ok(r == ERROR_INVALID_PARAMETER,
11538        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11539     ok(!lstrcmpA(patch, "apple"),
11540        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11541     ok(!lstrcmpA(transforms, "banana"),
11542        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11543     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11544 
11545     /* guid without brackets */
11546     size = MAX_PATH;
11547     lstrcpyA(patch, "apple");
11548     lstrcpyA(transforms, "banana");
11549     r = MsiEnumPatchesA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", 0, patch,
11550                         transforms, &size);
11551     ok(r == ERROR_INVALID_PARAMETER,
11552        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11553     ok(!lstrcmpA(patch, "apple"),
11554        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11555     ok(!lstrcmpA(transforms, "banana"),
11556        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11557     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11558 
11559     /* guid with brackets */
11560     size = MAX_PATH;
11561     lstrcpyA(patch, "apple");
11562     lstrcpyA(transforms, "banana");
11563     r = MsiEnumPatchesA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", 0, patch,
11564                         transforms, &size);
11565     ok(r == ERROR_UNKNOWN_PRODUCT,
11566        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11567     ok(!lstrcmpA(patch, "apple"),
11568        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11569     ok(!lstrcmpA(transforms, "banana"),
11570        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11571     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11572 
11573     /* same length as guid, but random */
11574     size = MAX_PATH;
11575     lstrcpyA(patch, "apple");
11576     lstrcpyA(transforms, "banana");
11577     r = MsiEnumPatchesA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", 0, patch,
11578                         transforms, &size);
11579     ok(r == ERROR_INVALID_PARAMETER,
11580        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11581     ok(!lstrcmpA(patch, "apple"),
11582        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11583     ok(!lstrcmpA(transforms, "banana"),
11584        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11585     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11586 
11587     /* MSIINSTALLCONTEXT_USERMANAGED */
11588 
11589     size = MAX_PATH;
11590     lstrcpyA(patch, "apple");
11591     lstrcpyA(transforms, "banana");
11592     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11593     ok(r == ERROR_UNKNOWN_PRODUCT,
11594        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11595     ok(!lstrcmpA(patch, "apple"),
11596        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11597     ok(!lstrcmpA(transforms, "banana"),
11598        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11599     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11600 
11601     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
11602     lstrcatA(keypath, usersid);
11603     lstrcatA(keypath, "\\Installer\\Products\\");
11604     lstrcatA(keypath, prod_squashed);
11605 
11606     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
11607     if (res == ERROR_ACCESS_DENIED)
11608     {
11609         skip("Not enough rights to perform tests\n");
11610         LocalFree(usersid);
11611         return;
11612     }
11613     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11614 
11615     /* managed product key exists */
11616     size = MAX_PATH;
11617     lstrcpyA(patch, "apple");
11618     lstrcpyA(transforms, "banana");
11619     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11620     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11621     ok(!lstrcmpA(patch, "apple"),
11622        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11623     ok(!lstrcmpA(transforms, "banana"),
11624        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11625     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11626 
11627     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
11628     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11629 
11630     /* patches key exists */
11631     size = MAX_PATH;
11632     lstrcpyA(patch, "apple");
11633     lstrcpyA(transforms, "banana");
11634     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11635     ok(r == ERROR_NO_MORE_ITEMS ||
11636        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11637        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11638     ok(!lstrcmpA(patch, "apple"),
11639        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11640     ok(!lstrcmpA(transforms, "banana"),
11641        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11642     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11643 
11644     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
11645                          (const BYTE *)patch_squashed,
11646                          lstrlenA(patch_squashed) + 1);
11647     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11648 
11649     /* Patches value exists, is not REG_MULTI_SZ */
11650     size = MAX_PATH;
11651     lstrcpyA(patch, "apple");
11652     lstrcpyA(transforms, "banana");
11653     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11654     ok(r == ERROR_BAD_CONFIGURATION ||
11655        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
11656        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11657     ok(!lstrcmpA(patch, "apple"),
11658        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11659     ok(!lstrcmpA(transforms, "banana"),
11660        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11661     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11662 
11663     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11664                          (const BYTE *)"a\0b\0c\0\0", 7);
11665     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11666 
11667     /* Patches value exists, is not a squashed guid */
11668     size = MAX_PATH;
11669     lstrcpyA(patch, "apple");
11670     lstrcpyA(transforms, "banana");
11671     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11672     ok(r == ERROR_BAD_CONFIGURATION,
11673        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11674     ok(!lstrcmpA(patch, "apple"),
11675        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11676     ok(!lstrcmpA(transforms, "banana"),
11677        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11678     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11679 
11680     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
11681     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11682                          (const BYTE *)patch_squashed,
11683                          lstrlenA(patch_squashed) + 2);
11684     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11685 
11686     /* Patches value exists */
11687     size = MAX_PATH;
11688     lstrcpyA(patch, "apple");
11689     lstrcpyA(transforms, "banana");
11690     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11691     ok(r == ERROR_NO_MORE_ITEMS ||
11692        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11693        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11694     ok(!lstrcmpA(patch, "apple") ||
11695        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
11696        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11697     ok(!lstrcmpA(transforms, "banana"),
11698        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11699     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11700 
11701     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
11702                          (const BYTE *)"whatever", 9);
11703     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11704 
11705     /* patch squashed value exists */
11706     size = MAX_PATH;
11707     lstrcpyA(patch, "apple");
11708     lstrcpyA(transforms, "banana");
11709     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11710     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11711     ok(!lstrcmpA(patch, patchcode),
11712        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11713     ok(!lstrcmpA(transforms, "whatever"),
11714        "Expected \"whatever\", got \"%s\"\n", transforms);
11715     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
11716 
11717     /* lpPatchBuf is NULL */
11718     size = MAX_PATH;
11719     lstrcpyA(transforms, "banana");
11720     r = MsiEnumPatchesA(prodcode, 0, NULL, transforms, &size);
11721     ok(r == ERROR_INVALID_PARAMETER,
11722        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11723     ok(!lstrcmpA(transforms, "banana"),
11724        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11725     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11726 
11727     /* lpTransformsBuf is NULL, pcchTransformsBuf is not */
11728     size = MAX_PATH;
11729     lstrcpyA(patch, "apple");
11730     r = MsiEnumPatchesA(prodcode, 0, patch, NULL, &size);
11731     ok(r == ERROR_INVALID_PARAMETER,
11732        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11733     ok(!lstrcmpA(patch, "apple"),
11734        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11735     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11736 
11737     /* pcchTransformsBuf is NULL, lpTransformsBuf is not */
11738     lstrcpyA(patch, "apple");
11739     lstrcpyA(transforms, "banana");
11740     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, NULL);
11741     ok(r == ERROR_INVALID_PARAMETER,
11742        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11743     ok(!lstrcmpA(patch, "apple"),
11744        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11745     ok(!lstrcmpA(transforms, "banana"),
11746        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11747 
11748     /* pcchTransformsBuf is too small */
11749     size = 6;
11750     lstrcpyA(patch, "apple");
11751     lstrcpyA(transforms, "banana");
11752     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11753     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
11754     ok(!lstrcmpA(patch, patchcode),
11755        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11756     ok(!lstrcmpA(transforms, "whate") ||
11757        broken(!lstrcmpA(transforms, "banana")), /* Windows Installer < 3.0 */
11758        "Expected \"whate\", got \"%s\"\n", transforms);
11759     ok(size == 8 || size == 16, "Expected 8 or 16, got %d\n", size);
11760 
11761     /* increase the index */
11762     size = MAX_PATH;
11763     lstrcpyA(patch, "apple");
11764     lstrcpyA(transforms, "banana");
11765     r = MsiEnumPatchesA(prodcode, 1, patch, transforms, &size);
11766     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11767     ok(!lstrcmpA(patch, "apple"),
11768        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11769     ok(!lstrcmpA(transforms, "banana"),
11770        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11771     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11772 
11773     /* increase again */
11774     size = MAX_PATH;
11775     lstrcpyA(patch, "apple");
11776     lstrcpyA(transforms, "banana");
11777     r = MsiEnumPatchesA(prodcode, 2, patch, transforms, &size);
11778     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11779     ok(!lstrcmpA(patch, "apple"),
11780        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11781     ok(!lstrcmpA(transforms, "banana"),
11782        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11783     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11784 
11785     RegDeleteValueA(patches, "Patches");
11786     delete_key(patches, "", access & KEY_WOW64_64KEY);
11787     RegCloseKey(patches);
11788     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
11789     RegCloseKey(prodkey);
11790 
11791     /* MSIINSTALLCONTEXT_USERUNMANAGED */
11792 
11793     size = MAX_PATH;
11794     lstrcpyA(patch, "apple");
11795     lstrcpyA(transforms, "banana");
11796     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11797     ok(r == ERROR_UNKNOWN_PRODUCT,
11798        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11799     ok(!lstrcmpA(patch, "apple"),
11800        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11801     ok(!lstrcmpA(transforms, "banana"),
11802        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11803     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11804 
11805     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
11806     lstrcatA(keypath, prod_squashed);
11807 
11808     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
11809     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11810 
11811     /* current user product key exists */
11812     size = MAX_PATH;
11813     lstrcpyA(patch, "apple");
11814     lstrcpyA(transforms, "banana");
11815     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11816     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11817     ok(!lstrcmpA(patch, "apple"),
11818        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11819     ok(!lstrcmpA(transforms, "banana"),
11820        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11821     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11822 
11823     res = RegCreateKeyA(prodkey, "Patches", &patches);
11824     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11825 
11826     /* Patches key exists */
11827     size = MAX_PATH;
11828     lstrcpyA(patch, "apple");
11829     lstrcpyA(transforms, "banana");
11830     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11831     ok(r == ERROR_NO_MORE_ITEMS ||
11832        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11833        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11834     ok(!lstrcmpA(patch, "apple"),
11835        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11836     ok(!lstrcmpA(transforms, "banana"),
11837        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11838     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11839 
11840     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
11841                          (const BYTE *)patch_squashed,
11842                          lstrlenA(patch_squashed) + 1);
11843     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11844 
11845     /* Patches value exists, is not REG_MULTI_SZ */
11846     size = MAX_PATH;
11847     lstrcpyA(patch, "apple");
11848     lstrcpyA(transforms, "banana");
11849     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11850     ok(r == ERROR_BAD_CONFIGURATION ||
11851        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
11852        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11853     ok(!lstrcmpA(patch, "apple"),
11854        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11855     ok(!lstrcmpA(transforms, "banana"),
11856        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11857     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11858 
11859     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11860                          (const BYTE *)"a\0b\0c\0\0", 7);
11861     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11862 
11863     /* Patches value exists, is not a squashed guid */
11864     size = MAX_PATH;
11865     lstrcpyA(patch, "apple");
11866     lstrcpyA(transforms, "banana");
11867     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11868     ok(r == ERROR_BAD_CONFIGURATION,
11869        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11870     ok(!lstrcmpA(patch, "apple"),
11871        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11872     ok(!lstrcmpA(transforms, "banana"),
11873        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11874     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11875 
11876     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
11877     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11878                          (const BYTE *)patch_squashed,
11879                          lstrlenA(patch_squashed) + 2);
11880     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11881 
11882     /* Patches value exists */
11883     size = MAX_PATH;
11884     lstrcpyA(patch, "apple");
11885     lstrcpyA(transforms, "banana");
11886     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11887     ok(r == ERROR_NO_MORE_ITEMS ||
11888        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11889        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11890     ok(!lstrcmpA(patch, "apple") ||
11891        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
11892        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11893     ok(!lstrcmpA(transforms, "banana"),
11894        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11895     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11896 
11897     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
11898                          (const BYTE *)"whatever", 9);
11899     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11900 
11901     /* patch code value exists */
11902     size = MAX_PATH;
11903     lstrcpyA(patch, "apple");
11904     lstrcpyA(transforms, "banana");
11905     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11906     ok(r == ERROR_NO_MORE_ITEMS ||
11907        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
11908        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11909     ok(!lstrcmpA(patch, "apple") ||
11910        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
11911        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11912     ok(!lstrcmpA(transforms, "banana") ||
11913        broken(!lstrcmpA(transforms, "whatever")), /* Windows Installer < 3.0 */
11914        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11915     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11916 
11917     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
11918     lstrcatA(keypath, usersid);
11919     lstrcatA(keypath, "\\Patches\\");
11920     lstrcatA(keypath, patch_squashed);
11921 
11922     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
11923     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11924 
11925     /* userdata patch key exists */
11926     size = MAX_PATH;
11927     lstrcpyA(patch, "apple");
11928     lstrcpyA(transforms, "banana");
11929     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11930     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11931     ok(!lstrcmpA(patch, patchcode),
11932        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11933     ok(!lstrcmpA(transforms, "whatever"),
11934        "Expected \"whatever\", got \"%s\"\n", transforms);
11935     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
11936 
11937     delete_key(userkey, "", access & KEY_WOW64_64KEY);
11938     RegCloseKey(userkey);
11939     RegDeleteValueA(patches, patch_squashed);
11940     RegDeleteValueA(patches, "Patches");
11941     RegDeleteKeyA(patches, "");
11942     RegCloseKey(patches);
11943     RegDeleteKeyA(prodkey, "");
11944     RegCloseKey(prodkey);
11945 
11946     /* MSIINSTALLCONTEXT_MACHINE */
11947 
11948     size = MAX_PATH;
11949     lstrcpyA(patch, "apple");
11950     lstrcpyA(transforms, "banana");
11951     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11952     ok(r == ERROR_UNKNOWN_PRODUCT,
11953        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11954     ok(!lstrcmpA(patch, "apple"),
11955        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11956     ok(!lstrcmpA(transforms, "banana"),
11957        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11958     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11959 
11960     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
11961     lstrcatA(keypath, prod_squashed);
11962 
11963     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
11964     if (res == ERROR_ACCESS_DENIED)
11965     {
11966         skip("Not enough rights to perform tests\n");
11967         LocalFree(usersid);
11968         return;
11969     }
11970     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11971 
11972     /* local product key exists */
11973     size = MAX_PATH;
11974     lstrcpyA(patch, "apple");
11975     lstrcpyA(transforms, "banana");
11976     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11977     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11978     ok(!lstrcmpA(patch, "apple"),
11979        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11980     ok(!lstrcmpA(transforms, "banana"),
11981        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11982     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11983 
11984     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
11985     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11986 
11987     /* Patches key exists */
11988     size = MAX_PATH;
11989     lstrcpyA(patch, "apple");
11990     lstrcpyA(transforms, "banana");
11991     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11992     ok(r == ERROR_NO_MORE_ITEMS ||
11993        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11994        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11995     ok(!lstrcmpA(patch, "apple"),
11996        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11997     ok(!lstrcmpA(transforms, "banana"),
11998        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11999     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12000 
12001     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
12002                          (const BYTE *)patch_squashed,
12003                          lstrlenA(patch_squashed) + 1);
12004     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12005 
12006     /* Patches value exists, is not REG_MULTI_SZ */
12007     size = MAX_PATH;
12008     lstrcpyA(patch, "apple");
12009     lstrcpyA(transforms, "banana");
12010     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12011     ok(r == ERROR_BAD_CONFIGURATION ||
12012        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
12013        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
12014     ok(!lstrcmpA(patch, "apple"),
12015        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
12016     ok(!lstrcmpA(transforms, "banana"),
12017        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
12018     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12019 
12020     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
12021                          (const BYTE *)"a\0b\0c\0\0", 7);
12022     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12023 
12024     /* Patches value exists, is not a squashed guid */
12025     size = MAX_PATH;
12026     lstrcpyA(patch, "apple");
12027     lstrcpyA(transforms, "banana");
12028     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12029     ok(r == ERROR_BAD_CONFIGURATION,
12030        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
12031     ok(!lstrcmpA(patch, "apple"),
12032        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
12033     ok(!lstrcmpA(transforms, "banana"),
12034        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
12035     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12036 
12037     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
12038     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
12039                          (const BYTE *)patch_squashed,
12040                          lstrlenA(patch_squashed) + 2);
12041     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12042 
12043     /* Patches value exists */
12044     size = MAX_PATH;
12045     lstrcpyA(patch, "apple");
12046     lstrcpyA(transforms, "banana");
12047     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12048     ok(r == ERROR_NO_MORE_ITEMS ||
12049        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
12050        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
12051     ok(!lstrcmpA(patch, "apple") ||
12052        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
12053        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
12054     ok(!lstrcmpA(transforms, "banana"),
12055        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
12056     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12057 
12058     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
12059                          (const BYTE *)"whatever", 9);
12060     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12061 
12062     /* patch code value exists */
12063     size = MAX_PATH;
12064     lstrcpyA(patch, "apple");
12065     lstrcpyA(transforms, "banana");
12066     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12067     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12068     ok(!lstrcmpA(patch, patchcode),
12069        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
12070     ok(!lstrcmpA(transforms, "whatever"),
12071        "Expected \"whatever\", got \"%s\"\n", transforms);
12072     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
12073 
12074     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
12075     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
12076     lstrcatA(keypath, prod_squashed);
12077 
12078     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
12079     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12080 
12081     /* local UserData product key exists */
12082     size = MAX_PATH;
12083     lstrcpyA(patch, "apple");
12084     lstrcpyA(transforms, "banana");
12085     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12086     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12087     ok(!lstrcmpA(patch, patchcode),
12088        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
12089     ok(!lstrcmpA(transforms, "whatever"),
12090        "Expected \"whatever\", got \"%s\"\n", transforms);
12091     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
12092 
12093     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
12094     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12095 
12096     /* local UserData Patches key exists */
12097     size = MAX_PATH;
12098     lstrcpyA(patch, "apple");
12099     lstrcpyA(transforms, "banana");
12100     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12101     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12102     ok(!lstrcmpA(patch, patchcode),
12103        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
12104     ok(!lstrcmpA(transforms, "whatever"),
12105        "Expected \"whatever\", got \"%s\"\n", transforms);
12106     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
12107 
12108     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
12109     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12110 
12111     /* local UserData Product patch key exists */
12112     size = MAX_PATH;
12113     lstrcpyA(patch, "apple");
12114     lstrcpyA(transforms, "banana");
12115     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12116     ok(r == ERROR_NO_MORE_ITEMS ||
12117        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
12118        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
12119     ok(!lstrcmpA(patch, "apple") ||
12120        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
12121        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
12122     ok(!lstrcmpA(transforms, "banana") ||
12123        broken(!lstrcmpA(transforms, "whatever")), /* Windows Installer < 3.0 */
12124        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
12125     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12126 
12127     data = MSIPATCHSTATE_APPLIED;
12128     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
12129                          (const BYTE *)&data, sizeof(DWORD));
12130     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12131 
12132     /* State value exists */
12133     size = MAX_PATH;
12134     lstrcpyA(patch, "apple");
12135     lstrcpyA(transforms, "banana");
12136     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12137     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12138     ok(!lstrcmpA(patch, patchcode),
12139        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
12140     ok(!lstrcmpA(transforms, "whatever"),
12141        "Expected \"whatever\", got \"%s\"\n", transforms);
12142     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
12143 
12144     /* now duplicate some of the tests for the W version */
12145 
12146     /* pcchTransformsBuf is too small */
12147     size = 6;
12148     MultiByteToWideChar( CP_ACP, 0, prodcode, -1, prodcodeW, MAX_PATH );
12149     MultiByteToWideChar( CP_ACP, 0, "apple", -1, patchW, MAX_PATH );
12150     MultiByteToWideChar( CP_ACP, 0, "banana", -1, transformsW, MAX_PATH );
12151     r = MsiEnumPatchesW(prodcodeW, 0, patchW, transformsW, &size);
12152     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
12153     WideCharToMultiByte( CP_ACP, 0, patchW, -1, patch, MAX_PATH, NULL, NULL );
12154     WideCharToMultiByte( CP_ACP, 0, transformsW, -1, transforms, MAX_PATH, NULL, NULL );
12155     ok(!lstrcmpA(patch, patchcode),
12156        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
12157     ok(!lstrcmpA(transforms, "whate") ||
12158        broken(!lstrcmpA(transforms, "banana")), /* Windows Installer < 3.0 */
12159        "Expected \"whate\", got \"%s\"\n", transforms);
12160     ok(size == 8, "Expected 8, got %d\n", size);
12161 
12162     /* patch code value exists */
12163     size = MAX_PATH;
12164     MultiByteToWideChar( CP_ACP, 0, "apple", -1, patchW, MAX_PATH );
12165     MultiByteToWideChar( CP_ACP, 0, "banana", -1, transformsW, MAX_PATH );
12166     r = MsiEnumPatchesW(prodcodeW, 0, patchW, transformsW, &size);
12167     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12168     WideCharToMultiByte( CP_ACP, 0, patchW, -1, patch, MAX_PATH, NULL, NULL );
12169     WideCharToMultiByte( CP_ACP, 0, transformsW, -1, transforms, MAX_PATH, NULL, NULL );
12170     ok(!lstrcmpA(patch, patchcode),
12171        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
12172     ok(!lstrcmpA(transforms, "whatever"),
12173        "Expected \"whatever\", got \"%s\"\n", transforms);
12174     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
12175 
12176     RegDeleteValueA(patches, patch_squashed);
12177     RegDeleteValueA(patches, "Patches");
12178     delete_key(patches, "", access & KEY_WOW64_64KEY);
12179     RegCloseKey(patches);
12180     RegDeleteValueA(hpatch, "State");
12181     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
12182     RegCloseKey(hpatch);
12183     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
12184     RegCloseKey(udpatch);
12185     delete_key(udprod, "", access & KEY_WOW64_64KEY);
12186     RegCloseKey(udprod);
12187     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
12188     RegCloseKey(prodkey);
12189     LocalFree(usersid);
12190 }
12191 
12192 static void test_MsiGetPatchInfoEx(void)
12193 {
12194     CHAR keypath[MAX_PATH], val[MAX_PATH];
12195     CHAR patchcode[MAX_PATH], patch_squashed[MAX_PATH];
12196     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
12197     HKEY prodkey, patches, udprod, props;
12198     HKEY hpatch, udpatch, prodpatches;
12199     LPSTR usersid;
12200     DWORD size;
12201     LONG res;
12202     UINT r;
12203     REGSAM access = KEY_ALL_ACCESS;
12204 
12205     if (!pMsiGetPatchInfoExA)
12206     {
12207         win_skip("MsiGetPatchInfoEx not implemented\n");
12208         return;
12209     }
12210 
12211     create_test_guid(prodcode, prod_squashed);
12212     create_test_guid(patchcode, patch_squashed);
12213     usersid = get_user_sid();
12214 
12215     if (is_wow64)
12216         access |= KEY_WOW64_64KEY;
12217 
12218     /* NULL szPatchCode */
12219     lstrcpyA(val, "apple");
12220     size = MAX_PATH;
12221     r = pMsiGetPatchInfoExA(NULL, prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED,
12222                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12223     ok(r == ERROR_INVALID_PARAMETER,
12224        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12225     ok(!lstrcmpA(val, "apple"),
12226        "Expected val to be unchanged, got \"%s\"\n", val);
12227     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12228 
12229     /* empty szPatchCode */
12230     size = MAX_PATH;
12231     lstrcpyA(val, "apple");
12232     r = pMsiGetPatchInfoExA("", prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED,
12233                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12234     ok(r == ERROR_INVALID_PARAMETER,
12235        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12236     ok(!lstrcmpA(val, "apple"),
12237        "Expected val to be unchanged, got \"%s\"\n", val);
12238     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12239 
12240     /* garbage szPatchCode */
12241     size = MAX_PATH;
12242     lstrcpyA(val, "apple");
12243     r = pMsiGetPatchInfoExA("garbage", prodcode, NULL,
12244                             MSIINSTALLCONTEXT_USERMANAGED,
12245                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12246     ok(r == ERROR_INVALID_PARAMETER,
12247        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12248     ok(!lstrcmpA(val, "apple"),
12249        "Expected val to be unchanged, got \"%s\"\n", val);
12250     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12251 
12252     /* guid without brackets */
12253     size = MAX_PATH;
12254     lstrcpyA(val, "apple");
12255     r = pMsiGetPatchInfoExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", prodcode,
12256                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
12257                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12258     ok(r == ERROR_INVALID_PARAMETER,
12259        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12260     ok(!lstrcmpA(val, "apple"),
12261        "Expected val to be unchanged, got \"%s\"\n", val);
12262     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12263 
12264     /* guid with brackets */
12265     size = MAX_PATH;
12266     lstrcpyA(val, "apple");
12267     r = pMsiGetPatchInfoExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", prodcode,
12268                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
12269                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12270     ok(r == ERROR_UNKNOWN_PRODUCT,
12271        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12272     ok(!lstrcmpA(val, "apple"),
12273        "Expected val to be unchanged, got \"%s\"\n", val);
12274     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12275 
12276     /* same length as guid, but random */
12277     size = MAX_PATH;
12278     lstrcpyA(val, "apple");
12279     r = pMsiGetPatchInfoExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", prodcode,
12280                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
12281                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12282     ok(r == ERROR_INVALID_PARAMETER,
12283        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12284     ok(!lstrcmpA(val, "apple"),
12285        "Expected val to be unchanged, got \"%s\"\n", val);
12286     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12287 
12288     /* NULL szProductCode */
12289     lstrcpyA(val, "apple");
12290     size = MAX_PATH;
12291     r = pMsiGetPatchInfoExA(patchcode, NULL, NULL, MSIINSTALLCONTEXT_USERMANAGED,
12292                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12293     ok(r == ERROR_INVALID_PARAMETER,
12294        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12295     ok(!lstrcmpA(val, "apple"),
12296        "Expected val to be unchanged, got \"%s\"\n", val);
12297     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12298 
12299     /* empty szProductCode */
12300     size = MAX_PATH;
12301     lstrcpyA(val, "apple");
12302     r = pMsiGetPatchInfoExA(patchcode, "", NULL, MSIINSTALLCONTEXT_USERMANAGED,
12303                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12304     ok(r == ERROR_INVALID_PARAMETER,
12305        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12306     ok(!lstrcmpA(val, "apple"),
12307        "Expected val to be unchanged, got \"%s\"\n", val);
12308     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12309 
12310     /* garbage szProductCode */
12311     size = MAX_PATH;
12312     lstrcpyA(val, "apple");
12313     r = pMsiGetPatchInfoExA(patchcode, "garbage", NULL,
12314                             MSIINSTALLCONTEXT_USERMANAGED,
12315                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12316     ok(r == ERROR_INVALID_PARAMETER,
12317        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12318     ok(!lstrcmpA(val, "apple"),
12319        "Expected val to be unchanged, got \"%s\"\n", val);
12320     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12321 
12322     /* guid without brackets */
12323     size = MAX_PATH;
12324     lstrcpyA(val, "apple");
12325     r = pMsiGetPatchInfoExA(patchcode, "6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
12326                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
12327                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12328     ok(r == ERROR_INVALID_PARAMETER,
12329        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12330     ok(!lstrcmpA(val, "apple"),
12331        "Expected val to be unchanged, got \"%s\"\n", val);
12332     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12333 
12334     /* guid with brackets */
12335     size = MAX_PATH;
12336     lstrcpyA(val, "apple");
12337     r = pMsiGetPatchInfoExA(patchcode, "{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
12338                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
12339                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12340     ok(r == ERROR_UNKNOWN_PRODUCT,
12341        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12342     ok(!lstrcmpA(val, "apple"),
12343        "Expected val to be unchanged, got \"%s\"\n", val);
12344     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12345 
12346     /* same length as guid, but random */
12347     size = MAX_PATH;
12348     lstrcpyA(val, "apple");
12349     r = pMsiGetPatchInfoExA(patchcode, "A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
12350                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
12351                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12352     ok(r == ERROR_INVALID_PARAMETER,
12353        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12354     ok(!lstrcmpA(val, "apple"),
12355        "Expected val to be unchanged, got \"%s\"\n", val);
12356     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12357 
12358     /* szUserSid cannot be S-1-5-18 for MSIINSTALLCONTEXT_USERMANAGED */
12359     size = MAX_PATH;
12360     lstrcpyA(val, "apple");
12361     r = pMsiGetPatchInfoExA(patchcode, prodcode, "S-1-5-18",
12362                             MSIINSTALLCONTEXT_USERMANAGED,
12363                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12364     ok(r == ERROR_INVALID_PARAMETER,
12365        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12366     ok(!lstrcmpA(val, "apple"),
12367        "Expected val to be unchanged, got \"%s\"\n", val);
12368     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12369 
12370     /* szUserSid cannot be S-1-5-18 for MSIINSTALLCONTEXT_USERUNMANAGED */
12371     size = MAX_PATH;
12372     lstrcpyA(val, "apple");
12373     r = pMsiGetPatchInfoExA(patchcode, prodcode, "S-1-5-18",
12374                             MSIINSTALLCONTEXT_USERUNMANAGED,
12375                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12376     ok(r == ERROR_INVALID_PARAMETER,
12377        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12378     ok(!lstrcmpA(val, "apple"),
12379        "Expected val to be unchanged, got \"%s\"\n", val);
12380     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12381 
12382     /* szUserSid cannot be S-1-5-18 for MSIINSTALLCONTEXT_MACHINE */
12383     size = MAX_PATH;
12384     lstrcpyA(val, "apple");
12385     r = pMsiGetPatchInfoExA(patchcode, prodcode, "S-1-5-18",
12386                             MSIINSTALLCONTEXT_MACHINE,
12387                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12388     ok(r == ERROR_INVALID_PARAMETER,
12389        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12390     ok(!lstrcmpA(val, "apple"),
12391        "Expected val to be unchanged, got \"%s\"\n", val);
12392     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12393 
12394     /* szUserSid must be NULL for MSIINSTALLCONTEXT_MACHINE */
12395     size = MAX_PATH;
12396     lstrcpyA(val, "apple");
12397     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12398                             MSIINSTALLCONTEXT_MACHINE,
12399                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12400     ok(r == ERROR_INVALID_PARAMETER,
12401        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12402     ok(!lstrcmpA(val, "apple"),
12403        "Expected val to be unchanged, got \"%s\"\n", val);
12404     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12405 
12406     /* dwContext is out of range */
12407     size = MAX_PATH;
12408     lstrcpyA(val, "apple");
12409     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12410                             MSIINSTALLCONTEXT_NONE,
12411                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12412     ok(r == ERROR_INVALID_PARAMETER,
12413        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12414     ok(!lstrcmpA(val, "apple"),
12415        "Expected val to be unchanged, got \"%s\"\n", val);
12416     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12417 
12418     /* dwContext is out of range */
12419     size = MAX_PATH;
12420     lstrcpyA(val, "apple");
12421     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12422                             MSIINSTALLCONTEXT_ALL,
12423                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12424     ok(r == ERROR_INVALID_PARAMETER,
12425        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12426     ok(!lstrcmpA(val, "apple"),
12427        "Expected val to be unchanged, got \"%s\"\n", val);
12428     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12429 
12430     /* dwContext is invalid */
12431     size = MAX_PATH;
12432     lstrcpyA(val, "apple");
12433     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid, 3,
12434                            INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12435     ok(r == ERROR_INVALID_PARAMETER,
12436        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12437     ok(!lstrcmpA(val, "apple"),
12438        "Expected val to be unchanged, got \"%s\"\n", val);
12439     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12440 
12441     /* MSIINSTALLCONTEXT_USERMANAGED */
12442 
12443     size = MAX_PATH;
12444     lstrcpyA(val, "apple");
12445     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12446                             MSIINSTALLCONTEXT_USERMANAGED,
12447                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12448     ok(r == ERROR_UNKNOWN_PRODUCT,
12449        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12450     ok(!lstrcmpA(val, "apple"),
12451        "Expected val to be unchanged, got \"%s\"\n", val);
12452     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12453 
12454     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
12455     lstrcatA(keypath, usersid);
12456     lstrcatA(keypath, "\\Products\\");
12457     lstrcatA(keypath, prod_squashed);
12458 
12459     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
12460     if (res == ERROR_ACCESS_DENIED)
12461     {
12462         skip("Not enough rights to perform tests\n");
12463         LocalFree(usersid);
12464         return;
12465     }
12466     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12467 
12468     /* local UserData product key exists */
12469     size = MAX_PATH;
12470     lstrcpyA(val, "apple");
12471     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12472                             MSIINSTALLCONTEXT_USERMANAGED,
12473                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12474     ok(r == ERROR_UNKNOWN_PRODUCT,
12475        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12476     ok(!lstrcmpA(val, "apple"),
12477        "Expected val to be unchanged, got \"%s\"\n", val);
12478     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12479 
12480     res = RegCreateKeyExA(udprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
12481     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12482 
12483     /* InstallProperties key exists */
12484     size = MAX_PATH;
12485     lstrcpyA(val, "apple");
12486     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12487                             MSIINSTALLCONTEXT_USERMANAGED,
12488                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12489     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12490     ok(!lstrcmpA(val, "apple"),
12491        "Expected val to be unchanged, got \"%s\"\n", val);
12492     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12493 
12494     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
12495     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12496 
12497     /* Patches key exists */
12498     size = MAX_PATH;
12499     lstrcpyA(val, "apple");
12500     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12501                             MSIINSTALLCONTEXT_USERMANAGED,
12502                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12503     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCHA, got %d\n", r);
12504     ok(!lstrcmpA(val, "apple"),
12505        "Expected val to be unchanged, got \"%s\"\n", val);
12506     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12507 
12508     res = RegCreateKeyExA(patches, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
12509     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12510 
12511     /* Patches key exists */
12512     size = MAX_PATH;
12513     lstrcpyA(val, "apple");
12514     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12515                             MSIINSTALLCONTEXT_USERMANAGED,
12516                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12517     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12518     ok(!lstrcmpA(val, "apple"),
12519        "Expected val to be unchanged, got \"%s\"\n", val);
12520     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12521 
12522     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
12523     lstrcatA(keypath, usersid);
12524     lstrcatA(keypath, "\\Installer\\Products\\");
12525     lstrcatA(keypath, prod_squashed);
12526 
12527     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
12528     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12529 
12530     /* managed product key exists */
12531     size = MAX_PATH;
12532     lstrcpyA(val, "apple");
12533     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12534                             MSIINSTALLCONTEXT_USERMANAGED,
12535                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12536     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12537     ok(!lstrcmpA(val, "apple"),
12538        "Expected val to be unchanged, got \"%s\"\n", val);
12539     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12540 
12541     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &prodpatches, NULL);
12542     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12543 
12544     /* Patches key exists */
12545     size = MAX_PATH;
12546     lstrcpyA(val, "apple");
12547     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12548                             MSIINSTALLCONTEXT_USERMANAGED,
12549                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12550     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12551     ok(!lstrcmpA(val, "apple"),
12552        "Expected val to be unchanged, got \"%s\"\n", val);
12553     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12554 
12555     res = RegSetValueExA(prodpatches, patch_squashed, 0, REG_SZ,
12556                          (const BYTE *)"transforms", 11);
12557     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12558 
12559     /* specific patch value exists */
12560     size = MAX_PATH;
12561     lstrcpyA(val, "apple");
12562     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12563                             MSIINSTALLCONTEXT_USERMANAGED,
12564                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12565     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12566     ok(!lstrcmpA(val, "apple"),
12567        "Expected val to be unchanged, got \"%s\"\n", val);
12568     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12569 
12570     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
12571     lstrcatA(keypath, usersid);
12572     lstrcatA(keypath, "\\Patches\\");
12573     lstrcatA(keypath, patch_squashed);
12574 
12575     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udpatch, NULL);
12576     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12577 
12578     /* UserData Patches key exists */
12579     size = MAX_PATH;
12580     lstrcpyA(val, "apple");
12581     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12582                             MSIINSTALLCONTEXT_USERMANAGED,
12583                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12584     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12585     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
12586     ok(size == 0, "Expected 0, got %d\n", size);
12587 
12588     res = RegSetValueExA(udpatch, "ManagedLocalPackage", 0, REG_SZ,
12589                          (const BYTE *)"pack", 5);
12590     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12591 
12592     /* ManagedLocalPatch value exists */
12593     size = MAX_PATH;
12594     lstrcpyA(val, "apple");
12595     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12596                             MSIINSTALLCONTEXT_USERMANAGED,
12597                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12598     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12599     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12600     ok(size == 4, "Expected 4, got %d\n", size);
12601 
12602     size = MAX_PATH;
12603     lstrcpyA(val, "apple");
12604     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12605                             MSIINSTALLCONTEXT_USERMANAGED,
12606                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12607     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12608     ok(!lstrcmpA(val, "transforms"), "Expected \"transforms\", got \"%s\"\n", val);
12609     ok(size == 10, "Expected 10, got %d\n", size);
12610 
12611     res = RegSetValueExA(hpatch, "Installed", 0, REG_SZ,
12612                          (const BYTE *)"mydate", 7);
12613     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12614 
12615     /* Installed value exists */
12616     size = MAX_PATH;
12617     lstrcpyA(val, "apple");
12618     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12619                             MSIINSTALLCONTEXT_USERMANAGED,
12620                             INSTALLPROPERTY_INSTALLDATEA, val, &size);
12621     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12622     ok(!lstrcmpA(val, "mydate"), "Expected \"mydate\", got \"%s\"\n", val);
12623     ok(size == 6, "Expected 6, got %d\n", size);
12624 
12625     res = RegSetValueExA(hpatch, "Uninstallable", 0, REG_SZ,
12626                          (const BYTE *)"yes", 4);
12627     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12628 
12629     /* Uninstallable value exists */
12630     size = MAX_PATH;
12631     lstrcpyA(val, "apple");
12632     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12633                             MSIINSTALLCONTEXT_USERMANAGED,
12634                             INSTALLPROPERTY_UNINSTALLABLEA, val, &size);
12635     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12636     ok(!lstrcmpA(val, "yes"), "Expected \"yes\", got \"%s\"\n", val);
12637     ok(size == 3, "Expected 3, got %d\n", size);
12638 
12639     res = RegSetValueExA(hpatch, "State", 0, REG_SZ,
12640                          (const BYTE *)"good", 5);
12641     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12642 
12643     /* State value exists */
12644     size = MAX_PATH;
12645     lstrcpyA(val, "apple");
12646     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12647                             MSIINSTALLCONTEXT_USERMANAGED,
12648                             INSTALLPROPERTY_PATCHSTATEA, val, &size);
12649     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12650     ok(!lstrcmpA(val, "good"), "Expected \"good\", got \"%s\"\n", val);
12651     ok(size == 4, "Expected 4, got %d\n", size);
12652 
12653     size = 1;
12654     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
12655                          (const BYTE *)&size, sizeof(DWORD));
12656     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12657 
12658     /* State value exists */
12659     size = MAX_PATH;
12660     lstrcpyA(val, "apple");
12661     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12662                             MSIINSTALLCONTEXT_USERMANAGED,
12663                             INSTALLPROPERTY_PATCHSTATEA, val, &size);
12664     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12665     ok(!lstrcmpA(val, "1"), "Expected \"1\", got \"%s\"\n", val);
12666     ok(size == 1, "Expected 1, got %d\n", size);
12667 
12668     size = 1;
12669     res = RegSetValueExA(hpatch, "Uninstallable", 0, REG_DWORD,
12670                          (const BYTE *)&size, sizeof(DWORD));
12671     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12672 
12673     /* Uninstallable value exists */
12674     size = MAX_PATH;
12675     lstrcpyA(val, "apple");
12676     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12677                             MSIINSTALLCONTEXT_USERMANAGED,
12678                             INSTALLPROPERTY_UNINSTALLABLEA, val, &size);
12679     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12680     ok(!lstrcmpA(val, "1"), "Expected \"1\", got \"%s\"\n", val);
12681     ok(size == 1, "Expected 1, got %d\n", size);
12682 
12683     res = RegSetValueExA(hpatch, "DisplayName", 0, REG_SZ,
12684                          (const BYTE *)"display", 8);
12685     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12686 
12687     /* DisplayName value exists */
12688     size = MAX_PATH;
12689     lstrcpyA(val, "apple");
12690     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12691                             MSIINSTALLCONTEXT_USERMANAGED,
12692                             INSTALLPROPERTY_DISPLAYNAMEA, val, &size);
12693     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12694     ok(!lstrcmpA(val, "display"), "Expected \"display\", got \"%s\"\n", val);
12695     ok(size == 7, "Expected 7, got %d\n", size);
12696 
12697     res = RegSetValueExA(hpatch, "MoreInfoURL", 0, REG_SZ,
12698                          (const BYTE *)"moreinfo", 9);
12699     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12700 
12701     /* MoreInfoURL value exists */
12702     size = MAX_PATH;
12703     lstrcpyA(val, "apple");
12704     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12705                             MSIINSTALLCONTEXT_USERMANAGED,
12706                             INSTALLPROPERTY_MOREINFOURLA, val, &size);
12707     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12708     ok(!lstrcmpA(val, "moreinfo"), "Expected \"moreinfo\", got \"%s\"\n", val);
12709     ok(size == 8, "Expected 8, got %d\n", size);
12710 
12711     /* szProperty is invalid */
12712     size = MAX_PATH;
12713     lstrcpyA(val, "apple");
12714     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12715                             MSIINSTALLCONTEXT_USERMANAGED,
12716                             "IDontExist", val, &size);
12717     ok(r == ERROR_UNKNOWN_PROPERTY,
12718        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
12719     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
12720     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
12721 
12722     /* lpValue is NULL, while pcchValue is non-NULL */
12723     size = MAX_PATH;
12724     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12725                             MSIINSTALLCONTEXT_USERMANAGED,
12726                             INSTALLPROPERTY_MOREINFOURLA, NULL, &size);
12727     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12728     ok(size == 16, "Expected 16, got %d\n", size);
12729 
12730     /* pcchValue is NULL, while lpValue is non-NULL */
12731     lstrcpyA(val, "apple");
12732     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12733                             MSIINSTALLCONTEXT_USERMANAGED,
12734                             INSTALLPROPERTY_MOREINFOURLA, val, NULL);
12735     ok(r == ERROR_INVALID_PARAMETER,
12736        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12737     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
12738 
12739     /* both lpValue and pcchValue are NULL */
12740     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12741                             MSIINSTALLCONTEXT_USERMANAGED,
12742                             INSTALLPROPERTY_MOREINFOURLA, NULL, NULL);
12743     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12744 
12745     /* pcchValue doesn't have enough room for NULL terminator */
12746     size = 8;
12747     lstrcpyA(val, "apple");
12748     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12749                             MSIINSTALLCONTEXT_USERMANAGED,
12750                             INSTALLPROPERTY_MOREINFOURLA, val, &size);
12751     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
12752     ok(!lstrcmpA(val, "moreinf"),
12753        "Expected \"moreinf\", got \"%s\"\n", val);
12754     ok(size == 16, "Expected 16, got %d\n", size);
12755 
12756     /* pcchValue has exactly enough room for NULL terminator */
12757     size = 9;
12758     lstrcpyA(val, "apple");
12759     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12760                             MSIINSTALLCONTEXT_USERMANAGED,
12761                             INSTALLPROPERTY_MOREINFOURLA, val, &size);
12762     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12763     ok(!lstrcmpA(val, "moreinfo"),
12764        "Expected \"moreinfo\", got \"%s\"\n", val);
12765     ok(size == 8, "Expected 8, got %d\n", size);
12766 
12767     /* pcchValue is too small, lpValue is NULL */
12768     size = 0;
12769     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12770                             MSIINSTALLCONTEXT_USERMANAGED,
12771                             INSTALLPROPERTY_MOREINFOURLA, NULL, &size);
12772     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12773     ok(size == 16, "Expected 16, got %d\n", size);
12774 
12775     RegDeleteValueA(prodpatches, patch_squashed);
12776     delete_key(prodpatches, "", access & KEY_WOW64_64KEY);
12777     RegCloseKey(prodpatches);
12778     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
12779     RegCloseKey(prodkey);
12780 
12781     /* UserData is sufficient for all properties
12782      * except INSTALLPROPERTY_TRANSFORMS
12783      */
12784     size = MAX_PATH;
12785     lstrcpyA(val, "apple");
12786     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12787                             MSIINSTALLCONTEXT_USERMANAGED,
12788                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12789     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12790     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12791     ok(size == 4, "Expected 4, got %d\n", size);
12792 
12793     /* UserData is sufficient for all properties
12794      * except INSTALLPROPERTY_TRANSFORMS
12795      */
12796     size = MAX_PATH;
12797     lstrcpyA(val, "apple");
12798     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12799                             MSIINSTALLCONTEXT_USERMANAGED,
12800                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12801     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12802     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
12803     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
12804 
12805     RegDeleteValueA(hpatch, "MoreInfoURL");
12806     RegDeleteValueA(hpatch, "Display");
12807     RegDeleteValueA(hpatch, "State");
12808     RegDeleteValueA(hpatch, "Uninstallable");
12809     RegDeleteValueA(hpatch, "Installed");
12810     RegDeleteValueA(udpatch, "ManagedLocalPackage");
12811     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
12812     RegCloseKey(udpatch);
12813     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
12814     RegCloseKey(hpatch);
12815     delete_key(patches, "", access & KEY_WOW64_64KEY);
12816     RegCloseKey(patches);
12817     delete_key(props, "", access & KEY_WOW64_64KEY);
12818     RegCloseKey(props);
12819     delete_key(udprod, "", access & KEY_WOW64_64KEY);
12820     RegCloseKey(udprod);
12821 
12822     /* MSIINSTALLCONTEXT_USERUNMANAGED */
12823 
12824     size = MAX_PATH;
12825     lstrcpyA(val, "apple");
12826     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12827                             MSIINSTALLCONTEXT_USERUNMANAGED,
12828                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12829     ok(r == ERROR_UNKNOWN_PRODUCT,
12830        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12831     ok(!lstrcmpA(val, "apple"),
12832        "Expected val to be unchanged, got \"%s\"\n", val);
12833     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12834 
12835     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
12836     lstrcatA(keypath, usersid);
12837     lstrcatA(keypath, "\\Products\\");
12838     lstrcatA(keypath, prod_squashed);
12839 
12840     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
12841     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12842 
12843     /* local UserData product key exists */
12844     size = MAX_PATH;
12845     lstrcpyA(val, "apple");
12846     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12847                             MSIINSTALLCONTEXT_USERUNMANAGED,
12848                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12849     ok(r == ERROR_UNKNOWN_PRODUCT,
12850        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12851     ok(!lstrcmpA(val, "apple"),
12852        "Expected val to be unchanged, got \"%s\"\n", val);
12853     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12854 
12855     res = RegCreateKeyExA(udprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
12856     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12857 
12858     /* InstallProperties key exists */
12859     size = MAX_PATH;
12860     lstrcpyA(val, "apple");
12861     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12862                             MSIINSTALLCONTEXT_USERUNMANAGED,
12863                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12864     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12865     ok(!lstrcmpA(val, "apple"),
12866        "Expected val to be unchanged, got \"%s\"\n", val);
12867     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12868 
12869     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
12870     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12871 
12872     /* Patches key exists */
12873     size = MAX_PATH;
12874     lstrcpyA(val, "apple");
12875     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12876                             MSIINSTALLCONTEXT_USERUNMANAGED,
12877                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12878     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12879     ok(!lstrcmpA(val, "apple"),
12880        "Expected val to be unchanged, got \"%s\"\n", val);
12881     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12882 
12883     res = RegCreateKeyExA(patches, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
12884     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12885 
12886     /* Patches key exists */
12887     size = MAX_PATH;
12888     lstrcpyA(val, "apple");
12889     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12890                             MSIINSTALLCONTEXT_USERUNMANAGED,
12891                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12892     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12893     ok(!lstrcmpA(val, "apple"),
12894        "Expected val to be unchanged, got \"%s\"\n", val);
12895     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12896 
12897     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
12898     lstrcatA(keypath, prod_squashed);
12899 
12900     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
12901     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12902 
12903     /* current user product key exists */
12904     size = MAX_PATH;
12905     lstrcpyA(val, "apple");
12906     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12907                             MSIINSTALLCONTEXT_USERUNMANAGED,
12908                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12909     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12910     ok(!lstrcmpA(val, "apple"),
12911        "Expected val to be unchanged, got \"%s\"\n", val);
12912     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12913 
12914     res = RegCreateKeyA(prodkey, "Patches", &prodpatches);
12915     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12916 
12917     /* Patches key exists */
12918     size = MAX_PATH;
12919     lstrcpyA(val, "apple");
12920     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12921                             MSIINSTALLCONTEXT_USERUNMANAGED,
12922                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12923     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12924     ok(!lstrcmpA(val, "apple"),
12925        "Expected val to be unchanged, got \"%s\"\n", val);
12926     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12927 
12928     res = RegSetValueExA(prodpatches, patch_squashed, 0, REG_SZ,
12929                          (const BYTE *)"transforms", 11);
12930     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12931 
12932     /* specific patch value exists */
12933     size = MAX_PATH;
12934     lstrcpyA(val, "apple");
12935     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12936                             MSIINSTALLCONTEXT_USERUNMANAGED,
12937                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12938     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12939     ok(!lstrcmpA(val, "apple"),
12940        "Expected val to be unchanged, got \"%s\"\n", val);
12941     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12942 
12943     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
12944     lstrcatA(keypath, usersid);
12945     lstrcatA(keypath, "\\Patches\\");
12946     lstrcatA(keypath, patch_squashed);
12947 
12948     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udpatch, NULL);
12949     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12950 
12951     /* UserData Patches key exists */
12952     size = MAX_PATH;
12953     lstrcpyA(val, "apple");
12954     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12955                             MSIINSTALLCONTEXT_USERUNMANAGED,
12956                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12957     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12958     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
12959     ok(size == 0, "Expected 0, got %d\n", size);
12960 
12961     res = RegSetValueExA(udpatch, "LocalPackage", 0, REG_SZ,
12962                          (const BYTE *)"pack", 5);
12963     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12964 
12965     /* LocalPatch value exists */
12966     size = MAX_PATH;
12967     lstrcpyA(val, "apple");
12968     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12969                             MSIINSTALLCONTEXT_USERUNMANAGED,
12970                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12971     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12972     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12973     ok(size == 4, "Expected 4, got %d\n", size);
12974 
12975     size = MAX_PATH;
12976     lstrcpyA(val, "apple");
12977     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12978                             MSIINSTALLCONTEXT_USERUNMANAGED,
12979                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12980     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12981     ok(!lstrcmpA(val, "transforms"), "Expected \"transforms\", got \"%s\"\n", val);
12982     ok(size == 10, "Expected 10, got %d\n", size);
12983 
12984     RegDeleteValueA(prodpatches, patch_squashed);
12985     delete_key(prodpatches, "", access & KEY_WOW64_64KEY);
12986     RegCloseKey(prodpatches);
12987     RegDeleteKeyA(prodkey, "");
12988     RegCloseKey(prodkey);
12989 
12990     /* UserData is sufficient for all properties
12991      * except INSTALLPROPERTY_TRANSFORMS
12992      */
12993     size = MAX_PATH;
12994     lstrcpyA(val, "apple");
12995     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12996                             MSIINSTALLCONTEXT_USERUNMANAGED,
12997                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12998     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12999     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
13000     ok(size == 4, "Expected 4, got %d\n", size);
13001 
13002     /* UserData is sufficient for all properties
13003      * except INSTALLPROPERTY_TRANSFORMS
13004      */
13005     size = MAX_PATH;
13006     lstrcpyA(val, "apple");
13007     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
13008                             MSIINSTALLCONTEXT_USERUNMANAGED,
13009                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
13010     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
13011     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
13012     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
13013 
13014     RegDeleteValueA(udpatch, "LocalPackage");
13015     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
13016     RegCloseKey(udpatch);
13017     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
13018     RegCloseKey(hpatch);
13019     delete_key(patches, "", access & KEY_WOW64_64KEY);
13020     RegCloseKey(patches);
13021     delete_key(props, "", access & KEY_WOW64_64KEY);
13022     RegCloseKey(props);
13023     delete_key(udprod, "", access & KEY_WOW64_64KEY);
13024     RegCloseKey(udprod);
13025 
13026     /* MSIINSTALLCONTEXT_MACHINE */
13027 
13028     size = MAX_PATH;
13029     lstrcpyA(val, "apple");
13030     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13031                             MSIINSTALLCONTEXT_MACHINE,
13032                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13033     ok(r == ERROR_UNKNOWN_PRODUCT,
13034        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
13035     ok(!lstrcmpA(val, "apple"),
13036        "Expected val to be unchanged, got \"%s\"\n", val);
13037     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
13038 
13039     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
13040     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Products\\");
13041     lstrcatA(keypath, prod_squashed);
13042 
13043     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
13044     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13045 
13046     /* local UserData product key exists */
13047     size = MAX_PATH;
13048     lstrcpyA(val, "apple");
13049     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13050                             MSIINSTALLCONTEXT_MACHINE,
13051                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13052     ok(r == ERROR_UNKNOWN_PRODUCT,
13053        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
13054     ok(!lstrcmpA(val, "apple"),
13055        "Expected val to be unchanged, got \"%s\"\n", val);
13056     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
13057 
13058     res = RegCreateKeyExA(udprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
13059     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13060 
13061     /* InstallProperties key exists */
13062     size = MAX_PATH;
13063     lstrcpyA(val, "apple");
13064     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13065                             MSIINSTALLCONTEXT_MACHINE,
13066                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13067     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
13068     ok(!lstrcmpA(val, "apple"),
13069        "Expected val to be unchanged, got \"%s\"\n", val);
13070     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
13071 
13072     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
13073     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13074 
13075     /* Patches key exists */
13076     size = MAX_PATH;
13077     lstrcpyA(val, "apple");
13078     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13079                             MSIINSTALLCONTEXT_MACHINE,
13080                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13081     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
13082     ok(!lstrcmpA(val, "apple"),
13083        "Expected val to be unchanged, got \"%s\"\n", val);
13084     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
13085 
13086     res = RegCreateKeyExA(patches, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
13087     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13088 
13089     /* Patches key exists */
13090     size = MAX_PATH;
13091     lstrcpyA(val, "apple");
13092     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13093                             MSIINSTALLCONTEXT_MACHINE,
13094                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13095     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
13096     ok(!lstrcmpA(val, "apple"),
13097        "Expected val to be unchanged, got \"%s\"\n", val);
13098     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
13099 
13100     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
13101     lstrcatA(keypath, prod_squashed);
13102 
13103     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
13104     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13105 
13106     /* local product key exists */
13107     size = MAX_PATH;
13108     lstrcpyA(val, "apple");
13109     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13110                             MSIINSTALLCONTEXT_MACHINE,
13111                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13112     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
13113     ok(!lstrcmpA(val, "apple"),
13114        "Expected val to be unchanged, got \"%s\"\n", val);
13115     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
13116 
13117     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &prodpatches, NULL);
13118     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13119 
13120     /* Patches key exists */
13121     size = MAX_PATH;
13122     lstrcpyA(val, "apple");
13123     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13124                             MSIINSTALLCONTEXT_MACHINE,
13125                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13126     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
13127     ok(!lstrcmpA(val, "apple"),
13128        "Expected val to be unchanged, got \"%s\"\n", val);
13129     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
13130 
13131     res = RegSetValueExA(prodpatches, patch_squashed, 0, REG_SZ,
13132                          (const BYTE *)"transforms", 11);
13133     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13134 
13135     /* specific patch value exists */
13136     size = MAX_PATH;
13137     lstrcpyA(val, "apple");
13138     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13139                             MSIINSTALLCONTEXT_MACHINE,
13140                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13141     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
13142     ok(!lstrcmpA(val, "apple"),
13143        "Expected val to be unchanged, got \"%s\"\n", val);
13144     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
13145 
13146     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
13147     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Patches\\");
13148     lstrcatA(keypath, patch_squashed);
13149 
13150     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udpatch, NULL);
13151     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13152 
13153     /* UserData Patches key exists */
13154     size = MAX_PATH;
13155     lstrcpyA(val, "apple");
13156     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13157                             MSIINSTALLCONTEXT_MACHINE,
13158                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13159     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13160     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
13161     ok(size == 0, "Expected 0, got %d\n", size);
13162 
13163     res = RegSetValueExA(udpatch, "LocalPackage", 0, REG_SZ,
13164                          (const BYTE *)"pack", 5);
13165     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13166 
13167     /* LocalPatch value exists */
13168     size = MAX_PATH;
13169     lstrcpyA(val, "apple");
13170     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13171                             MSIINSTALLCONTEXT_MACHINE,
13172                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13173     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13174     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
13175     ok(size == 4, "Expected 4, got %d\n", size);
13176 
13177     size = MAX_PATH;
13178     lstrcpyA(val, "apple");
13179     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13180                             MSIINSTALLCONTEXT_MACHINE,
13181                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
13182     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13183     ok(!lstrcmpA(val, "transforms"), "Expected \"transforms\", got \"%s\"\n", val);
13184     ok(size == 10, "Expected 10, got %d\n", size);
13185 
13186     RegDeleteValueA(prodpatches, patch_squashed);
13187     delete_key(prodpatches, "", access & KEY_WOW64_64KEY);
13188     RegCloseKey(prodpatches);
13189     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
13190     RegCloseKey(prodkey);
13191 
13192     /* UserData is sufficient for all properties
13193      * except INSTALLPROPERTY_TRANSFORMS
13194      */
13195     size = MAX_PATH;
13196     lstrcpyA(val, "apple");
13197     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13198                             MSIINSTALLCONTEXT_MACHINE,
13199                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13200     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13201     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
13202     ok(size == 4, "Expected 4, got %d\n", size);
13203 
13204     /* UserData is sufficient for all properties
13205      * except INSTALLPROPERTY_TRANSFORMS
13206      */
13207     size = MAX_PATH;
13208     lstrcpyA(val, "apple");
13209     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13210                             MSIINSTALLCONTEXT_MACHINE,
13211                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
13212     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
13213     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
13214     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
13215 
13216     RegDeleteValueA(udpatch, "LocalPackage");
13217     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
13218     RegCloseKey(udpatch);
13219     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
13220     RegCloseKey(hpatch);
13221     delete_key(patches, "", access & KEY_WOW64_64KEY);
13222     RegCloseKey(patches);
13223     delete_key(props, "", access & KEY_WOW64_64KEY);
13224     RegCloseKey(props);
13225     delete_key(udprod, "", access & KEY_WOW64_64KEY);
13226     RegCloseKey(udprod);
13227     LocalFree(usersid);
13228 }
13229 
13230 static void test_MsiGetPatchInfo(void)
13231 {
13232     UINT r;
13233     char prod_code[MAX_PATH], prod_squashed[MAX_PATH], val[MAX_PATH];
13234     char patch_code[MAX_PATH], patch_squashed[MAX_PATH], keypath[MAX_PATH];
13235     WCHAR valW[MAX_PATH], patch_codeW[MAX_PATH];
13236     HKEY hkey_product, hkey_patch, hkey_patches, hkey_udprops, hkey_udproduct;
13237     HKEY hkey_udpatch, hkey_udpatches, hkey_udproductpatches, hkey_udproductpatch;
13238     DWORD size;
13239     LONG res;
13240     REGSAM access = KEY_ALL_ACCESS;
13241 
13242     create_test_guid(patch_code, patch_squashed);
13243     create_test_guid(prod_code, prod_squashed);
13244     MultiByteToWideChar(CP_ACP, 0, patch_code, -1, patch_codeW, MAX_PATH);
13245 
13246     if (is_wow64)
13247         access |= KEY_WOW64_64KEY;
13248 
13249     r = MsiGetPatchInfoA(NULL, NULL, NULL, NULL);
13250     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
13251 
13252     r = MsiGetPatchInfoA(patch_code, NULL, NULL, NULL);
13253     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
13254 
13255     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, NULL, NULL);
13256     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
13257 
13258     size = 0;
13259     r = MsiGetPatchInfoA(patch_code, NULL, NULL, &size);
13260     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
13261 
13262     r = MsiGetPatchInfoA(patch_code, "", NULL, &size);
13263     ok(r == ERROR_UNKNOWN_PROPERTY, "expected ERROR_UNKNOWN_PROPERTY, got %u\n", r);
13264 
13265     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
13266     lstrcatA(keypath, prod_squashed);
13267 
13268     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey_product, NULL);
13269     if (res == ERROR_ACCESS_DENIED)
13270     {
13271         skip("Not enough rights to perform tests\n");
13272         return;
13273     }
13274     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13275 
13276     /* product key exists */
13277     size = MAX_PATH;
13278     lstrcpyA(val, "apple");
13279     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13280     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13281     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged, got \"%s\"\n", val);
13282     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
13283 
13284     res = RegCreateKeyExA(hkey_product, "Patches", 0, NULL, 0, access, NULL, &hkey_patches, NULL);
13285     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13286 
13287     /* patches key exists */
13288     size = MAX_PATH;
13289     lstrcpyA(val, "apple");
13290     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13291     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13292     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
13293     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
13294 
13295     res = RegCreateKeyExA(hkey_patches, patch_squashed, 0, NULL, 0, access, NULL, &hkey_patch, NULL);
13296     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13297 
13298     /* patch key exists */
13299     size = MAX_PATH;
13300     lstrcpyA(val, "apple");
13301     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13302     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13303     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
13304     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
13305 
13306     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
13307     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Products\\");
13308     lstrcatA(keypath, prod_squashed);
13309 
13310     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey_udproduct, NULL);
13311     if (res == ERROR_ACCESS_DENIED)
13312     {
13313         skip("Not enough rights to perform tests\n");
13314         goto done;
13315     }
13316     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
13317 
13318     /* UserData product key exists */
13319     size = MAX_PATH;
13320     lstrcpyA(val, "apple");
13321     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13322     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13323     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
13324     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
13325 
13326     res = RegCreateKeyExA(hkey_udproduct, "InstallProperties", 0, NULL, 0, access, NULL, &hkey_udprops, NULL);
13327     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13328 
13329     /* InstallProperties key exists */
13330     size = MAX_PATH;
13331     lstrcpyA(val, "apple");
13332     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13333     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13334     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged, got \"%s\"\n", val);
13335     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
13336 
13337     res = RegCreateKeyExA(hkey_udproduct, "Patches", 0, NULL, 0, access, NULL, &hkey_udpatches, NULL);
13338     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13339 
13340     /* UserData Patches key exists */
13341     size = MAX_PATH;
13342     lstrcpyA(val, "apple");
13343     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13344     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13345     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
13346     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
13347 
13348     res = RegCreateKeyExA(hkey_udproduct, "Patches", 0, NULL, 0, access, NULL, &hkey_udproductpatches, NULL);
13349     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13350 
13351     res = RegCreateKeyExA(hkey_udproductpatches, patch_squashed, 0, NULL, 0, access, NULL, &hkey_udproductpatch, NULL);
13352     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13353 
13354     /* UserData product patch key exists */
13355     size = MAX_PATH;
13356     lstrcpyA(val, "apple");
13357     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13358     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13359     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
13360     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
13361 
13362     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
13363     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Patches\\");
13364     lstrcatA(keypath, patch_squashed);
13365 
13366     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey_udpatch, NULL);
13367     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13368 
13369     res = RegSetValueExA(hkey_udpatch, "LocalPackage", 0, REG_SZ, (const BYTE *)"c:\\test.msp", 12);
13370     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13371 
13372     /* UserData Patch key exists */
13373     size = 0;
13374     lstrcpyA(val, "apple");
13375     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13376     ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", r);
13377     ok(!lstrcmpA(val, "apple"), "expected \"apple\", got \"%s\"\n", val);
13378     ok(size == 11, "expected 11 got %u\n", size);
13379 
13380     size = MAX_PATH;
13381     lstrcpyA(val, "apple");
13382     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13383     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS got %u\n", r);
13384     ok(!lstrcmpA(val, "c:\\test.msp"), "expected \"c:\\test.msp\", got \"%s\"\n", val);
13385     ok(size == 11, "expected 11 got %u\n", size);
13386 
13387     size = 0;
13388     valW[0] = 0;
13389     r = MsiGetPatchInfoW(patch_codeW, INSTALLPROPERTY_LOCALPACKAGEW, valW, &size);
13390     ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", r);
13391     ok(!valW[0], "expected 0 got %u\n", valW[0]);
13392     ok(size == 11, "expected 11 got %u\n", size);
13393 
13394     size = MAX_PATH;
13395     valW[0] = 0;
13396     r = MsiGetPatchInfoW(patch_codeW, INSTALLPROPERTY_LOCALPACKAGEW, valW, &size);
13397     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS got %u\n", r);
13398     ok(valW[0], "expected > 0 got %u\n", valW[0]);
13399     ok(size == 11, "expected 11 got %u\n", size);
13400 
13401     delete_key(hkey_udproductpatch, "", access & KEY_WOW64_64KEY);
13402     RegCloseKey(hkey_udproductpatch);
13403     delete_key(hkey_udproductpatches, "", access & KEY_WOW64_64KEY);
13404     RegCloseKey(hkey_udproductpatches);
13405     delete_key(hkey_udpatch, "", access & KEY_WOW64_64KEY);
13406     RegCloseKey(hkey_udpatch);
13407     delete_key(hkey_udpatches, "", access & KEY_WOW64_64KEY);
13408     RegCloseKey(hkey_udpatches);
13409     delete_key(hkey_udprops, "", access & KEY_WOW64_64KEY);
13410     RegCloseKey(hkey_udprops);
13411     delete_key(hkey_udproduct, "", access & KEY_WOW64_64KEY);
13412     RegCloseKey(hkey_udproduct);
13413 
13414 done:
13415     delete_key(hkey_patches, "", access & KEY_WOW64_64KEY);
13416     RegCloseKey(hkey_patches);
13417     delete_key(hkey_product, "", access & KEY_WOW64_64KEY);
13418     RegCloseKey(hkey_product);
13419     delete_key(hkey_patch, "", access & KEY_WOW64_64KEY);
13420     RegCloseKey(hkey_patch);
13421 }
13422 
13423 static void test_MsiEnumProducts(void)
13424 {
13425     UINT r;
13426     BOOL found1, found2, found3;
13427     DWORD index;
13428     char product1[39], product2[39], product3[39], guid[39];
13429     char product_squashed1[33], product_squashed2[33], product_squashed3[33];
13430     char keypath1[MAX_PATH], keypath2[MAX_PATH], keypath3[MAX_PATH];
13431     char *usersid;
13432     HKEY key1, key2, key3;
13433     REGSAM access = KEY_ALL_ACCESS;
13434 
13435     create_test_guid(product1, product_squashed1);
13436     create_test_guid(product2, product_squashed2);
13437     create_test_guid(product3, product_squashed3);
13438     usersid = get_user_sid();
13439 
13440     if (is_wow64)
13441         access |= KEY_WOW64_64KEY;
13442 
13443     strcpy(keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
13444     strcat(keypath2, usersid);
13445     strcat(keypath2, "\\Installer\\Products\\");
13446     strcat(keypath2, product_squashed2);
13447 
13448     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL);
13449     if (r == ERROR_ACCESS_DENIED)
13450     {
13451         skip("Not enough rights to perform tests\n");
13452         LocalFree(usersid);
13453         return;
13454     }
13455     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13456 
13457     strcpy(keypath1, "Software\\Classes\\Installer\\Products\\");
13458     strcat(keypath1, product_squashed1);
13459 
13460     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL);
13461     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13462 
13463     strcpy(keypath3, "Software\\Microsoft\\Installer\\Products\\");
13464     strcat(keypath3, product_squashed3);
13465 
13466     r = RegCreateKeyA(HKEY_CURRENT_USER, keypath3, &key3);
13467     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13468 
13469     index = 0;
13470     r = MsiEnumProductsA(index, guid);
13471     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13472 
13473     r = MsiEnumProductsA(index, NULL);
13474     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
13475 
13476     index = 2;
13477     r = MsiEnumProductsA(index, guid);
13478     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
13479 
13480     index = 0;
13481     r = MsiEnumProductsA(index, guid);
13482     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13483 
13484     found1 = found2 = found3 = FALSE;
13485     while ((r = MsiEnumProductsA(index, guid)) == ERROR_SUCCESS)
13486     {
13487         if (!strcmp(product1, guid)) found1 = TRUE;
13488         if (!strcmp(product2, guid)) found2 = TRUE;
13489         if (!strcmp(product3, guid)) found3 = TRUE;
13490         index++;
13491     }
13492     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %u\n", r);
13493     ok(found1, "product1 not found\n");
13494     ok(found2, "product2 not found\n");
13495     ok(found3, "product3 not found\n");
13496 
13497     delete_key(key1, "", access & KEY_WOW64_64KEY);
13498     delete_key(key2, "", access & KEY_WOW64_64KEY);
13499     RegDeleteKeyA(key3, "");
13500     RegCloseKey(key1);
13501     RegCloseKey(key2);
13502     RegCloseKey(key3);
13503     LocalFree(usersid);
13504 }
13505 
13506 static void test_MsiGetFileSignatureInformation(void)
13507 {
13508     HRESULT hr;
13509     const CERT_CONTEXT *cert;
13510     DWORD len;
13511 
13512     hr = MsiGetFileSignatureInformationA( NULL, 0, NULL, NULL, NULL );
13513     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13514 
13515     hr = MsiGetFileSignatureInformationA( NULL, 0, NULL, NULL, &len );
13516     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13517 
13518     hr = MsiGetFileSignatureInformationA( NULL, 0, &cert, NULL, &len );
13519     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13520 
13521     hr = MsiGetFileSignatureInformationA( "", 0, NULL, NULL, NULL );
13522     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13523 
13524     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, NULL );
13525     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13526 
13527     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, &len );
13528     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13529 
13530     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, &cert, NULL, &len );
13531     todo_wine ok(hr == CRYPT_E_FILE_ERROR, "expected CRYPT_E_FILE_ERROR got 0x%08x\n", hr);
13532 
13533     create_file( "signature.bin", "signature", sizeof("signature") );
13534 
13535     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, NULL );
13536     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13537 
13538     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, &len );
13539     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13540 
13541     cert = (const CERT_CONTEXT *)0xdeadbeef;
13542     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, &cert, NULL, &len );
13543     todo_wine ok(hr == HRESULT_FROM_WIN32(ERROR_FUNCTION_FAILED), "got 0x%08x\n", hr);
13544     ok(cert == NULL, "got %p\n", cert);
13545 
13546     DeleteFileA( "signature.bin" );
13547 }
13548 
13549 static void test_MsiEnumProductsEx(void)
13550 {
13551     UINT r;
13552     DWORD len, index;
13553     MSIINSTALLCONTEXT context;
13554     char product0[39], product1[39], product2[39], product3[39], guid[39], sid[128];
13555     char product_squashed1[33], product_squashed2[33], product_squashed3[33];
13556     char keypath1[MAX_PATH], keypath2[MAX_PATH], keypath3[MAX_PATH];
13557     HKEY key1 = NULL, key2 = NULL, key3 = NULL;
13558     REGSAM access = KEY_ALL_ACCESS;
13559     char *usersid = get_user_sid();
13560 
13561     if (!pMsiEnumProductsExA)
13562     {
13563         win_skip("MsiEnumProductsExA not implemented\n");
13564         return;
13565     }
13566 
13567     create_test_guid( product0, NULL );
13568     create_test_guid( product1, product_squashed1 );
13569     create_test_guid( product2, product_squashed2 );
13570     create_test_guid( product3, product_squashed3 );
13571 
13572     if (is_wow64) access |= KEY_WOW64_64KEY;
13573 
13574     strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\" );
13575     strcat( keypath2, usersid );
13576     strcat( keypath2, "\\Installer\\Products\\" );
13577     strcat( keypath2, product_squashed2 );
13578 
13579     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
13580     if (r == ERROR_ACCESS_DENIED)
13581     {
13582         skip( "insufficient rights\n" );
13583         goto done;
13584     }
13585     ok( r == ERROR_SUCCESS, "got %u\n", r );
13586 
13587     strcpy( keypath1, "Software\\Classes\\Installer\\Products\\" );
13588     strcat( keypath1, product_squashed1 );
13589 
13590     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
13591     ok( r == ERROR_SUCCESS, "got %u\n", r );
13592 
13593     strcpy( keypath3, usersid );
13594     strcat( keypath3, "\\Software\\Microsoft\\Installer\\Products\\" );
13595     strcat( keypath3, product_squashed3 );
13596 
13597     r = RegCreateKeyExA( HKEY_USERS, keypath3, 0, NULL, 0, access, NULL, &key3, NULL );
13598     ok( r == ERROR_SUCCESS, "got %u\n", r );
13599 
13600     r = pMsiEnumProductsExA( NULL, NULL, 0, 0, NULL, NULL, NULL, NULL );
13601     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13602 
13603     len = sizeof(sid);
13604     r = pMsiEnumProductsExA( NULL, NULL, 0, 0, NULL, NULL, NULL, &len );
13605     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13606     ok( len == sizeof(sid), "got %u\n", len );
13607 
13608     r = pMsiEnumProductsExA( NULL, NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, NULL, NULL );
13609     ok( r == ERROR_SUCCESS, "got %u\n", r );
13610 
13611     sid[0] = 0;
13612     len = sizeof(sid);
13613     r = pMsiEnumProductsExA( product0, NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, &len );
13614     ok( r == ERROR_NO_MORE_ITEMS, "got %u\n", r );
13615     ok( len == sizeof(sid), "got %u\n", len );
13616     ok( !sid[0], "got %s\n", sid );
13617 
13618     sid[0] = 0;
13619     len = sizeof(sid);
13620     r = pMsiEnumProductsExA( product0, usersid, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, &len );
13621     ok( r == ERROR_NO_MORE_ITEMS, "got %u\n", r );
13622     ok( len == sizeof(sid), "got %u\n", len );
13623     ok( !sid[0], "got %s\n", sid );
13624 
13625     sid[0] = 0;
13626     len = 0;
13627     r = pMsiEnumProductsExA( NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, 0, NULL, NULL, sid, &len );
13628     ok( r == ERROR_MORE_DATA, "got %u\n", r );
13629     ok( len, "length unchanged\n" );
13630     ok( !sid[0], "got %s\n", sid );
13631 
13632     guid[0] = 0;
13633     context = 0xdeadbeef;
13634     sid[0] = 0;
13635     len = sizeof(sid);
13636     r = pMsiEnumProductsExA( NULL, NULL, MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
13637     ok( r == ERROR_SUCCESS, "got %u\n", r );
13638     ok( guid[0], "empty guid\n" );
13639     ok( context != 0xdeadbeef, "context unchanged\n" );
13640     ok( !len, "got %u\n", len );
13641     ok( !sid[0], "got %s\n", sid );
13642 
13643     guid[0] = 0;
13644     context = 0xdeadbeef;
13645     sid[0] = 0;
13646     len = sizeof(sid);
13647     r = pMsiEnumProductsExA( NULL, usersid, MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
13648     ok( r == ERROR_SUCCESS, "got %u\n", r );
13649     ok( guid[0], "empty guid\n" );
13650     ok( context != 0xdeadbeef, "context unchanged\n" );
13651     ok( !len, "got %u\n", len );
13652     ok( !sid[0], "got %s\n", sid );
13653 
13654     guid[0] = 0;
13655     context = 0xdeadbeef;
13656     sid[0] = 0;
13657     len = sizeof(sid);
13658     r = pMsiEnumProductsExA( NULL, "S-1-1-0", MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
13659     if (r == ERROR_ACCESS_DENIED)
13660     {
13661         skip( "insufficient rights\n" );
13662         goto done;
13663     }
13664     ok( r == ERROR_SUCCESS, "got %u\n", r );
13665     ok( guid[0], "empty guid\n" );
13666     ok( context != 0xdeadbeef, "context unchanged\n" );
13667     ok( !len, "got %u\n", len );
13668     ok( !sid[0], "got %s\n", sid );
13669 
13670     index = 0;
13671     guid[0] = 0;
13672     context = 0xdeadbeef;
13673     sid[0] = 0;
13674     len = sizeof(sid);
13675     while (!pMsiEnumProductsExA( NULL, "S-1-1-0", MSIINSTALLCONTEXT_ALL, index, guid, &context, sid, &len ))
13676     {
13677         if (!strcmp( product1, guid ))
13678         {
13679             ok( context == MSIINSTALLCONTEXT_MACHINE, "got %u\n", context );
13680             ok( !sid[0], "got \"%s\"\n", sid );
13681             ok( !len, "unexpected length %u\n", len );
13682         }
13683         if (!strcmp( product2, guid ))
13684         {
13685             ok( context == MSIINSTALLCONTEXT_USERMANAGED, "got %u\n", context );
13686             ok( sid[0], "empty sid\n" );
13687             ok( len == strlen(sid), "unexpected length %u\n", len );
13688         }
13689         if (!strcmp( product3, guid ))
13690         {
13691             ok( context == MSIINSTALLCONTEXT_USERUNMANAGED, "got %u\n", context );
13692             ok( sid[0], "empty sid\n" );
13693             ok( len == strlen(sid), "unexpected length %u\n", len );
13694         }
13695         index++;
13696         guid[0] = 0;
13697         context = 0xdeadbeef;
13698         sid[0] = 0;
13699         len = sizeof(sid);
13700     }
13701 
13702 done:
13703     delete_key( key1, "", access );
13704     delete_key( key2, "", access );
13705     delete_key( key3, "", access );
13706     RegCloseKey( key1 );
13707     RegCloseKey( key2 );
13708     RegCloseKey( key3 );
13709     LocalFree( usersid );
13710 }
13711 
13712 static void test_MsiEnumComponents(void)
13713 {
13714     UINT r;
13715     BOOL found1, found2;
13716     DWORD index;
13717     char comp1[39], comp2[39], guid[39];
13718     char comp_squashed1[33], comp_squashed2[33];
13719     char keypath1[MAX_PATH], keypath2[MAX_PATH];
13720     REGSAM access = KEY_ALL_ACCESS;
13721     char *usersid = get_user_sid();
13722     HKEY key1 = NULL, key2 = NULL;
13723 
13724     create_test_guid( comp1, comp_squashed1 );
13725     create_test_guid( comp2, comp_squashed2 );
13726 
13727     if (is_wow64) access |= KEY_WOW64_64KEY;
13728 
13729     strcpy( keypath1, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
13730     strcat( keypath1, "S-1-5-18\\Components\\" );
13731     strcat( keypath1, comp_squashed1 );
13732 
13733     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
13734     if (r == ERROR_ACCESS_DENIED)
13735     {
13736         skip( "insufficient rights\n" );
13737         goto done;
13738     }
13739     ok( r == ERROR_SUCCESS, "got %u\n", r );
13740 
13741     strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
13742     strcat( keypath2, usersid );
13743     strcat( keypath2, "\\Components\\" );
13744     strcat( keypath2, comp_squashed2 );
13745 
13746     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
13747     if (r == ERROR_ACCESS_DENIED)
13748     {
13749         skip( "insufficient rights\n" );
13750         goto done;
13751     }
13752 
13753     r = MsiEnumComponentsA( 0, NULL );
13754     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13755 
13756     index = 0;
13757     guid[0] = 0;
13758     found1 = found2 = FALSE;
13759     while (!MsiEnumComponentsA( index, guid ))
13760     {
13761         if (!strcmp( guid, comp1 )) found1 = TRUE;
13762         if (!strcmp( guid, comp2 )) found2 = TRUE;
13763         ok( guid[0], "empty guid\n" );
13764         guid[0] = 0;
13765         index++;
13766     }
13767     ok( found1, "comp1 not found\n" );
13768     ok( found2, "comp2 not found\n" );
13769 
13770 done:
13771     delete_key( key1, "", access );
13772     delete_key( key2, "", access );
13773     RegCloseKey( key1 );
13774     RegCloseKey( key2 );
13775     LocalFree( usersid );
13776 }
13777 
13778 static void test_MsiEnumComponentsEx(void)
13779 {
13780     UINT r;
13781     BOOL found1, found2;
13782     DWORD len, index;
13783     MSIINSTALLCONTEXT context;
13784     char comp1[39], comp2[39], guid[39], sid[128];
13785     char comp_squashed1[33], comp_squashed2[33];
13786     char keypath1[MAX_PATH], keypath2[MAX_PATH];
13787     HKEY key1 = NULL, key2 = NULL;
13788     REGSAM access = KEY_ALL_ACCESS;
13789     char *usersid = get_user_sid();
13790 
13791     if (!pMsiEnumComponentsExA)
13792     {
13793         win_skip( "MsiEnumComponentsExA not implemented\n" );
13794         return;
13795     }
13796     create_test_guid( comp1, comp_squashed1 );
13797     create_test_guid( comp2, comp_squashed2 );
13798 
13799     if (is_wow64) access |= KEY_WOW64_64KEY;
13800 
13801     strcpy( keypath1, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
13802     strcat( keypath1, "S-1-5-18\\Components\\" );
13803     strcat( keypath1, comp_squashed1 );
13804 
13805     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
13806     if (r == ERROR_ACCESS_DENIED)
13807     {
13808         skip( "insufficient rights\n" );
13809         goto done;
13810     }
13811     ok( r == ERROR_SUCCESS, "got %u\n", r );
13812 
13813     strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
13814     strcat( keypath2, usersid );
13815     strcat( keypath2, "\\Components\\" );
13816     strcat( keypath2, comp_squashed2 );
13817 
13818     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
13819     if (r == ERROR_ACCESS_DENIED)
13820     {
13821         skip( "insufficient rights\n" );
13822         goto done;
13823     }
13824     ok( r == ERROR_SUCCESS, "got %u\n", r );
13825     r = RegSetValueExA( key2, comp_squashed2, 0, REG_SZ, (const BYTE *)"c:\\doesnotexist",
13826                         sizeof("c:\\doesnotexist"));
13827     ok( r == ERROR_SUCCESS, "got %u\n", r );
13828 
13829     index = 0;
13830     guid[0] = 0;
13831     context = 0xdeadbeef;
13832     sid[0] = 0;
13833     len = sizeof(sid);
13834     found1 = found2 = FALSE;
13835     while (!pMsiEnumComponentsExA( "S-1-1-0", MSIINSTALLCONTEXT_ALL, index, guid, &context, sid, &len ))
13836     {
13837         if (!strcmp( comp1, guid ))
13838         {
13839             ok( context == MSIINSTALLCONTEXT_MACHINE, "got %u\n", context );
13840             ok( !sid[0], "got \"%s\"\n", sid );
13841             ok( !len, "unexpected length %u\n", len );
13842             found1 = TRUE;
13843         }
13844         if (!strcmp( comp2, guid ))
13845         {
13846             ok( context == MSIINSTALLCONTEXT_USERUNMANAGED, "got %u\n", context );
13847             ok( sid[0], "empty sid\n" );
13848             ok( len == strlen(sid), "unexpected length %u\n", len );
13849             found2 = TRUE;
13850         }
13851         index++;
13852         guid[0] = 0;
13853         context = 0xdeadbeef;
13854         sid[0] = 0;
13855         len = sizeof(sid);
13856     }
13857     ok( found1, "comp1 not found\n" );
13858     ok( found2, "comp2 not found\n" );
13859 
13860     r = pMsiEnumComponentsExA( NULL, 0, 0, NULL, NULL, NULL, NULL );
13861     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13862 
13863     r = pMsiEnumComponentsExA( NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, NULL );
13864     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13865 
13866 done:
13867     RegDeleteValueA( key2, comp_squashed2 );
13868     delete_key( key1, "", access );
13869     delete_key( key2, "", access );
13870     RegCloseKey( key1 );
13871     RegCloseKey( key2 );
13872     LocalFree( usersid );
13873 }
13874 
13875 static void test_MsiConfigureProductEx(void)
13876 {
13877     UINT r;
13878     LONG res;
13879     DWORD type, size;
13880     HKEY props, source;
13881     CHAR keypath[MAX_PATH * 2], localpackage[MAX_PATH], packagename[MAX_PATH];
13882     REGSAM access = KEY_ALL_ACCESS;
13883 
13884     if (is_process_limited())
13885     {
13886         skip("process is limited\n");
13887         return;
13888     }
13889 
13890     CreateDirectoryA("msitest", NULL);
13891     create_file("msitest\\hydrogen", "hydrogen", 500);
13892     create_file("msitest\\helium", "helium", 500);
13893     create_file("msitest\\lithium", "lithium", 500);
13894 
13895     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
13896 
13897     if (is_wow64)
13898         access |= KEY_WOW64_64KEY;
13899 
13900     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
13901 
13902     /* NULL szProduct */
13903     r = MsiConfigureProductExA(NULL, INSTALLLEVEL_DEFAULT,
13904                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
13905     ok(r == ERROR_INVALID_PARAMETER,
13906        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
13907 
13908     /* empty szProduct */
13909     r = MsiConfigureProductExA("", INSTALLLEVEL_DEFAULT,
13910                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
13911     ok(r == ERROR_INVALID_PARAMETER,
13912        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
13913 
13914     /* garbage szProduct */
13915     r = MsiConfigureProductExA("garbage", INSTALLLEVEL_DEFAULT,
13916                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
13917     ok(r == ERROR_INVALID_PARAMETER,
13918        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
13919 
13920     /* guid without brackets */
13921     r = MsiConfigureProductExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
13922                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13923                                "PROPVAR=42");
13924     ok(r == ERROR_INVALID_PARAMETER,
13925        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
13926 
13927     /* guid with brackets */
13928     r = MsiConfigureProductExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
13929                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13930                                "PROPVAR=42");
13931     ok(r == ERROR_UNKNOWN_PRODUCT,
13932        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
13933 
13934     /* same length as guid, but random */
13935     r = MsiConfigureProductExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
13936                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13937                                "PROPVAR=42");
13938     ok(r == ERROR_UNKNOWN_PRODUCT,
13939        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
13940 
13941     /* product not installed yet */
13942     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
13943                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13944                                "PROPVAR=42");
13945     ok(r == ERROR_UNKNOWN_PRODUCT,
13946        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
13947 
13948     /* install the product, per-user unmanaged */
13949     r = MsiInstallProductA(msifile, "INSTALLLEVEL=10 PROPVAR=42");
13950     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
13951     {
13952         skip("Not enough rights to perform tests\n");
13953         goto error;
13954     }
13955     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13956     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13957     ok(pf_exists("msitest\\helium"), "File not installed\n");
13958     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13959     ok(pf_exists("msitest"), "File not installed\n");
13960 
13961     /* product is installed per-user managed, remove it */
13962     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13963                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13964                                "PROPVAR=42");
13965     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13966     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
13967     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
13968     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
13969     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
13970 
13971     /* product has been removed */
13972     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13973                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13974                                "PROPVAR=42");
13975     ok(r == ERROR_UNKNOWN_PRODUCT,
13976        "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
13977 
13978     /* install the product, machine */
13979     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
13980     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13981     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13982     ok(pf_exists("msitest\\helium"), "File not installed\n");
13983     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13984     ok(pf_exists("msitest"), "File not installed\n");
13985 
13986     /* product is installed machine, remove it */
13987     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13988                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13989                                "PROPVAR=42");
13990     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13991     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
13992     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
13993     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
13994     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
13995 
13996     /* product has been removed */
13997     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13998                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13999                                "PROPVAR=42");
14000     ok(r == ERROR_UNKNOWN_PRODUCT,
14001        "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14002 
14003     /* install the product, machine */
14004     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
14005     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14006     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
14007     ok(pf_exists("msitest\\helium"), "File not installed\n");
14008     ok(pf_exists("msitest\\lithium"), "File not installed\n");
14009     ok(pf_exists("msitest"), "File not installed\n");
14010 
14011     DeleteFileA(msifile);
14012 
14013     /* msifile is removed */
14014     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
14015                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
14016                                "PROPVAR=42");
14017     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
14018     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
14019     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
14020     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
14021     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
14022 
14023     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
14024 
14025     /* install the product, machine */
14026     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
14027     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14028     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
14029     ok(pf_exists("msitest\\helium"), "File not installed\n");
14030     ok(pf_exists("msitest\\lithium"), "File not installed\n");
14031     ok(pf_exists("msitest"), "File not installed\n");
14032 
14033     DeleteFileA(msifile);
14034 
14035     lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
14036     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
14037     lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\InstallProperties");
14038 
14039     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &props);
14040     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14041 
14042     type = REG_SZ;
14043     size = MAX_PATH;
14044     res = RegQueryValueExA(props, "LocalPackage", NULL, &type,
14045                            (LPBYTE)localpackage, &size);
14046     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14047 
14048     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
14049                          (const BYTE *)"C:\\idontexist.msi", 18);
14050     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14051 
14052     /* LocalPackage is used to find the cached msi package */
14053     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
14054                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
14055                                "PROPVAR=42");
14056     ok(r == ERROR_INSTALL_SOURCE_ABSENT,
14057        "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
14058     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
14059     ok(pf_exists("msitest\\helium"), "File not installed\n");
14060     ok(pf_exists("msitest\\lithium"), "File not installed\n");
14061     ok(pf_exists("msitest"), "File not installed\n");
14062 
14063     RegCloseKey(props);
14064     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
14065 
14066     /* LastUsedSource can be used as a last resort */
14067     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
14068                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
14069                                "PROPVAR=42");
14070     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
14071     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
14072     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
14073     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
14074     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
14075     DeleteFileA( localpackage );
14076 
14077     /* install the product, machine */
14078     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
14079     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14080     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
14081     ok(pf_exists("msitest\\helium"), "File not installed\n");
14082     ok(pf_exists("msitest\\lithium"), "File not installed\n");
14083     ok(pf_exists("msitest"), "File not installed\n");
14084 
14085     lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
14086     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
14087     lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\InstallProperties");
14088 
14089     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &props);
14090     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14091 
14092     type = REG_SZ;
14093     size = MAX_PATH;
14094     res = RegQueryValueExA(props, "LocalPackage", NULL, &type,
14095                            (LPBYTE)localpackage, &size);
14096     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14097 
14098     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
14099                          (const BYTE *)"C:\\idontexist.msi", 18);
14100     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14101 
14102     lstrcpyA(keypath, "SOFTWARE\\Classes\\Installer\\Products\\");
14103     lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\SourceList");
14104 
14105     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &source);
14106     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14107 
14108     type = REG_SZ;
14109     size = MAX_PATH;
14110     res = RegQueryValueExA(source, "PackageName", NULL, &type,
14111                            (LPBYTE)packagename, &size);
14112     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14113 
14114     res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
14115                          (const BYTE *)"idontexist.msi", 15);
14116     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14117 
14118     /* SourceList is altered */
14119     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
14120                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
14121                                "PROPVAR=42");
14122     ok(r == ERROR_INSTALL_SOURCE_ABSENT,
14123        "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
14124     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
14125     ok(pf_exists("msitest\\helium"), "File not installed\n");
14126     ok(pf_exists("msitest\\lithium"), "File not installed\n");
14127     ok(pf_exists("msitest"), "File not installed\n");
14128 
14129     /* restore PackageName */
14130     res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
14131                          (const BYTE *)packagename, lstrlenA(packagename) + 1);
14132     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14133 
14134     /* restore LocalPackage */
14135     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
14136                          (const BYTE *)localpackage, lstrlenA(localpackage) + 1);
14137     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14138 
14139     /* finally remove the product */
14140     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
14141                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
14142                                "PROPVAR=42");
14143     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
14144     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
14145     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
14146     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
14147     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
14148 
14149     RegCloseKey(source);
14150     RegCloseKey(props);
14151 
14152 error:
14153     DeleteFileA("msitest\\hydrogen");
14154     DeleteFileA("msitest\\helium");
14155     DeleteFileA("msitest\\lithium");
14156     RemoveDirectoryA("msitest");
14157     DeleteFileA(msifile);
14158 }
14159 
14160 static void test_MsiSetFeatureAttributes(void)
14161 {
14162     UINT r;
14163     DWORD attrs;
14164     char path[MAX_PATH];
14165     MSIHANDLE package;
14166 
14167     if (is_process_limited())
14168     {
14169         skip("process is limited\n");
14170         return;
14171     }
14172     create_database( msifile, tables, sizeof(tables) / sizeof(tables[0]) );
14173 
14174     strcpy( path, CURR_DIR );
14175     strcat( path, "\\" );
14176     strcat( path, msifile );
14177 
14178     r = MsiOpenPackageA( path, &package );
14179     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14180     {
14181         skip("Not enough rights to perform tests\n");
14182         DeleteFileA( msifile );
14183         return;
14184     }
14185     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14186 
14187     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
14188     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %u\n", r);
14189 
14190     r = MsiDoActionA( package, "CostInitialize" );
14191     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14192 
14193     r = MsiSetFeatureAttributesA( 0, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
14194     ok(r == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", r);
14195 
14196     r = MsiSetFeatureAttributesA( package, "", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
14197     ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
14198 
14199     r = MsiSetFeatureAttributesA( package, NULL, INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
14200     ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
14201 
14202     r = MsiSetFeatureAttributesA( package, "One", 0 );
14203     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14204 
14205     attrs = 0xdeadbeef;
14206     r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL );
14207     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14208     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL,
14209        "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got 0x%08x\n", attrs);
14210 
14211     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
14212     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14213 
14214     attrs = 0;
14215     r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL );
14216     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14217     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL,
14218        "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got 0x%08x\n", attrs);
14219 
14220     r = MsiDoActionA( package, "FileCost" );
14221     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14222 
14223     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORSOURCE );
14224     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14225 
14226     attrs = 0;
14227     r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL );
14228     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14229     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORSOURCE,
14230        "expected INSTALLFEATUREATTRIBUTE_FAVORSOURCE, got 0x%08x\n", attrs);
14231 
14232     r = MsiDoActionA( package, "CostFinalize" );
14233     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14234 
14235     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
14236     ok(r == ERROR_FUNCTION_FAILED, "expected ERROR_FUNCTION_FAILED, got %u\n", r);
14237 
14238     MsiCloseHandle( package );
14239     DeleteFileA( msifile );
14240 }
14241 
14242 static void test_MsiGetFeatureInfo(void)
14243 {
14244     UINT r;
14245     MSIHANDLE package;
14246     char title[32], help[32], path[MAX_PATH];
14247     DWORD attrs, title_len, help_len;
14248 
14249     if (is_process_limited())
14250     {
14251         skip("process is limited\n");
14252         return;
14253     }
14254     create_database( msifile, tables, sizeof(tables) / sizeof(tables[0]) );
14255 
14256     strcpy( path, CURR_DIR );
14257     strcat( path, "\\" );
14258     strcat( path, msifile );
14259 
14260     r = MsiOpenPackageA( path, &package );
14261     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14262     {
14263         skip("Not enough rights to perform tests\n");
14264         DeleteFileA( msifile );
14265         return;
14266     }
14267     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14268 
14269     r = MsiGetFeatureInfoA( 0, NULL, NULL, NULL, NULL, NULL, NULL );
14270     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
14271 
14272     r = MsiGetFeatureInfoA( package, NULL, NULL, NULL, NULL, NULL, NULL );
14273     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
14274 
14275     r = MsiGetFeatureInfoA( package, "", NULL, NULL, NULL, NULL, NULL );
14276     ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
14277 
14278     r = MsiGetFeatureInfoA( package, "One", NULL, NULL, NULL, NULL, NULL );
14279     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14280 
14281     r = MsiGetFeatureInfoA( 0, "One", NULL, NULL, NULL, NULL, NULL );
14282     ok(r == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", r);
14283 
14284     title_len = help_len = 0;
14285     r = MsiGetFeatureInfoA( package, "One", NULL, NULL, &title_len, NULL, &help_len );
14286     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14287     ok(title_len == 3, "expected 3, got %u\n", title_len);
14288     ok(help_len == 3, "expected 3, got %u\n", help_len);
14289 
14290     title[0] = help[0] = 0;
14291     title_len = help_len = 0;
14292     r = MsiGetFeatureInfoA( package, "One", NULL, title, &title_len, help, &help_len );
14293     ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %u\n", r);
14294     ok(title_len == 3, "expected 3, got %u\n", title_len);
14295     ok(help_len == 3, "expected 3, got %u\n", help_len);
14296 
14297     attrs = 0;
14298     title[0] = help[0] = 0;
14299     title_len = sizeof(title);
14300     help_len = sizeof(help);
14301     r = MsiGetFeatureInfoA( package, "One", &attrs, title, &title_len, help, &help_len );
14302     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14303     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %u\n", attrs);
14304     ok(title_len == 3, "expected 3, got %u\n", title_len);
14305     ok(help_len == 3, "expected 3, got %u\n", help_len);
14306     ok(!strcmp(title, "One"), "expected \"One\", got \"%s\"\n", title);
14307     ok(!strcmp(help, "One"), "expected \"One\", got \"%s\"\n", help);
14308 
14309     attrs = 0;
14310     title[0] = help[0] = 0;
14311     title_len = sizeof(title);
14312     help_len = sizeof(help);
14313     r = MsiGetFeatureInfoA( package, "Two", &attrs, title, &title_len, help, &help_len );
14314     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14315     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %u\n", attrs);
14316     ok(!title_len, "expected 0, got %u\n", title_len);
14317     ok(!help_len, "expected 0, got %u\n", help_len);
14318     ok(!title[0], "expected \"\", got \"%s\"\n", title);
14319     ok(!help[0], "expected \"\", got \"%s\"\n", help);
14320 
14321     MsiCloseHandle( package );
14322     DeleteFileA( msifile );
14323 }
14324 
14325 static INT CALLBACK handler_a(LPVOID context, UINT type, LPCSTR msg)
14326 {
14327     return IDOK;
14328 }
14329 
14330 static INT CALLBACK handler_w(LPVOID context, UINT type, LPCWSTR msg)
14331 {
14332     return IDOK;
14333 }
14334 
14335 static INT CALLBACK handler_record(LPVOID context, UINT type, MSIHANDLE record)
14336 {
14337     return IDOK;
14338 }
14339 
14340 static void test_MsiSetInternalUI(void)
14341 {
14342     INSTALLUILEVEL level;
14343 
14344     level = MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
14345     ok(level == INSTALLUILEVEL_DEFAULT, "expected INSTALLUILEVEL_DEFAULT, got %d\n", level);
14346 
14347     level = MsiSetInternalUI(INSTALLUILEVEL_DEFAULT, NULL);
14348     ok(level == INSTALLUILEVEL_FULL, "expected INSTALLUILEVEL_FULL, got %d\n", level);
14349 
14350     level = MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE, NULL);
14351     ok(level == INSTALLUILEVEL_DEFAULT, "expected INSTALLUILEVEL_DEFAULT, got %d\n", level);
14352 
14353     level = MsiSetInternalUI(0xdeadbeef, NULL);
14354     ok(level == INSTALLUILEVEL_NOCHANGE, "expected INSTALLUILEVEL_NOCHANGE, got %d\n", level);
14355 }
14356 
14357 static void test_MsiSetExternalUI(void)
14358 {
14359     INSTALLUI_HANDLERA ret_a;
14360     INSTALLUI_HANDLERW ret_w;
14361     INSTALLUI_HANDLER_RECORD prev;
14362     UINT error;
14363 
14364     ret_a = MsiSetExternalUIA(handler_a, INSTALLLOGMODE_ERROR, NULL);
14365     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
14366 
14367     ret_a = MsiSetExternalUIA(NULL, 0, NULL);
14368     ok(ret_a == handler_a, "expected %p, got %p\n", handler_a, ret_a);
14369 
14370     /* Not present before Installer 3.1 */
14371     if (!pMsiSetExternalUIRecord) {
14372         win_skip("MsiSetExternalUIRecord is not available\n");
14373         return;
14374     }
14375 
14376     error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, &prev);
14377     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14378     ok(prev == NULL, "expected NULL, got %p\n", prev);
14379 
14380     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
14381     error = pMsiSetExternalUIRecord(NULL, INSTALLLOGMODE_ERROR, NULL, &prev);
14382     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14383     ok(prev == handler_record, "expected %p, got %p\n", handler_record, prev);
14384 
14385     ret_w = MsiSetExternalUIW(handler_w, INSTALLLOGMODE_ERROR, NULL);
14386     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
14387 
14388     ret_w = MsiSetExternalUIW(NULL, 0, NULL);
14389     ok(ret_w == handler_w, "expected %p, got %p\n", handler_w, ret_w);
14390 
14391     ret_a = MsiSetExternalUIA(handler_a, INSTALLLOGMODE_ERROR, NULL);
14392     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
14393 
14394     ret_w = MsiSetExternalUIW(handler_w, INSTALLLOGMODE_ERROR, NULL);
14395     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
14396 
14397     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
14398     error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, &prev);
14399     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14400     ok(prev == NULL, "expected NULL, got %p\n", prev);
14401 
14402     ret_a = MsiSetExternalUIA(NULL, 0, NULL);
14403     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
14404 
14405     ret_w = MsiSetExternalUIW(NULL, 0, NULL);
14406     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
14407 
14408     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
14409     error = pMsiSetExternalUIRecord(NULL, 0, NULL, &prev);
14410     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14411     ok(prev == handler_record, "expected %p, got %p\n", handler_record, prev);
14412 
14413     error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, NULL);
14414     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14415 
14416     error = pMsiSetExternalUIRecord(NULL, 0, NULL, NULL);
14417     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14418 }
14419 
14420 static void test_lastusedsource(void)
14421 {
14422     static const char prodcode[] = "{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}";
14423     char value[MAX_PATH], path[MAX_PATH];
14424     DWORD size;
14425     UINT r;
14426 
14427     if (!pMsiSourceListGetInfoA)
14428     {
14429         win_skip("MsiSourceListGetInfoA is not available\n");
14430         return;
14431     }
14432 
14433     CreateDirectoryA("msitest", NULL);
14434     create_file("maximus", "maximus", 500);
14435     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
14436     DeleteFileA("maximus");
14437 
14438     create_database("msifile0.msi", lus0_tables, sizeof(lus0_tables) / sizeof(msi_table));
14439     create_database("msifile1.msi", lus1_tables, sizeof(lus1_tables) / sizeof(msi_table));
14440     create_database("msifile2.msi", lus2_tables, sizeof(lus2_tables) / sizeof(msi_table));
14441 
14442     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
14443 
14444     /* no cabinet file */
14445 
14446     size = MAX_PATH;
14447     lstrcpyA(value, "aaa");
14448     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14449                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14450     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14451     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
14452 
14453     r = MsiInstallProductA("msifile0.msi", "PUBLISH_PRODUCT=1");
14454     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14455     {
14456         skip("Not enough rights to perform tests\n");
14457         goto error;
14458     }
14459     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14460 
14461     lstrcpyA(path, CURR_DIR);
14462     lstrcatA(path, "\\");
14463 
14464     size = MAX_PATH;
14465     lstrcpyA(value, "aaa");
14466     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14467                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14468     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14469     ok(!lstrcmpA(value, path), "expected \"%s\", got \"%s\"\n", path, value);
14470     ok(size == lstrlenA(path), "expected %d, got %d\n", lstrlenA(path), size);
14471 
14472     r = MsiInstallProductA("msifile0.msi", "REMOVE=ALL");
14473     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14474 
14475     /* separate cabinet file */
14476 
14477     size = MAX_PATH;
14478     lstrcpyA(value, "aaa");
14479     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14480                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14481     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14482     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
14483 
14484     r = MsiInstallProductA("msifile1.msi", "PUBLISH_PRODUCT=1");
14485     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14486 
14487     lstrcpyA(path, CURR_DIR);
14488     lstrcatA(path, "\\");
14489 
14490     size = MAX_PATH;
14491     lstrcpyA(value, "aaa");
14492     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14493                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14494     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14495     ok(!lstrcmpA(value, path), "expected \"%s\", got \"%s\"\n", path, value);
14496     ok(size == lstrlenA(path), "expected %d, got %d\n", lstrlenA(path), size);
14497 
14498     r = MsiInstallProductA("msifile1.msi", "REMOVE=ALL");
14499     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14500 
14501     size = MAX_PATH;
14502     lstrcpyA(value, "aaa");
14503     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14504                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14505     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14506     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
14507 
14508     /* embedded cabinet stream */
14509 
14510     add_cabinet_storage("msifile2.msi", "test1.cab");
14511 
14512     r = MsiInstallProductA("msifile2.msi", "PUBLISH_PRODUCT=1");
14513     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14514 
14515     size = MAX_PATH;
14516     lstrcpyA(value, "aaa");
14517     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14518                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14519     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14520     ok(!lstrcmpA(value, path), "expected \"%s\", got \"%s\"\n", path, value);
14521     ok(size == lstrlenA(path), "expected %d, got %d\n", lstrlenA(path), size);
14522 
14523     r = MsiInstallProductA("msifile2.msi", "REMOVE=ALL");
14524     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14525 
14526     size = MAX_PATH;
14527     lstrcpyA(value, "aaa");
14528     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14529                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14530     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14531     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
14532 
14533 error:
14534     delete_cab_files();
14535     DeleteFileA("msitest\\maximus");
14536     RemoveDirectoryA("msitest");
14537     DeleteFileA("msifile0.msi");
14538     DeleteFileA("msifile1.msi");
14539     DeleteFileA("msifile2.msi");
14540 }
14541 
14542 static void test_setpropertyfolder(void)
14543 {
14544     UINT r;
14545     CHAR path[MAX_PATH];
14546     DWORD attr;
14547 
14548     if (is_process_limited())
14549     {
14550         skip("process is limited\n");
14551         return;
14552     }
14553 
14554     lstrcpyA(path, PROG_FILES_DIR);
14555     lstrcatA(path, "\\msitest\\added");
14556 
14557     CreateDirectoryA("msitest", NULL);
14558     create_file("msitest\\maximus", "msitest\\maximus", 500);
14559 
14560     create_database(msifile, spf_tables, sizeof(spf_tables) / sizeof(msi_table));
14561 
14562     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
14563 
14564     r = MsiInstallProductA(msifile, NULL);
14565     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14566     {
14567         skip("Not enough rights to perform tests\n");
14568         goto error;
14569     }
14570     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14571     attr = GetFileAttributesA(path);
14572     if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY))
14573     {
14574         ok(delete_pf("msitest\\added\\maximus", TRUE), "File not installed\n");
14575         ok(delete_pf("msitest\\added", FALSE), "Directory not created\n");
14576         ok(delete_pf("msitest", FALSE), "Directory not created\n");
14577     }
14578     else
14579     {
14580         trace("changing folder property not supported\n");
14581         ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
14582         ok(delete_pf("msitest", FALSE), "Directory not created\n");
14583     }
14584 
14585 error:
14586     DeleteFileA(msifile);
14587     DeleteFileA("msitest\\maximus");
14588     RemoveDirectoryA("msitest");
14589 }
14590 
14591 static void test_sourcedir_props(void)
14592 {
14593     UINT r;
14594 
14595     if (is_process_limited())
14596     {
14597         skip("process is limited\n");
14598         return;
14599     }
14600 
14601     create_test_files();
14602     create_file("msitest\\sourcedir.txt", "msitest\\sourcedir.txt", 1000);
14603     create_database(msifile, sd_tables, sizeof(sd_tables) / sizeof(msi_table));
14604 
14605     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
14606 
14607     /* full UI, no ResolveSource action */
14608     r = MsiInstallProductA(msifile, NULL);
14609     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14610 
14611     r = MsiInstallProductA(msifile, "REMOVE=ALL");
14612     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14613 
14614     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
14615     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
14616 
14617     /* full UI, ResolveSource action */
14618     r = MsiInstallProductA(msifile, "ResolveSource=1");
14619     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14620 
14621     r = MsiInstallProductA(msifile, "REMOVE=ALL");
14622     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14623 
14624     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
14625     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
14626 
14627     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
14628 
14629     /* no UI, no ResolveSource action */
14630     r = MsiInstallProductA(msifile, NULL);
14631     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14632 
14633     r = MsiInstallProductA(msifile, "REMOVE=ALL");
14634     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14635 
14636     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
14637     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
14638 
14639     /* no UI, ResolveSource action */
14640     r = MsiInstallProductA(msifile, "ResolveSource=1");
14641     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14642 
14643     r = MsiInstallProductA(msifile, "REMOVE=ALL");
14644     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14645 
14646     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
14647     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
14648 
14649     DeleteFileA("msitest\\sourcedir.txt");
14650     delete_test_files();
14651     DeleteFileA(msifile);
14652 }
14653 
14654 static void test_concurrentinstall(void)
14655 {
14656     UINT r;
14657     CHAR path[MAX_PATH];
14658 
14659     if (is_process_limited())
14660     {
14661         skip("process is limited\n");
14662         return;
14663     }
14664 
14665     CreateDirectoryA("msitest", NULL);
14666     CreateDirectoryA("msitest\\msitest", NULL);
14667     create_file("msitest\\maximus", "msitest\\maximus", 500);
14668     create_file("msitest\\msitest\\augustus", "msitest\\msitest\\augustus", 500);
14669 
14670     create_database(msifile, ci_tables, sizeof(ci_tables) / sizeof(msi_table));
14671 
14672     lstrcpyA(path, CURR_DIR);
14673     lstrcatA(path, "\\msitest\\concurrent.msi");
14674     create_database(path, ci2_tables, sizeof(ci2_tables) / sizeof(msi_table));
14675 
14676     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
14677 
14678     r = MsiInstallProductA(msifile, NULL);
14679     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14680     {
14681         skip("Not enough rights to perform tests\n");
14682         goto error;
14683     }
14684     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14685     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
14686     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
14687     ok(delete_pf("msitest", FALSE), "Directory not created\n");
14688 
14689     r = MsiConfigureProductA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", INSTALLLEVEL_DEFAULT,
14690                              INSTALLSTATE_ABSENT);
14691     ok(r == ERROR_SUCCESS, "got %u\n", r);
14692 
14693     r = MsiConfigureProductA("{FF4AFE9C-6AC2-44F9-A060-9EA6BD16C75E}", INSTALLLEVEL_DEFAULT,
14694                              INSTALLSTATE_ABSENT);
14695     ok(r == ERROR_SUCCESS, "got %u\n", r);
14696 
14697 error:
14698     DeleteFileA(path);
14699     DeleteFileA(msifile);
14700     DeleteFileA("msitest\\msitest\\augustus");
14701     DeleteFileA("msitest\\maximus");
14702     RemoveDirectoryA("msitest\\msitest");
14703     RemoveDirectoryA("msitest");
14704 }
14705 
14706 static void test_command_line_parsing(void)
14707 {
14708     UINT r;
14709     const char *cmd;
14710 
14711     if (is_process_limited())
14712     {
14713         skip("process is limited\n");
14714         return;
14715     }
14716 
14717     create_test_files();
14718     create_database(msifile, cl_tables, sizeof(cl_tables)/sizeof(msi_table));
14719 
14720     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
14721 
14722     cmd = " ";
14723     r = MsiInstallProductA(msifile, cmd);
14724     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14725 
14726     cmd = "=";
14727     r = MsiInstallProductA(msifile, cmd);
14728     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14729 
14730     cmd = "==";
14731     r = MsiInstallProductA(msifile, cmd);
14732     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14733 
14734     cmd = "one";
14735     r = MsiInstallProductA(msifile, cmd);
14736     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14737 
14738     cmd = "=one";
14739     r = MsiInstallProductA(msifile, cmd);
14740     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14741 
14742     cmd = "P=";
14743     r = MsiInstallProductA(msifile, cmd);
14744     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14745 
14746     cmd = "  P=";
14747     r = MsiInstallProductA(msifile, cmd);
14748     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14749 
14750     cmd = "P=  ";
14751     r = MsiInstallProductA(msifile, cmd);
14752     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14753 
14754     cmd = "P=\"";
14755     r = MsiInstallProductA(msifile, cmd);
14756     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14757 
14758     cmd = "P=\"\"";
14759     r = MsiInstallProductA(msifile, cmd);
14760     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14761 
14762     cmd = "P=\"\"\"";
14763     r = MsiInstallProductA(msifile, cmd);
14764     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14765 
14766     cmd = "P=\"\"\"\"";
14767     r = MsiInstallProductA(msifile, cmd);
14768     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14769 
14770     cmd = "P=\" ";
14771     r = MsiInstallProductA(msifile, cmd);
14772     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14773 
14774     cmd = "P= \"";
14775     r = MsiInstallProductA(msifile, cmd);
14776     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14777 
14778     cmd = "P= \"\" ";
14779     r = MsiInstallProductA(msifile, cmd);
14780     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14781 
14782     cmd = "P=\"  \"";
14783     r = MsiInstallProductA(msifile, cmd);
14784     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14785 
14786     cmd = "P=one";
14787     r = MsiInstallProductA(msifile, cmd);
14788     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14789 
14790     cmd = "P= one";
14791     r = MsiInstallProductA(msifile, cmd);
14792     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14793 
14794     cmd = "P=\"one";
14795     r = MsiInstallProductA(msifile, cmd);
14796     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14797 
14798     cmd = "P=one\"";
14799     r = MsiInstallProductA(msifile, cmd);
14800     todo_wine ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14801 
14802     cmd = "P=\"one\"";
14803     r = MsiInstallProductA(msifile, cmd);
14804     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14805 
14806     cmd = "P= \"one\" ";
14807     r = MsiInstallProductA(msifile, cmd);
14808     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14809 
14810     cmd = "P=\"one\"\"";
14811     r = MsiInstallProductA(msifile, cmd);
14812     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14813 
14814     cmd = "P=\"\"one\"";
14815     r = MsiInstallProductA(msifile, cmd);
14816     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14817 
14818     cmd = "P=\"\"one\"\"";
14819     r = MsiInstallProductA(msifile, cmd);
14820     todo_wine ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14821 
14822     cmd = "P=\"one two\"";
14823     r = MsiInstallProductA(msifile, cmd);
14824     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14825 
14826     cmd = "P=\"\"\"one\"\" two\"";
14827     r = MsiInstallProductA(msifile, cmd);
14828     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14829 
14830     cmd = "P=\"\"\"one\"\" two\" Q=three";
14831     r = MsiInstallProductA(msifile, cmd);
14832     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14833 
14834     cmd = "P=\"\" Q=\"two\"";
14835     r = MsiInstallProductA(msifile, cmd);
14836     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14837 
14838     cmd = "P=\"one\" Q=\"two\"";
14839     r = MsiInstallProductA(msifile, cmd);
14840     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14841 
14842     cmd = "P=\"one=two\"";
14843     r = MsiInstallProductA(msifile, cmd);
14844     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14845 
14846     cmd = "Q=\"\" P=\"one\"";
14847     r = MsiInstallProductA(msifile, cmd);
14848     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14849 
14850     cmd = "P=\"\"\"one\"\"\" Q=\"two\"";
14851     r = MsiInstallProductA(msifile, cmd);
14852     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14853 
14854     cmd = "P=\"one \"\"two\"\"\" Q=\"three\"";
14855     r = MsiInstallProductA(msifile, cmd);
14856     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14857 
14858     cmd = "P=\"\"\"one\"\" two\" Q=\"three\"";
14859     r = MsiInstallProductA(msifile, cmd);
14860     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14861 
14862     DeleteFileA(msifile);
14863     delete_test_files();
14864 }
14865 
14866 START_TEST(msi)
14867 {
14868     DWORD len;
14869     char temp_path[MAX_PATH], prev_path[MAX_PATH];
14870 
14871 #ifdef __REACTOS__
14872     if (!winetest_interactive &&
14873         !strcmp(winetest_platform, "windows"))
14874     {
14875         skip("ROSTESTS-180: Skipping msi_winetest:msi because it hangs on WHS-Testbot. Set winetest_interactive to run it anyway.\n");
14876         return;
14877     }
14878 #endif
14879 
14880     init_functionpointers();
14881 
14882     if (pIsWow64Process)
14883         pIsWow64Process(GetCurrentProcess(), &is_wow64);
14884 
14885     GetCurrentDirectoryA(MAX_PATH, prev_path);
14886     GetTempPathA(MAX_PATH, temp_path);
14887     SetCurrentDirectoryA(temp_path);
14888 
14889     lstrcpyA(CURR_DIR, temp_path);
14890     len = lstrlenA(CURR_DIR);
14891 
14892     if(len && (CURR_DIR[len - 1] == '\\'))
14893         CURR_DIR[len - 1] = 0;
14894 
14895     ok(get_system_dirs(), "failed to retrieve system dirs\n");
14896 
14897     test_usefeature();
14898     test_null();
14899     test_getcomponentpath();
14900     test_MsiGetFileHash();
14901     test_MsiSetInternalUI();
14902 
14903     if (!pConvertSidToStringSidA)
14904         win_skip("ConvertSidToStringSidA not implemented\n");
14905     else
14906     {
14907         /* These tests rely on get_user_sid that needs ConvertSidToStringSidA */
14908         test_MsiQueryProductState();
14909         test_MsiQueryFeatureState();
14910         test_MsiQueryComponentState();
14911         test_MsiGetComponentPath();
14912         test_MsiGetComponentPathEx();
14913         test_MsiProvideComponent();
14914         test_MsiGetProductCode();
14915         test_MsiEnumClients();
14916         test_MsiGetProductInfo();
14917         test_MsiGetProductInfoEx();
14918         test_MsiGetUserInfo();
14919         test_MsiOpenProduct();
14920         test_MsiEnumPatchesEx();
14921         test_MsiEnumPatches();
14922         test_MsiGetPatchInfoEx();
14923         test_MsiGetPatchInfo();
14924         test_MsiEnumProducts();
14925         test_MsiEnumProductsEx();
14926         test_MsiEnumComponents();
14927         test_MsiEnumComponentsEx();
14928     }
14929     test_MsiGetFileVersion();
14930     test_MsiGetFileSignatureInformation();
14931     test_MsiConfigureProductEx();
14932     test_MsiSetFeatureAttributes();
14933     test_MsiGetFeatureInfo();
14934     test_MsiSetExternalUI();
14935     test_lastusedsource();
14936     test_setpropertyfolder();
14937     test_sourcedir_props();
14938     if (pMsiGetComponentPathExA)
14939         test_concurrentinstall();
14940     test_command_line_parsing();
14941     test_MsiProvideQualifiedComponentEx();
14942 
14943     SetCurrentDirectoryA(prev_path);
14944 }
14945