xref: /reactos/modules/rostests/winetests/msi/msi.c (revision c2c66aff)
1 /*
2  * tests for Microsoft Installer functionality
3  *
4  * Copyright 2005 Mike McCormack for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #define _WIN32_MSI 300
22 #define COBJMACROS
23 
24 #include <stdio.h>
25 #include <windows.h>
26 #include <msi.h>
27 #include <msiquery.h>
28 #include <msidefs.h>
29 #include <sddl.h>
30 #include <fci.h>
31 
32 #include "wine/test.h"
33 
34 static BOOL is_wow64;
35 static const char msifile[] = "winetest.msi";
36 static const WCHAR msifileW[] = {'w','i','n','e','t','e','s','t','.','m','s','i',0};
37 static char CURR_DIR[MAX_PATH];
38 static char PROG_FILES_DIR[MAX_PATH];
39 static char PROG_FILES_DIR_NATIVE[MAX_PATH];
40 static char COMMON_FILES_DIR[MAX_PATH];
41 static char WINDOWS_DIR[MAX_PATH];
42 
43 static BOOL (WINAPI *pCheckTokenMembership)(HANDLE,PSID,PBOOL);
44 static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
45 static BOOL (WINAPI *pOpenProcessToken)( HANDLE, DWORD, PHANDLE );
46 static LONG (WINAPI *pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD);
47 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
48 
49 static INSTALLSTATE (WINAPI *pMsiGetComponentPathA)
50     (LPCSTR, LPCSTR, LPSTR, DWORD*);
51 static INSTALLSTATE (WINAPI *pMsiGetComponentPathExA)
52     (LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPSTR, LPDWORD);
53 static INSTALLSTATE (WINAPI *pMsiProvideComponentA)
54     (LPCSTR, LPCSTR, LPCSTR, DWORD, LPSTR, LPDWORD);
55 static INSTALLSTATE (WINAPI *pMsiProvideComponentW)
56     (LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPWSTR, LPDWORD);
57 static UINT (WINAPI *pMsiGetFileHashA)
58     (LPCSTR, DWORD, PMSIFILEHASHINFO);
59 static UINT (WINAPI *pMsiGetProductInfoExA)
60     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, LPSTR, LPDWORD);
61 static UINT (WINAPI *pMsiOpenPackageExA)
62     (LPCSTR, DWORD, MSIHANDLE*);
63 static UINT (WINAPI *pMsiOpenPackageExW)
64     (LPCWSTR, DWORD, MSIHANDLE*);
65 static UINT (WINAPI *pMsiEnumPatchesExA)
66     (LPCSTR, LPCSTR, DWORD, DWORD, DWORD, LPSTR, LPSTR,
67     MSIINSTALLCONTEXT*, LPSTR, LPDWORD);
68 static UINT (WINAPI *pMsiQueryComponentStateA)
69     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, INSTALLSTATE*);
70 static INSTALLSTATE (WINAPI *pMsiUseFeatureExA)
71     (LPCSTR, LPCSTR ,DWORD, DWORD);
72 static UINT (WINAPI *pMsiGetPatchInfoExA)
73     (LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, LPSTR, DWORD *);
74 static UINT (WINAPI *pMsiEnumProductsExA)
75     (LPCSTR, LPCSTR, DWORD, DWORD, CHAR[39], MSIINSTALLCONTEXT *, LPSTR, LPDWORD);
76 static UINT (WINAPI *pMsiEnumComponentsExA)
77     (LPCSTR, DWORD, DWORD, CHAR[39], MSIINSTALLCONTEXT *, LPSTR, LPDWORD);
78 static UINT (WINAPI *pMsiSetExternalUIRecord)
79     (INSTALLUI_HANDLER_RECORD, DWORD, LPVOID, PINSTALLUI_HANDLER_RECORD);
80 static UINT (WINAPI *pMsiSourceListGetInfoA)
81     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, LPSTR, LPDWORD);
82 
83 static void init_functionpointers(void)
84 {
85     HMODULE hmsi = GetModuleHandleA("msi.dll");
86     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
87     HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
88 
89 #define GET_PROC(dll, func) \
90     p ## func = (void *)GetProcAddress(dll, #func); \
91     if(!p ## func) \
92       trace("GetProcAddress(%s) failed\n", #func);
93 
94     GET_PROC(hmsi, MsiGetComponentPathA)
95     GET_PROC(hmsi, MsiGetComponentPathExA);
96     GET_PROC(hmsi, MsiProvideComponentA)
97     GET_PROC(hmsi, MsiProvideComponentW)
98     GET_PROC(hmsi, MsiGetFileHashA)
99     GET_PROC(hmsi, MsiGetProductInfoExA)
100     GET_PROC(hmsi, MsiOpenPackageExA)
101     GET_PROC(hmsi, MsiOpenPackageExW)
102     GET_PROC(hmsi, MsiEnumPatchesExA)
103     GET_PROC(hmsi, MsiQueryComponentStateA)
104     GET_PROC(hmsi, MsiSetExternalUIRecord)
105     GET_PROC(hmsi, MsiUseFeatureExA)
106     GET_PROC(hmsi, MsiGetPatchInfoExA)
107     GET_PROC(hmsi, MsiEnumProductsExA)
108     GET_PROC(hmsi, MsiEnumComponentsExA)
109     GET_PROC(hmsi, MsiSourceListGetInfoA)
110 
111     GET_PROC(hadvapi32, CheckTokenMembership);
112     GET_PROC(hadvapi32, ConvertSidToStringSidA)
113     GET_PROC(hadvapi32, OpenProcessToken);
114     GET_PROC(hadvapi32, RegDeleteKeyExA)
115     GET_PROC(hkernel32, IsWow64Process)
116 
117 #undef GET_PROC
118 }
119 
120 static BOOL get_system_dirs(void)
121 {
122     HKEY hkey;
123     DWORD type, size;
124 
125     if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", &hkey))
126         return FALSE;
127 
128     size = MAX_PATH;
129     if (RegQueryValueExA(hkey, "ProgramFilesDir (x86)", 0, &type, (LPBYTE)PROG_FILES_DIR, &size) &&
130         RegQueryValueExA(hkey, "ProgramFilesDir", 0, &type, (LPBYTE)PROG_FILES_DIR, &size))
131     {
132         RegCloseKey(hkey);
133         return FALSE;
134     }
135     size = MAX_PATH;
136     if (RegQueryValueExA(hkey, "CommonFilesDir (x86)", 0, &type, (LPBYTE)COMMON_FILES_DIR, &size) &&
137         RegQueryValueExA(hkey, "CommonFilesDir", 0, &type, (LPBYTE)COMMON_FILES_DIR, &size))
138     {
139         RegCloseKey(hkey);
140         return FALSE;
141     }
142     size = MAX_PATH;
143     if (RegQueryValueExA(hkey, "ProgramFilesDir", 0, &type, (LPBYTE)PROG_FILES_DIR_NATIVE, &size))
144     {
145         RegCloseKey(hkey);
146         return FALSE;
147     }
148     RegCloseKey(hkey);
149     if (!GetWindowsDirectoryA(WINDOWS_DIR, MAX_PATH)) return FALSE;
150     return TRUE;
151 }
152 
153 static BOOL file_exists(const char *file)
154 {
155     return GetFileAttributesA(file) != INVALID_FILE_ATTRIBUTES;
156 }
157 
158 static BOOL pf_exists(const char *file)
159 {
160     char path[MAX_PATH];
161 
162     lstrcpyA(path, PROG_FILES_DIR);
163     lstrcatA(path, "\\");
164     lstrcatA(path, file);
165     return file_exists(path);
166 }
167 
168 static BOOL delete_pf(const char *rel_path, BOOL is_file)
169 {
170     char path[MAX_PATH];
171 
172     lstrcpyA(path, PROG_FILES_DIR);
173     lstrcatA(path, "\\");
174     lstrcatA(path, rel_path);
175 
176     if (is_file)
177         return DeleteFileA(path);
178     else
179         return RemoveDirectoryA(path);
180 }
181 
182 static BOOL is_process_limited(void)
183 {
184     SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
185     PSID Group = NULL;
186     BOOL IsInGroup;
187     HANDLE token;
188 
189     if (!pCheckTokenMembership || !pOpenProcessToken) return FALSE;
190 
191     if (!AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
192                                   DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &Group) ||
193         !pCheckTokenMembership(NULL, Group, &IsInGroup))
194     {
195         trace("Could not check if the current user is an administrator\n");
196         FreeSid(Group);
197         return FALSE;
198     }
199     FreeSid(Group);
200 
201     if (!IsInGroup)
202     {
203         /* Only administrators have enough privileges for these tests */
204         return TRUE;
205     }
206 
207     if (pOpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
208     {
209         BOOL ret;
210         TOKEN_ELEVATION_TYPE type = TokenElevationTypeDefault;
211         DWORD size;
212 
213         ret = GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &size);
214         CloseHandle(token);
215         return (ret && type == TokenElevationTypeLimited);
216     }
217     return FALSE;
218 }
219 
220 /* cabinet definitions */
221 
222 /* make the max size large so there is only one cab file */
223 #define MEDIA_SIZE          0x7FFFFFFF
224 #define FOLDER_THRESHOLD    900000
225 
226 /* the FCI callbacks */
227 
228 static void * CDECL mem_alloc(ULONG cb)
229 {
230     return HeapAlloc(GetProcessHeap(), 0, cb);
231 }
232 
233 static void CDECL mem_free(void *memory)
234 {
235     HeapFree(GetProcessHeap(), 0, memory);
236 }
237 
238 static BOOL CDECL get_next_cabinet(PCCAB pccab, ULONG  cbPrevCab, void *pv)
239 {
240     sprintf(pccab->szCab, pv, pccab->iCab);
241     return TRUE;
242 }
243 
244 static LONG CDECL progress(UINT typeStatus, ULONG cb1, ULONG cb2, void *pv)
245 {
246     return 0;
247 }
248 
249 static int CDECL file_placed(PCCAB pccab, char *pszFile, LONG cbFile,
250                              BOOL fContinuation, void *pv)
251 {
252     return 0;
253 }
254 
255 static INT_PTR CDECL fci_open(char *pszFile, int oflag, int pmode, int *err, void *pv)
256 {
257     HANDLE handle;
258     DWORD dwAccess = 0;
259     DWORD dwShareMode = 0;
260     DWORD dwCreateDisposition = OPEN_EXISTING;
261 
262     dwAccess = GENERIC_READ | GENERIC_WRITE;
263     /* FILE_SHARE_DELETE is not supported by Windows Me/98/95 */
264     dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
265 
266     if (GetFileAttributesA(pszFile) != INVALID_FILE_ATTRIBUTES)
267         dwCreateDisposition = OPEN_EXISTING;
268     else
269         dwCreateDisposition = CREATE_NEW;
270 
271     handle = CreateFileA(pszFile, dwAccess, dwShareMode, NULL,
272                          dwCreateDisposition, 0, NULL);
273 
274     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszFile);
275 
276     return (INT_PTR)handle;
277 }
278 
279 static UINT CDECL fci_read(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
280 {
281     HANDLE handle = (HANDLE)hf;
282     DWORD dwRead;
283     BOOL res;
284 
285     res = ReadFile(handle, memory, cb, &dwRead, NULL);
286     ok(res, "Failed to ReadFile\n");
287 
288     return dwRead;
289 }
290 
291 static UINT CDECL fci_write(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
292 {
293     HANDLE handle = (HANDLE)hf;
294     DWORD dwWritten;
295     BOOL res;
296 
297     res = WriteFile(handle, memory, cb, &dwWritten, NULL);
298     ok(res, "Failed to WriteFile\n");
299 
300     return dwWritten;
301 }
302 
303 static int CDECL fci_close(INT_PTR hf, int *err, void *pv)
304 {
305     HANDLE handle = (HANDLE)hf;
306     ok(CloseHandle(handle), "Failed to CloseHandle\n");
307 
308     return 0;
309 }
310 
311 static LONG CDECL fci_seek(INT_PTR hf, LONG dist, int seektype, int *err, void *pv)
312 {
313     HANDLE handle = (HANDLE)hf;
314     DWORD ret;
315 
316     ret = SetFilePointer(handle, dist, NULL, seektype);
317     ok(ret != INVALID_SET_FILE_POINTER, "Failed to SetFilePointer\n");
318 
319     return ret;
320 }
321 
322 static int CDECL fci_delete(char *pszFile, int *err, void *pv)
323 {
324     BOOL ret = DeleteFileA(pszFile);
325     ok(ret, "Failed to DeleteFile %s\n", pszFile);
326 
327     return 0;
328 }
329 
330 static BOOL CDECL get_temp_file(char *pszTempName, int cbTempName, void *pv)
331 {
332     LPSTR tempname;
333 
334     tempname = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
335     GetTempFileNameA(".", "xx", 0, tempname);
336 
337     if (tempname && (strlen(tempname) < (unsigned)cbTempName))
338     {
339         lstrcpyA(pszTempName, tempname);
340         HeapFree(GetProcessHeap(), 0, tempname);
341         return TRUE;
342     }
343 
344     HeapFree(GetProcessHeap(), 0, tempname);
345 
346     return FALSE;
347 }
348 
349 static INT_PTR CDECL get_open_info(char *pszName, USHORT *pdate, USHORT *ptime,
350                                    USHORT *pattribs, int *err, void *pv)
351 {
352     BY_HANDLE_FILE_INFORMATION finfo;
353     FILETIME filetime;
354     HANDLE handle;
355     DWORD attrs;
356     BOOL res;
357 
358     handle = CreateFileA(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
359                          OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
360     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszName);
361 
362     res = GetFileInformationByHandle(handle, &finfo);
363     ok(res, "Expected GetFileInformationByHandle to succeed\n");
364 
365     FileTimeToLocalFileTime(&finfo.ftLastWriteTime, &filetime);
366     FileTimeToDosDateTime(&filetime, pdate, ptime);
367 
368     attrs = GetFileAttributesA(pszName);
369     ok(attrs != INVALID_FILE_ATTRIBUTES, "Failed to GetFileAttributes\n");
370 
371     return (INT_PTR)handle;
372 }
373 
374 static BOOL add_file(HFCI hfci, const char *file, TCOMP compress)
375 {
376     char path[MAX_PATH];
377     char filename[MAX_PATH];
378 
379     lstrcpyA(path, CURR_DIR);
380     lstrcatA(path, "\\");
381     lstrcatA(path, file);
382 
383     lstrcpyA(filename, file);
384 
385     return FCIAddFile(hfci, path, filename, FALSE, get_next_cabinet,
386                       progress, get_open_info, compress);
387 }
388 
389 static void set_cab_parameters(PCCAB pCabParams, const CHAR *name, DWORD max_size)
390 {
391     ZeroMemory(pCabParams, sizeof(CCAB));
392 
393     pCabParams->cb = max_size;
394     pCabParams->cbFolderThresh = FOLDER_THRESHOLD;
395     pCabParams->setID = 0xbeef;
396     pCabParams->iCab = 1;
397     lstrcpyA(pCabParams->szCabPath, CURR_DIR);
398     lstrcatA(pCabParams->szCabPath, "\\");
399     lstrcpyA(pCabParams->szCab, name);
400 }
401 
402 static void create_cab_file(const CHAR *name, DWORD max_size, const CHAR *files)
403 {
404     CCAB cabParams;
405     LPCSTR ptr;
406     HFCI hfci;
407     ERF erf;
408     BOOL res;
409 
410     set_cab_parameters(&cabParams, name, max_size);
411 
412     hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
413                       fci_read, fci_write, fci_close, fci_seek, fci_delete,
414                       get_temp_file, &cabParams, NULL);
415 
416     ok(hfci != NULL, "Failed to create an FCI context\n");
417 
418     ptr = files;
419     while (*ptr)
420     {
421         res = add_file(hfci, ptr, tcompTYPE_MSZIP);
422         ok(res, "Failed to add file: %s\n", ptr);
423         ptr += lstrlenA(ptr) + 1;
424     }
425 
426     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
427     ok(res, "Failed to flush the cabinet\n");
428 
429     res = FCIDestroy(hfci);
430     ok(res, "Failed to destroy the cabinet\n");
431 }
432 
433 static BOOL add_cabinet_storage(LPCSTR db, LPCSTR cabinet)
434 {
435     WCHAR dbW[MAX_PATH], cabinetW[MAX_PATH];
436     IStorage *stg;
437     IStream *stm;
438     HRESULT hr;
439     HANDLE handle;
440 
441     MultiByteToWideChar(CP_ACP, 0, db, -1, dbW, MAX_PATH);
442     hr = StgOpenStorage(dbW, NULL, STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
443     if (FAILED(hr))
444         return FALSE;
445 
446     MultiByteToWideChar(CP_ACP, 0, cabinet, -1, cabinetW, MAX_PATH);
447     hr = IStorage_CreateStream(stg, cabinetW, STGM_WRITE|STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
448     if (FAILED(hr))
449     {
450         IStorage_Release(stg);
451         return FALSE;
452     }
453 
454     handle = CreateFileW(cabinetW, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
455     if (handle != INVALID_HANDLE_VALUE)
456     {
457         DWORD count;
458         char buffer[1024];
459         if (ReadFile(handle, buffer, sizeof(buffer), &count, NULL))
460             IStream_Write(stm, buffer, count, &count);
461         CloseHandle(handle);
462     }
463 
464     IStream_Release(stm);
465     IStorage_Release(stg);
466 
467     return TRUE;
468 }
469 
470 static void delete_cab_files(void)
471 {
472     SHFILEOPSTRUCTA shfl;
473     CHAR path[MAX_PATH+10];
474 
475     lstrcpyA(path, CURR_DIR);
476     lstrcatA(path, "\\*.cab");
477     path[strlen(path) + 1] = '\0';
478 
479     shfl.hwnd = NULL;
480     shfl.wFunc = FO_DELETE;
481     shfl.pFrom = path;
482     shfl.pTo = NULL;
483     shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
484 
485     SHFileOperationA(&shfl);
486 }
487 
488 /* msi database data */
489 
490 static const char directory_dat[] =
491     "Directory\tDirectory_Parent\tDefaultDir\n"
492     "s72\tS72\tl255\n"
493     "Directory\tDirectory\n"
494     "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
495     "ProgramFilesFolder\tTARGETDIR\t.\n"
496     "TARGETDIR\t\tSourceDir";
497 
498 static const char component_dat[] =
499     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
500     "s72\tS38\ts72\ti2\tS255\tS72\n"
501     "Component\tComponent\n"
502     "One\t{8F5BAEEF-DD92-40AC-9397-BE3CF9F97C81}\tMSITESTDIR\t2\tNOT REINSTALL\tone.txt\n";
503 
504 static const char feature_dat[] =
505     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
506     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
507     "Feature\tFeature\n"
508     "One\t\tOne\tOne\t1\t3\tMSITESTDIR\t0\n"
509     "Two\t\t\t\t2\t1\tTARGETDIR\t0\n";
510 
511 static const char feature_comp_dat[] =
512     "Feature_\tComponent_\n"
513     "s38\ts72\n"
514     "FeatureComponents\tFeature_\tComponent_\n"
515     "One\tOne\n";
516 
517 static const char file_dat[] =
518     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
519     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
520     "File\tFile\n"
521     "one.txt\tOne\tone.txt\t1000\t\t\t0\t1\n";
522 
523 static const char install_exec_seq_dat[] =
524     "Action\tCondition\tSequence\n"
525     "s72\tS255\tI2\n"
526     "InstallExecuteSequence\tAction\n"
527     "ValidateProductID\t\t700\n"
528     "CostInitialize\t\t800\n"
529     "FileCost\t\t900\n"
530     "CostFinalize\t\t1000\n"
531     "InstallValidate\t\t1400\n"
532     "InstallInitialize\t\t1500\n"
533     "ProcessComponents\t\t1600\n"
534     "UnpublishFeatures\t\t1800\n"
535     "RemoveFiles\t\t3500\n"
536     "InstallFiles\t\t4000\n"
537     "RegisterProduct\t\t6100\n"
538     "PublishFeatures\t\t6300\n"
539     "PublishProduct\t\t6400\n"
540     "InstallFinalize\t\t6600";
541 
542 static const char media_dat[] =
543     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
544     "i2\ti4\tL64\tS255\tS32\tS72\n"
545     "Media\tDiskId\n"
546     "1\t1\t\t\tDISK1\t\n";
547 
548 static const char property_dat[] =
549     "Property\tValue\n"
550     "s72\tl0\n"
551     "Property\tProperty\n"
552     "INSTALLLEVEL\t3\n"
553     "Manufacturer\tWine\n"
554     "ProductCode\t{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}\n"
555     "ProductName\tMSITEST\n"
556     "ProductVersion\t1.1.1\n"
557     "UpgradeCode\t{9574448F-9B86-4E07-B6F6-8D199DA12127}\n"
558     "MSIFASTINSTALL\t1\n";
559 
560 static const char ci2_property_dat[] =
561     "Property\tValue\n"
562     "s72\tl0\n"
563     "Property\tProperty\n"
564     "INSTALLLEVEL\t3\n"
565     "Manufacturer\tWine\n"
566     "ProductCode\t{FF4AFE9C-6AC2-44F9-A060-9EA6BD16C75E}\n"
567     "ProductName\tMSITEST2\n"
568     "ProductVersion\t1.1.1\n"
569     "UpgradeCode\t{6B60C3CA-B8CA-4FB7-A395-092D98FF5D2A}\n"
570     "MSIFASTINSTALL\t1\n";
571 
572 static const char mcp_component_dat[] =
573     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
574     "s72\tS38\ts72\ti2\tS255\tS72\n"
575     "Component\tComponent\n"
576     "hydrogen\t{C844BD1E-1907-4C00-8BC9-150BD70DF0A1}\tMSITESTDIR\t2\t\thydrogen\n"
577     "helium\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t2\t\thelium\n"
578     "lithium\t{4AF28FFC-71C7-4307-BDE4-B77C5338F56F}\tMSITESTDIR\t2\tPROPVAR=42\tlithium\n";
579 
580 static const char mcp_feature_dat[] =
581     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
582     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
583     "Feature\tFeature\n"
584     "hydroxyl\t\thydroxyl\thydroxyl\t2\t1\tTARGETDIR\t0\n"
585     "heliox\t\theliox\theliox\t2\t5\tTARGETDIR\t0\n"
586     "lithia\t\tlithia\tlithia\t2\t10\tTARGETDIR\t0";
587 
588 static const char mcp_feature_comp_dat[] =
589     "Feature_\tComponent_\n"
590     "s38\ts72\n"
591     "FeatureComponents\tFeature_\tComponent_\n"
592     "hydroxyl\thydrogen\n"
593     "heliox\thelium\n"
594     "lithia\tlithium";
595 
596 static const char mcp_file_dat[] =
597     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
598     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
599     "File\tFile\n"
600     "hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n"
601     "helium\thelium\thelium\t0\t\t\t8192\t1\n"
602     "lithium\tlithium\tlithium\t0\t\t\t8192\t1";
603 
604 static const char lus_component_dat[] =
605     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
606     "s72\tS38\ts72\ti2\tS255\tS72\n"
607     "Component\tComponent\n"
608     "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
609 
610 static const char lus_feature_dat[] =
611     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
612     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
613     "Feature\tFeature\n"
614     "feature\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0\n"
615     "montecristo\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0";
616 
617 static const char lus_file_dat[] =
618     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
619     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
620     "File\tFile\n"
621     "maximus\tmaximus\tmaximus\t500\t\t\t8192\t1";
622 
623 static const char lus_feature_comp_dat[] =
624     "Feature_\tComponent_\n"
625     "s38\ts72\n"
626     "FeatureComponents\tFeature_\tComponent_\n"
627     "feature\tmaximus\n"
628     "montecristo\tmaximus";
629 
630 static const char lus_install_exec_seq_dat[] =
631     "Action\tCondition\tSequence\n"
632     "s72\tS255\tI2\n"
633     "InstallExecuteSequence\tAction\n"
634     "ValidateProductID\t\t700\n"
635     "CostInitialize\t\t800\n"
636     "FileCost\t\t900\n"
637     "CostFinalize\t\t1000\n"
638     "InstallValidate\t\t1400\n"
639     "InstallInitialize\t\t1500\n"
640     "ProcessComponents\tPROCESS_COMPONENTS=1 Or FULL=1\t1600\n"
641     "UnpublishFeatures\tUNPUBLISH_FEATURES=1 Or FULL=1\t1800\n"
642     "RemoveFiles\t\t3500\n"
643     "InstallFiles\t\t4000\n"
644     "RegisterUser\tREGISTER_USER=1 Or FULL=1\t6000\n"
645     "RegisterProduct\tREGISTER_PRODUCT=1 Or FULL=1\t6100\n"
646     "PublishFeatures\tPUBLISH_FEATURES=1 Or FULL=1\t6300\n"
647     "PublishProduct\tPUBLISH_PRODUCT=1 Or FULL=1\t6400\n"
648     "InstallFinalize\t\t6600";
649 
650 static const char lus0_media_dat[] =
651     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
652     "i2\ti4\tL64\tS255\tS32\tS72\n"
653     "Media\tDiskId\n"
654     "1\t1\t\t\tDISK1\t\n";
655 
656 static const char lus1_media_dat[] =
657     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
658     "i2\ti4\tL64\tS255\tS32\tS72\n"
659     "Media\tDiskId\n"
660     "1\t1\t\ttest1.cab\tDISK1\t\n";
661 
662 static const char lus2_media_dat[] =
663     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
664     "i2\ti4\tL64\tS255\tS32\tS72\n"
665     "Media\tDiskId\n"
666     "1\t1\t\t#test1.cab\tDISK1\t\n";
667 
668 static const char spf_custom_action_dat[] =
669     "Action\tType\tSource\tTarget\tISComments\n"
670     "s72\ti2\tS64\tS0\tS255\n"
671     "CustomAction\tAction\n"
672     "SetFolderProp\t51\tMSITESTDIR\t[ProgramFilesFolder]\\msitest\\added\t\n";
673 
674 static const char spf_install_exec_seq_dat[] =
675     "Action\tCondition\tSequence\n"
676     "s72\tS255\tI2\n"
677     "InstallExecuteSequence\tAction\n"
678     "CostFinalize\t\t1000\n"
679     "CostInitialize\t\t800\n"
680     "FileCost\t\t900\n"
681     "SetFolderProp\t\t950\n"
682     "InstallFiles\t\t4000\n"
683     "InstallServices\t\t5000\n"
684     "InstallFinalize\t\t6600\n"
685     "InstallInitialize\t\t1500\n"
686     "InstallValidate\t\t1400\n"
687     "LaunchConditions\t\t100";
688 
689 static const char spf_install_ui_seq_dat[] =
690     "Action\tCondition\tSequence\n"
691     "s72\tS255\tI2\n"
692     "InstallUISequence\tAction\n"
693     "CostInitialize\t\t800\n"
694     "FileCost\t\t900\n"
695     "CostFinalize\t\t1000\n"
696     "ExecuteAction\t\t1100\n";
697 
698 static const char sd_file_dat[] =
699     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
700     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
701     "File\tFile\n"
702     "sourcedir.txt\tsourcedir\tsourcedir.txt\t1000\t\t\t8192\t1\n";
703 
704 static const char sd_feature_dat[] =
705     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
706     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
707     "Feature\tFeature\n"
708     "sourcedir\t\t\tsourcedir feature\t1\t2\tMSITESTDIR\t0\n";
709 
710 static const char sd_feature_comp_dat[] =
711     "Feature_\tComponent_\n"
712     "s38\ts72\n"
713     "FeatureComponents\tFeature_\tComponent_\n"
714     "sourcedir\tsourcedir\n";
715 
716 static const char sd_component_dat[] =
717     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
718     "s72\tS38\ts72\ti2\tS255\tS72\n"
719     "Component\tComponent\n"
720     "sourcedir\t{DD422F92-3ED8-49B5-A0B7-F266F98357DF}\tMSITESTDIR\t0\t\tsourcedir.txt\n";
721 
722 static const char sd_install_ui_seq_dat[] =
723     "Action\tCondition\tSequence\n"
724     "s72\tS255\tI2\n"
725     "InstallUISequence\tAction\n"
726     "TestSourceDirProp1\tnot SourceDir and not SOURCEDIR and not Installed\t99\n"
727     "AppSearch\t\t100\n"
728     "TestSourceDirProp2\tnot SourceDir and not SOURCEDIR and not Installed\t101\n"
729     "LaunchConditions\tnot Installed \t110\n"
730     "TestSourceDirProp3\tnot SourceDir and not SOURCEDIR and not Installed\t111\n"
731     "FindRelatedProducts\t\t120\n"
732     "TestSourceDirProp4\tnot SourceDir and not SOURCEDIR and not Installed\t121\n"
733     "CCPSearch\t\t130\n"
734     "TestSourceDirProp5\tnot SourceDir and not SOURCEDIR and not Installed\t131\n"
735     "RMCCPSearch\t\t140\n"
736     "TestSourceDirProp6\tnot SourceDir and not SOURCEDIR and not Installed\t141\n"
737     "ValidateProductID\t\t150\n"
738     "TestSourceDirProp7\tnot SourceDir and not SOURCEDIR and not Installed\t151\n"
739     "CostInitialize\t\t800\n"
740     "TestSourceDirProp8\tnot SourceDir and not SOURCEDIR and not Installed\t801\n"
741     "FileCost\t\t900\n"
742     "TestSourceDirProp9\tnot SourceDir and not SOURCEDIR and not Installed\t901\n"
743     "IsolateComponents\t\t1000\n"
744     "TestSourceDirProp10\tnot SourceDir and not SOURCEDIR and not Installed\t1001\n"
745     "CostFinalize\t\t1100\n"
746     "TestSourceDirProp11\tnot SourceDir and not SOURCEDIR and not Installed\t1101\n"
747     "MigrateFeatureStates\t\t1200\n"
748     "TestSourceDirProp12\tnot SourceDir and not SOURCEDIR and not Installed\t1201\n"
749     "ExecuteAction\t\t1300\n"
750     "TestSourceDirProp13\tnot SourceDir and not SOURCEDIR and not Installed\t1301\n";
751 
752 static const char sd_install_exec_seq_dat[] =
753     "Action\tCondition\tSequence\n"
754     "s72\tS255\tI2\n"
755     "InstallExecuteSequence\tAction\n"
756     "TestSourceDirProp14\tSourceDir and SOURCEDIR and not Installed\t99\n"
757     "LaunchConditions\t\t100\n"
758     "TestSourceDirProp15\tSourceDir and SOURCEDIR and not Installed\t101\n"
759     "ValidateProductID\t\t700\n"
760     "TestSourceDirProp16\tSourceDir and SOURCEDIR and not Installed\t701\n"
761     "CostInitialize\t\t800\n"
762     "TestSourceDirProp17\tSourceDir and SOURCEDIR and not Installed\t801\n"
763     "ResolveSource\tResolveSource and not Installed\t850\n"
764     "TestSourceDirProp18\tResolveSource and not SourceDir and not SOURCEDIR and not Installed\t851\n"
765     "TestSourceDirProp19\tnot ResolveSource and SourceDir and SOURCEDIR and not Installed\t852\n"
766     "FileCost\t\t900\n"
767     "TestSourceDirProp20\tSourceDir and SOURCEDIR and not Installed\t901\n"
768     "IsolateComponents\t\t1000\n"
769     "TestSourceDirProp21\tSourceDir and SOURCEDIR and not Installed\t1001\n"
770     "CostFinalize\t\t1100\n"
771     "TestSourceDirProp22\tSourceDir and SOURCEDIR and not Installed\t1101\n"
772     "MigrateFeatureStates\t\t1200\n"
773     "TestSourceDirProp23\tSourceDir and SOURCEDIR and not Installed\t1201\n"
774     "InstallValidate\t\t1400\n"
775     "TestSourceDirProp24\tSourceDir and SOURCEDIR and not Installed\t1401\n"
776     "InstallInitialize\t\t1500\n"
777     "TestSourceDirProp25\tSourceDir and SOURCEDIR and not Installed\t1501\n"
778     "ProcessComponents\t\t1600\n"
779     "TestSourceDirProp26\tnot SourceDir and not SOURCEDIR and not Installed\t1601\n"
780     "UnpublishFeatures\t\t1800\n"
781     "TestSourceDirProp27\tnot SourceDir and not SOURCEDIR and not Installed\t1801\n"
782     "RemoveFiles\t\t3500\n"
783     "TestSourceDirProp28\tnot SourceDir and not SOURCEDIR and not Installed\t3501\n"
784     "InstallFiles\t\t4000\n"
785     "TestSourceDirProp29\tnot SourceDir and not SOURCEDIR and not Installed\t4001\n"
786     "RegisterUser\t\t6000\n"
787     "TestSourceDirProp30\tnot SourceDir and not SOURCEDIR and not Installed\t6001\n"
788     "RegisterProduct\t\t6100\n"
789     "TestSourceDirProp31\tnot SourceDir and not SOURCEDIR and not Installed\t6101\n"
790     "PublishFeatures\t\t6300\n"
791     "TestSourceDirProp32\tnot SourceDir and not SOURCEDIR and not Installed\t6301\n"
792     "PublishProduct\t\t6400\n"
793     "TestSourceDirProp33\tnot SourceDir and not SOURCEDIR and not Installed\t6401\n"
794     "InstallExecute\t\t6500\n"
795     "TestSourceDirProp34\tnot SourceDir and not SOURCEDIR and not Installed\t6501\n"
796     "InstallFinalize\t\t6600\n"
797     "TestSourceDirProp35\tnot SourceDir and not SOURCEDIR and not Installed\t6601\n";
798 
799 static const char sd_custom_action_dat[] =
800     "Action\tType\tSource\tTarget\tISComments\n"
801     "s72\ti2\tS64\tS0\tS255\n"
802     "CustomAction\tAction\n"
803     "TestSourceDirProp1\t19\t\tTest 1 failed\t\n"
804     "TestSourceDirProp2\t19\t\tTest 2 failed\t\n"
805     "TestSourceDirProp3\t19\t\tTest 3 failed\t\n"
806     "TestSourceDirProp4\t19\t\tTest 4 failed\t\n"
807     "TestSourceDirProp5\t19\t\tTest 5 failed\t\n"
808     "TestSourceDirProp6\t19\t\tTest 6 failed\t\n"
809     "TestSourceDirProp7\t19\t\tTest 7 failed\t\n"
810     "TestSourceDirProp8\t19\t\tTest 8 failed\t\n"
811     "TestSourceDirProp9\t19\t\tTest 9 failed\t\n"
812     "TestSourceDirProp10\t19\t\tTest 10 failed\t\n"
813     "TestSourceDirProp11\t19\t\tTest 11 failed\t\n"
814     "TestSourceDirProp12\t19\t\tTest 12 failed\t\n"
815     "TestSourceDirProp13\t19\t\tTest 13 failed\t\n"
816     "TestSourceDirProp14\t19\t\tTest 14 failed\t\n"
817     "TestSourceDirProp15\t19\t\tTest 15 failed\t\n"
818     "TestSourceDirProp16\t19\t\tTest 16 failed\t\n"
819     "TestSourceDirProp17\t19\t\tTest 17 failed\t\n"
820     "TestSourceDirProp18\t19\t\tTest 18 failed\t\n"
821     "TestSourceDirProp19\t19\t\tTest 19 failed\t\n"
822     "TestSourceDirProp20\t19\t\tTest 20 failed\t\n"
823     "TestSourceDirProp21\t19\t\tTest 21 failed\t\n"
824     "TestSourceDirProp22\t19\t\tTest 22 failed\t\n"
825     "TestSourceDirProp23\t19\t\tTest 23 failed\t\n"
826     "TestSourceDirProp24\t19\t\tTest 24 failed\t\n"
827     "TestSourceDirProp25\t19\t\tTest 25 failed\t\n"
828     "TestSourceDirProp26\t19\t\tTest 26 failed\t\n"
829     "TestSourceDirProp27\t19\t\tTest 27 failed\t\n"
830     "TestSourceDirProp28\t19\t\tTest 28 failed\t\n"
831     "TestSourceDirProp29\t19\t\tTest 29 failed\t\n"
832     "TestSourceDirProp30\t19\t\tTest 30 failed\t\n"
833     "TestSourceDirProp31\t19\t\tTest 31 failed\t\n"
834     "TestSourceDirProp32\t19\t\tTest 32 failed\t\n"
835     "TestSourceDirProp33\t19\t\tTest 33 failed\t\n"
836     "TestSourceDirProp34\t19\t\tTest 34 failed\t\n"
837     "TestSourceDirProp35\t19\t\tTest 35 failed\t\n";
838 
839 static const char ci_install_exec_seq_dat[] =
840     "Action\tCondition\tSequence\n"
841     "s72\tS255\tI2\n"
842     "InstallExecuteSequence\tAction\n"
843     "CostInitialize\t\t800\n"
844     "FileCost\t\t900\n"
845     "CostFinalize\t\t1000\n"
846     "InstallValidate\t\t1400\n"
847     "InstallInitialize\t\t1500\n"
848     "RunInstall\tnot Installed\t1550\n"
849     "ProcessComponents\t\t1600\n"
850     "UnpublishFeatures\t\t1800\n"
851     "RemoveFiles\t\t3500\n"
852     "InstallFiles\t\t4000\n"
853     "RegisterProduct\t\t6100\n"
854     "PublishFeatures\t\t6300\n"
855     "PublishProduct\t\t6400\n"
856     "InstallFinalize\t\t6600\n";
857 
858 static const char ci_custom_action_dat[] =
859     "Action\tType\tSource\tTarget\tISComments\n"
860     "s72\ti2\tS64\tS0\tS255\n"
861     "CustomAction\tAction\n"
862     "RunInstall\t23\tmsitest\\concurrent.msi\tMYPROP=[UILevel]\t\n";
863 
864 static const char ci_component_dat[] =
865     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
866     "s72\tS38\ts72\ti2\tS255\tS72\n"
867     "Component\tComponent\n"
868     "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
869 
870 static const char ci2_component_dat[] =
871     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
872     "s72\tS38\ts72\ti2\tS255\tS72\n"
873     "Component\tComponent\n"
874     "augustus\t\tMSITESTDIR\t0\tUILevel=3 AND MYPROP=5\taugustus\n";
875 
876 static const char ci2_feature_comp_dat[] =
877     "Feature_\tComponent_\n"
878     "s38\ts72\n"
879     "FeatureComponents\tFeature_\tComponent_\n"
880     "feature\taugustus";
881 
882 static const char ci2_file_dat[] =
883     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
884     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
885     "File\tFile\n"
886     "augustus\taugustus\taugustus\t500\t\t\t8192\t1";
887 
888 static const char cl_custom_action_dat[] =
889     "Action\tType\tSource\tTarget\tISComments\n"
890     "s72\ti2\tS64\tS0\tS255\n"
891     "CustomAction\tAction\n"
892     "TestCommandlineProp\t19\t\tTest1\t\n";
893 
894 static const char cl_install_exec_seq_dat[] =
895     "Action\tCondition\tSequence\n"
896     "s72\tS255\tI2\n"
897     "InstallExecuteSequence\tAction\n"
898     "LaunchConditions\t\t100\n"
899     "ValidateProductID\t\t700\n"
900     "CostInitialize\t\t800\n"
901     "FileCost\t\t900\n"
902     "CostFinalize\t\t1000\n"
903     "TestCommandlineProp\tP=\"one\"\t1100\n"
904     "InstallInitialize\t\t1500\n"
905     "ProcessComponents\t\t1600\n"
906     "InstallValidate\t\t1400\n"
907     "InstallFinalize\t\t5000\n";
908 
909 typedef struct _msi_table
910 {
911     const CHAR *filename;
912     const CHAR *data;
913     int size;
914 } msi_table;
915 
916 #define ADD_TABLE(x) {#x".idt", x##_dat, sizeof(x##_dat)}
917 
918 static const msi_table tables[] =
919 {
920     ADD_TABLE(directory),
921     ADD_TABLE(component),
922     ADD_TABLE(feature),
923     ADD_TABLE(feature_comp),
924     ADD_TABLE(file),
925     ADD_TABLE(install_exec_seq),
926     ADD_TABLE(media),
927     ADD_TABLE(property),
928 };
929 
930 static const msi_table mcp_tables[] =
931 {
932     ADD_TABLE(directory),
933     ADD_TABLE(mcp_component),
934     ADD_TABLE(mcp_feature),
935     ADD_TABLE(mcp_feature_comp),
936     ADD_TABLE(mcp_file),
937     ADD_TABLE(install_exec_seq),
938     ADD_TABLE(media),
939     ADD_TABLE(property)
940 };
941 
942 static const msi_table lus0_tables[] =
943 {
944     ADD_TABLE(lus_component),
945     ADD_TABLE(directory),
946     ADD_TABLE(lus_feature),
947     ADD_TABLE(lus_feature_comp),
948     ADD_TABLE(lus_file),
949     ADD_TABLE(lus_install_exec_seq),
950     ADD_TABLE(lus0_media),
951     ADD_TABLE(property)
952 };
953 
954 static const msi_table lus1_tables[] =
955 {
956     ADD_TABLE(lus_component),
957     ADD_TABLE(directory),
958     ADD_TABLE(lus_feature),
959     ADD_TABLE(lus_feature_comp),
960     ADD_TABLE(lus_file),
961     ADD_TABLE(lus_install_exec_seq),
962     ADD_TABLE(lus1_media),
963     ADD_TABLE(property)
964 };
965 
966 static const msi_table lus2_tables[] =
967 {
968     ADD_TABLE(lus_component),
969     ADD_TABLE(directory),
970     ADD_TABLE(lus_feature),
971     ADD_TABLE(lus_feature_comp),
972     ADD_TABLE(lus_file),
973     ADD_TABLE(lus_install_exec_seq),
974     ADD_TABLE(lus2_media),
975     ADD_TABLE(property)
976 };
977 
978 static const msi_table spf_tables[] =
979 {
980     ADD_TABLE(lus_component),
981     ADD_TABLE(directory),
982     ADD_TABLE(lus_feature),
983     ADD_TABLE(lus_feature_comp),
984     ADD_TABLE(lus_file),
985     ADD_TABLE(lus0_media),
986     ADD_TABLE(property),
987     ADD_TABLE(spf_custom_action),
988     ADD_TABLE(spf_install_exec_seq),
989     ADD_TABLE(spf_install_ui_seq)
990 };
991 
992 static const msi_table sd_tables[] =
993 {
994     ADD_TABLE(directory),
995     ADD_TABLE(sd_component),
996     ADD_TABLE(sd_feature),
997     ADD_TABLE(sd_feature_comp),
998     ADD_TABLE(sd_file),
999     ADD_TABLE(sd_install_exec_seq),
1000     ADD_TABLE(sd_install_ui_seq),
1001     ADD_TABLE(sd_custom_action),
1002     ADD_TABLE(media),
1003     ADD_TABLE(property)
1004 };
1005 
1006 static const msi_table ci_tables[] =
1007 {
1008     ADD_TABLE(ci_component),
1009     ADD_TABLE(directory),
1010     ADD_TABLE(lus_feature),
1011     ADD_TABLE(lus_feature_comp),
1012     ADD_TABLE(lus_file),
1013     ADD_TABLE(ci_install_exec_seq),
1014     ADD_TABLE(lus0_media),
1015     ADD_TABLE(property),
1016     ADD_TABLE(ci_custom_action),
1017 };
1018 
1019 static const msi_table ci2_tables[] =
1020 {
1021     ADD_TABLE(ci2_component),
1022     ADD_TABLE(directory),
1023     ADD_TABLE(lus_feature),
1024     ADD_TABLE(ci2_feature_comp),
1025     ADD_TABLE(ci2_file),
1026     ADD_TABLE(install_exec_seq),
1027     ADD_TABLE(lus0_media),
1028     ADD_TABLE(ci2_property),
1029 };
1030 
1031 static const msi_table cl_tables[] =
1032 {
1033     ADD_TABLE(component),
1034     ADD_TABLE(directory),
1035     ADD_TABLE(feature),
1036     ADD_TABLE(feature_comp),
1037     ADD_TABLE(file),
1038     ADD_TABLE(cl_custom_action),
1039     ADD_TABLE(cl_install_exec_seq),
1040     ADD_TABLE(media),
1041     ADD_TABLE(property)
1042 };
1043 
1044 static void write_file(const CHAR *filename, const char *data, int data_size)
1045 {
1046     DWORD size;
1047 
1048     HANDLE hf = CreateFileA(filename, GENERIC_WRITE, 0, NULL,
1049                             CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1050     WriteFile(hf, data, data_size, &size, NULL);
1051     CloseHandle(hf);
1052 }
1053 
1054 static void write_msi_summary_info(MSIHANDLE db, INT version, INT wordcount, const char *template)
1055 {
1056     MSIHANDLE summary;
1057     UINT r;
1058 
1059     r = MsiGetSummaryInformationA(db, NULL, 5, &summary);
1060     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1061 
1062     r = MsiSummaryInfoSetPropertyA(summary, PID_TEMPLATE, VT_LPSTR, 0, NULL, template);
1063     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1064 
1065     r = MsiSummaryInfoSetPropertyA(summary, PID_REVNUMBER, VT_LPSTR, 0, NULL,
1066                                    "{004757CA-5092-49C2-AD20-28E1CE0DF5F2}");
1067     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1068 
1069     r = MsiSummaryInfoSetPropertyA(summary, PID_PAGECOUNT, VT_I4, version, NULL, NULL);
1070     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1071 
1072     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, wordcount, NULL, NULL);
1073     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1074 
1075     r = MsiSummaryInfoSetPropertyA(summary, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
1076     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1077 
1078     /* write the summary changes back to the stream */
1079     r = MsiSummaryInfoPersist(summary);
1080     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1081 
1082     MsiCloseHandle(summary);
1083 }
1084 
1085 #define create_database(name, tables, num_tables) \
1086     create_database_wordcount(name, tables, num_tables, 100, 0, ";1033");
1087 
1088 #define create_database_template(name, tables, num_tables, version, template) \
1089     create_database_wordcount(name, tables, num_tables, version, 0, template);
1090 
1091 static void create_database_wordcount(const CHAR *name, const msi_table *tables,
1092                                       int num_tables, INT version, INT wordcount,
1093                                       const char *template)
1094 {
1095     MSIHANDLE db;
1096     UINT r;
1097     WCHAR *nameW;
1098     int j, len;
1099 
1100     len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 );
1101     if (!(nameW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return;
1102     MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, len );
1103 
1104     r = MsiOpenDatabaseW(nameW, MSIDBOPEN_CREATE, &db);
1105     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1106 
1107     /* import the tables into the database */
1108     for (j = 0; j < num_tables; j++)
1109     {
1110         const msi_table *table = &tables[j];
1111 
1112         write_file(table->filename, table->data, (table->size - 1) * sizeof(char));
1113 
1114         r = MsiDatabaseImportA(db, CURR_DIR, table->filename);
1115         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1116 
1117         DeleteFileA(table->filename);
1118     }
1119 
1120     write_msi_summary_info(db, version, wordcount, template);
1121 
1122     r = MsiDatabaseCommit(db);
1123     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1124 
1125     MsiCloseHandle(db);
1126     HeapFree( GetProcessHeap(), 0, nameW );
1127 }
1128 
1129 static UINT run_query(MSIHANDLE hdb, const char *query)
1130 {
1131     MSIHANDLE hview = 0;
1132     UINT r;
1133 
1134     r = MsiDatabaseOpenViewA(hdb, query, &hview);
1135     if (r != ERROR_SUCCESS)
1136         return r;
1137 
1138     r = MsiViewExecute(hview, 0);
1139     if (r == ERROR_SUCCESS)
1140         r = MsiViewClose(hview);
1141     MsiCloseHandle(hview);
1142     return r;
1143 }
1144 
1145 static UINT set_summary_info(MSIHANDLE hdb, LPSTR prodcode)
1146 {
1147     UINT res;
1148     MSIHANDLE suminfo;
1149 
1150     /* build summary info */
1151     res = MsiGetSummaryInformationA(hdb, NULL, 7, &suminfo);
1152     ok(res == ERROR_SUCCESS, "Failed to open summaryinfo\n");
1153 
1154     res = MsiSummaryInfoSetPropertyA(suminfo, 2, VT_LPSTR, 0, NULL,
1155                                     "Installation Database");
1156     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1157 
1158     res = MsiSummaryInfoSetPropertyA(suminfo, 3, VT_LPSTR, 0, NULL,
1159                                     "Installation Database");
1160     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1161 
1162     res = MsiSummaryInfoSetPropertyA(suminfo, 4, VT_LPSTR, 0, NULL,
1163                                     "Wine Hackers");
1164     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1165 
1166     res = MsiSummaryInfoSetPropertyA(suminfo, 7, VT_LPSTR, 0, NULL,
1167                                     ";1033");
1168     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1169 
1170     res = MsiSummaryInfoSetPropertyA(suminfo, PID_REVNUMBER, VT_LPSTR, 0, NULL,
1171                                     "{A2078D65-94D6-4205-8DEE-F68D6FD622AA}");
1172     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1173 
1174     res = MsiSummaryInfoSetPropertyA(suminfo, 14, VT_I4, 100, NULL, NULL);
1175     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1176 
1177     res = MsiSummaryInfoSetPropertyA(suminfo, 15, VT_I4, 0, NULL, NULL);
1178     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1179 
1180     res = MsiSummaryInfoPersist(suminfo);
1181     ok(res == ERROR_SUCCESS, "Failed to make summary info persist\n");
1182 
1183     res = MsiCloseHandle(suminfo);
1184     ok(res == ERROR_SUCCESS, "Failed to close suminfo\n");
1185 
1186     return res;
1187 }
1188 
1189 static MSIHANDLE create_package_db(LPSTR prodcode)
1190 {
1191     MSIHANDLE hdb = 0;
1192     CHAR query[MAX_PATH];
1193     UINT res;
1194 
1195     DeleteFileA(msifile);
1196 
1197     /* create an empty database */
1198     res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
1199     ok( res == ERROR_SUCCESS , "Failed to create database\n" );
1200     if (res != ERROR_SUCCESS)
1201         return hdb;
1202 
1203     res = MsiDatabaseCommit(hdb);
1204     ok(res == ERROR_SUCCESS, "Failed to commit database\n");
1205 
1206     set_summary_info(hdb, prodcode);
1207 
1208     res = run_query(hdb,
1209             "CREATE TABLE `Directory` ( "
1210             "`Directory` CHAR(255) NOT NULL, "
1211             "`Directory_Parent` CHAR(255), "
1212             "`DefaultDir` CHAR(255) NOT NULL "
1213             "PRIMARY KEY `Directory`)");
1214     ok(res == ERROR_SUCCESS , "Failed to create directory table\n");
1215 
1216     res = run_query(hdb,
1217             "CREATE TABLE `Property` ( "
1218             "`Property` CHAR(72) NOT NULL, "
1219             "`Value` CHAR(255) "
1220             "PRIMARY KEY `Property`)");
1221     ok(res == ERROR_SUCCESS , "Failed to create directory table\n");
1222 
1223     sprintf(query, "INSERT INTO `Property` "
1224             "(`Property`, `Value`) "
1225             "VALUES( 'ProductCode', '%s' )", prodcode);
1226     res = run_query(hdb, query);
1227     ok(res == ERROR_SUCCESS , "Failed\n");
1228 
1229     res = MsiDatabaseCommit(hdb);
1230     ok(res == ERROR_SUCCESS, "Failed to commit database\n");
1231 
1232     return hdb;
1233 }
1234 
1235 static void test_usefeature(void)
1236 {
1237     INSTALLSTATE r;
1238 
1239     if (!pMsiUseFeatureExA)
1240     {
1241         win_skip("MsiUseFeatureExA not implemented\n");
1242         return;
1243     }
1244 
1245     r = MsiQueryFeatureStateA(NULL, NULL);
1246     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1247 
1248     r = MsiQueryFeatureStateA("{9085040-6000-11d3-8cfe-0150048383c9}" ,NULL);
1249     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1250 
1251     r = pMsiUseFeatureExA(NULL,NULL,0,0);
1252     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1253 
1254     r = pMsiUseFeatureExA(NULL, "WORDVIEWFiles", -2, 1 );
1255     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1256 
1257     r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}",
1258                          NULL, -2, 0 );
1259     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1260 
1261     r = pMsiUseFeatureExA("{9085040-6000-11d3-8cfe-0150048383c9}",
1262                          "WORDVIEWFiles", -2, 0 );
1263     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1264 
1265     r = pMsiUseFeatureExA("{0085040-6000-11d3-8cfe-0150048383c9}",
1266                          "WORDVIEWFiles", -2, 0 );
1267     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1268 
1269     r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}",
1270                          "WORDVIEWFiles", -2, 1 );
1271     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1272 }
1273 
1274 static LONG delete_key( HKEY key, LPCSTR subkey, REGSAM access )
1275 {
1276     if (pRegDeleteKeyExA)
1277         return pRegDeleteKeyExA( key, subkey, access, 0 );
1278     return RegDeleteKeyA( key, subkey );
1279 }
1280 
1281 static void test_null(void)
1282 {
1283     MSIHANDLE hpkg;
1284     UINT r;
1285     HKEY hkey;
1286     DWORD dwType, cbData;
1287     LPBYTE lpData = NULL;
1288     INSTALLSTATE state;
1289     REGSAM access = KEY_ALL_ACCESS;
1290 
1291     if (is_wow64)
1292         access |= KEY_WOW64_64KEY;
1293 
1294     r = pMsiOpenPackageExW(NULL, 0, &hpkg);
1295     ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
1296 
1297     state = MsiQueryProductStateW(NULL);
1298     ok( state == INSTALLSTATE_INVALIDARG, "wrong return\n");
1299 
1300     r = MsiEnumFeaturesW(NULL,0,NULL,NULL);
1301     ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
1302 
1303     r = MsiConfigureFeatureW(NULL, NULL, 0);
1304     ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
1305 
1306     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", NULL, 0);
1307     ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
1308 
1309     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000001}", "foo", 0);
1310     ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
1311 
1312     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000002}", "foo", INSTALLSTATE_DEFAULT);
1313     ok( r == ERROR_UNKNOWN_PRODUCT, "wrong error %d\n", r);
1314 
1315     /* make sure empty string to MsiGetProductInfo is not a handle to default registry value, saving and restoring the
1316      * necessary registry values */
1317 
1318     /* empty product string */
1319     r = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", 0, access, &hkey);
1320     if (r == ERROR_ACCESS_DENIED)
1321     {
1322         skip("Not enough rights to perform tests\n");
1323         return;
1324     }
1325     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1326 
1327     r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
1328     ok ( r == ERROR_SUCCESS || r == ERROR_FILE_NOT_FOUND, "wrong error %d\n", r);
1329     if ( r == ERROR_SUCCESS )
1330     {
1331         lpData = HeapAlloc(GetProcessHeap(), 0, cbData);
1332         if (!lpData)
1333             skip("Out of memory\n");
1334         else
1335         {
1336             r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
1337             ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
1338         }
1339     }
1340 
1341     r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
1342     if (r == ERROR_ACCESS_DENIED)
1343     {
1344         skip("Not enough rights to perform tests\n");
1345         HeapFree(GetProcessHeap(), 0, lpData);
1346         RegCloseKey(hkey);
1347         return;
1348     }
1349     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1350 
1351     r = MsiGetProductInfoA("", "", NULL, NULL);
1352     ok ( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
1353 
1354     if (lpData)
1355     {
1356         r = RegSetValueExA(hkey, NULL, 0, dwType, lpData, cbData);
1357         ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
1358 
1359         HeapFree(GetProcessHeap(), 0, lpData);
1360     }
1361     else
1362     {
1363         r = RegDeleteValueA(hkey, NULL);
1364         ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
1365     }
1366 
1367     r = RegCloseKey(hkey);
1368     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1369 
1370     /* empty attribute */
1371     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}",
1372                         0, NULL, 0, access, NULL, &hkey, NULL);
1373     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1374 
1375     r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
1376     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1377 
1378     r = MsiGetProductInfoA("{F1C3AF50-8B56-4A69-A00C-00773FE42F30}", "", NULL, NULL);
1379     ok ( r == ERROR_UNKNOWN_PROPERTY, "wrong error %d\n", r);
1380 
1381     r = RegCloseKey(hkey);
1382     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1383 
1384     r = delete_key(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}",
1385                    access & KEY_WOW64_64KEY);
1386     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1387 }
1388 
1389 static void test_getcomponentpath(void)
1390 {
1391     INSTALLSTATE r;
1392     char buffer[0x100];
1393     DWORD sz;
1394 
1395     if(!pMsiGetComponentPathA)
1396         return;
1397 
1398     r = pMsiGetComponentPathA( NULL, NULL, NULL, NULL );
1399     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1400 
1401     r = pMsiGetComponentPathA( "bogus", "bogus", NULL, NULL );
1402     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1403 
1404     r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", NULL, NULL );
1405     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1406 
1407     sz = sizeof buffer;
1408     buffer[0]=0;
1409     r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", buffer, &sz );
1410     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1411 
1412     r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C998E7}",
1413         "{00000000-0000-0000-0000-000000000000}", buffer, &sz );
1414     ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
1415 
1416     r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
1417         "{00000000-0000-0000-0000-00000000}", buffer, &sz );
1418     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1419 
1420     r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
1421         "{029E403D-A86A-1D11-5B5B0006799C897E}", buffer, &sz );
1422     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1423 
1424     r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C9987e}",
1425                             "{00000000-A68A-11d1-5B5B-0006799C897E}", buffer, &sz );
1426     ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
1427 }
1428 
1429 static void create_file(LPCSTR name, LPCSTR data, DWORD size)
1430 {
1431     HANDLE file;
1432     DWORD written;
1433 
1434     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1435     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
1436     WriteFile(file, data, strlen(data), &written, NULL);
1437 
1438     if (size)
1439     {
1440         SetFilePointer(file, size, NULL, FILE_BEGIN);
1441         SetEndOfFile(file);
1442     }
1443 
1444     CloseHandle(file);
1445 }
1446 
1447 static void create_test_files(void)
1448 {
1449     CreateDirectoryA("msitest", NULL);
1450     create_file("msitest\\one.txt", "msitest\\one.txt", 100);
1451     CreateDirectoryA("msitest\\first", NULL);
1452     create_file("msitest\\first\\two.txt", "msitest\\first\\two.txt", 100);
1453     CreateDirectoryA("msitest\\second", NULL);
1454     create_file("msitest\\second\\three.txt", "msitest\\second\\three.txt", 100);
1455 
1456     create_file("four.txt", "four.txt", 100);
1457     create_file("five.txt", "five.txt", 100);
1458     create_cab_file("msitest.cab", MEDIA_SIZE, "four.txt\0five.txt\0");
1459 
1460     create_file("msitest\\filename", "msitest\\filename", 100);
1461     create_file("msitest\\service.exe", "msitest\\service.exe", 100);
1462 
1463     DeleteFileA("four.txt");
1464     DeleteFileA("five.txt");
1465 }
1466 
1467 static void delete_test_files(void)
1468 {
1469     DeleteFileA("msitest.msi");
1470     DeleteFileA("msitest.cab");
1471     DeleteFileA("msitest\\second\\three.txt");
1472     DeleteFileA("msitest\\first\\two.txt");
1473     DeleteFileA("msitest\\one.txt");
1474     DeleteFileA("msitest\\service.exe");
1475     DeleteFileA("msitest\\filename");
1476     RemoveDirectoryA("msitest\\second");
1477     RemoveDirectoryA("msitest\\first");
1478     RemoveDirectoryA("msitest");
1479 }
1480 
1481 #define HASHSIZE sizeof(MSIFILEHASHINFO)
1482 
1483 static const struct
1484 {
1485     LPCSTR data;
1486     DWORD size;
1487     MSIFILEHASHINFO hash;
1488 } hash_data[] =
1489 {
1490     { "", 0,
1491       { HASHSIZE,
1492         { 0, 0, 0, 0 },
1493       },
1494     },
1495 
1496     { "abc", 0,
1497       { HASHSIZE,
1498         { 0x98500190, 0xb04fd23c, 0x7d3f96d6, 0x727fe128 },
1499       },
1500     },
1501 
1502     { "C:\\Program Files\\msitest\\caesar\n", 0,
1503       { HASHSIZE,
1504         { 0x2b566794, 0xfd42181b, 0x2514d6e4, 0x5768b4e2 },
1505       },
1506     },
1507 
1508     { "C:\\Program Files\\msitest\\caesar\n", 500,
1509       { HASHSIZE,
1510         { 0x58095058, 0x805efeff, 0x10f3483e, 0x0147d653 },
1511       },
1512     },
1513 };
1514 
1515 static void test_MsiGetFileHash(void)
1516 {
1517     const char name[] = "msitest.bin";
1518     UINT r;
1519     MSIFILEHASHINFO hash;
1520     DWORD i;
1521 
1522     if (!pMsiGetFileHashA)
1523     {
1524         win_skip("MsiGetFileHash not implemented\n");
1525         return;
1526     }
1527 
1528     hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
1529 
1530     /* szFilePath is NULL */
1531     r = pMsiGetFileHashA(NULL, 0, &hash);
1532     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1533 
1534     /* szFilePath is empty */
1535     r = pMsiGetFileHashA("", 0, &hash);
1536     ok(r == ERROR_PATH_NOT_FOUND || r == ERROR_BAD_PATHNAME,
1537        "Expected ERROR_PATH_NOT_FOUND or ERROR_BAD_PATHNAME, got %d\n", r);
1538 
1539     /* szFilePath is nonexistent */
1540     r = pMsiGetFileHashA(name, 0, &hash);
1541     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
1542 
1543     /* dwOptions is non-zero */
1544     r = pMsiGetFileHashA(name, 1, &hash);
1545     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1546 
1547     /* pHash.dwFileHashInfoSize is not correct */
1548     hash.dwFileHashInfoSize = 0;
1549     r = pMsiGetFileHashA(name, 0, &hash);
1550     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1551 
1552     /* pHash is NULL */
1553     r = pMsiGetFileHashA(name, 0, NULL);
1554     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1555 
1556     for (i = 0; i < sizeof(hash_data) / sizeof(hash_data[0]); i++)
1557     {
1558         int ret;
1559 
1560         create_file(name, hash_data[i].data, hash_data[i].size);
1561 
1562         memset(&hash, 0, sizeof(MSIFILEHASHINFO));
1563         hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
1564 
1565         r = pMsiGetFileHashA(name, 0, &hash);
1566         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1567 
1568         ret = memcmp(&hash, &hash_data[i].hash, HASHSIZE);
1569         ok(!ret, "Hash incorrect\n");
1570 
1571         DeleteFileA(name);
1572     }
1573 }
1574 
1575 /* copied from dlls/msi/registry.c */
1576 static BOOL squash_guid(LPCWSTR in, LPWSTR out)
1577 {
1578     DWORD i,n=1;
1579     GUID guid;
1580 
1581     if (FAILED(CLSIDFromString((LPCOLESTR)in, &guid)))
1582         return FALSE;
1583 
1584     for(i=0; i<8; i++)
1585         out[7-i] = in[n++];
1586     n++;
1587     for(i=0; i<4; i++)
1588         out[11-i] = in[n++];
1589     n++;
1590     for(i=0; i<4; i++)
1591         out[15-i] = in[n++];
1592     n++;
1593     for(i=0; i<2; i++)
1594     {
1595         out[17+i*2] = in[n++];
1596         out[16+i*2] = in[n++];
1597     }
1598     n++;
1599     for( ; i<8; i++)
1600     {
1601         out[17+i*2] = in[n++];
1602         out[16+i*2] = in[n++];
1603     }
1604     out[32]=0;
1605     return TRUE;
1606 }
1607 
1608 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
1609 {
1610     WCHAR guidW[MAX_PATH];
1611     WCHAR squashedW[MAX_PATH];
1612     GUID guid;
1613     HRESULT hr;
1614     int size;
1615 
1616     hr = CoCreateGuid(&guid);
1617     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
1618 
1619     size = StringFromGUID2(&guid, guidW, MAX_PATH);
1620     ok(size == 39, "Expected 39, got %d\n", hr);
1621 
1622     WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
1623     if (squashed)
1624     {
1625         squash_guid(guidW, squashedW);
1626         WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
1627     }
1628 }
1629 
1630 static char *get_user_sid(void)
1631 {
1632     HANDLE token;
1633     DWORD size = 0;
1634     TOKEN_USER *user;
1635     char *usersid = NULL;
1636 
1637     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
1638     GetTokenInformation(token, TokenUser, NULL, size, &size);
1639 
1640     user = HeapAlloc(GetProcessHeap(), 0, size);
1641     GetTokenInformation(token, TokenUser, user, size, &size);
1642     pConvertSidToStringSidA(user->User.Sid, &usersid);
1643     HeapFree(GetProcessHeap(), 0, user);
1644 
1645     CloseHandle(token);
1646     return usersid;
1647 }
1648 
1649 static void test_MsiQueryProductState(void)
1650 {
1651     CHAR prodcode[MAX_PATH];
1652     CHAR prod_squashed[MAX_PATH];
1653     CHAR keypath[MAX_PATH*2];
1654     LPSTR usersid;
1655     INSTALLSTATE state;
1656     LONG res;
1657     HKEY userkey, localkey, props;
1658     HKEY prodkey;
1659     DWORD data, error;
1660     REGSAM access = KEY_ALL_ACCESS;
1661 
1662     create_test_guid(prodcode, prod_squashed);
1663     usersid = get_user_sid();
1664 
1665     if (is_wow64)
1666         access |= KEY_WOW64_64KEY;
1667 
1668     /* NULL prodcode */
1669     SetLastError(0xdeadbeef);
1670     state = MsiQueryProductStateA(NULL);
1671     error = GetLastError();
1672     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1673     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1674 
1675     /* empty prodcode */
1676     SetLastError(0xdeadbeef);
1677     state = MsiQueryProductStateA("");
1678     error = GetLastError();
1679     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1680     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1681 
1682     /* garbage prodcode */
1683     SetLastError(0xdeadbeef);
1684     state = MsiQueryProductStateA("garbage");
1685     error = GetLastError();
1686     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1687     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1688 
1689     /* guid without brackets */
1690     SetLastError(0xdeadbeef);
1691     state = MsiQueryProductStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D");
1692     error = GetLastError();
1693     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1694     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1695 
1696     /* guid with brackets */
1697     SetLastError(0xdeadbeef);
1698     state = MsiQueryProductStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}");
1699     error = GetLastError();
1700     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1701     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1702        "expected ERROR_SUCCESS, got %u\n", error);
1703 
1704     /* same length as guid, but random */
1705     SetLastError(0xdeadbeef);
1706     state = MsiQueryProductStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93");
1707     error = GetLastError();
1708     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1709     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1710 
1711     /* MSIINSTALLCONTEXT_USERUNMANAGED */
1712 
1713     SetLastError(0xdeadbeef);
1714     state = MsiQueryProductStateA(prodcode);
1715     error = GetLastError();
1716     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1717     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1718        "expected ERROR_SUCCESS, got %u\n", error);
1719 
1720     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
1721     lstrcatA(keypath, prod_squashed);
1722 
1723     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
1724     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1725 
1726     /* user product key exists */
1727     SetLastError(0xdeadbeef);
1728     state = MsiQueryProductStateA(prodcode);
1729     error = GetLastError();
1730     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1731     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1732        "expected ERROR_SUCCESS, got %u\n", error);
1733 
1734     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
1735     lstrcatA(keypath, prodcode);
1736 
1737     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1738     if (res == ERROR_ACCESS_DENIED)
1739     {
1740         skip("Not enough rights to perform tests\n");
1741         RegDeleteKeyA(userkey, "");
1742         RegCloseKey(userkey);
1743         LocalFree(usersid);
1744         return;
1745     }
1746     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1747 
1748     /* local uninstall key exists */
1749     SetLastError(0xdeadbeef);
1750     state = MsiQueryProductStateA(prodcode);
1751     error = GetLastError();
1752     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1753     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1754        "expected ERROR_SUCCESS, got %u\n", error);
1755 
1756     data = 1;
1757     res = RegSetValueExA(localkey, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1758     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1759 
1760     /* WindowsInstaller value exists */
1761     SetLastError(0xdeadbeef);
1762     state = MsiQueryProductStateA(prodcode);
1763     error = GetLastError();
1764     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1765     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1766        "expected ERROR_SUCCESS, got %u\n", error);
1767 
1768     RegDeleteValueA(localkey, "WindowsInstaller");
1769     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1770 
1771     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1772     lstrcatA(keypath, usersid);
1773     lstrcatA(keypath, "\\Products\\");
1774     lstrcatA(keypath, prod_squashed);
1775 
1776     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1777     if (res == ERROR_ACCESS_DENIED)
1778     {
1779         skip("Not enough rights to perform tests\n");
1780         RegDeleteKeyA(userkey, "");
1781         RegCloseKey(userkey);
1782         LocalFree(usersid);
1783         return;
1784     }
1785     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1786 
1787     /* local product 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     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1796     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1797 
1798     /* install properties key exists */
1799     SetLastError(0xdeadbeef);
1800     state = MsiQueryProductStateA(prodcode);
1801     error = GetLastError();
1802     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1803     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1804        "expected ERROR_SUCCESS, got %u\n", error);
1805 
1806     data = 1;
1807     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1808     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1809 
1810     /* WindowsInstaller value exists */
1811     SetLastError(0xdeadbeef);
1812     state = MsiQueryProductStateA(prodcode);
1813     error = GetLastError();
1814     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1815     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1816        "expected ERROR_SUCCESS, got %u\n", error);
1817 
1818     data = 2;
1819     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1820     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1821 
1822     /* WindowsInstaller value is not 1 */
1823     SetLastError(0xdeadbeef);
1824     state = MsiQueryProductStateA(prodcode);
1825     error = GetLastError();
1826     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1827     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1828        "expected ERROR_SUCCESS, got %u\n", error);
1829 
1830     RegDeleteKeyA(userkey, "");
1831 
1832     /* user product key does not exist */
1833     SetLastError(0xdeadbeef);
1834     state = MsiQueryProductStateA(prodcode);
1835     error = GetLastError();
1836     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1837     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1838        "expected ERROR_SUCCESS, got %u\n", error);
1839 
1840     RegDeleteValueA(props, "WindowsInstaller");
1841     delete_key(props, "", access & KEY_WOW64_64KEY);
1842     RegCloseKey(props);
1843     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1844     RegCloseKey(localkey);
1845     RegDeleteKeyA(userkey, "");
1846     RegCloseKey(userkey);
1847 
1848     /* MSIINSTALLCONTEXT_USERMANAGED */
1849 
1850     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
1851     lstrcatA(keypath, usersid);
1852     lstrcatA(keypath, "\\Installer\\Products\\");
1853     lstrcatA(keypath, prod_squashed);
1854 
1855     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
1856     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1857 
1858     state = MsiQueryProductStateA(prodcode);
1859     ok(state == INSTALLSTATE_ADVERTISED,
1860        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1861 
1862     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1863     lstrcatA(keypath, usersid);
1864     lstrcatA(keypath, "\\Products\\");
1865     lstrcatA(keypath, prod_squashed);
1866 
1867     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1868     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1869 
1870     state = MsiQueryProductStateA(prodcode);
1871     ok(state == INSTALLSTATE_ADVERTISED,
1872        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1873 
1874     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1875     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1876 
1877     state = MsiQueryProductStateA(prodcode);
1878     ok(state == INSTALLSTATE_ADVERTISED,
1879        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1880 
1881     data = 1;
1882     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1883     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1884 
1885     /* WindowsInstaller value exists */
1886     state = MsiQueryProductStateA(prodcode);
1887     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1888 
1889     RegDeleteValueA(props, "WindowsInstaller");
1890     delete_key(props, "", access & KEY_WOW64_64KEY);
1891     RegCloseKey(props);
1892     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1893     RegCloseKey(localkey);
1894     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
1895     RegCloseKey(prodkey);
1896 
1897     /* MSIINSTALLCONTEXT_MACHINE */
1898 
1899     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
1900     lstrcatA(keypath, prod_squashed);
1901 
1902     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
1903     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1904 
1905     state = MsiQueryProductStateA(prodcode);
1906     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1907 
1908     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1909     lstrcatA(keypath, "S-1-5-18\\Products\\");
1910     lstrcatA(keypath, prod_squashed);
1911 
1912     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1913     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1914 
1915     state = MsiQueryProductStateA(prodcode);
1916     ok(state == INSTALLSTATE_ADVERTISED,
1917        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1918 
1919     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1920     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1921 
1922     state = MsiQueryProductStateA(prodcode);
1923     ok(state == INSTALLSTATE_ADVERTISED,
1924        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1925 
1926     data = 1;
1927     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1928     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1929 
1930     /* WindowsInstaller value exists */
1931     state = MsiQueryProductStateA(prodcode);
1932     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1933 
1934     RegDeleteValueA(props, "WindowsInstaller");
1935     delete_key(props, "", access & KEY_WOW64_64KEY);
1936     RegCloseKey(props);
1937     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1938     RegCloseKey(localkey);
1939     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
1940     RegCloseKey(prodkey);
1941 
1942     LocalFree(usersid);
1943 }
1944 
1945 static const char table_enc85[] =
1946 "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
1947 "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
1948 "yz{}~";
1949 
1950 /*
1951  *  Encodes a base85 guid given a GUID pointer
1952  *  Caller should provide a 21 character buffer for the encoded string.
1953  */
1954 static void encode_base85_guid( GUID *guid, LPWSTR str )
1955 {
1956     unsigned int x, *p, i;
1957 
1958     p = (unsigned int*) guid;
1959     for( i=0; i<4; i++ )
1960     {
1961         x = p[i];
1962         *str++ = table_enc85[x%85];
1963         x = x/85;
1964         *str++ = table_enc85[x%85];
1965         x = x/85;
1966         *str++ = table_enc85[x%85];
1967         x = x/85;
1968         *str++ = table_enc85[x%85];
1969         x = x/85;
1970         *str++ = table_enc85[x%85];
1971     }
1972     *str = 0;
1973 }
1974 
1975 static void compose_base85_guid(LPSTR component, LPSTR comp_base85, LPSTR squashed)
1976 {
1977     WCHAR guidW[MAX_PATH];
1978     WCHAR base85W[MAX_PATH];
1979     WCHAR squashedW[MAX_PATH];
1980     GUID guid;
1981     HRESULT hr;
1982     int size;
1983 
1984     hr = CoCreateGuid(&guid);
1985     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
1986 
1987     size = StringFromGUID2(&guid, guidW, MAX_PATH);
1988     ok(size == 39, "Expected 39, got %d\n", hr);
1989 
1990     WideCharToMultiByte(CP_ACP, 0, guidW, size, component, MAX_PATH, NULL, NULL);
1991     encode_base85_guid(&guid, base85W);
1992     WideCharToMultiByte(CP_ACP, 0, base85W, -1, comp_base85, MAX_PATH, NULL, NULL);
1993     squash_guid(guidW, squashedW);
1994     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
1995 }
1996 
1997 static void test_MsiQueryFeatureState(void)
1998 {
1999     HKEY userkey, localkey, compkey, compkey2;
2000     CHAR prodcode[MAX_PATH];
2001     CHAR prod_squashed[MAX_PATH];
2002     CHAR component[MAX_PATH];
2003     CHAR comp_base85[MAX_PATH];
2004     CHAR comp_squashed[MAX_PATH], comp_squashed2[MAX_PATH];
2005     CHAR keypath[MAX_PATH*2];
2006     INSTALLSTATE state;
2007     LPSTR usersid;
2008     LONG res;
2009     REGSAM access = KEY_ALL_ACCESS;
2010     DWORD error;
2011 
2012     create_test_guid(prodcode, prod_squashed);
2013     compose_base85_guid(component, comp_base85, comp_squashed);
2014     compose_base85_guid(component, comp_base85 + 20, comp_squashed2);
2015     usersid = get_user_sid();
2016 
2017     if (is_wow64)
2018         access |= KEY_WOW64_64KEY;
2019 
2020     /* NULL prodcode */
2021     SetLastError(0xdeadbeef);
2022     state = MsiQueryFeatureStateA(NULL, "feature");
2023     error = GetLastError();
2024     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2025     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2026 
2027     /* empty prodcode */
2028     SetLastError(0xdeadbeef);
2029     state = MsiQueryFeatureStateA("", "feature");
2030     error = GetLastError();
2031     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2032     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2033 
2034     /* garbage prodcode */
2035     SetLastError(0xdeadbeef);
2036     state = MsiQueryFeatureStateA("garbage", "feature");
2037     error = GetLastError();
2038     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2039     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2040 
2041     /* guid without brackets */
2042     SetLastError(0xdeadbeef);
2043     state = MsiQueryFeatureStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", "feature");
2044     error = GetLastError();
2045     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2046     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2047 
2048     /* guid with brackets */
2049     SetLastError(0xdeadbeef);
2050     state = MsiQueryFeatureStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", "feature");
2051     error = GetLastError();
2052     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2053     ok(error == ERROR_SUCCESS || broken(error == ERROR_ALREADY_EXISTS) /* win2k */,
2054        "expected ERROR_SUCCESS, got %u\n", error);
2055 
2056     /* same length as guid, but random */
2057     SetLastError(0xdeadbeef);
2058     state = MsiQueryFeatureStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", "feature");
2059     error = GetLastError();
2060     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2061     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2062 
2063     /* NULL szFeature */
2064     SetLastError(0xdeadbeef);
2065     state = MsiQueryFeatureStateA(prodcode, NULL);
2066     error = GetLastError();
2067     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2068     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2069 
2070     /* empty szFeature */
2071     SetLastError(0xdeadbeef);
2072     state = MsiQueryFeatureStateA(prodcode, "");
2073     error = GetLastError();
2074     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2075     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2076        "expected ERROR_SUCCESS, got %u\n", error);
2077 
2078     /* feature key does not exist yet */
2079     SetLastError(0xdeadbeef);
2080     state = MsiQueryFeatureStateA(prodcode, "feature");
2081     error = GetLastError();
2082     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2083     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2084        "expected ERROR_SUCCESS, got %u\n", error);
2085 
2086     /* MSIINSTALLCONTEXT_USERUNMANAGED */
2087 
2088     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Features\\");
2089     lstrcatA(keypath, prod_squashed);
2090 
2091     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
2092     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2093 
2094     /* feature key exists */
2095     SetLastError(0xdeadbeef);
2096     state = MsiQueryFeatureStateA(prodcode, "feature");
2097     error = GetLastError();
2098     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, 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     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 2);
2103     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2104 
2105     /* feature value exists */
2106     SetLastError(0xdeadbeef);
2107     state = MsiQueryFeatureStateA(prodcode, "feature");
2108     error = GetLastError();
2109     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2110     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2111        "expected ERROR_SUCCESS, got %u\n", error);
2112 
2113     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2114     lstrcatA(keypath, usersid);
2115     lstrcatA(keypath, "\\Products\\");
2116     lstrcatA(keypath, prod_squashed);
2117     lstrcatA(keypath, "\\Features");
2118 
2119     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
2120     if (res == ERROR_ACCESS_DENIED)
2121     {
2122         skip("Not enough rights to perform tests\n");
2123         RegDeleteKeyA(userkey, "");
2124         RegCloseKey(userkey);
2125         LocalFree(usersid);
2126         return;
2127     }
2128     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2129 
2130     /* userdata features key exists */
2131     SetLastError(0xdeadbeef);
2132     state = MsiQueryFeatureStateA(prodcode, "feature");
2133     error = GetLastError();
2134     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2135     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2136        "expected ERROR_SUCCESS, got %u\n", error);
2137 
2138     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
2139     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2140 
2141     SetLastError(0xdeadbeef);
2142     state = MsiQueryFeatureStateA(prodcode, "feature");
2143     error = GetLastError();
2144     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
2145     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2146        "expected ERROR_SUCCESS, got %u\n", error);
2147 
2148     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
2149     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2150 
2151     SetLastError(0xdeadbeef);
2152     state = MsiQueryFeatureStateA(prodcode, "feature");
2153     error = GetLastError();
2154     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2155     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2156        "expected ERROR_SUCCESS, got %u\n", error);
2157 
2158     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
2159     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2160 
2161     SetLastError(0xdeadbeef);
2162     state = MsiQueryFeatureStateA(prodcode, "feature");
2163     error = GetLastError();
2164     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2165     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2166        "expected ERROR_SUCCESS, got %u\n", error);
2167 
2168     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
2169     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2170 
2171     SetLastError(0xdeadbeef);
2172     state = MsiQueryFeatureStateA(prodcode, "feature");
2173     error = GetLastError();
2174     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2175     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2176        "expected ERROR_SUCCESS, got %u\n", error);
2177 
2178     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2179     lstrcatA(keypath, usersid);
2180     lstrcatA(keypath, "\\Components\\");
2181     lstrcatA(keypath, comp_squashed);
2182 
2183     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2184     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2185 
2186     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2187     lstrcatA(keypath, usersid);
2188     lstrcatA(keypath, "\\Components\\");
2189     lstrcatA(keypath, comp_squashed2);
2190 
2191     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
2192     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2193 
2194     SetLastError(0xdeadbeef);
2195     state = MsiQueryFeatureStateA(prodcode, "feature");
2196     error = GetLastError();
2197     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2198     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2199        "expected ERROR_SUCCESS, got %u\n", error);
2200 
2201     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
2202     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2203 
2204     SetLastError(0xdeadbeef);
2205     state = MsiQueryFeatureStateA(prodcode, "feature");
2206     error = GetLastError();
2207     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2208     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2209        "expected ERROR_SUCCESS, got %u\n", error);
2210 
2211     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
2212     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2213 
2214     SetLastError(0xdeadbeef);
2215     state = MsiQueryFeatureStateA(prodcode, "feature");
2216     error = GetLastError();
2217     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, 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(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
2222     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2223 
2224     /* INSTALLSTATE_LOCAL */
2225     SetLastError(0xdeadbeef);
2226     state = MsiQueryFeatureStateA(prodcode, "feature");
2227     error = GetLastError();
2228     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, 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\\", 4);
2233     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2234 
2235     /* INSTALLSTATE_SOURCE */
2236     SetLastError(0xdeadbeef);
2237     state = MsiQueryFeatureStateA(prodcode, "feature");
2238     error = GetLastError();
2239     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, 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 *)"01", 3);
2244     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2245 
2246     /* bad INSTALLSTATE_SOURCE */
2247     SetLastError(0xdeadbeef);
2248     state = MsiQueryFeatureStateA(prodcode, "feature");
2249     error = GetLastError();
2250     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, 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 *)"01a", 4);
2255     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2256 
2257     /* INSTALLSTATE_SOURCE */
2258     SetLastError(0xdeadbeef);
2259     state = MsiQueryFeatureStateA(prodcode, "feature");
2260     error = GetLastError();
2261     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, 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     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
2266     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2267 
2268     /* bad INSTALLSTATE_SOURCE */
2269     SetLastError(0xdeadbeef);
2270     state = MsiQueryFeatureStateA(prodcode, "feature");
2271     error = GetLastError();
2272     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2273     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2274        "expected ERROR_SUCCESS, got %u\n", error);
2275 
2276     RegDeleteValueA(compkey, prod_squashed);
2277     RegDeleteValueA(compkey2, prod_squashed);
2278     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2279     delete_key(compkey2, "", access & KEY_WOW64_64KEY);
2280     RegDeleteValueA(localkey, "feature");
2281     RegDeleteValueA(userkey, "feature");
2282     RegDeleteKeyA(userkey, "");
2283     RegCloseKey(compkey);
2284     RegCloseKey(compkey2);
2285     RegCloseKey(localkey);
2286     RegCloseKey(userkey);
2287 
2288     /* MSIINSTALLCONTEXT_USERMANAGED */
2289 
2290     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
2291     lstrcatA(keypath, usersid);
2292     lstrcatA(keypath, "\\Installer\\Features\\");
2293     lstrcatA(keypath, prod_squashed);
2294 
2295     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
2296     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2297 
2298     /* feature key exists */
2299     state = MsiQueryFeatureStateA(prodcode, "feature");
2300     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2301 
2302     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 1);
2303     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2304 
2305     /* feature value exists */
2306     state = MsiQueryFeatureStateA(prodcode, "feature");
2307     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2308 
2309     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2310     lstrcatA(keypath, usersid);
2311     lstrcatA(keypath, "\\Products\\");
2312     lstrcatA(keypath, prod_squashed);
2313     lstrcatA(keypath, "\\Features");
2314 
2315     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
2316     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2317 
2318     /* userdata features key exists */
2319     state = MsiQueryFeatureStateA(prodcode, "feature");
2320     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2321 
2322     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
2323     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2324 
2325     state = MsiQueryFeatureStateA(prodcode, "feature");
2326     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
2327 
2328     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
2329     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2330 
2331     state = MsiQueryFeatureStateA(prodcode, "feature");
2332     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2333 
2334     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
2335     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2336 
2337     state = MsiQueryFeatureStateA(prodcode, "feature");
2338     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2339 
2340     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
2341     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2342 
2343     state = MsiQueryFeatureStateA(prodcode, "feature");
2344     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2345 
2346     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2347     lstrcatA(keypath, usersid);
2348     lstrcatA(keypath, "\\Components\\");
2349     lstrcatA(keypath, comp_squashed);
2350 
2351     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2352     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2353 
2354     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2355     lstrcatA(keypath, usersid);
2356     lstrcatA(keypath, "\\Components\\");
2357     lstrcatA(keypath, comp_squashed2);
2358 
2359     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
2360     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2361 
2362     state = MsiQueryFeatureStateA(prodcode, "feature");
2363     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2364 
2365     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
2366     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2367 
2368     state = MsiQueryFeatureStateA(prodcode, "feature");
2369     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2370 
2371     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
2372     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2373 
2374     state = MsiQueryFeatureStateA(prodcode, "feature");
2375     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2376 
2377     res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
2378     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2379 
2380     state = MsiQueryFeatureStateA(prodcode, "feature");
2381     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2382 
2383     RegDeleteValueA(compkey, prod_squashed);
2384     RegDeleteValueA(compkey2, prod_squashed);
2385     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2386     delete_key(compkey2, "", access & KEY_WOW64_64KEY);
2387     RegDeleteValueA(localkey, "feature");
2388     RegDeleteValueA(userkey, "feature");
2389     delete_key(userkey, "", access & KEY_WOW64_64KEY);
2390     RegCloseKey(compkey);
2391     RegCloseKey(compkey2);
2392     RegCloseKey(localkey);
2393     RegCloseKey(userkey);
2394 
2395     /* MSIINSTALLCONTEXT_MACHINE */
2396 
2397     lstrcpyA(keypath, "Software\\Classes\\Installer\\Features\\");
2398     lstrcatA(keypath, prod_squashed);
2399 
2400     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
2401     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2402 
2403     /* feature key exists */
2404     state = MsiQueryFeatureStateA(prodcode, "feature");
2405     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2406 
2407     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 1);
2408     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2409 
2410     /* feature value exists */
2411     state = MsiQueryFeatureStateA(prodcode, "feature");
2412     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2413 
2414     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2415     lstrcatA(keypath, "S-1-5-18\\Products\\");
2416     lstrcatA(keypath, prod_squashed);
2417     lstrcatA(keypath, "\\Features");
2418 
2419     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
2420     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2421 
2422     /* userdata features key exists */
2423     state = MsiQueryFeatureStateA(prodcode, "feature");
2424     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2425 
2426     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
2427     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2428 
2429     state = MsiQueryFeatureStateA(prodcode, "feature");
2430     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
2431 
2432     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
2433     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2434 
2435     state = MsiQueryFeatureStateA(prodcode, "feature");
2436     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2437 
2438     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
2439     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2440 
2441     state = MsiQueryFeatureStateA(prodcode, "feature");
2442     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2443 
2444     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
2445     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2446 
2447     state = MsiQueryFeatureStateA(prodcode, "feature");
2448     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2449 
2450     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2451     lstrcatA(keypath, "S-1-5-18\\Components\\");
2452     lstrcatA(keypath, comp_squashed);
2453 
2454     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2455     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2456 
2457     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2458     lstrcatA(keypath, "S-1-5-18\\Components\\");
2459     lstrcatA(keypath, comp_squashed2);
2460 
2461     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
2462     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2463 
2464     state = MsiQueryFeatureStateA(prodcode, "feature");
2465     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2466 
2467     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
2468     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2469 
2470     state = MsiQueryFeatureStateA(prodcode, "feature");
2471     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2472 
2473     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
2474     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2475 
2476     state = MsiQueryFeatureStateA(prodcode, "feature");
2477     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2478 
2479     res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
2480     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2481 
2482     state = MsiQueryFeatureStateA(prodcode, "feature");
2483     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2484 
2485     RegDeleteValueA(compkey, prod_squashed);
2486     RegDeleteValueA(compkey2, prod_squashed);
2487     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2488     delete_key(compkey2, "", access & KEY_WOW64_64KEY);
2489     RegDeleteValueA(localkey, "feature");
2490     RegDeleteValueA(userkey, "feature");
2491     delete_key(userkey, "", access & KEY_WOW64_64KEY);
2492     RegCloseKey(compkey);
2493     RegCloseKey(compkey2);
2494     RegCloseKey(localkey);
2495     RegCloseKey(userkey);
2496     LocalFree(usersid);
2497 }
2498 
2499 static void test_MsiQueryComponentState(void)
2500 {
2501     HKEY compkey, prodkey;
2502     CHAR prodcode[MAX_PATH];
2503     CHAR prod_squashed[MAX_PATH];
2504     CHAR component[MAX_PATH];
2505     CHAR comp_base85[MAX_PATH];
2506     CHAR comp_squashed[MAX_PATH];
2507     CHAR keypath[MAX_PATH];
2508     INSTALLSTATE state;
2509     LPSTR usersid;
2510     LONG res;
2511     UINT r;
2512     REGSAM access = KEY_ALL_ACCESS;
2513     DWORD error;
2514 
2515     static const INSTALLSTATE MAGIC_ERROR = 0xdeadbeef;
2516 
2517     if (!pMsiQueryComponentStateA)
2518     {
2519         win_skip("MsiQueryComponentStateA not implemented\n");
2520         return;
2521     }
2522 
2523     create_test_guid(prodcode, prod_squashed);
2524     compose_base85_guid(component, comp_base85, comp_squashed);
2525     usersid = get_user_sid();
2526 
2527     if (is_wow64)
2528         access |= KEY_WOW64_64KEY;
2529 
2530     /* NULL szProductCode */
2531     state = MAGIC_ERROR;
2532     SetLastError(0xdeadbeef);
2533     r = pMsiQueryComponentStateA(NULL, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2534     error = GetLastError();
2535     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2536     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2537     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2538 
2539     /* empty szProductCode */
2540     state = MAGIC_ERROR;
2541     SetLastError(0xdeadbeef);
2542     r = pMsiQueryComponentStateA("", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2543     error = GetLastError();
2544     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2545     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2546     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2547 
2548     /* random szProductCode */
2549     state = MAGIC_ERROR;
2550     SetLastError(0xdeadbeef);
2551     r = pMsiQueryComponentStateA("random", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2552     error = GetLastError();
2553     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2554     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2555     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2556 
2557     /* GUID-length szProductCode */
2558     state = MAGIC_ERROR;
2559     SetLastError(0xdeadbeef);
2560     r = pMsiQueryComponentStateA("DJANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KDE", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2561     error = GetLastError();
2562     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2563     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2564     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2565 
2566     /* GUID-length with brackets */
2567     state = MAGIC_ERROR;
2568     SetLastError(0xdeadbeef);
2569     r = pMsiQueryComponentStateA("{JANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KD}", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2570     error = GetLastError();
2571     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2572     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2573     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2574 
2575     /* actual GUID */
2576     state = MAGIC_ERROR;
2577     SetLastError(0xdeadbeef);
2578     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2579     error = GetLastError();
2580     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2581     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2582     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2583 
2584     state = MAGIC_ERROR;
2585     SetLastError(0xdeadbeef);
2586     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2587     error = GetLastError();
2588     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2589     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2590     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2591 
2592     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
2593     lstrcatA(keypath, prod_squashed);
2594 
2595     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2596     if (res == ERROR_ACCESS_DENIED)
2597     {
2598         skip("Not enough rights to perform tests\n");
2599         LocalFree(usersid);
2600         return;
2601     }
2602     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2603 
2604     state = MAGIC_ERROR;
2605     SetLastError(0xdeadbeef);
2606     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2607     error = GetLastError();
2608     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2609     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2610     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2611 
2612     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2613     RegCloseKey(prodkey);
2614 
2615     /* create local system product key */
2616     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\");
2617     lstrcatA(keypath, prod_squashed);
2618     lstrcatA(keypath, "\\InstallProperties");
2619 
2620     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2621     if (res == ERROR_ACCESS_DENIED)
2622     {
2623         skip("Not enough rights to perform tests\n");
2624         LocalFree(usersid);
2625         return;
2626     }
2627     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2628 
2629     /* local system product key exists */
2630     state = MAGIC_ERROR;
2631     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2632     error = GetLastError();
2633     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2634     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2635     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2636 
2637     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2638     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2639 
2640     /* LocalPackage value exists */
2641     state = MAGIC_ERROR;
2642     SetLastError(0xdeadbeef);
2643     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2644     error = GetLastError();
2645     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2646     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2647     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2648 
2649     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\");
2650     lstrcatA(keypath, comp_squashed);
2651 
2652     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2653     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2654 
2655     /* component key exists */
2656     state = MAGIC_ERROR;
2657     SetLastError(0xdeadbeef);
2658     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2659     error = GetLastError();
2660     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2661     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2662     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2663 
2664     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
2665     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2666 
2667     /* component\product exists */
2668     state = MAGIC_ERROR;
2669     SetLastError(0xdeadbeef);
2670     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2671     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2672     error = GetLastError();
2673     ok(state == INSTALLSTATE_NOTUSED || state == INSTALLSTATE_LOCAL,
2674        "Expected INSTALLSTATE_NOTUSED or INSTALLSTATE_LOCAL, got %d\n", state);
2675     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2676 
2677     /* NULL component, product exists */
2678     state = MAGIC_ERROR;
2679     SetLastError(0xdeadbeef);
2680     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, NULL, &state);
2681     error = GetLastError();
2682     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2683     ok(state == MAGIC_ERROR, "Expected state not changed, got %d\n", state);
2684     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2685 
2686     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
2687     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2688 
2689     /* INSTALLSTATE_LOCAL */
2690     state = MAGIC_ERROR;
2691     SetLastError(0xdeadbeef);
2692     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2693     error = GetLastError();
2694     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2695     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2696     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2697 
2698     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01\\", 4);
2699     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2700 
2701     /* INSTALLSTATE_SOURCE */
2702     state = MAGIC_ERROR;
2703     SetLastError(0xdeadbeef);
2704     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2705     error = GetLastError();
2706     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2707     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2708     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2709 
2710     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
2711     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2712 
2713     /* bad INSTALLSTATE_SOURCE */
2714     state = MAGIC_ERROR;
2715     SetLastError(0xdeadbeef);
2716     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2717     error = GetLastError();
2718     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2719     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2720     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2721 
2722     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01a", 4);
2723     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2724 
2725     /* INSTALLSTATE_SOURCE */
2726     state = MAGIC_ERROR;
2727     SetLastError(0xdeadbeef);
2728     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2729     error = GetLastError();
2730     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2731     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2732     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2733 
2734     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01:", 4);
2735     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2736 
2737     /* registry component */
2738     state = MAGIC_ERROR;
2739     SetLastError(0xdeadbeef);
2740     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2741     error = GetLastError();
2742     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2743     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2744     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2745 
2746     RegDeleteValueA(prodkey, "LocalPackage");
2747     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2748     RegDeleteValueA(compkey, prod_squashed);
2749     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2750     RegCloseKey(prodkey);
2751     RegCloseKey(compkey);
2752 
2753     /* MSIINSTALLCONTEXT_USERUNMANAGED */
2754 
2755     state = MAGIC_ERROR;
2756     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2757     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2758     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2759 
2760     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2761     lstrcatA(keypath, prod_squashed);
2762 
2763     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
2764     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2765 
2766     state = MAGIC_ERROR;
2767     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2768     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2769     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2770 
2771     RegDeleteKeyA(prodkey, "");
2772     RegCloseKey(prodkey);
2773 
2774     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2775     lstrcatA(keypath, usersid);
2776     lstrcatA(keypath, "\\Products\\");
2777     lstrcatA(keypath, prod_squashed);
2778     lstrcatA(keypath, "\\InstallProperties");
2779 
2780     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2781     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2782 
2783     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2784     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2785 
2786     RegCloseKey(prodkey);
2787 
2788     state = MAGIC_ERROR;
2789     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2790     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2791     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2792 
2793     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2794     lstrcatA(keypath, usersid);
2795     lstrcatA(keypath, "\\Components\\");
2796     lstrcatA(keypath, comp_squashed);
2797 
2798     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2799     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2800 
2801     /* component key exists */
2802     state = MAGIC_ERROR;
2803     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2804     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2805     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2806 
2807     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
2808     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2809 
2810     /* component\product exists */
2811     state = MAGIC_ERROR;
2812     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2813     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2814     ok(state == INSTALLSTATE_NOTUSED || state == INSTALLSTATE_LOCAL,
2815        "Expected INSTALLSTATE_NOTUSED or INSTALLSTATE_LOCAL, got %d\n", state);
2816 
2817     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
2818     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2819 
2820     state = MAGIC_ERROR;
2821     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2822     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2823     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2824 
2825     /* MSIINSTALLCONTEXT_USERMANAGED */
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     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2833     lstrcatA(keypath, prod_squashed);
2834 
2835     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
2836     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2837 
2838     state = MAGIC_ERROR;
2839     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2840     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2841     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2842 
2843     RegDeleteKeyA(prodkey, "");
2844     RegCloseKey(prodkey);
2845 
2846     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
2847     lstrcatA(keypath, usersid);
2848     lstrcatA(keypath, "\\Installer\\Products\\");
2849     lstrcatA(keypath, prod_squashed);
2850 
2851     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2852     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2853 
2854     state = MAGIC_ERROR;
2855     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2856     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2857     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2858 
2859     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2860     RegCloseKey(prodkey);
2861 
2862     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2863     lstrcatA(keypath, usersid);
2864     lstrcatA(keypath, "\\Products\\");
2865     lstrcatA(keypath, prod_squashed);
2866     lstrcatA(keypath, "\\InstallProperties");
2867 
2868     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2869     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2870 
2871     res = RegSetValueExA(prodkey, "ManagedLocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2872     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2873 
2874     state = MAGIC_ERROR;
2875     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2876     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2877     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2878 
2879     RegDeleteValueA(prodkey, "LocalPackage");
2880     RegDeleteValueA(prodkey, "ManagedLocalPackage");
2881     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2882     RegDeleteValueA(compkey, prod_squashed);
2883     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2884     RegCloseKey(prodkey);
2885     RegCloseKey(compkey);
2886     LocalFree(usersid);
2887 }
2888 
2889 static void test_MsiGetComponentPath(void)
2890 {
2891     HKEY compkey, prodkey, installprop;
2892     CHAR prodcode[MAX_PATH];
2893     CHAR prod_squashed[MAX_PATH];
2894     CHAR component[MAX_PATH];
2895     CHAR comp_base85[MAX_PATH];
2896     CHAR comp_squashed[MAX_PATH];
2897     CHAR keypath[MAX_PATH];
2898     CHAR path[MAX_PATH];
2899     INSTALLSTATE state;
2900     LPSTR usersid;
2901     DWORD size, val;
2902     REGSAM access = KEY_ALL_ACCESS;
2903     LONG res;
2904 
2905     create_test_guid(prodcode, prod_squashed);
2906     compose_base85_guid(component, comp_base85, comp_squashed);
2907     usersid = get_user_sid();
2908 
2909     if (is_wow64)
2910         access |= KEY_WOW64_64KEY;
2911 
2912     /* NULL szProduct */
2913     size = MAX_PATH;
2914     state = MsiGetComponentPathA(NULL, component, 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 szComponent */
2919     size = MAX_PATH;
2920     state = MsiGetComponentPathA(prodcode, NULL, path, &size);
2921     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, 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(NULL, path, &size);
2926     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2927     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2928 
2929     /* NULL lpPathBuf */
2930     size = MAX_PATH;
2931     state = MsiGetComponentPathA(prodcode, component, NULL, &size);
2932     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, 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, NULL, &size);
2937     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2938     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2939 
2940     /* NULL pcchBuf */
2941     size = MAX_PATH;
2942     state = MsiGetComponentPathA(prodcode, component, path, NULL);
2943     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, 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, NULL);
2948     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2949     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2950 
2951     /* all params valid */
2952     size = MAX_PATH;
2953     state = MsiGetComponentPathA(prodcode, component, path, &size);
2954     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2955     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2956 
2957     size = MAX_PATH;
2958     state = MsiLocateComponentA(component, path, &size);
2959     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2960     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2961 
2962     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2963     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
2964     lstrcatA(keypath, comp_squashed);
2965 
2966     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2967     if (res == ERROR_ACCESS_DENIED)
2968     {
2969         skip("Not enough rights to perform tests\n");
2970         LocalFree(usersid);
2971         return;
2972     }
2973     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2974 
2975     /* local system component key exists */
2976     size = MAX_PATH;
2977     state = MsiGetComponentPathA(prodcode, component, path, &size);
2978     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2979     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2980 
2981     size = MAX_PATH;
2982     state = MsiLocateComponentA(component, path, &size);
2983     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2984     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2985 
2986     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2987     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2988 
2989     /* product value exists */
2990     path[0] = 0;
2991     size = MAX_PATH;
2992     state = MsiGetComponentPathA(prodcode, component, path, &size);
2993     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2994     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2995     ok(size == 10, "Expected 10, got %d\n", size);
2996 
2997     path[0] = 0;
2998     size = MAX_PATH;
2999     state = MsiLocateComponentA(component, path, &size);
3000     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3001     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3002     ok(size == 10, "Expected 10, got %d\n", size);
3003 
3004     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3005     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
3006     lstrcatA(keypath, prod_squashed);
3007     lstrcatA(keypath, "\\InstallProperties");
3008 
3009     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &installprop, NULL);
3010     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3011 
3012     val = 1;
3013     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
3014     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3015 
3016     /* install properties key exists */
3017     path[0] = 0;
3018     size = MAX_PATH;
3019     state = MsiGetComponentPathA(prodcode, component, path, &size);
3020     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3021     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3022     ok(size == 10, "Expected 10, got %d\n", size);
3023 
3024     path[0] = 0;
3025     size = MAX_PATH;
3026     state = MsiLocateComponentA(component, path, &size);
3027     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3028     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3029     ok(size == 10, "Expected 10, got %d\n", size);
3030 
3031     create_file("C:\\imapath", "C:\\imapath", 11);
3032 
3033     /* file exists */
3034     path[0] = 'a';
3035     size = 0;
3036     state = MsiGetComponentPathA(prodcode, component, path, &size);
3037     ok(state == INSTALLSTATE_MOREDATA, "Expected INSTALLSTATE_MOREDATA, got %d\n", state);
3038     ok(path[0] == 'a', "got %s\n", path);
3039     ok(size == 10, "Expected 10, got %d\n", size);
3040 
3041     path[0] = 0;
3042     size = MAX_PATH;
3043     state = MsiGetComponentPathA(prodcode, component, path, &size);
3044     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3045     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3046     ok(size == 10, "Expected 10, got %d\n", size);
3047 
3048     size = 0;
3049     path[0] = 'a';
3050     state = MsiLocateComponentA(component, path, &size);
3051     ok(state == INSTALLSTATE_MOREDATA, "Expected INSTALLSTATE_MOREDATA, got %d\n", state);
3052     ok(path[0] == 'a', "got %s\n", path);
3053     ok(size == 10, "Expected 10, got %d\n", size);
3054 
3055     path[0] = 0;
3056     size = MAX_PATH;
3057     state = MsiLocateComponentA(component, path, &size);
3058     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3059     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3060     ok(size == 10, "Expected 10, got %d\n", size);
3061 
3062     RegDeleteValueA(compkey, prod_squashed);
3063     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3064     RegDeleteValueA(installprop, "WindowsInstaller");
3065     delete_key(installprop, "", access & KEY_WOW64_64KEY);
3066     RegCloseKey(compkey);
3067     RegCloseKey(installprop);
3068     DeleteFileA("C:\\imapath");
3069 
3070     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3071     lstrcatA(keypath, "Installer\\UserData\\");
3072     lstrcatA(keypath, usersid);
3073     lstrcatA(keypath, "\\Components\\");
3074     lstrcatA(keypath, comp_squashed);
3075 
3076     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3077     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3078 
3079     /* user managed component key exists */
3080     size = MAX_PATH;
3081     state = MsiGetComponentPathA(prodcode, component, path, &size);
3082     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3083     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3084 
3085     size = MAX_PATH;
3086     state = MsiLocateComponentA(component, path, &size);
3087     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3088     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3089 
3090     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3091     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3092 
3093     /* product value exists */
3094     path[0] = 0;
3095     size = MAX_PATH;
3096     state = MsiGetComponentPathA(prodcode, component, path, &size);
3097     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3098     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3099     ok(size == 10, "Expected 10, got %d\n", size);
3100 
3101     path[0] = 0;
3102     size = MAX_PATH;
3103     state = MsiLocateComponentA(component, path, &size);
3104     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3105     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3106     ok(size == 10, "Expected 10, got %d\n", size);
3107 
3108     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3109     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
3110     lstrcatA(keypath, prod_squashed);
3111     lstrcatA(keypath, "\\InstallProperties");
3112 
3113     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &installprop, NULL);
3114     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3115 
3116     val = 1;
3117     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
3118     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3119 
3120     /* install properties key exists */
3121     path[0] = 0;
3122     size = MAX_PATH;
3123     state = MsiGetComponentPathA(prodcode, component, path, &size);
3124     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3125     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3126     ok(size == 10, "Expected 10, got %d\n", size);
3127 
3128     path[0] = 0;
3129     size = MAX_PATH;
3130     state = MsiLocateComponentA(component, path, &size);
3131     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3132     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3133     ok(size == 10, "Expected 10, got %d\n", size);
3134 
3135     create_file("C:\\imapath", "C:\\imapath", 11);
3136 
3137     /* file exists */
3138     path[0] = 0;
3139     size = MAX_PATH;
3140     state = MsiGetComponentPathA(prodcode, component, path, &size);
3141     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3142     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3143     ok(size == 10, "Expected 10, got %d\n", size);
3144 
3145     path[0] = 0;
3146     size = MAX_PATH;
3147     state = MsiLocateComponentA(component, path, &size);
3148     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3149     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3150     ok(size == 10, "Expected 10, got %d\n", size);
3151 
3152     RegDeleteValueA(compkey, prod_squashed);
3153     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3154     RegDeleteValueA(installprop, "WindowsInstaller");
3155     delete_key(installprop, "", access & KEY_WOW64_64KEY);
3156     RegCloseKey(compkey);
3157     RegCloseKey(installprop);
3158     DeleteFileA("C:\\imapath");
3159 
3160     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3161     lstrcatA(keypath, "Installer\\Managed\\");
3162     lstrcatA(keypath, usersid);
3163     lstrcatA(keypath, "\\Installer\\Products\\");
3164     lstrcatA(keypath, prod_squashed);
3165 
3166     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3167     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3168 
3169     /* user managed product key exists */
3170     size = MAX_PATH;
3171     state = MsiGetComponentPathA(prodcode, component, path, &size);
3172     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3173     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3174 
3175     size = MAX_PATH;
3176     state = MsiLocateComponentA(component, path, &size);
3177     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3178     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3179 
3180     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3181     lstrcatA(keypath, "Installer\\UserData\\");
3182     lstrcatA(keypath, usersid);
3183     lstrcatA(keypath, "\\Components\\");
3184     lstrcatA(keypath, comp_squashed);
3185 
3186     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3187     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3188 
3189     /* user managed component key exists */
3190     size = MAX_PATH;
3191     state = MsiGetComponentPathA(prodcode, component, path, &size);
3192     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3193     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3194 
3195     size = MAX_PATH;
3196     state = MsiLocateComponentA(component, path, &size);
3197     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3198     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3199 
3200     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3201     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3202 
3203     /* product value exists */
3204     path[0] = 0;
3205     size = MAX_PATH;
3206     state = MsiGetComponentPathA(prodcode, component, path, &size);
3207     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3208     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3209     ok(size == 10, "Expected 10, got %d\n", size);
3210 
3211     path[0] = 0;
3212     size = MAX_PATH;
3213     state = MsiLocateComponentA(component, path, &size);
3214     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3215     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3216     ok(size == 10, "Expected 10, got %d\n", size);
3217 
3218     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3219     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
3220     lstrcatA(keypath, prod_squashed);
3221     lstrcatA(keypath, "\\InstallProperties");
3222 
3223     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &installprop, NULL);
3224     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3225 
3226     val = 1;
3227     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
3228     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3229 
3230     /* install properties key exists */
3231     path[0] = 0;
3232     size = MAX_PATH;
3233     state = MsiGetComponentPathA(prodcode, component, path, &size);
3234     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3235     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3236     ok(size == 10, "Expected 10, got %d\n", size);
3237 
3238     path[0] = 0;
3239     size = MAX_PATH;
3240     state = MsiLocateComponentA(component, path, &size);
3241     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3242     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3243     ok(size == 10, "Expected 10, got %d\n", size);
3244 
3245     create_file("C:\\imapath", "C:\\imapath", 11);
3246 
3247     /* file exists */
3248     path[0] = 0;
3249     size = MAX_PATH;
3250     state = MsiGetComponentPathA(prodcode, component, path, &size);
3251     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3252     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3253     ok(size == 10, "Expected 10, got %d\n", size);
3254 
3255     path[0] = 0;
3256     size = MAX_PATH;
3257     state = MsiLocateComponentA(component, path, &size);
3258     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3259     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3260     ok(size == 10, "Expected 10, got %d\n", size);
3261 
3262     RegDeleteValueA(compkey, prod_squashed);
3263     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3264     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3265     RegDeleteValueA(installprop, "WindowsInstaller");
3266     delete_key(installprop, "", access & KEY_WOW64_64KEY);
3267     RegCloseKey(prodkey);
3268     RegCloseKey(compkey);
3269     RegCloseKey(installprop);
3270     DeleteFileA("C:\\imapath");
3271 
3272     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
3273     lstrcatA(keypath, prod_squashed);
3274 
3275     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
3276     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3277 
3278     /* user unmanaged product key exists */
3279     size = MAX_PATH;
3280     state = MsiGetComponentPathA(prodcode, component, path, &size);
3281     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3282     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3283 
3284     size = MAX_PATH;
3285     state = MsiLocateComponentA(component, path, &size);
3286     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3287     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3288 
3289     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3290     lstrcatA(keypath, "Installer\\UserData\\");
3291     lstrcatA(keypath, usersid);
3292     lstrcatA(keypath, "\\Components\\");
3293     lstrcatA(keypath, comp_squashed);
3294 
3295     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3296     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3297 
3298     /* user unmanaged component key exists */
3299     size = MAX_PATH;
3300     state = MsiGetComponentPathA(prodcode, component, path, &size);
3301     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3302     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3303 
3304     size = MAX_PATH;
3305     state = MsiLocateComponentA(component, path, &size);
3306     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3307     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3308 
3309     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3310     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3311 
3312     /* product value exists */
3313     path[0] = 0;
3314     size = MAX_PATH;
3315     state = MsiGetComponentPathA(prodcode, component, path, &size);
3316     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3317     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3318     ok(size == 10, "Expected 10, got %d\n", size);
3319 
3320     path[0] = 0;
3321     size = MAX_PATH;
3322     state = MsiLocateComponentA(component, path, &size);
3323     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3324     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3325     ok(size == 10, "Expected 10, got %d\n", size);
3326 
3327     create_file("C:\\imapath", "C:\\imapath", 11);
3328 
3329     /* file exists */
3330     path[0] = 0;
3331     size = MAX_PATH;
3332     state = MsiGetComponentPathA(prodcode, component, path, &size);
3333     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3334     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3335     ok(size == 10, "Expected 10, got %d\n", size);
3336 
3337     path[0] = 0;
3338     size = MAX_PATH;
3339     state = MsiLocateComponentA(component, path, &size);
3340     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3341     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3342     ok(size == 10, "Expected 10, got %d\n", size);
3343 
3344     RegDeleteValueA(compkey, prod_squashed);
3345     RegDeleteKeyA(prodkey, "");
3346     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3347     RegCloseKey(prodkey);
3348     RegCloseKey(compkey);
3349     DeleteFileA("C:\\imapath");
3350 
3351     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
3352     lstrcatA(keypath, prod_squashed);
3353 
3354     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3355     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3356 
3357     /* local classes product key exists */
3358     size = MAX_PATH;
3359     state = MsiGetComponentPathA(prodcode, component, path, &size);
3360     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3361     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3362 
3363     size = MAX_PATH;
3364     state = MsiLocateComponentA(component, path, &size);
3365     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3366     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3367 
3368     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3369     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
3370     lstrcatA(keypath, comp_squashed);
3371 
3372     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3373     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3374 
3375     /* local user component key exists */
3376     size = MAX_PATH;
3377     state = MsiGetComponentPathA(prodcode, component, path, &size);
3378     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3379     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3380 
3381     size = MAX_PATH;
3382     state = MsiLocateComponentA(component, path, &size);
3383     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3384     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3385 
3386     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3387     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3388 
3389     /* product value exists */
3390     path[0] = 0;
3391     size = MAX_PATH;
3392     state = MsiGetComponentPathA(prodcode, component, path, &size);
3393     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3394     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3395     ok(size == 10, "Expected 10, got %d\n", size);
3396 
3397     path[0] = 0;
3398     size = MAX_PATH;
3399     state = MsiLocateComponentA(component, path, &size);
3400     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3401     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3402     ok(size == 10, "Expected 10, got %d\n", size);
3403 
3404     create_file("C:\\imapath", "C:\\imapath", 11);
3405 
3406     /* file exists */
3407     path[0] = 0;
3408     size = MAX_PATH;
3409     state = MsiGetComponentPathA(prodcode, component, path, &size);
3410     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3411     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3412     ok(size == 10, "Expected 10, got %d\n", size);
3413 
3414     path[0] = 0;
3415     size = MAX_PATH;
3416     state = MsiLocateComponentA(component, path, &size);
3417     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3418     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3419     ok(size == 10, "Expected 10, got %d\n", size);
3420 
3421     RegDeleteValueA(compkey, prod_squashed);
3422     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3423     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3424     RegCloseKey(prodkey);
3425     RegCloseKey(compkey);
3426     DeleteFileA("C:\\imapath");
3427     LocalFree(usersid);
3428 }
3429 
3430 static void test_MsiGetComponentPathEx(void)
3431 {
3432     HKEY key_comp, key_installprop, key_prod;
3433     char prod[MAX_PATH], prod_squashed[MAX_PATH];
3434     char comp[MAX_PATH], comp_base85[MAX_PATH], comp_squashed[MAX_PATH];
3435     char path[MAX_PATH], path_key[MAX_PATH], *usersid;
3436     INSTALLSTATE state;
3437     DWORD size, val;
3438     REGSAM access = KEY_ALL_ACCESS;
3439     LONG res;
3440 
3441     if (!pMsiGetComponentPathExA)
3442     {
3443         win_skip( "MsiGetComponentPathExA not present\n" );
3444         return;
3445     }
3446 
3447     if (is_wow64) access |= KEY_WOW64_64KEY;
3448 
3449     create_test_guid( prod, prod_squashed );
3450     compose_base85_guid( comp, comp_base85, comp_squashed );
3451     usersid = get_user_sid();
3452 
3453     /* NULL product */
3454     size = MAX_PATH;
3455     state = pMsiGetComponentPathExA( NULL, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3456     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
3457     todo_wine ok( !size, "got %u\n", size );
3458 
3459     /* NULL component */
3460     size = MAX_PATH;
3461     state = pMsiGetComponentPathExA( prod, NULL, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3462     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
3463     todo_wine ok( !size, "got %u\n", size );
3464 
3465     /* non-NULL usersid, MSIINSTALLCONTEXT_MACHINE */
3466     size = MAX_PATH;
3467     state = pMsiGetComponentPathExA( prod, comp, usersid, MSIINSTALLCONTEXT_MACHINE, path, &size);
3468     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
3469     todo_wine ok( !size, "got %u\n", size );
3470 
3471     /* NULL buf */
3472     size = MAX_PATH;
3473     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, NULL, &size );
3474     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3475     todo_wine ok( size == MAX_PATH * 2, "got %u\n", size );
3476 
3477     /* NULL buflen */
3478     size = MAX_PATH;
3479     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, NULL );
3480     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
3481     ok( size == MAX_PATH, "got %u\n", size );
3482 
3483     /* all params valid */
3484     size = MAX_PATH;
3485     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3486     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3487     todo_wine ok( !size, "got %u\n", size );
3488 
3489     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3490     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Components\\" );
3491     lstrcatA( path_key, comp_squashed );
3492 
3493     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3494     if (res == ERROR_ACCESS_DENIED)
3495     {
3496         skip( "insufficient rights\n" );
3497         LocalFree( usersid );
3498         return;
3499     }
3500     ok( res == ERROR_SUCCESS, "got %d\n", res );
3501 
3502     /* local system component key exists */
3503     size = MAX_PATH;
3504     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3505     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3506 
3507     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3508     ok( res == ERROR_SUCCESS, "got %d\n", res );
3509 
3510     /* product value exists */
3511     path[0] = 0;
3512     size = MAX_PATH;
3513     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3514     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3515     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3516     ok( size == 20, "got %u\n", size );
3517 
3518     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3519     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Products\\" );
3520     lstrcatA( path_key, prod_squashed );
3521     lstrcatA( path_key, "\\InstallProperties" );
3522 
3523     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_installprop, NULL );
3524     ok( res == ERROR_SUCCESS, "got %d\n", res );
3525 
3526     val = 1;
3527     res = RegSetValueExA( key_installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(val) );
3528     ok( res == ERROR_SUCCESS, "got %d\n", res );
3529 
3530     /* install properties key exists */
3531     path[0] = 0;
3532     size = MAX_PATH;
3533     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3534     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3535     ok( !lstrcmpA( path, "c:\\testcomponentpath"), "got %s\n", path );
3536     ok( size == 20, "got %u\n", size );
3537 
3538     create_file( "c:\\testcomponentpath", "c:\\testcomponentpath", 21 );
3539 
3540     /* file exists */
3541     path[0] = 0;
3542     size = 0;
3543     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3544     ok( state == INSTALLSTATE_MOREDATA, "got %d\n", state );
3545     ok( !path[0], "got %s\n", path );
3546     todo_wine ok( size == 40, "got %u\n", size );
3547 
3548     path[0] = 0;
3549     size = MAX_PATH;
3550     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3551     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3552     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3553     ok( size == 20, "got %d\n", size );
3554 
3555     RegDeleteValueA( key_comp, prod_squashed );
3556     delete_key( key_comp, "", access & KEY_WOW64_64KEY );
3557     RegDeleteValueA( key_installprop, "WindowsInstaller" );
3558     delete_key( key_installprop, "", access & KEY_WOW64_64KEY );
3559     RegCloseKey( key_comp );
3560     RegCloseKey( key_installprop );
3561     DeleteFileA( "c:\\testcomponentpath" );
3562 
3563     lstrcpyA( path_key, "Software\\Microsoft\\Installer\\Products\\" );
3564     lstrcatA( path_key, prod_squashed );
3565 
3566     res = RegCreateKeyA( HKEY_CURRENT_USER, path_key, &key_prod );
3567     ok( res == ERROR_SUCCESS, "got %d\n", res );
3568 
3569     /* user unmanaged product key exists */
3570     size = MAX_PATH;
3571     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3572     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3573     todo_wine ok(!size, "got %u\n", size);
3574 
3575     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3576     lstrcatA( path_key, "Installer\\UserData\\" );
3577     lstrcatA( path_key, usersid );
3578     lstrcatA( path_key, "\\Components\\" );
3579     lstrcatA( path_key, comp_squashed );
3580 
3581     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3582     ok( res == ERROR_SUCCESS, "got %d\n", res );
3583 
3584     /* user unmanaged component key exists */
3585     size = MAX_PATH;
3586     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3587     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3588     todo_wine ok(!size, "got %u\n", size);
3589 
3590     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3591     ok( res == ERROR_SUCCESS, "got %d\n", res );
3592 
3593     /* product value exists */
3594     path[0] = 0;
3595     size = MAX_PATH;
3596     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3597     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3598     ok( !lstrcmpA( path, "c:\\testcomponentpath"), "got %s\n", path );
3599     ok( size == 20, "got %u\n", size );
3600 
3601     create_file( "c:\\testcomponentpath", "c:\\testcomponentpath", 21 );
3602 
3603     /* file exists */
3604     path[0] = 0;
3605     size = MAX_PATH;
3606     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3607     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3608     ok( !lstrcmpA( path, "c:\\testcomponentpath"), "got %s\n", path );
3609     ok( size == 20, "got %u\n", size );
3610 
3611     RegDeleteValueA( key_comp, prod_squashed );
3612     RegDeleteKeyA( key_prod, "" );
3613     delete_key( key_comp, "", access & KEY_WOW64_64KEY );
3614     RegCloseKey( key_prod );
3615     RegCloseKey( key_comp );
3616     DeleteFileA( "c:\\testcomponentpath" );
3617 
3618     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3619     lstrcatA( path_key, "Installer\\Managed\\" );
3620     lstrcatA( path_key, usersid );
3621     lstrcatA( path_key, "\\Installer\\Products\\" );
3622     lstrcatA( path_key, prod_squashed );
3623 
3624     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_prod, NULL );
3625     ok( res == ERROR_SUCCESS, "got %d\n", res );
3626 
3627     /* user managed product key exists */
3628     size = MAX_PATH;
3629     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3630     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3631 
3632     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3633     lstrcatA( path_key, "Installer\\UserData\\" );
3634     lstrcatA( path_key, usersid );
3635     lstrcatA( path_key, "\\Components\\" );
3636     lstrcatA( path_key, comp_squashed );
3637 
3638     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3639     ok( res == ERROR_SUCCESS, "got %d\n", res );
3640 
3641     /* user managed component key exists */
3642     size = MAX_PATH;
3643     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3644     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3645 
3646     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3647     ok( res == ERROR_SUCCESS, "got %d\n", res );
3648 
3649     /* product value exists */
3650     path[0] = 0;
3651     size = MAX_PATH;
3652     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3653     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3654     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3655     ok( size == 20, "got %u\n", size );
3656 
3657     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3658     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Products\\" );
3659     lstrcatA( path_key, prod_squashed );
3660     lstrcatA( path_key, "\\InstallProperties" );
3661 
3662     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_installprop, NULL );
3663     ok( res == ERROR_SUCCESS, "got %d\n", res );
3664 
3665     val = 1;
3666     res = RegSetValueExA( key_installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(val) );
3667     ok( res == ERROR_SUCCESS, "got %d\n", res );
3668 
3669     /* install properties key exists */
3670     path[0] = 0;
3671     size = MAX_PATH;
3672     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3673     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3674     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3675     ok( size == 20, "got %u\n", size );
3676 
3677     create_file( "c:\\testcomponentpath", "C:\\testcomponentpath", 21 );
3678 
3679     /* file exists */
3680     path[0] = 0;
3681     size = MAX_PATH;
3682     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3683     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3684     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3685     ok( size == 20, "got %u\n", size );
3686 
3687     RegDeleteValueA( key_comp, prod_squashed );
3688     delete_key( key_prod, "", access & KEY_WOW64_64KEY );
3689     delete_key( key_comp, "", access & KEY_WOW64_64KEY );
3690     RegDeleteValueA( key_installprop, "WindowsInstaller" );
3691     delete_key( key_installprop, "", access & KEY_WOW64_64KEY );
3692     RegCloseKey( key_prod );
3693     RegCloseKey( key_comp );
3694     RegCloseKey( key_installprop );
3695     DeleteFileA( "c:\\testcomponentpath" );
3696     lstrcpyA( path_key, "Software\\Classes\\Installer\\Products\\" );
3697     lstrcatA( path_key, prod_squashed );
3698 
3699     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_prod, NULL );
3700     ok( res == ERROR_SUCCESS, "got %d\n", res );
3701 
3702     /* local classes product key exists */
3703     size = MAX_PATH;
3704     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3705     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3706     todo_wine ok(!size, "got %u\n", size);
3707 
3708     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3709     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Components\\" );
3710     lstrcatA( path_key, comp_squashed );
3711 
3712     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE,  path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3713     ok( res == ERROR_SUCCESS, "got %d\n", res );
3714 
3715     /* local user component key exists */
3716     size = MAX_PATH;
3717     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3718     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3719     todo_wine ok(!size, "got %u\n", size);
3720 
3721     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3722     ok( res == ERROR_SUCCESS, "got %d\n", res );
3723 
3724     /* product value exists */
3725     path[0] = 0;
3726     size = MAX_PATH;
3727     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3728     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3729     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3730     ok( size == 20, "got %u\n", size );
3731 
3732     create_file( "c:\\testcomponentpath", "c:\\testcomponentpath", 21 );
3733 
3734     /* file exists */
3735     path[0] = 0;
3736     size = MAX_PATH;
3737     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3738     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3739     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3740     ok( size == 20, "got %u\n", size );
3741 
3742     RegDeleteValueA( key_comp, prod_squashed );
3743     delete_key( key_prod, "", access & KEY_WOW64_64KEY );
3744     delete_key( key_comp, "", access & KEY_WOW64_64KEY );
3745     RegCloseKey( key_prod );
3746     RegCloseKey( key_comp );
3747     DeleteFileA( "c:\\testcomponentpath" );
3748     LocalFree( usersid );
3749 }
3750 
3751 static void test_MsiProvideComponent(void)
3752 {
3753     static const WCHAR sourcedirW[] =
3754         {'s','o','u','r','c','e','d','i','r',0};
3755     static const WCHAR productW[] =
3756         {'{','3','8','8','4','7','3','3','8','-','1','B','B','C','-','4','1','0','4','-',
3757          '8','1','A','C','-','2','F','A','A','C','7','E','C','D','D','C','D','}',0};
3758     static const WCHAR componentW[] =
3759         {'{','D','D','4','2','2','F','9','2','-','3','E','D','8','-','4','9','B','5','-',
3760          'A','0','B','7','-','F','2','6','6','F','9','8','3','5','7','D','F','}',0};
3761     INSTALLSTATE state;
3762     char buf[0x100];
3763     WCHAR bufW[0x100];
3764     DWORD len, len2;
3765     UINT r;
3766 
3767     if (is_process_limited())
3768     {
3769         skip("process is limited\n");
3770         return;
3771     }
3772 
3773     create_test_files();
3774     create_file("msitest\\sourcedir.txt", "msitest\\sourcedir.txt", 1000);
3775     create_database(msifile, sd_tables, sizeof(sd_tables) / sizeof(msi_table));
3776 
3777     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3778 
3779     buf[0] = 0;
3780     len = sizeof(buf);
3781     r = pMsiProvideComponentA("{90120000-0070-0000-0000-4000000FF1CE}",
3782                               "{17961602-C4E2-482E-800A-DF6E627549CF}",
3783                               "ProductFiles", INSTALLMODE_NODETECTION, buf, &len);
3784     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
3785 
3786     r = MsiInstallProductA(msifile, NULL);
3787     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3788 
3789     state = MsiQueryFeatureStateA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir");
3790     ok(state == INSTALLSTATE_LOCAL, "got %d\n", state);
3791 
3792     buf[0] = 0;
3793     len = sizeof(buf);
3794     r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir",
3795                               "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
3796                               INSTALLMODE_NODETECTION, buf, &len);
3797     ok(r == ERROR_SUCCESS, "got %u\n", r);
3798     ok(buf[0], "empty path\n");
3799     ok(len == lstrlenA(buf), "got %u\n", len);
3800 
3801     len2 = 0;
3802     r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir",
3803                               "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
3804                               INSTALLMODE_NODETECTION, NULL, &len2);
3805     ok(r == ERROR_SUCCESS, "got %u\n", r);
3806     ok(len2 == len, "got %u\n", len2);
3807 
3808     len2 = 0;
3809     r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir",
3810                               "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
3811                               INSTALLMODE_NODETECTION, buf, &len2);
3812     ok(r == ERROR_MORE_DATA, "got %u\n", r);
3813     ok(len2 == len, "got %u\n", len2);
3814 
3815     /* wide version */
3816 
3817     bufW[0] = 0;
3818     len = sizeof(buf);
3819     r = pMsiProvideComponentW(productW, sourcedirW, componentW,
3820                               INSTALLMODE_NODETECTION, bufW, &len);
3821     ok(r == ERROR_SUCCESS, "got %u\n", r);
3822     ok(bufW[0], "empty path\n");
3823     ok(len == lstrlenW(bufW), "got %u\n", len);
3824 
3825     len2 = 0;
3826     r = pMsiProvideComponentW(productW, sourcedirW, componentW,
3827                               INSTALLMODE_NODETECTION, NULL, &len2);
3828     ok(r == ERROR_SUCCESS, "got %u\n", r);
3829     ok(len2 == len, "got %u\n", len2);
3830 
3831     len2 = 0;
3832     r = pMsiProvideComponentW(productW, sourcedirW, componentW,
3833                               INSTALLMODE_NODETECTION, bufW, &len2);
3834     ok(r == ERROR_MORE_DATA, "got %u\n", r);
3835     ok(len2 == len, "got %u\n", len2);
3836 
3837     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3838     ok(r == ERROR_SUCCESS, "got %u\n", r);
3839 
3840     DeleteFileA("msitest\\sourcedir.txt");
3841     delete_test_files();
3842     DeleteFileA(msifile);
3843 }
3844 
3845 static void test_MsiProvideQualifiedComponentEx(void)
3846 {
3847     UINT r;
3848     INSTALLSTATE state;
3849     char comp[39], comp_squashed[33], comp2[39], comp2_base85[21], comp2_squashed[33];
3850     char prod[39], prod_base85[21], prod_squashed[33];
3851     char desc[MAX_PATH], buf[MAX_PATH], keypath[MAX_PATH], path[MAX_PATH];
3852     DWORD len = sizeof(buf);
3853     REGSAM access = KEY_ALL_ACCESS;
3854     HKEY hkey, hkey2, hkey3, hkey4, hkey5;
3855     LONG res;
3856 
3857     if (is_process_limited())
3858     {
3859         skip( "process is limited\n" );
3860         return;
3861     }
3862 
3863     create_test_guid( comp, comp_squashed );
3864     compose_base85_guid( comp2, comp2_base85, comp2_squashed );
3865     compose_base85_guid( prod, prod_base85, prod_squashed );
3866 
3867     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3868     ok( r == ERROR_UNKNOWN_COMPONENT, "got %u\n", r );
3869 
3870     lstrcpyA( keypath, "Software\\Classes\\Installer\\Components\\" );
3871     lstrcatA( keypath, comp_squashed );
3872 
3873     if (is_wow64) access |= KEY_WOW64_64KEY;
3874     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey, NULL );
3875     ok( res == ERROR_SUCCESS, "got %d\n", res );
3876 
3877     lstrcpyA( desc, prod_base85 );
3878     memcpy( desc + lstrlenA(desc), "feature<\0", sizeof("feature<\0") );
3879     res = RegSetValueExA( hkey, "qualifier", 0, REG_MULTI_SZ, (const BYTE *)desc,
3880                           lstrlenA(prod_base85) + sizeof("feature<\0") );
3881     ok( res == ERROR_SUCCESS, "got %d\n", res );
3882 
3883     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3884     ok( r == ERROR_UNKNOWN_PRODUCT, "got %u\n", r );
3885 
3886     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, NULL, 0, 0, buf, &len );
3887     ok( r == ERROR_UNKNOWN_PRODUCT, "got %u\n", r );
3888 
3889     state = MsiQueryProductStateA( prod );
3890     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3891 
3892     lstrcpyA( keypath, "Software\\Classes\\Installer\\Products\\" );
3893     lstrcatA( keypath, prod_squashed );
3894 
3895     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey2, NULL );
3896     ok( res == ERROR_SUCCESS, "got %d\n", res );
3897 
3898     state = MsiQueryProductStateA( prod );
3899     ok( state == INSTALLSTATE_ADVERTISED, "got %d\n", state );
3900 
3901     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3902     todo_wine ok( r == ERROR_UNKNOWN_FEATURE, "got %u\n", r );
3903 
3904     lstrcpyA( keypath, "Software\\Classes\\Installer\\Features\\" );
3905     lstrcatA( keypath, prod_squashed );
3906 
3907     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey3, NULL );
3908     ok( res == ERROR_SUCCESS, "got %d\n", res );
3909 
3910     state = MsiQueryFeatureStateA( prod, "feature" );
3911     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3912 
3913     res = RegSetValueExA( hkey3, "feature", 0, REG_SZ, (const BYTE *)"", 1 );
3914     ok( res == ERROR_SUCCESS, "got %d\n", res );
3915 
3916     state = MsiQueryFeatureStateA( prod, "feature" );
3917     ok( state == INSTALLSTATE_ADVERTISED, "got %d\n", state );
3918 
3919     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3920     ok( r == ERROR_FILE_NOT_FOUND, "got %u\n", r );
3921 
3922     len = sizeof(buf);
3923     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, NULL, 0, 0, buf, &len );
3924     ok( r == ERROR_FILE_NOT_FOUND, "got %u\n", r );
3925 
3926     lstrcpyA( keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\" );
3927     lstrcatA( keypath, prod_squashed );
3928     lstrcatA( keypath, "\\Features" );
3929 
3930     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey4, NULL );
3931     ok( res == ERROR_SUCCESS, "got %d\n", res );
3932 
3933     res = RegSetValueExA( hkey4, "feature", 0, REG_SZ, (const BYTE *)comp2_base85, sizeof(comp2_base85) );
3934     ok( res == ERROR_SUCCESS, "got %d\n", res );
3935 
3936     state = MsiQueryFeatureStateA( prod, "feature" );
3937     ok( state == INSTALLSTATE_ADVERTISED, "got %d\n", state );
3938 
3939     lstrcpyA( keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\" );
3940     lstrcatA( keypath, comp2_squashed );
3941 
3942     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey5, NULL );
3943     ok( res == ERROR_SUCCESS, "got %d\n", res );
3944 
3945     res = RegSetValueExA( hkey5, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\nosuchfile", sizeof("c:\\nosuchfile") );
3946     ok( res == ERROR_SUCCESS, "got %d\n", res );
3947 
3948     state = MsiQueryFeatureStateA( prod, "feature" );
3949     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3950 
3951     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3952     ok( r == ERROR_FILE_NOT_FOUND, "got %u\n", r );
3953 
3954     GetCurrentDirectoryA( MAX_PATH, path );
3955     lstrcatA( path, "\\msitest" );
3956     CreateDirectoryA( path, NULL );
3957     lstrcatA( path, "\\test.txt" );
3958     create_file( path, "test", 100 );
3959 
3960     res = RegSetValueExA( hkey5, prod_squashed, 0, REG_SZ, (const BYTE *)path, lstrlenA(path) + 1 );
3961     ok( res == ERROR_SUCCESS, "got %d\n", res );
3962 
3963     buf[0] = 0;
3964     len = sizeof(buf);
3965     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3966     ok( r == ERROR_SUCCESS, "got %u\n", r );
3967     ok( len == lstrlenA(path), "got %u\n", len );
3968     ok( !lstrcmpA( path, buf ), "got '%s'\n", buf );
3969 
3970     DeleteFileA( "msitest\\text.txt" );
3971     RemoveDirectoryA( "msitest" );
3972 
3973     delete_key( hkey5, "", access & KEY_WOW64_64KEY );
3974     RegCloseKey( hkey5 );
3975     delete_key( hkey4, "", access & KEY_WOW64_64KEY );
3976     RegCloseKey( hkey4 );
3977     delete_key( hkey3, "", access & KEY_WOW64_64KEY );
3978     RegCloseKey( hkey3 );
3979     delete_key( hkey2, "", access & KEY_WOW64_64KEY );
3980     RegCloseKey( hkey2 );
3981     delete_key( hkey, "", access & KEY_WOW64_64KEY );
3982     RegCloseKey( hkey );
3983 }
3984 
3985 static void test_MsiGetProductCode(void)
3986 {
3987     HKEY compkey, prodkey;
3988     CHAR prodcode[MAX_PATH];
3989     CHAR prod_squashed[MAX_PATH];
3990     CHAR prodcode2[MAX_PATH];
3991     CHAR prod2_squashed[MAX_PATH];
3992     CHAR component[MAX_PATH];
3993     CHAR comp_base85[MAX_PATH];
3994     CHAR comp_squashed[MAX_PATH];
3995     CHAR keypath[MAX_PATH];
3996     CHAR product[MAX_PATH];
3997     LPSTR usersid;
3998     LONG res;
3999     UINT r;
4000     REGSAM access = KEY_ALL_ACCESS;
4001 
4002     create_test_guid(prodcode, prod_squashed);
4003     create_test_guid(prodcode2, prod2_squashed);
4004     compose_base85_guid(component, comp_base85, comp_squashed);
4005     usersid = get_user_sid();
4006 
4007     if (is_wow64)
4008         access |= KEY_WOW64_64KEY;
4009 
4010     /* szComponent is NULL */
4011     lstrcpyA(product, "prod");
4012     r = MsiGetProductCodeA(NULL, product);
4013     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4014     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4015 
4016     /* szComponent is empty */
4017     lstrcpyA(product, "prod");
4018     r = MsiGetProductCodeA("", product);
4019     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4020     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4021 
4022     /* garbage szComponent */
4023     lstrcpyA(product, "prod");
4024     r = MsiGetProductCodeA("garbage", product);
4025     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4026     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4027 
4028     /* guid without brackets */
4029     lstrcpyA(product, "prod");
4030     r = MsiGetProductCodeA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", product);
4031     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4032     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4033 
4034     /* guid with brackets */
4035     lstrcpyA(product, "prod");
4036     r = MsiGetProductCodeA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", product);
4037     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
4038     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4039 
4040     /* same length as guid, but random */
4041     lstrcpyA(product, "prod");
4042     r = MsiGetProductCodeA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", product);
4043     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4044     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4045 
4046     /* all params correct, szComponent not published */
4047     lstrcpyA(product, "prod");
4048     r = MsiGetProductCodeA(component, product);
4049     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
4050     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4051 
4052     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4053     lstrcatA(keypath, "Installer\\UserData\\");
4054     lstrcatA(keypath, usersid);
4055     lstrcatA(keypath, "\\Components\\");
4056     lstrcatA(keypath, comp_squashed);
4057 
4058     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
4059     if (res == ERROR_ACCESS_DENIED)
4060     {
4061         skip("Not enough rights to perform tests\n");
4062         LocalFree(usersid);
4063         return;
4064     }
4065     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4066 
4067     /* user unmanaged component key exists */
4068     lstrcpyA(product, "prod");
4069     r = MsiGetProductCodeA(component, product);
4070     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
4071     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4072 
4073     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
4074     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4075 
4076     /* product value exists */
4077     lstrcpyA(product, "prod");
4078     r = MsiGetProductCodeA(component, product);
4079     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4080     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4081 
4082     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
4083     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4084 
4085     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4086     lstrcatA(keypath, "Installer\\Managed\\");
4087     lstrcatA(keypath, usersid);
4088     lstrcatA(keypath, "\\Installer\\Products\\");
4089     lstrcatA(keypath, prod_squashed);
4090 
4091     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4092     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4093 
4094     /* user managed product key of first product exists */
4095     lstrcpyA(product, "prod");
4096     r = MsiGetProductCodeA(component, product);
4097     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4098     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4099 
4100     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4101     RegCloseKey(prodkey);
4102 
4103     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
4104     lstrcatA(keypath, prod_squashed);
4105 
4106     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
4107     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4108 
4109     /* user unmanaged product key exists */
4110     lstrcpyA(product, "prod");
4111     r = MsiGetProductCodeA(component, product);
4112     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4113     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4114 
4115     RegDeleteKeyA(prodkey, "");
4116     RegCloseKey(prodkey);
4117 
4118     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
4119     lstrcatA(keypath, prod_squashed);
4120 
4121     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4122     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4123 
4124     /* local classes product key exists */
4125     lstrcpyA(product, "prod");
4126     r = MsiGetProductCodeA(component, product);
4127     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4128     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4129 
4130     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4131     RegCloseKey(prodkey);
4132 
4133     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4134     lstrcatA(keypath, "Installer\\Managed\\");
4135     lstrcatA(keypath, usersid);
4136     lstrcatA(keypath, "\\Installer\\Products\\");
4137     lstrcatA(keypath, prod2_squashed);
4138 
4139     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4140     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4141 
4142     /* user managed product key of second product exists */
4143     lstrcpyA(product, "prod");
4144     r = MsiGetProductCodeA(component, product);
4145     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4146     ok(!lstrcmpA(product, prodcode2), "Expected %s, got %s\n", prodcode2, product);
4147 
4148     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4149     RegCloseKey(prodkey);
4150     RegDeleteValueA(compkey, prod_squashed);
4151     RegDeleteValueA(compkey, prod2_squashed);
4152     delete_key(compkey, "", access & KEY_WOW64_64KEY);
4153     RegCloseKey(compkey);
4154 
4155     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4156     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
4157     lstrcatA(keypath, comp_squashed);
4158 
4159     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
4160     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4161 
4162     /* local user component key exists */
4163     lstrcpyA(product, "prod");
4164     r = MsiGetProductCodeA(component, product);
4165     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
4166     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4167 
4168     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
4169     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4170 
4171     /* product value exists */
4172     lstrcpyA(product, "prod");
4173     r = MsiGetProductCodeA(component, product);
4174     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4175     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4176 
4177     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
4178     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4179 
4180     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4181     lstrcatA(keypath, "Installer\\Managed\\");
4182     lstrcatA(keypath, usersid);
4183     lstrcatA(keypath, "\\Installer\\Products\\");
4184     lstrcatA(keypath, prod_squashed);
4185 
4186     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4187     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4188 
4189     /* user managed product key of first product exists */
4190     lstrcpyA(product, "prod");
4191     r = MsiGetProductCodeA(component, product);
4192     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4193     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4194 
4195     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4196     RegCloseKey(prodkey);
4197 
4198     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
4199     lstrcatA(keypath, prod_squashed);
4200 
4201     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
4202     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4203 
4204     /* user unmanaged product key exists */
4205     lstrcpyA(product, "prod");
4206     r = MsiGetProductCodeA(component, product);
4207     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4208     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4209 
4210     RegDeleteKeyA(prodkey, "");
4211     RegCloseKey(prodkey);
4212 
4213     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
4214     lstrcatA(keypath, prod_squashed);
4215 
4216     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4217     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4218 
4219     /* local classes product key exists */
4220     lstrcpyA(product, "prod");
4221     r = MsiGetProductCodeA(component, product);
4222     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4223     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4224 
4225     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4226     RegCloseKey(prodkey);
4227 
4228     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4229     lstrcatA(keypath, "Installer\\Managed\\");
4230     lstrcatA(keypath, usersid);
4231     lstrcatA(keypath, "\\Installer\\Products\\");
4232     lstrcatA(keypath, prod2_squashed);
4233 
4234     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4235     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4236 
4237     /* user managed product key of second product exists */
4238     lstrcpyA(product, "prod");
4239     r = MsiGetProductCodeA(component, product);
4240     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4241     ok(!lstrcmpA(product, prodcode2), "Expected %s, got %s\n", prodcode2, product);
4242 
4243     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4244     RegCloseKey(prodkey);
4245     RegDeleteValueA(compkey, prod_squashed);
4246     RegDeleteValueA(compkey, prod2_squashed);
4247     delete_key(compkey, "", access & KEY_WOW64_64KEY);
4248     RegCloseKey(compkey);
4249     LocalFree(usersid);
4250 }
4251 
4252 static void test_MsiEnumClients(void)
4253 {
4254     HKEY compkey;
4255     CHAR prodcode[MAX_PATH];
4256     CHAR prod_squashed[MAX_PATH];
4257     CHAR prodcode2[MAX_PATH];
4258     CHAR prod2_squashed[MAX_PATH];
4259     CHAR component[MAX_PATH];
4260     CHAR comp_base85[MAX_PATH];
4261     CHAR comp_squashed[MAX_PATH];
4262     CHAR product[MAX_PATH];
4263     CHAR keypath[MAX_PATH];
4264     LPSTR usersid;
4265     LONG res;
4266     UINT r;
4267     REGSAM access = KEY_ALL_ACCESS;
4268 
4269     create_test_guid(prodcode, prod_squashed);
4270     create_test_guid(prodcode2, prod2_squashed);
4271     compose_base85_guid(component, comp_base85, comp_squashed);
4272     usersid = get_user_sid();
4273 
4274     if (is_wow64)
4275         access |= KEY_WOW64_64KEY;
4276 
4277     /* NULL szComponent */
4278     product[0] = '\0';
4279     r = MsiEnumClientsA(NULL, 0, product);
4280     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4281     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4282 
4283     /* empty szComponent */
4284     product[0] = '\0';
4285     r = MsiEnumClientsA("", 0, product);
4286     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4287     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4288 
4289     /* NULL lpProductBuf */
4290     r = MsiEnumClientsA(component, 0, NULL);
4291     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4292 
4293     /* all params correct, component missing */
4294     product[0] = '\0';
4295     r = MsiEnumClientsA(component, 0, product);
4296     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
4297     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4298 
4299     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4300     lstrcatA(keypath, "Installer\\UserData\\");
4301     lstrcatA(keypath, usersid);
4302     lstrcatA(keypath, "\\Components\\");
4303     lstrcatA(keypath, comp_squashed);
4304 
4305     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
4306     if (res == ERROR_ACCESS_DENIED)
4307     {
4308         skip("Not enough rights to perform tests\n");
4309         LocalFree(usersid);
4310         return;
4311     }
4312     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4313 
4314     /* user unmanaged component key exists */
4315     product[0] = '\0';
4316     r = MsiEnumClientsA(component, 0, product);
4317     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
4318     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4319 
4320     /* index > 0, no products exist */
4321     product[0] = '\0';
4322     r = MsiEnumClientsA(component, 1, product);
4323     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4324     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4325 
4326     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
4327     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4328 
4329     /* product value exists */
4330     r = MsiEnumClientsA(component, 0, product);
4331     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4332     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4333 
4334     /* try index 0 again */
4335     product[0] = '\0';
4336     r = MsiEnumClientsA(component, 0, product);
4337     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4338     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4339 
4340     /* try index 1, second product value does not exist */
4341     product[0] = '\0';
4342     r = MsiEnumClientsA(component, 1, product);
4343     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4344     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4345 
4346     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
4347     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4348 
4349     /* try index 1, second product value does exist */
4350     product[0] = '\0';
4351     r = MsiEnumClientsA(component, 1, product);
4352     todo_wine
4353     {
4354         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4355         ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4356     }
4357 
4358     /* start the enumeration over */
4359     product[0] = '\0';
4360     r = MsiEnumClientsA(component, 0, product);
4361     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4362     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
4363        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
4364 
4365     /* correctly query second product */
4366     product[0] = '\0';
4367     r = MsiEnumClientsA(component, 1, product);
4368     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4369     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
4370        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
4371 
4372     RegDeleteValueA(compkey, prod_squashed);
4373     RegDeleteValueA(compkey, prod2_squashed);
4374     delete_key(compkey, "", access & KEY_WOW64_64KEY);
4375     RegCloseKey(compkey);
4376 
4377     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4378     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
4379     lstrcatA(keypath, comp_squashed);
4380 
4381     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
4382     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4383 
4384     /* user local component key exists */
4385     product[0] = '\0';
4386     r = MsiEnumClientsA(component, 0, product);
4387     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
4388     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4389 
4390     /* index > 0, no products exist */
4391     product[0] = '\0';
4392     r = MsiEnumClientsA(component, 1, product);
4393     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4394     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4395 
4396     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
4397     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4398 
4399     /* product value exists */
4400     product[0] = '\0';
4401     r = MsiEnumClientsA(component, 0, product);
4402     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4403     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4404 
4405     /* try index 0 again */
4406     product[0] = '\0';
4407     r = MsiEnumClientsA(component, 0, product);
4408     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4409 
4410     /* try index 1, second product value does not exist */
4411     product[0] = '\0';
4412     r = MsiEnumClientsA(component, 1, product);
4413     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4414     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4415 
4416     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
4417     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4418 
4419     /* try index 1, second product value does exist */
4420     product[0] = '\0';
4421     r = MsiEnumClientsA(component, 1, product);
4422     todo_wine
4423     {
4424         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4425         ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4426     }
4427 
4428     /* start the enumeration over */
4429     product[0] = '\0';
4430     r = MsiEnumClientsA(component, 0, product);
4431     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4432     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
4433        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
4434 
4435     /* correctly query second product */
4436     product[0] = '\0';
4437     r = MsiEnumClientsA(component, 1, product);
4438     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4439     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
4440        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
4441 
4442     RegDeleteValueA(compkey, prod_squashed);
4443     RegDeleteValueA(compkey, prod2_squashed);
4444     delete_key(compkey, "", access & KEY_WOW64_64KEY);
4445     RegCloseKey(compkey);
4446     LocalFree(usersid);
4447 }
4448 
4449 static void get_version_info(LPSTR path, LPSTR *vercheck, LPDWORD verchecksz,
4450                              LPSTR *langcheck, LPDWORD langchecksz)
4451 {
4452     LPSTR version;
4453     VS_FIXEDFILEINFO *ffi;
4454     DWORD size = GetFileVersionInfoSizeA(path, NULL);
4455     USHORT *lang;
4456 
4457     version = HeapAlloc(GetProcessHeap(), 0, size);
4458     GetFileVersionInfoA(path, 0, size, version);
4459 
4460     VerQueryValueA(version, "\\", (LPVOID *)&ffi, &size);
4461     *vercheck = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
4462     sprintf(*vercheck, "%d.%d.%d.%d", HIWORD(ffi->dwFileVersionMS),
4463             LOWORD(ffi->dwFileVersionMS), HIWORD(ffi->dwFileVersionLS),
4464             LOWORD(ffi->dwFileVersionLS));
4465     *verchecksz = lstrlenA(*vercheck);
4466 
4467     VerQueryValueA(version, "\\VarFileInfo\\Translation", (void **)&lang, &size);
4468     *langcheck = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
4469     sprintf(*langcheck, "%d", *lang);
4470     *langchecksz = lstrlenA(*langcheck);
4471 
4472     HeapFree(GetProcessHeap(), 0, version);
4473 }
4474 
4475 static void test_MsiGetFileVersion(void)
4476 {
4477     UINT r;
4478     DWORD versz, langsz;
4479     char version[MAX_PATH];
4480     char lang[MAX_PATH];
4481     char path[MAX_PATH];
4482     LPSTR vercheck, langcheck;
4483     DWORD verchecksz, langchecksz;
4484 
4485     /* NULL szFilePath */
4486     r = MsiGetFileVersionA(NULL, NULL, NULL, NULL, NULL);
4487     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4488 
4489     versz = MAX_PATH;
4490     langsz = MAX_PATH;
4491     lstrcpyA(version, "version");
4492     lstrcpyA(lang, "lang");
4493     r = MsiGetFileVersionA(NULL, version, &versz, lang, &langsz);
4494     ok(r == ERROR_INVALID_PARAMETER,
4495        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4496     ok(!lstrcmpA(version, "version"),
4497        "Expected version to be unchanged, got %s\n", version);
4498     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4499     ok(!lstrcmpA(lang, "lang"),
4500        "Expected lang to be unchanged, got %s\n", lang);
4501     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4502 
4503     /* empty szFilePath */
4504     r = MsiGetFileVersionA("", NULL, NULL, NULL, NULL);
4505     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4506 
4507     versz = MAX_PATH;
4508     langsz = MAX_PATH;
4509     lstrcpyA(version, "version");
4510     lstrcpyA(lang, "lang");
4511     r = MsiGetFileVersionA("", version, &versz, lang, &langsz);
4512     ok(r == ERROR_FILE_NOT_FOUND,
4513        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4514     ok(!lstrcmpA(version, "version"),
4515        "Expected version to be unchanged, got %s\n", version);
4516     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4517     ok(!lstrcmpA(lang, "lang"),
4518        "Expected lang to be unchanged, got %s\n", lang);
4519     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4520 
4521     /* nonexistent szFilePath */
4522     versz = MAX_PATH;
4523     langsz = MAX_PATH;
4524     lstrcpyA(version, "version");
4525     lstrcpyA(lang, "lang");
4526     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
4527     ok(r == ERROR_FILE_NOT_FOUND,
4528        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4529     ok(!lstrcmpA(version, "version"),
4530        "Expected version to be unchanged, got %s\n", version);
4531     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4532     ok(!lstrcmpA(lang, "lang"),
4533        "Expected lang to be unchanged, got %s\n", lang);
4534     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4535 
4536     /* nonexistent szFilePath, valid lpVersionBuf, NULL pcchVersionBuf */
4537     versz = MAX_PATH;
4538     langsz = MAX_PATH;
4539     lstrcpyA(version, "version");
4540     lstrcpyA(lang, "lang");
4541     r = MsiGetFileVersionA("nonexistent", version, NULL, lang, &langsz);
4542     ok(r == ERROR_INVALID_PARAMETER,
4543        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4544     ok(!lstrcmpA(version, "version"),
4545        "Expected version to be unchanged, got %s\n", version);
4546     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4547     ok(!lstrcmpA(lang, "lang"),
4548        "Expected lang to be unchanged, got %s\n", lang);
4549     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4550 
4551     /* nonexistent szFilePath, valid lpLangBuf, NULL pcchLangBuf */
4552     versz = MAX_PATH;
4553     langsz = MAX_PATH;
4554     lstrcpyA(version, "version");
4555     lstrcpyA(lang, "lang");
4556     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, NULL);
4557     ok(r == ERROR_INVALID_PARAMETER,
4558        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4559     ok(!lstrcmpA(version, "version"),
4560        "Expected version to be unchanged, got %s\n", version);
4561     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4562     ok(!lstrcmpA(lang, "lang"),
4563        "Expected lang to be unchanged, got %s\n", lang);
4564     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4565 
4566     /* nonexistent szFilePath, valid lpVersionBuf, pcchVersionBuf is zero */
4567     versz = 0;
4568     langsz = MAX_PATH;
4569     lstrcpyA(version, "version");
4570     lstrcpyA(lang, "lang");
4571     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
4572     ok(r == ERROR_FILE_NOT_FOUND,
4573        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4574     ok(!lstrcmpA(version, "version"),
4575        "Expected version to be unchanged, got %s\n", version);
4576     ok(versz == 0, "Expected 0, got %d\n", versz);
4577     ok(!lstrcmpA(lang, "lang"),
4578        "Expected lang to be unchanged, got %s\n", lang);
4579     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4580 
4581     /* nonexistent szFilePath, valid lpLangBuf, pcchLangBuf is zero */
4582     versz = MAX_PATH;
4583     langsz = 0;
4584     lstrcpyA(version, "version");
4585     lstrcpyA(lang, "lang");
4586     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
4587     ok(r == ERROR_FILE_NOT_FOUND,
4588        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4589     ok(!lstrcmpA(version, "version"),
4590        "Expected version to be unchanged, got %s\n", version);
4591     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4592     ok(!lstrcmpA(lang, "lang"),
4593        "Expected lang to be unchanged, got %s\n", lang);
4594     ok(langsz == 0, "Expected 0, got %d\n", langsz);
4595 
4596     /* nonexistent szFilePath, rest NULL */
4597     r = MsiGetFileVersionA("nonexistent", NULL, NULL, NULL, NULL);
4598     ok(r == ERROR_FILE_NOT_FOUND,
4599        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4600 
4601     create_file("ver.txt", "ver.txt", 20);
4602 
4603     /* file exists, no version information */
4604     r = MsiGetFileVersionA("ver.txt", NULL, NULL, NULL, NULL);
4605     ok(r == ERROR_FILE_INVALID, "Expected ERROR_FILE_INVALID, got %d\n", r);
4606 
4607     versz = MAX_PATH;
4608     langsz = MAX_PATH;
4609     lstrcpyA(version, "version");
4610     lstrcpyA(lang, "lang");
4611     r = MsiGetFileVersionA("ver.txt", version, &versz, lang, &langsz);
4612     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4613     ok(!lstrcmpA(version, "version"),
4614        "Expected version to be unchanged, got %s\n", version);
4615     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4616     ok(!lstrcmpA(lang, "lang"),
4617        "Expected lang to be unchanged, got %s\n", lang);
4618     ok(r == ERROR_FILE_INVALID,
4619        "Expected ERROR_FILE_INVALID, got %d\n", r);
4620 
4621     DeleteFileA("ver.txt");
4622 
4623     /* relative path, has version information */
4624     versz = MAX_PATH;
4625     langsz = MAX_PATH;
4626     lstrcpyA(version, "version");
4627     lstrcpyA(lang, "lang");
4628     r = MsiGetFileVersionA("kernel32.dll", version, &versz, lang, &langsz);
4629     todo_wine
4630     {
4631         ok(r == ERROR_FILE_NOT_FOUND,
4632            "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4633         ok(!lstrcmpA(version, "version"),
4634            "Expected version to be unchanged, got %s\n", version);
4635         ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4636         ok(!lstrcmpA(lang, "lang"),
4637            "Expected lang to be unchanged, got %s\n", lang);
4638         ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4639     }
4640 
4641     GetSystemDirectoryA(path, MAX_PATH);
4642     lstrcatA(path, "\\kernel32.dll");
4643 
4644     get_version_info(path, &vercheck, &verchecksz, &langcheck, &langchecksz);
4645 
4646     /* absolute path, has version information */
4647     versz = MAX_PATH;
4648     langsz = MAX_PATH;
4649     lstrcpyA(version, "version");
4650     lstrcpyA(lang, "lang");
4651     r = MsiGetFileVersionA(path, version, &versz, lang, &langsz);
4652     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4653     if (langchecksz && !langsz)
4654     {
4655         win_skip("broken MsiGetFileVersionA detected\n");
4656         HeapFree(GetProcessHeap(), 0, vercheck);
4657         HeapFree(GetProcessHeap(), 0, langcheck);
4658         return;
4659     }
4660     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4661     ok(strstr(lang, langcheck) != NULL, "Expected \"%s\" in \"%s\"\n", langcheck, lang);
4662     ok(!lstrcmpA(version, vercheck),
4663         "Expected %s, got %s\n", vercheck, version);
4664 
4665     /* only check version */
4666     versz = MAX_PATH;
4667     lstrcpyA(version, "version");
4668     r = MsiGetFileVersionA(path, version, &versz, NULL, NULL);
4669     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4670     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4671     ok(!lstrcmpA(version, vercheck),
4672        "Expected %s, got %s\n", vercheck, version);
4673 
4674     /* only check language */
4675     langsz = MAX_PATH;
4676     lstrcpyA(lang, "lang");
4677     r = MsiGetFileVersionA(path, NULL, NULL, lang, &langsz);
4678     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4679     ok(strstr(lang, langcheck) != NULL, "Expected \"%s\" in \"%s\"\n", langcheck, lang);
4680 
4681     /* check neither version nor language */
4682     r = MsiGetFileVersionA(path, NULL, NULL, NULL, NULL);
4683     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4684 
4685     /* get pcchVersionBuf */
4686     versz = MAX_PATH;
4687     r = MsiGetFileVersionA(path, NULL, &versz, NULL, NULL);
4688     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4689     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4690 
4691     /* get pcchLangBuf */
4692     langsz = MAX_PATH;
4693     r = MsiGetFileVersionA(path, NULL, NULL, NULL, &langsz);
4694     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4695     ok(langsz >= langchecksz, "Expected %d >= %d\n", langsz, langchecksz);
4696 
4697     /* pcchVersionBuf not big enough */
4698     versz = 5;
4699     lstrcpyA(version, "version");
4700     r = MsiGetFileVersionA(path, version, &versz, NULL, NULL);
4701     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4702     ok(!strncmp(version, vercheck, 4),
4703        "Expected first 4 characters of \"%s\", got \"%s\"\n", vercheck, version);
4704     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4705 
4706     /* pcchLangBuf not big enough */
4707     langsz = 4;
4708     lstrcpyA(lang, "lang");
4709     r = MsiGetFileVersionA(path, NULL, NULL, lang, &langsz);
4710     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4711     ok(lstrcmpA(lang, "lang"), "lang not set\n");
4712     ok(langsz >= langchecksz, "Expected %d >= %d\n", langsz, langchecksz);
4713 
4714     /* pcchVersionBuf big enough, pcchLangBuf not big enough */
4715     versz = MAX_PATH;
4716     langsz = 0;
4717     lstrcpyA(version, "version");
4718     r = MsiGetFileVersionA(path, version, &versz, NULL, &langsz);
4719     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4720     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4721     ok(!lstrcmpA(version, vercheck), "Expected \"%s\", got \"%s\"\n", vercheck, version);
4722     ok(langsz >= langchecksz && langsz < MAX_PATH, "Expected %d >= %d\n", langsz, langchecksz);
4723 
4724     /* pcchVersionBuf not big enough, pcchLangBuf big enough */
4725     versz = 5;
4726     langsz = MAX_PATH;
4727     lstrcpyA(lang, "lang");
4728     r = MsiGetFileVersionA(path, NULL, &versz, lang, &langsz);
4729     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4730     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4731     ok(langsz >= langchecksz && langsz < MAX_PATH, "Expected %d >= %d\n", langsz, langchecksz);
4732     ok(strstr(lang, langcheck) != NULL, "expected %s in %s\n", langcheck, lang);
4733 
4734     /* NULL pcchVersionBuf and pcchLangBuf */
4735     r = MsiGetFileVersionA(path, version, NULL, lang, NULL);
4736     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4737 
4738     /* All NULL except szFilePath */
4739     r = MsiGetFileVersionA(path, NULL, NULL, NULL, NULL);
4740     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4741 
4742     HeapFree(GetProcessHeap(), 0, vercheck);
4743     HeapFree(GetProcessHeap(), 0, langcheck);
4744 }
4745 
4746 static void test_MsiGetProductInfo(void)
4747 {
4748     UINT r;
4749     LONG res;
4750     HKEY propkey, source;
4751     HKEY prodkey, localkey;
4752     CHAR prodcode[MAX_PATH];
4753     CHAR prod_squashed[MAX_PATH];
4754     CHAR packcode[MAX_PATH];
4755     CHAR pack_squashed[MAX_PATH];
4756     CHAR buf[MAX_PATH];
4757     CHAR keypath[MAX_PATH];
4758     LPSTR usersid;
4759     DWORD sz, val = 42;
4760     REGSAM access = KEY_ALL_ACCESS;
4761 
4762     create_test_guid(prodcode, prod_squashed);
4763     create_test_guid(packcode, pack_squashed);
4764     usersid = get_user_sid();
4765 
4766     if (is_wow64)
4767         access |= KEY_WOW64_64KEY;
4768 
4769     /* NULL szProduct */
4770     sz = MAX_PATH;
4771     lstrcpyA(buf, "apple");
4772     r = MsiGetProductInfoA(NULL, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4773     ok(r == ERROR_INVALID_PARAMETER,
4774        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4775     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4776     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4777 
4778     /* empty szProduct */
4779     sz = MAX_PATH;
4780     lstrcpyA(buf, "apple");
4781     r = MsiGetProductInfoA("", INSTALLPROPERTY_HELPLINKA, buf, &sz);
4782     ok(r == ERROR_INVALID_PARAMETER,
4783        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4784     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4785     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4786 
4787     /* garbage szProduct */
4788     sz = MAX_PATH;
4789     lstrcpyA(buf, "apple");
4790     r = MsiGetProductInfoA("garbage", INSTALLPROPERTY_HELPLINKA, buf, &sz);
4791     ok(r == ERROR_INVALID_PARAMETER,
4792        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4793     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4794     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4795 
4796     /* guid without brackets */
4797     sz = MAX_PATH;
4798     lstrcpyA(buf, "apple");
4799     r = MsiGetProductInfoA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
4800                            INSTALLPROPERTY_HELPLINKA, buf, &sz);
4801     ok(r == ERROR_INVALID_PARAMETER,
4802        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4803     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4804     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4805 
4806     /* guid with brackets */
4807     sz = MAX_PATH;
4808     lstrcpyA(buf, "apple");
4809     r = MsiGetProductInfoA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
4810                            INSTALLPROPERTY_HELPLINKA, buf, &sz);
4811     ok(r == ERROR_UNKNOWN_PRODUCT,
4812        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4813     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4814     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4815 
4816     /* same length as guid, but random */
4817     sz = MAX_PATH;
4818     lstrcpyA(buf, "apple");
4819     r = MsiGetProductInfoA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
4820                            INSTALLPROPERTY_HELPLINKA, buf, &sz);
4821     ok(r == ERROR_INVALID_PARAMETER,
4822        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4823     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4824     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4825 
4826     /* not installed, NULL szAttribute */
4827     sz = MAX_PATH;
4828     lstrcpyA(buf, "apple");
4829     r = MsiGetProductInfoA(prodcode, NULL, buf, &sz);
4830     ok(r == ERROR_INVALID_PARAMETER,
4831        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4832     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4833     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4834 
4835     /* not installed, NULL lpValueBuf */
4836     sz = MAX_PATH;
4837     lstrcpyA(buf, "apple");
4838     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, &sz);
4839     ok(r == ERROR_UNKNOWN_PRODUCT,
4840        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4841     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4842     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4843 
4844     /* not installed, NULL pcchValueBuf */
4845     sz = MAX_PATH;
4846     lstrcpyA(buf, "apple");
4847     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, NULL);
4848     ok(r == ERROR_INVALID_PARAMETER,
4849        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4850     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4851     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4852 
4853     /* created guid cannot possibly be an installed product code */
4854     sz = MAX_PATH;
4855     lstrcpyA(buf, "apple");
4856     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4857     ok(r == ERROR_UNKNOWN_PRODUCT,
4858        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4859     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4860     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4861 
4862     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
4863     lstrcatA(keypath, usersid);
4864     lstrcatA(keypath, "\\Installer\\Products\\");
4865     lstrcatA(keypath, prod_squashed);
4866 
4867     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4868     if (res == ERROR_ACCESS_DENIED)
4869     {
4870         skip("Not enough rights to perform tests\n");
4871         LocalFree(usersid);
4872         return;
4873     }
4874     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4875 
4876     /* managed product code exists */
4877     sz = MAX_PATH;
4878     lstrcpyA(buf, "apple");
4879     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4880     ok(r == ERROR_UNKNOWN_PROPERTY,
4881        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4882     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4883     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4884 
4885     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4886     RegCloseKey(prodkey);
4887 
4888     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
4889     lstrcatA(keypath, usersid);
4890     lstrcatA(keypath, "\\Products\\");
4891     lstrcatA(keypath, prod_squashed);
4892 
4893     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
4894     if (res == ERROR_ACCESS_DENIED)
4895     {
4896         skip("Not enough rights to perform tests\n");
4897         LocalFree(usersid);
4898         return;
4899     }
4900     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4901 
4902     /* local user product code exists */
4903     sz = MAX_PATH;
4904     lstrcpyA(buf, "apple");
4905     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4906     ok(r == ERROR_UNKNOWN_PRODUCT,
4907        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4908     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4909     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4910 
4911     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
4912     lstrcatA(keypath, usersid);
4913     lstrcatA(keypath, "\\Installer\\Products\\");
4914     lstrcatA(keypath, prod_squashed);
4915 
4916     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4917     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4918 
4919     /* both local and managed product code exist */
4920     sz = MAX_PATH;
4921     lstrcpyA(buf, "apple");
4922     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4923     ok(r == ERROR_UNKNOWN_PROPERTY,
4924        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4925     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4926     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4927 
4928     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
4929     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4930 
4931     /* InstallProperties key 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, ""), "Expected \"\", got \"%s\"\n", buf);
4937     ok(sz == 0, "Expected 0, got %d\n", sz);
4938 
4939     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
4940     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4941 
4942     /* HelpLink value exists */
4943     sz = MAX_PATH;
4944     lstrcpyA(buf, "apple");
4945     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4946     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4947     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
4948     ok(sz == 4, "Expected 4, got %d\n", sz);
4949 
4950     /* pcchBuf is NULL */
4951     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, NULL);
4952     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4953 
4954     /* lpValueBuf is NULL */
4955     sz = MAX_PATH;
4956     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, &sz);
4957     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4958     ok(sz == 4, "Expected 4, got %d\n", sz);
4959 
4960     /* lpValueBuf is NULL, pcchValueBuf is too small */
4961     sz = 2;
4962     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, &sz);
4963     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4964     ok(sz == 4, "Expected 4, got %d\n", sz);
4965 
4966     /* lpValueBuf is non-NULL, pcchValueBuf is too small */
4967     sz = 2;
4968     lstrcpyA(buf, "apple");
4969     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4970     ok(!lstrcmpA(buf, "apple"), "Expected buf to remain unchanged, got \"%s\"\n", buf);
4971     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4972     ok(sz == 4, "Expected 4, got %d\n", sz);
4973 
4974     /* lpValueBuf is non-NULL, pcchValueBuf is exactly 4 */
4975     sz = 4;
4976     lstrcpyA(buf, "apple");
4977     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4978     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4979     ok(!lstrcmpA(buf, "apple"),
4980        "Expected buf to remain unchanged, got \"%s\"\n", buf);
4981     ok(sz == 4, "Expected 4, got %d\n", sz);
4982 
4983     res = RegSetValueExA(propkey, "IMadeThis", 0, REG_SZ, (LPBYTE)"random", 7);
4984     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4985 
4986     /* random property not supported by MSI, value exists */
4987     sz = MAX_PATH;
4988     lstrcpyA(buf, "apple");
4989     r = MsiGetProductInfoA(prodcode, "IMadeThis", buf, &sz);
4990     ok(r == ERROR_UNKNOWN_PROPERTY,
4991        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4992     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4993     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4994 
4995     RegDeleteValueA(propkey, "IMadeThis");
4996     RegDeleteValueA(propkey, "HelpLink");
4997     delete_key(propkey, "", access & KEY_WOW64_64KEY);
4998     delete_key(localkey, "", access & KEY_WOW64_64KEY);
4999     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
5000     RegCloseKey(propkey);
5001     RegCloseKey(localkey);
5002     RegCloseKey(prodkey);
5003 
5004     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
5005     lstrcatA(keypath, prod_squashed);
5006 
5007     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
5008     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5009 
5010     /* user product key exists */
5011     sz = MAX_PATH;
5012     lstrcpyA(buf, "apple");
5013     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5014     ok(r == ERROR_UNKNOWN_PROPERTY,
5015        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5016     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
5017     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5018 
5019     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
5020     lstrcatA(keypath, usersid);
5021     lstrcatA(keypath, "\\Products\\");
5022     lstrcatA(keypath, prod_squashed);
5023 
5024     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
5025     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5026 
5027     /* local user product key exists */
5028     sz = MAX_PATH;
5029     lstrcpyA(buf, "apple");
5030     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5031     ok(r == ERROR_UNKNOWN_PROPERTY,
5032        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5033     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
5034     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5035 
5036     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
5037     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5038 
5039     /* InstallProperties key 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, ""), "Expected \"\", got \"%s\"\n", buf);
5045     ok(sz == 0, "Expected 0, got %d\n", sz);
5046 
5047     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
5048     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5049 
5050     /* HelpLink value exists */
5051     sz = MAX_PATH;
5052     lstrcpyA(buf, "apple");
5053     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5054     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5055     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
5056     ok(sz == 4, "Expected 4, got %d\n", sz);
5057 
5058     RegDeleteValueA(propkey, "HelpLink");
5059     delete_key(propkey, "", access & KEY_WOW64_64KEY);
5060     delete_key(localkey, "", access & KEY_WOW64_64KEY);
5061     RegDeleteKeyA(prodkey, "");
5062     RegCloseKey(propkey);
5063     RegCloseKey(localkey);
5064     RegCloseKey(prodkey);
5065 
5066     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
5067     lstrcatA(keypath, prod_squashed);
5068 
5069     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
5070     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5071 
5072     /* classes product key exists */
5073     sz = MAX_PATH;
5074     lstrcpyA(buf, "apple");
5075     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5076     ok(r == ERROR_UNKNOWN_PROPERTY,
5077        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5078     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
5079     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5080 
5081     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
5082     lstrcatA(keypath, usersid);
5083     lstrcatA(keypath, "\\Products\\");
5084     lstrcatA(keypath, prod_squashed);
5085 
5086     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
5087     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5088 
5089     /* local user product key exists */
5090     sz = MAX_PATH;
5091     lstrcpyA(buf, "apple");
5092     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5093     ok(r == ERROR_UNKNOWN_PROPERTY,
5094        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5095     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
5096     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5097 
5098     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
5099     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5100 
5101     /* InstallProperties key exists */
5102     sz = MAX_PATH;
5103     lstrcpyA(buf, "apple");
5104     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5105     ok(r == ERROR_UNKNOWN_PROPERTY,
5106        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5107     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
5108     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5109 
5110     delete_key(propkey, "", access & KEY_WOW64_64KEY);
5111     delete_key(localkey, "", access & KEY_WOW64_64KEY);
5112     RegCloseKey(propkey);
5113     RegCloseKey(localkey);
5114 
5115     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
5116     lstrcatA(keypath, "S-1-5-18\\\\Products\\");
5117     lstrcatA(keypath, prod_squashed);
5118 
5119     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
5120     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5121 
5122     /* Local System product key exists */
5123     sz = MAX_PATH;
5124     lstrcpyA(buf, "apple");
5125     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5126     ok(r == ERROR_UNKNOWN_PROPERTY,
5127         "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5128     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
5129     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5130 
5131     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
5132     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5133 
5134     /* InstallProperties key 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, ""), "Expected \"\", got \"%s\"\n", buf);
5140     ok(sz == 0, "Expected 0, got %d\n", sz);
5141 
5142     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
5143     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5144 
5145     /* HelpLink value exists */
5146     sz = MAX_PATH;
5147     lstrcpyA(buf, "apple");
5148     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5149     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5150     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
5151     ok(sz == 4, "Expected 4, got %d\n", sz);
5152 
5153     res = RegSetValueExA(propkey, "HelpLink", 0, REG_DWORD,
5154                          (const BYTE *)&val, sizeof(DWORD));
5155     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5156 
5157     /* HelpLink type is REG_DWORD */
5158     sz = MAX_PATH;
5159     lstrcpyA(buf, "apple");
5160     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5161     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5162     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5163     ok(sz == 2, "Expected 2, got %d\n", sz);
5164 
5165     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
5166     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5167 
5168     /* DisplayName value exists */
5169     sz = MAX_PATH;
5170     lstrcpyA(buf, "apple");
5171     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
5172     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5173     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
5174     ok(sz == 4, "Expected 4, got %d\n", sz);
5175 
5176     res = RegSetValueExA(propkey, "DisplayName", 0, REG_DWORD,
5177                          (const BYTE *)&val, sizeof(DWORD));
5178     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5179 
5180     /* DisplayName type is REG_DWORD */
5181     sz = MAX_PATH;
5182     lstrcpyA(buf, "apple");
5183     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
5184     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5185     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5186     ok(sz == 2, "Expected 2, got %d\n", sz);
5187 
5188     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"1.1.1", 6);
5189     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5190 
5191     /* DisplayVersion value exists */
5192     sz = MAX_PATH;
5193     lstrcpyA(buf, "apple");
5194     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
5195     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5196     ok(!lstrcmpA(buf, "1.1.1"), "Expected \"1.1.1\", got \"%s\"\n", buf);
5197     ok(sz == 5, "Expected 5, got %d\n", sz);
5198 
5199     res = RegSetValueExA(propkey, "DisplayVersion", 0,
5200                          REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
5201     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5202 
5203     /* DisplayVersion type is REG_DWORD */
5204     sz = MAX_PATH;
5205     lstrcpyA(buf, "apple");
5206     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
5207     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5208     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5209     ok(sz == 2, "Expected 2, got %d\n", sz);
5210 
5211     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"tele", 5);
5212     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5213 
5214     /* HelpTelephone value exists */
5215     sz = MAX_PATH;
5216     lstrcpyA(buf, "apple");
5217     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
5218     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5219     ok(!lstrcmpA(buf, "tele"), "Expected \"tele\", got \"%s\"\n", buf);
5220     ok(sz == 4, "Expected 4, got %d\n", sz);
5221 
5222     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_DWORD,
5223                          (const BYTE *)&val, sizeof(DWORD));
5224     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5225 
5226     /* HelpTelephone type is REG_DWORD */
5227     sz = MAX_PATH;
5228     lstrcpyA(buf, "apple");
5229     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
5230     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5231     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5232     ok(sz == 2, "Expected 2, got %d\n", sz);
5233 
5234     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
5235     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5236 
5237     /* InstallLocation value exists */
5238     sz = MAX_PATH;
5239     lstrcpyA(buf, "apple");
5240     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
5241     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5242     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
5243     ok(sz == 3, "Expected 3, got %d\n", sz);
5244 
5245     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_DWORD,
5246                          (const BYTE *)&val, sizeof(DWORD));
5247     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5248 
5249     /* InstallLocation type is REG_DWORD */
5250     sz = MAX_PATH;
5251     lstrcpyA(buf, "apple");
5252     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
5253     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5254     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5255     ok(sz == 2, "Expected 2, got %d\n", sz);
5256 
5257     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
5258     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5259 
5260     /* InstallSource value exists */
5261     sz = MAX_PATH;
5262     lstrcpyA(buf, "apple");
5263     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
5264     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5265     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
5266     ok(sz == 6, "Expected 6, got %d\n", sz);
5267 
5268     res = RegSetValueExA(propkey, "InstallSource", 0, REG_DWORD,
5269                          (const BYTE *)&val, sizeof(DWORD));
5270     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5271 
5272     /* InstallSource type is REG_DWORD */
5273     sz = MAX_PATH;
5274     lstrcpyA(buf, "apple");
5275     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
5276     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5277     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5278     ok(sz == 2, "Expected 2, got %d\n", sz);
5279 
5280     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
5281     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5282 
5283     /* InstallDate value exists */
5284     sz = MAX_PATH;
5285     lstrcpyA(buf, "apple");
5286     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
5287     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5288     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
5289     ok(sz == 4, "Expected 4, got %d\n", sz);
5290 
5291     res = RegSetValueExA(propkey, "InstallDate", 0, REG_DWORD,
5292                          (const BYTE *)&val, sizeof(DWORD));
5293     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5294 
5295     /* InstallDate type is REG_DWORD */
5296     sz = MAX_PATH;
5297     lstrcpyA(buf, "apple");
5298     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
5299     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5300     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5301     ok(sz == 2, "Expected 2, got %d\n", sz);
5302 
5303     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
5304     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5305 
5306     /* Publisher value exists */
5307     sz = MAX_PATH;
5308     lstrcpyA(buf, "apple");
5309     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PUBLISHERA, buf, &sz);
5310     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5311     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
5312     ok(sz == 3, "Expected 3, got %d\n", sz);
5313 
5314     res = RegSetValueExA(propkey, "Publisher", 0, REG_DWORD,
5315                          (const BYTE *)&val, sizeof(DWORD));
5316     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5317 
5318     /* Publisher type is REG_DWORD */
5319     sz = MAX_PATH;
5320     lstrcpyA(buf, "apple");
5321     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PUBLISHERA, buf, &sz);
5322     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5323     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5324     ok(sz == 2, "Expected 2, got %d\n", sz);
5325 
5326     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"pack", 5);
5327     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5328 
5329     /* LocalPackage value exists */
5330     sz = MAX_PATH;
5331     lstrcpyA(buf, "apple");
5332     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
5333     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5334     ok(!lstrcmpA(buf, "pack"), "Expected \"pack\", got \"%s\"\n", buf);
5335     ok(sz == 4, "Expected 4, got %d\n", sz);
5336 
5337     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_DWORD,
5338                          (const BYTE *)&val, sizeof(DWORD));
5339     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5340 
5341     /* LocalPackage type is REG_DWORD */
5342     sz = MAX_PATH;
5343     lstrcpyA(buf, "apple");
5344     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
5345     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5346     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5347     ok(sz == 2, "Expected 2, got %d\n", sz);
5348 
5349     res = RegSetValueExA(propkey, "UrlInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
5350     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5351 
5352     /* UrlInfoAbout value exists */
5353     sz = MAX_PATH;
5354     lstrcpyA(buf, "apple");
5355     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
5356     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5357     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
5358     ok(sz == 5, "Expected 5, got %d\n", sz);
5359 
5360     res = RegSetValueExA(propkey, "UrlInfoAbout", 0, REG_DWORD,
5361                          (const BYTE *)&val, sizeof(DWORD));
5362     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5363 
5364     /* UrlInfoAbout type is REG_DWORD */
5365     sz = MAX_PATH;
5366     lstrcpyA(buf, "apple");
5367     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
5368     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5369     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5370     ok(sz == 2, "Expected 2, got %d\n", sz);
5371 
5372     res = RegSetValueExA(propkey, "UrlUpdateInfo", 0, REG_SZ, (LPBYTE)"info", 5);
5373     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5374 
5375     /* UrlUpdateInfo value exists */
5376     sz = MAX_PATH;
5377     lstrcpyA(buf, "apple");
5378     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
5379     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5380     ok(!lstrcmpA(buf, "info"), "Expected \"info\", got \"%s\"\n", buf);
5381     ok(sz == 4, "Expected 4, got %d\n", sz);
5382 
5383     res = RegSetValueExA(propkey, "UrlUpdateInfo", 0, REG_DWORD,
5384                          (const BYTE *)&val, sizeof(DWORD));
5385     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5386 
5387     /* UrlUpdateInfo type is REG_DWORD */
5388     sz = MAX_PATH;
5389     lstrcpyA(buf, "apple");
5390     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
5391     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5392     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5393     ok(sz == 2, "Expected 2, got %d\n", sz);
5394 
5395     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"1", 2);
5396     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5397 
5398     /* VersionMinor value exists */
5399     sz = MAX_PATH;
5400     lstrcpyA(buf, "apple");
5401     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
5402     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5403     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
5404     ok(sz == 1, "Expected 1, got %d\n", sz);
5405 
5406     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_DWORD,
5407                          (const BYTE *)&val, sizeof(DWORD));
5408     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5409 
5410     /* VersionMinor type is REG_DWORD */
5411     sz = MAX_PATH;
5412     lstrcpyA(buf, "apple");
5413     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
5414     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5415     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5416     ok(sz == 2, "Expected 2, got %d\n", sz);
5417 
5418     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"1", 2);
5419     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5420 
5421     /* VersionMajor value exists */
5422     sz = MAX_PATH;
5423     lstrcpyA(buf, "apple");
5424     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
5425     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5426     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
5427     ok(sz == 1, "Expected 1, got %d\n", sz);
5428 
5429     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_DWORD,
5430                          (const BYTE *)&val, sizeof(DWORD));
5431     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5432 
5433     /* VersionMajor type is REG_DWORD */
5434     sz = MAX_PATH;
5435     lstrcpyA(buf, "apple");
5436     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
5437     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5438     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5439     ok(sz == 2, "Expected 2, got %d\n", sz);
5440 
5441     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
5442     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5443 
5444     /* ProductID value exists */
5445     sz = MAX_PATH;
5446     lstrcpyA(buf, "apple");
5447     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
5448     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5449     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
5450     ok(sz == 2, "Expected 2, got %d\n", sz);
5451 
5452     res = RegSetValueExA(propkey, "ProductID", 0, REG_DWORD,
5453                          (const BYTE *)&val, sizeof(DWORD));
5454     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5455 
5456     /* ProductID type is REG_DWORD */
5457     sz = MAX_PATH;
5458     lstrcpyA(buf, "apple");
5459     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
5460     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5461     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5462     ok(sz == 2, "Expected 2, got %d\n", sz);
5463 
5464     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
5465     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5466 
5467     /* RegCompany value exists */
5468     sz = MAX_PATH;
5469     lstrcpyA(buf, "apple");
5470     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
5471     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5472     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
5473     ok(sz == 4, "Expected 4, got %d\n", sz);
5474 
5475     res = RegSetValueExA(propkey, "RegCompany", 0, REG_DWORD,
5476                          (const BYTE *)&val, sizeof(DWORD));
5477     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5478 
5479     /* RegCompany type is REG_DWORD */
5480     sz = MAX_PATH;
5481     lstrcpyA(buf, "apple");
5482     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
5483     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5484     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5485     ok(sz == 2, "Expected 2, got %d\n", sz);
5486 
5487     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"own", 4);
5488     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5489 
5490     /* RegOwner value exists */
5491     sz = MAX_PATH;
5492     lstrcpyA(buf, "apple");
5493     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGOWNERA, buf, &sz);
5494     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5495     ok(!lstrcmpA(buf, "own"), "Expected \"own\", got \"%s\"\n", buf);
5496     ok(sz == 3, "Expected 3, got %d\n", sz);
5497 
5498     res = RegSetValueExA(propkey, "RegOwner", 0, REG_DWORD,
5499                          (const BYTE *)&val, sizeof(DWORD));
5500     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5501 
5502     /* RegOwner type is REG_DWORD */
5503     sz = MAX_PATH;
5504     lstrcpyA(buf, "apple");
5505     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGOWNERA, buf, &sz);
5506     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5507     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5508     ok(sz == 2, "Expected 2, got %d\n", sz);
5509 
5510     res = RegSetValueExA(propkey, "InstanceType", 0, REG_SZ, (LPBYTE)"type", 5);
5511     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5512 
5513     /* InstanceType value exists */
5514     sz = MAX_PATH;
5515     lstrcpyA(buf, "apple");
5516     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5517     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5518     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5519     ok(sz == 0, "Expected 0, got %d\n", sz);
5520 
5521     res = RegSetValueExA(propkey, "InstanceType", 0, REG_DWORD,
5522                          (const BYTE *)&val, sizeof(DWORD));
5523     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5524 
5525     /* InstanceType type is REG_DWORD */
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, ""), "Expected \"\", got \"%s\"\n", buf);
5531     ok(sz == 0, "Expected 0, got %d\n", sz);
5532 
5533     res = RegSetValueExA(prodkey, "InstanceType", 0, REG_SZ, (LPBYTE)"type", 5);
5534     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5535 
5536     /* InstanceType value exists */
5537     sz = MAX_PATH;
5538     lstrcpyA(buf, "apple");
5539     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5540     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5541     ok(!lstrcmpA(buf, "type"), "Expected \"type\", got \"%s\"\n", buf);
5542     ok(sz == 4, "Expected 4, got %d\n", sz);
5543 
5544     res = RegSetValueExA(prodkey, "InstanceType", 0, REG_DWORD,
5545                          (const BYTE *)&val, sizeof(DWORD));
5546     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5547 
5548     /* InstanceType type is REG_DWORD */
5549     sz = MAX_PATH;
5550     lstrcpyA(buf, "apple");
5551     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5552     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5553     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5554     ok(sz == 2, "Expected 2, got %d\n", sz);
5555 
5556     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"tforms", 7);
5557     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5558 
5559     /* Transforms value exists */
5560     sz = MAX_PATH;
5561     lstrcpyA(buf, "apple");
5562     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5563     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5564     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5565     ok(sz == 0, "Expected 0, got %d\n", sz);
5566 
5567     res = RegSetValueExA(propkey, "Transforms", 0, REG_DWORD,
5568                          (const BYTE *)&val, sizeof(DWORD));
5569     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5570 
5571     /* Transforms type is REG_DWORD */
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, ""), "Expected \"\", got \"%s\"\n", buf);
5577     ok(sz == 0, "Expected 0, got %d\n", sz);
5578 
5579     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"tforms", 7);
5580     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5581 
5582     /* Transforms value exists */
5583     sz = MAX_PATH;
5584     lstrcpyA(buf, "apple");
5585     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5586     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5587     ok(!lstrcmpA(buf, "tforms"), "Expected \"tforms\", got \"%s\"\n", buf);
5588     ok(sz == 6, "Expected 6, got %d\n", sz);
5589 
5590     res = RegSetValueExA(prodkey, "Transforms", 0, REG_DWORD,
5591                          (const BYTE *)&val, sizeof(DWORD));
5592     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5593 
5594     /* Transforms type is REG_DWORD */
5595     sz = MAX_PATH;
5596     lstrcpyA(buf, "apple");
5597     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5598     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5599     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5600     ok(sz == 2, "Expected 2, got %d\n", sz);
5601 
5602     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
5603     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5604 
5605     /* Language value exists */
5606     sz = MAX_PATH;
5607     lstrcpyA(buf, "apple");
5608     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5609     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5610     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5611     ok(sz == 0, "Expected 0, got %d\n", sz);
5612 
5613     res = RegSetValueExA(propkey, "Language", 0, REG_DWORD,
5614                          (const BYTE *)&val, sizeof(DWORD));
5615     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5616 
5617     /* Language type is REG_DWORD */
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, ""), "Expected \"\", got \"%s\"\n", buf);
5623     ok(sz == 0, "Expected 0, got %d\n", sz);
5624 
5625     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
5626     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5627 
5628     /* Language value exists */
5629     sz = MAX_PATH;
5630     lstrcpyA(buf, "apple");
5631     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5632     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5633     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
5634     ok(sz == 4, "Expected 4, got %d\n", sz);
5635 
5636     res = RegSetValueExA(prodkey, "Language", 0, REG_DWORD,
5637                          (const BYTE *)&val, sizeof(DWORD));
5638     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5639 
5640     /* Language type is REG_DWORD */
5641     sz = MAX_PATH;
5642     lstrcpyA(buf, "apple");
5643     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5644     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5645     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5646     ok(sz == 2, "Expected 2, got %d\n", sz);
5647 
5648     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
5649     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5650 
5651     /* ProductName value exists */
5652     sz = MAX_PATH;
5653     lstrcpyA(buf, "apple");
5654     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5655     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5656     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5657     ok(sz == 0, "Expected 0, got %d\n", sz);
5658 
5659     res = RegSetValueExA(propkey, "ProductName", 0, REG_DWORD,
5660                          (const BYTE *)&val, sizeof(DWORD));
5661     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5662 
5663     /* ProductName type is REG_DWORD */
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, ""), "Expected \"\", got \"%s\"\n", buf);
5669     ok(sz == 0, "Expected 0, got %d\n", sz);
5670 
5671     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
5672     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5673 
5674     /* ProductName value exists */
5675     sz = MAX_PATH;
5676     lstrcpyA(buf, "apple");
5677     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5678     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5679     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
5680     ok(sz == 4, "Expected 4, got %d\n", sz);
5681 
5682     res = RegSetValueExA(prodkey, "ProductName", 0, REG_DWORD,
5683                          (const BYTE *)&val, sizeof(DWORD));
5684     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5685 
5686     /* ProductName type is REG_DWORD */
5687     sz = MAX_PATH;
5688     lstrcpyA(buf, "apple");
5689     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5690     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5691     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5692     ok(sz == 2, "Expected 2, got %d\n", sz);
5693 
5694     res = RegSetValueExA(propkey, "Assignment", 0, REG_SZ, (LPBYTE)"at", 3);
5695     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5696 
5697     /* Assignment value exists */
5698     sz = MAX_PATH;
5699     lstrcpyA(buf, "apple");
5700     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5701     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5702     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5703     ok(sz == 0, "Expected 0, got %d\n", sz);
5704 
5705     res = RegSetValueExA(propkey, "Assignment", 0, REG_DWORD,
5706                          (const BYTE *)&val, sizeof(DWORD));
5707     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5708 
5709     /* Assignment type is REG_DWORD */
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, ""), "Expected \"\", got \"%s\"\n", buf);
5715     ok(sz == 0, "Expected 0, got %d\n", sz);
5716 
5717     res = RegSetValueExA(prodkey, "Assignment", 0, REG_SZ, (LPBYTE)"at", 3);
5718     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5719 
5720     /* Assignment value exists */
5721     sz = MAX_PATH;
5722     lstrcpyA(buf, "apple");
5723     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5724     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5725     ok(!lstrcmpA(buf, "at"), "Expected \"at\", got \"%s\"\n", buf);
5726     ok(sz == 2, "Expected 2, got %d\n", sz);
5727 
5728     res = RegSetValueExA(prodkey, "Assignment", 0, REG_DWORD,
5729                          (const BYTE *)&val, sizeof(DWORD));
5730     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5731 
5732     /* Assignment type is REG_DWORD */
5733     sz = MAX_PATH;
5734     lstrcpyA(buf, "apple");
5735     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5736     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5737     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5738     ok(sz == 2, "Expected 2, got %d\n", sz);
5739 
5740     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
5741     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5742 
5743     /* PackageCode value exists */
5744     sz = MAX_PATH;
5745     lstrcpyA(buf, "apple");
5746     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5747     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5748     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5749     ok(sz == 0, "Expected 0, got %d\n", sz);
5750 
5751     res = RegSetValueExA(propkey, "PackageCode", 0, REG_DWORD,
5752                          (const BYTE *)&val, sizeof(DWORD));
5753     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5754 
5755     /* PackageCode type is REG_DWORD */
5756     sz = MAX_PATH;
5757     lstrcpyA(buf, "apple");
5758     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5759     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5760     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5761     ok(sz == 0, "Expected 0, got %d\n", sz);
5762 
5763     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
5764     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5765 
5766     /* PackageCode value exists */
5767     sz = MAX_PATH;
5768     lstrcpyA(buf, "apple");
5769     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5770     ok(r == ERROR_BAD_CONFIGURATION,
5771        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
5772     ok(!lstrcmpA(buf, "code"), "Expected \"code\", got \"%s\"\n", buf);
5773     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5774 
5775     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_DWORD,
5776                          (const BYTE *)&val, sizeof(DWORD));
5777     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5778 
5779     /* PackageCode type is REG_DWORD */
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, "42"), "Expected \"42\", got \"%s\"\n", buf);
5785     ok(sz == 2, "Expected 2, got %d\n", sz);
5786 
5787     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)pack_squashed, 33);
5788     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5789 
5790     /* PackageCode value exists */
5791     sz = MAX_PATH;
5792     lstrcpyA(buf, "apple");
5793     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5794     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5795     ok(!lstrcmpA(buf, packcode), "Expected \"%s\", got \"%s\"\n", packcode, buf);
5796     ok(sz == 38, "Expected 38, got %d\n", sz);
5797 
5798     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
5799     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5800 
5801     /* Version value exists */
5802     sz = MAX_PATH;
5803     lstrcpyA(buf, "apple");
5804     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5805     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5806     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5807     ok(sz == 0, "Expected 0, got %d\n", sz);
5808 
5809     res = RegSetValueExA(propkey, "Version", 0, REG_DWORD,
5810                          (const BYTE *)&val, sizeof(DWORD));
5811     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5812 
5813     /* Version type is REG_DWORD */
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, ""), "Expected \"\", got \"%s\"\n", buf);
5819     ok(sz == 0, "Expected 0, got %d\n", sz);
5820 
5821     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
5822     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5823 
5824     /* Version value exists */
5825     sz = MAX_PATH;
5826     lstrcpyA(buf, "apple");
5827     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5828     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5829     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
5830     ok(sz == 3, "Expected 3, got %d\n", sz);
5831 
5832     res = RegSetValueExA(prodkey, "Version", 0, REG_DWORD,
5833                          (const BYTE *)&val, sizeof(DWORD));
5834     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5835 
5836     /* Version type is REG_DWORD */
5837     sz = MAX_PATH;
5838     lstrcpyA(buf, "apple");
5839     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5840     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5841     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5842     ok(sz == 2, "Expected 2, got %d\n", sz);
5843 
5844     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"ico", 4);
5845     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5846 
5847     /* ProductIcon value exists */
5848     sz = MAX_PATH;
5849     lstrcpyA(buf, "apple");
5850     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5851     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5852     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5853     ok(sz == 0, "Expected 0, got %d\n", sz);
5854 
5855     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_DWORD,
5856                          (const BYTE *)&val, sizeof(DWORD));
5857     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5858 
5859     /* ProductIcon type is REG_DWORD */
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, ""), "Expected \"\", got \"%s\"\n", buf);
5865     ok(sz == 0, "Expected 0, got %d\n", sz);
5866 
5867     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"ico", 4);
5868     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5869 
5870     /* ProductIcon value exists */
5871     sz = MAX_PATH;
5872     lstrcpyA(buf, "apple");
5873     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5874     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5875     ok(!lstrcmpA(buf, "ico"), "Expected \"ico\", got \"%s\"\n", buf);
5876     ok(sz == 3, "Expected 3, got %d\n", sz);
5877 
5878     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_DWORD,
5879                          (const BYTE *)&val, sizeof(DWORD));
5880     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5881 
5882     /* ProductIcon type is REG_DWORD */
5883     sz = MAX_PATH;
5884     lstrcpyA(buf, "apple");
5885     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5886     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5887     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5888     ok(sz == 2, "Expected 2, got %d\n", sz);
5889 
5890     /* SourceList key does not exist */
5891     sz = MAX_PATH;
5892     lstrcpyA(buf, "apple");
5893     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5894     ok(r == ERROR_UNKNOWN_PRODUCT,
5895        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5896     ok(!lstrcmpA(buf, "apple"),
5897        "Expected buf to be unchanged, got \"%s\"\n", buf);
5898     ok(sz == MAX_PATH, "Expected sz to be unchanged, got %d\n", sz);
5899 
5900     res = RegCreateKeyExA(prodkey, "SourceList", 0, NULL, 0, access, NULL, &source, NULL);
5901     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5902 
5903     /* SourceList key exists, but PackageName val does not exist */
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, ""), "Expected \"\", got \"%s\"\n", buf);
5909     ok(sz == 0, "Expected 0, got %d\n", sz);
5910 
5911     res = RegSetValueExA(source, "PackageName", 0, REG_SZ, (LPBYTE)"packname", 9);
5912     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5913 
5914     /* PackageName val exists */
5915     sz = MAX_PATH;
5916     lstrcpyA(buf, "apple");
5917     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5918     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5919     ok(!lstrcmpA(buf, "packname"), "Expected \"packname\", got \"%s\"\n", buf);
5920     ok(sz == 8, "Expected 8, got %d\n", sz);
5921 
5922     res = RegSetValueExA(source, "PackageName", 0, REG_DWORD,
5923                          (const BYTE *)&val, sizeof(DWORD));
5924     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5925 
5926     /* PackageName type is REG_DWORD */
5927     sz = MAX_PATH;
5928     lstrcpyA(buf, "apple");
5929     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5930     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5931     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5932     ok(sz == 2, "Expected 2, got %d\n", sz);
5933 
5934     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
5935     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5936 
5937     /* Authorized value exists */
5938     sz = MAX_PATH;
5939     lstrcpyA(buf, "apple");
5940     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5941     if (r != ERROR_UNKNOWN_PROPERTY)
5942     {
5943         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5944         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5945         ok(sz == 0, "Expected 0, got %d\n", sz);
5946     }
5947 
5948     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_DWORD,
5949                          (const BYTE *)&val, sizeof(DWORD));
5950     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5951 
5952     /* AuthorizedLUAApp type is REG_DWORD */
5953     sz = MAX_PATH;
5954     lstrcpyA(buf, "apple");
5955     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5956     if (r != ERROR_UNKNOWN_PROPERTY)
5957     {
5958         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5959         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5960         ok(sz == 0, "Expected 0, got %d\n", sz);
5961     }
5962 
5963     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
5964     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5965 
5966     /* Authorized value exists */
5967     sz = MAX_PATH;
5968     lstrcpyA(buf, "apple");
5969     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5970     if (r != ERROR_UNKNOWN_PROPERTY)
5971     {
5972         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5973         ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
5974         ok(sz == 4, "Expected 4, got %d\n", sz);
5975     }
5976 
5977     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_DWORD,
5978                          (const BYTE *)&val, sizeof(DWORD));
5979     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5980 
5981     /* AuthorizedLUAApp type is REG_DWORD */
5982     sz = MAX_PATH;
5983     lstrcpyA(buf, "apple");
5984     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5985     if (r != ERROR_UNKNOWN_PROPERTY)
5986     {
5987         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5988         ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5989         ok(sz == 2, "Expected 2, got %d\n", sz);
5990     }
5991 
5992     RegDeleteValueA(propkey, "HelpLink");
5993     RegDeleteValueA(propkey, "DisplayName");
5994     RegDeleteValueA(propkey, "DisplayVersion");
5995     RegDeleteValueA(propkey, "HelpTelephone");
5996     RegDeleteValueA(propkey, "InstallLocation");
5997     RegDeleteValueA(propkey, "InstallSource");
5998     RegDeleteValueA(propkey, "InstallDate");
5999     RegDeleteValueA(propkey, "Publisher");
6000     RegDeleteValueA(propkey, "LocalPackage");
6001     RegDeleteValueA(propkey, "UrlInfoAbout");
6002     RegDeleteValueA(propkey, "UrlUpdateInfo");
6003     RegDeleteValueA(propkey, "VersionMinor");
6004     RegDeleteValueA(propkey, "VersionMajor");
6005     RegDeleteValueA(propkey, "ProductID");
6006     RegDeleteValueA(propkey, "RegCompany");
6007     RegDeleteValueA(propkey, "RegOwner");
6008     RegDeleteValueA(propkey, "InstanceType");
6009     RegDeleteValueA(propkey, "Transforms");
6010     RegDeleteValueA(propkey, "Language");
6011     RegDeleteValueA(propkey, "ProductName");
6012     RegDeleteValueA(propkey, "Assignment");
6013     RegDeleteValueA(propkey, "PackageCode");
6014     RegDeleteValueA(propkey, "Version");
6015     RegDeleteValueA(propkey, "ProductIcon");
6016     RegDeleteValueA(propkey, "AuthorizedLUAApp");
6017     delete_key(propkey, "", access & KEY_WOW64_64KEY);
6018     delete_key(localkey, "", access & KEY_WOW64_64KEY);
6019     RegDeleteValueA(prodkey, "InstanceType");
6020     RegDeleteValueA(prodkey, "Transforms");
6021     RegDeleteValueA(prodkey, "Language");
6022     RegDeleteValueA(prodkey, "ProductName");
6023     RegDeleteValueA(prodkey, "Assignment");
6024     RegDeleteValueA(prodkey, "PackageCode");
6025     RegDeleteValueA(prodkey, "Version");
6026     RegDeleteValueA(prodkey, "ProductIcon");
6027     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
6028     RegDeleteValueA(source, "PackageName");
6029     delete_key(source, "", access & KEY_WOW64_64KEY);
6030     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
6031     RegCloseKey(propkey);
6032     RegCloseKey(localkey);
6033     RegCloseKey(source);
6034     RegCloseKey(prodkey);
6035     LocalFree(usersid);
6036 }
6037 
6038 static void test_MsiGetProductInfoEx(void)
6039 {
6040     UINT r;
6041     LONG res;
6042     HKEY propkey, userkey;
6043     HKEY prodkey, localkey;
6044     CHAR prodcode[MAX_PATH];
6045     CHAR prod_squashed[MAX_PATH];
6046     CHAR packcode[MAX_PATH];
6047     CHAR pack_squashed[MAX_PATH];
6048     CHAR buf[MAX_PATH];
6049     CHAR keypath[MAX_PATH];
6050     LPSTR usersid;
6051     DWORD sz;
6052     REGSAM access = KEY_ALL_ACCESS;
6053 
6054     if (!pMsiGetProductInfoExA)
6055     {
6056         win_skip("MsiGetProductInfoExA is not available\n");
6057         return;
6058     }
6059 
6060     create_test_guid(prodcode, prod_squashed);
6061     create_test_guid(packcode, pack_squashed);
6062     usersid = get_user_sid();
6063 
6064     if (is_wow64)
6065         access |= KEY_WOW64_64KEY;
6066 
6067     /* NULL szProductCode */
6068     sz = MAX_PATH;
6069     lstrcpyA(buf, "apple");
6070     r = pMsiGetProductInfoExA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
6071                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6072     ok(r == ERROR_INVALID_PARAMETER,
6073        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6074     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6075     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6076 
6077     /* empty szProductCode */
6078     sz = MAX_PATH;
6079     lstrcpyA(buf, "apple");
6080     r = pMsiGetProductInfoExA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
6081                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6082     ok(r == ERROR_INVALID_PARAMETER,
6083        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6084     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6085     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6086 
6087     /* garbage szProductCode */
6088     sz = MAX_PATH;
6089     lstrcpyA(buf, "apple");
6090     r = pMsiGetProductInfoExA("garbage", usersid, 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 without 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_INVALID_PARAMETER,
6104        "Expected ERROR_INVALID_PARAMETER, 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     /* guid with brackets */
6109     sz = MAX_PATH;
6110     lstrcpyA(buf, "apple");
6111     r = pMsiGetProductInfoExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", usersid,
6112                               MSIINSTALLCONTEXT_USERUNMANAGED,
6113                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6114     ok(r == ERROR_UNKNOWN_PRODUCT,
6115        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6116     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6117     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6118 
6119     /* szValue is non-NULL while pcchValue is NULL */
6120     lstrcpyA(buf, "apple");
6121     r = pMsiGetProductInfoExA(prodcode, usersid,
6122                               MSIINSTALLCONTEXT_USERUNMANAGED,
6123                               INSTALLPROPERTY_PRODUCTSTATEA, buf, NULL);
6124     ok(r == ERROR_INVALID_PARAMETER,
6125        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6126     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6127 
6128     /* dwContext is out of range */
6129     sz = MAX_PATH;
6130     lstrcpyA(buf, "apple");
6131     r = pMsiGetProductInfoExA(prodcode, usersid, 42,
6132                               INSTALLPROPERTY_PRODUCTSTATEA, 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 NULL */
6139     sz = MAX_PATH;
6140     lstrcpyA(buf, "apple");
6141     r = pMsiGetProductInfoExA(prodcode, usersid,
6142                               MSIINSTALLCONTEXT_USERUNMANAGED,
6143                               NULL, 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 empty */
6150     sz = MAX_PATH;
6151     lstrcpyA(buf, "apple");
6152     r = pMsiGetProductInfoExA(prodcode, usersid,
6153                               MSIINSTALLCONTEXT_USERUNMANAGED,
6154                               "", buf, &sz);
6155     ok(r == ERROR_INVALID_PARAMETER,
6156        "Expected ERROR_INVALID_PARAMETER, 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     /* szProperty is not a valid property */
6161     sz = MAX_PATH;
6162     lstrcpyA(buf, "apple");
6163     r = pMsiGetProductInfoExA(prodcode, usersid,
6164                               MSIINSTALLCONTEXT_USERUNMANAGED,
6165                               "notvalid", buf, &sz);
6166     ok(r == ERROR_UNKNOWN_PRODUCT,
6167        "Expected ERROR_UNKNOWN_PRODUCT, 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     /* same length as guid, but random */
6172     sz = MAX_PATH;
6173     lstrcpyA(buf, "apple");
6174     r = pMsiGetProductInfoExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", usersid,
6175                               MSIINSTALLCONTEXT_USERUNMANAGED,
6176                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6177     ok(r == ERROR_INVALID_PARAMETER,
6178        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6179     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6180     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6181 
6182     /* MSIINSTALLCONTEXT_USERUNMANAGED */
6183 
6184     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
6185     lstrcatA(keypath, usersid);
6186     lstrcatA(keypath, "\\Products\\");
6187     lstrcatA(keypath, prod_squashed);
6188 
6189     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
6190     if (res == ERROR_ACCESS_DENIED)
6191     {
6192         skip("Not enough rights to perform tests\n");
6193         LocalFree(usersid);
6194         return;
6195     }
6196     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6197 
6198     /* local user product key exists */
6199     sz = MAX_PATH;
6200     lstrcpyA(buf, "apple");
6201     r = pMsiGetProductInfoExA(prodcode, usersid,
6202                               MSIINSTALLCONTEXT_USERUNMANAGED,
6203                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6204     ok(r == ERROR_UNKNOWN_PRODUCT,
6205        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6206     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6207     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6208 
6209     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
6210     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6211 
6212     /* InstallProperties key exists */
6213     sz = MAX_PATH;
6214     lstrcpyA(buf, "apple");
6215     r = pMsiGetProductInfoExA(prodcode, usersid,
6216                               MSIINSTALLCONTEXT_USERUNMANAGED,
6217                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6218     ok(r == ERROR_UNKNOWN_PRODUCT,
6219        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6220     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6221     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6222 
6223     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6224     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6225 
6226     /* LocalPackage value exists */
6227     sz = MAX_PATH;
6228     lstrcpyA(buf, "apple");
6229     r = pMsiGetProductInfoExA(prodcode, usersid,
6230                               MSIINSTALLCONTEXT_USERUNMANAGED,
6231                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6232     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6233     ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
6234     ok(sz == 1, "Expected 1, got %d\n", sz);
6235 
6236     RegDeleteValueA(propkey, "LocalPackage");
6237 
6238     /* LocalPackage value must exist */
6239     sz = MAX_PATH;
6240     lstrcpyA(buf, "apple");
6241     r = pMsiGetProductInfoExA(prodcode, usersid,
6242                               MSIINSTALLCONTEXT_USERUNMANAGED,
6243                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
6244     ok(r == ERROR_UNKNOWN_PRODUCT,
6245        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6246     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6247     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6248 
6249     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6250     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6251 
6252     /* LocalPackage exists, but HelpLink does not exist */
6253     sz = MAX_PATH;
6254     lstrcpyA(buf, "apple");
6255     r = pMsiGetProductInfoExA(prodcode, usersid,
6256                               MSIINSTALLCONTEXT_USERUNMANAGED,
6257                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
6258     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6259     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
6260     ok(sz == 0, "Expected 0, got %d\n", sz);
6261 
6262     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
6263     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6264 
6265     /* HelpLink value exists */
6266     sz = MAX_PATH;
6267     lstrcpyA(buf, "apple");
6268     r = pMsiGetProductInfoExA(prodcode, usersid,
6269                               MSIINSTALLCONTEXT_USERUNMANAGED,
6270                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
6271     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6272     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
6273     ok(sz == 4, "Expected 4, got %d\n", sz);
6274 
6275     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
6276     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6277 
6278     /* HelpTelephone value exists */
6279     sz = MAX_PATH;
6280     lstrcpyA(buf, "apple");
6281     r = pMsiGetProductInfoExA(prodcode, usersid,
6282                               MSIINSTALLCONTEXT_USERUNMANAGED,
6283                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
6284     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6285     ok(!lstrcmpA(buf, "phone"), "Expected \"phone\", got \"%s\"\n", buf);
6286     ok(sz == 5, "Expected 5, got %d\n", sz);
6287 
6288     /* szValue and pcchValue are NULL */
6289     r = pMsiGetProductInfoExA(prodcode, usersid,
6290                               MSIINSTALLCONTEXT_USERUNMANAGED,
6291                               INSTALLPROPERTY_HELPTELEPHONEA, NULL, NULL);
6292     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6293 
6294     /* pcchValue is exactly 5 */
6295     sz = 5;
6296     lstrcpyA(buf, "apple");
6297     r = pMsiGetProductInfoExA(prodcode, usersid,
6298                               MSIINSTALLCONTEXT_USERUNMANAGED,
6299                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
6300     ok(r == ERROR_MORE_DATA,
6301        "Expected ERROR_MORE_DATA, got %d\n", r);
6302     ok(sz == 10, "Expected 10, got %d\n", sz);
6303 
6304     /* szValue is NULL, pcchValue is exactly 5 */
6305     sz = 5;
6306     r = pMsiGetProductInfoExA(prodcode, usersid,
6307                               MSIINSTALLCONTEXT_USERUNMANAGED,
6308                               INSTALLPROPERTY_HELPTELEPHONEA, NULL, &sz);
6309     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6310     ok(sz == 10, "Expected 10, got %d\n", sz);
6311 
6312     /* szValue is NULL, pcchValue is MAX_PATH */
6313     sz = MAX_PATH;
6314     r = pMsiGetProductInfoExA(prodcode, usersid,
6315                               MSIINSTALLCONTEXT_USERUNMANAGED,
6316                               INSTALLPROPERTY_HELPTELEPHONEA, NULL, &sz);
6317     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6318     ok(sz == 10, "Expected 10, got %d\n", sz);
6319 
6320     /* pcchValue is exactly 0 */
6321     sz = 0;
6322     lstrcpyA(buf, "apple");
6323     r = pMsiGetProductInfoExA(prodcode, usersid,
6324                               MSIINSTALLCONTEXT_USERUNMANAGED,
6325                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
6326     ok(r == ERROR_MORE_DATA,
6327        "Expected ERROR_MORE_DATA, got %d\n", r);
6328     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
6329     ok(sz == 10, "Expected 10, got %d\n", sz);
6330 
6331     res = RegSetValueExA(propkey, "notvalid", 0, REG_SZ, (LPBYTE)"invalid", 8);
6332     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6333 
6334     /* szProperty is not a valid property */
6335     sz = MAX_PATH;
6336     lstrcpyA(buf, "apple");
6337     r = pMsiGetProductInfoExA(prodcode, usersid,
6338                               MSIINSTALLCONTEXT_USERUNMANAGED,
6339                               "notvalid", buf, &sz);
6340     ok(r == ERROR_UNKNOWN_PROPERTY,
6341        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6342     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6343     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6344 
6345     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
6346     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6347 
6348     /* InstallDate value exists */
6349     sz = MAX_PATH;
6350     lstrcpyA(buf, "apple");
6351     r = pMsiGetProductInfoExA(prodcode, usersid,
6352                               MSIINSTALLCONTEXT_USERUNMANAGED,
6353                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
6354     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6355     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
6356     ok(sz == 4, "Expected 4, got %d\n", sz);
6357 
6358     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
6359     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6360 
6361     /* DisplayName value exists */
6362     sz = MAX_PATH;
6363     lstrcpyA(buf, "apple");
6364     r = pMsiGetProductInfoExA(prodcode, usersid,
6365                               MSIINSTALLCONTEXT_USERUNMANAGED,
6366                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
6367     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6368     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
6369     ok(sz == 4, "Expected 4, got %d\n", sz);
6370 
6371     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
6372     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6373 
6374     /* InstallLocation value exists */
6375     sz = MAX_PATH;
6376     lstrcpyA(buf, "apple");
6377     r = pMsiGetProductInfoExA(prodcode, usersid,
6378                               MSIINSTALLCONTEXT_USERUNMANAGED,
6379                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
6380     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6381     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
6382     ok(sz == 3, "Expected 3, got %d\n", sz);
6383 
6384     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
6385     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6386 
6387     /* InstallSource value exists */
6388     sz = MAX_PATH;
6389     lstrcpyA(buf, "apple");
6390     r = pMsiGetProductInfoExA(prodcode, usersid,
6391                               MSIINSTALLCONTEXT_USERUNMANAGED,
6392                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
6393     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6394     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
6395     ok(sz == 6, "Expected 6, got %d\n", sz);
6396 
6397     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6398     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6399 
6400     /* LocalPackage value exists */
6401     sz = MAX_PATH;
6402     lstrcpyA(buf, "apple");
6403     r = pMsiGetProductInfoExA(prodcode, usersid,
6404                               MSIINSTALLCONTEXT_USERUNMANAGED,
6405                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
6406     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6407     ok(!lstrcmpA(buf, "local"), "Expected \"local\", got \"%s\"\n", buf);
6408     ok(sz == 5, "Expected 5, got %d\n", sz);
6409 
6410     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
6411     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6412 
6413     /* Publisher value exists */
6414     sz = MAX_PATH;
6415     lstrcpyA(buf, "apple");
6416     r = pMsiGetProductInfoExA(prodcode, usersid,
6417                               MSIINSTALLCONTEXT_USERUNMANAGED,
6418                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
6419     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6420     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
6421     ok(sz == 3, "Expected 3, got %d\n", sz);
6422 
6423     res = RegSetValueExA(propkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
6424     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6425 
6426     /* URLInfoAbout value exists */
6427     sz = MAX_PATH;
6428     lstrcpyA(buf, "apple");
6429     r = pMsiGetProductInfoExA(prodcode, usersid,
6430                               MSIINSTALLCONTEXT_USERUNMANAGED,
6431                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
6432     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6433     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
6434     ok(sz == 5, "Expected 5, got %d\n", sz);
6435 
6436     res = RegSetValueExA(propkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
6437     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6438 
6439     /* URLUpdateInfo value exists */
6440     sz = MAX_PATH;
6441     lstrcpyA(buf, "apple");
6442     r = pMsiGetProductInfoExA(prodcode, usersid,
6443                               MSIINSTALLCONTEXT_USERUNMANAGED,
6444                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
6445     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6446     ok(!lstrcmpA(buf, "update"), "Expected \"update\", got \"%s\"\n", buf);
6447     ok(sz == 6, "Expected 6, got %d\n", sz);
6448 
6449     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
6450     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6451 
6452     /* VersionMinor value exists */
6453     sz = MAX_PATH;
6454     lstrcpyA(buf, "apple");
6455     r = pMsiGetProductInfoExA(prodcode, usersid,
6456                               MSIINSTALLCONTEXT_USERUNMANAGED,
6457                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
6458     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6459     ok(!lstrcmpA(buf, "2"), "Expected \"2\", got \"%s\"\n", buf);
6460     ok(sz == 1, "Expected 1, got %d\n", sz);
6461 
6462     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
6463     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6464 
6465     /* VersionMajor value exists */
6466     sz = MAX_PATH;
6467     lstrcpyA(buf, "apple");
6468     r = pMsiGetProductInfoExA(prodcode, usersid,
6469                               MSIINSTALLCONTEXT_USERUNMANAGED,
6470                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
6471     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6472     ok(!lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
6473     ok(sz == 1, "Expected 1, got %d\n", sz);
6474 
6475     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
6476     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6477 
6478     /* DisplayVersion value exists */
6479     sz = MAX_PATH;
6480     lstrcpyA(buf, "apple");
6481     r = pMsiGetProductInfoExA(prodcode, usersid,
6482                               MSIINSTALLCONTEXT_USERUNMANAGED,
6483                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
6484     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6485     ok(!lstrcmpA(buf, "3.2.1"), "Expected \"3.2.1\", got \"%s\"\n", buf);
6486     ok(sz == 5, "Expected 5, got %d\n", sz);
6487 
6488     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
6489     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6490 
6491     /* ProductID value exists */
6492     sz = MAX_PATH;
6493     lstrcpyA(buf, "apple");
6494     r = pMsiGetProductInfoExA(prodcode, usersid,
6495                               MSIINSTALLCONTEXT_USERUNMANAGED,
6496                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
6497     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6498     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
6499     ok(sz == 2, "Expected 2, got %d\n", sz);
6500 
6501     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
6502     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6503 
6504     /* RegCompany value exists */
6505     sz = MAX_PATH;
6506     lstrcpyA(buf, "apple");
6507     r = pMsiGetProductInfoExA(prodcode, usersid,
6508                               MSIINSTALLCONTEXT_USERUNMANAGED,
6509                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
6510     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6511     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
6512     ok(sz == 4, "Expected 4, got %d\n", sz);
6513 
6514     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
6515     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6516 
6517     /* RegOwner value exists */
6518     sz = MAX_PATH;
6519     lstrcpyA(buf, "apple");
6520     r = pMsiGetProductInfoExA(prodcode, usersid,
6521                               MSIINSTALLCONTEXT_USERUNMANAGED,
6522                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
6523     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6524     ok(!lstrcmpA(buf, "owner"), "Expected \"owner\", got \"%s\"\n", buf);
6525     ok(sz == 5, "Expected 5, got %d\n", sz);
6526 
6527     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
6528     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6529 
6530     /* Transforms value exists */
6531     sz = MAX_PATH;
6532     lstrcpyA(buf, "apple");
6533     r = pMsiGetProductInfoExA(prodcode, usersid,
6534                               MSIINSTALLCONTEXT_USERUNMANAGED,
6535                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
6536     ok(r == ERROR_UNKNOWN_PRODUCT,
6537        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6538     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6539     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6540 
6541     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
6542     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6543 
6544     /* Language value exists */
6545     sz = MAX_PATH;
6546     lstrcpyA(buf, "apple");
6547     r = pMsiGetProductInfoExA(prodcode, usersid,
6548                               MSIINSTALLCONTEXT_USERUNMANAGED,
6549                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
6550     ok(r == ERROR_UNKNOWN_PRODUCT,
6551        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6552     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6553     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6554 
6555     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
6556     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6557 
6558     /* ProductName value exists */
6559     sz = MAX_PATH;
6560     lstrcpyA(buf, "apple");
6561     r = pMsiGetProductInfoExA(prodcode, usersid,
6562                               MSIINSTALLCONTEXT_USERUNMANAGED,
6563                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
6564     ok(r == ERROR_UNKNOWN_PRODUCT,
6565        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6566     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6567     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6568 
6569     res = RegSetValueExA(propkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
6570     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6571 
6572     /* FIXME */
6573 
6574     /* AssignmentType value exists */
6575     sz = MAX_PATH;
6576     lstrcpyA(buf, "apple");
6577     r = pMsiGetProductInfoExA(prodcode, usersid,
6578                               MSIINSTALLCONTEXT_USERUNMANAGED,
6579                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
6580     ok(r == ERROR_UNKNOWN_PRODUCT,
6581        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6582     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6583     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6584 
6585     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
6586     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6587 
6588     /* PackageCode value exists */
6589     sz = MAX_PATH;
6590     lstrcpyA(buf, "apple");
6591     r = pMsiGetProductInfoExA(prodcode, usersid,
6592                               MSIINSTALLCONTEXT_USERUNMANAGED,
6593                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
6594     ok(r == ERROR_UNKNOWN_PRODUCT,
6595        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6596     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6597     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6598 
6599     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
6600     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6601 
6602     /* Version value exists */
6603     sz = MAX_PATH;
6604     lstrcpyA(buf, "apple");
6605     r = pMsiGetProductInfoExA(prodcode, usersid,
6606                               MSIINSTALLCONTEXT_USERUNMANAGED,
6607                               INSTALLPROPERTY_VERSIONA, buf, &sz);
6608     ok(r == ERROR_UNKNOWN_PRODUCT,
6609        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6610     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6611     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6612 
6613     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
6614     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6615 
6616     /* ProductIcon value exists */
6617     sz = MAX_PATH;
6618     lstrcpyA(buf, "apple");
6619     r = pMsiGetProductInfoExA(prodcode, usersid,
6620                               MSIINSTALLCONTEXT_USERUNMANAGED,
6621                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
6622     ok(r == ERROR_UNKNOWN_PRODUCT,
6623        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6624     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6625     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6626 
6627     res = RegSetValueExA(propkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
6628     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6629 
6630     /* PackageName value exists */
6631     sz = MAX_PATH;
6632     lstrcpyA(buf, "apple");
6633     r = pMsiGetProductInfoExA(prodcode, usersid,
6634                               MSIINSTALLCONTEXT_USERUNMANAGED,
6635                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
6636     ok(r == ERROR_UNKNOWN_PRODUCT,
6637        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6638     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6639     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6640 
6641     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
6642     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6643 
6644     /* AuthorizedLUAApp value exists */
6645     sz = MAX_PATH;
6646     lstrcpyA(buf, "apple");
6647     r = pMsiGetProductInfoExA(prodcode, usersid,
6648                               MSIINSTALLCONTEXT_USERUNMANAGED,
6649                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
6650     ok(r == ERROR_UNKNOWN_PRODUCT,
6651        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6652     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6653     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6654 
6655     RegDeleteValueA(propkey, "AuthorizedLUAApp");
6656     RegDeleteValueA(propkey, "PackageName");
6657     RegDeleteValueA(propkey, "ProductIcon");
6658     RegDeleteValueA(propkey, "Version");
6659     RegDeleteValueA(propkey, "PackageCode");
6660     RegDeleteValueA(propkey, "AssignmentType");
6661     RegDeleteValueA(propkey, "ProductName");
6662     RegDeleteValueA(propkey, "Language");
6663     RegDeleteValueA(propkey, "Transforms");
6664     RegDeleteValueA(propkey, "RegOwner");
6665     RegDeleteValueA(propkey, "RegCompany");
6666     RegDeleteValueA(propkey, "ProductID");
6667     RegDeleteValueA(propkey, "DisplayVersion");
6668     RegDeleteValueA(propkey, "VersionMajor");
6669     RegDeleteValueA(propkey, "VersionMinor");
6670     RegDeleteValueA(propkey, "URLUpdateInfo");
6671     RegDeleteValueA(propkey, "URLInfoAbout");
6672     RegDeleteValueA(propkey, "Publisher");
6673     RegDeleteValueA(propkey, "LocalPackage");
6674     RegDeleteValueA(propkey, "InstallSource");
6675     RegDeleteValueA(propkey, "InstallLocation");
6676     RegDeleteValueA(propkey, "DisplayName");
6677     RegDeleteValueA(propkey, "InstallDate");
6678     RegDeleteValueA(propkey, "HelpTelephone");
6679     RegDeleteValueA(propkey, "HelpLink");
6680     RegDeleteValueA(propkey, "LocalPackage");
6681     RegDeleteKeyA(propkey, "");
6682     RegCloseKey(propkey);
6683     RegDeleteKeyA(localkey, "");
6684     RegCloseKey(localkey);
6685 
6686     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
6687     lstrcatA(keypath, usersid);
6688     lstrcatA(keypath, "\\Installer\\Products\\");
6689     lstrcatA(keypath, prod_squashed);
6690 
6691     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
6692     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6693 
6694     /* user product key exists */
6695     sz = MAX_PATH;
6696     lstrcpyA(buf, "apple");
6697     r = pMsiGetProductInfoExA(prodcode, usersid,
6698                               MSIINSTALLCONTEXT_USERUNMANAGED,
6699                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6700     ok(r == ERROR_UNKNOWN_PRODUCT,
6701        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6702     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6703     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6704 
6705     RegDeleteKeyA(userkey, "");
6706     RegCloseKey(userkey);
6707 
6708     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
6709     lstrcatA(keypath, prod_squashed);
6710 
6711     res = RegCreateKeyExA(HKEY_CURRENT_USER, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
6712     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6713 
6714     sz = MAX_PATH;
6715     lstrcpyA(buf, "apple");
6716     r = pMsiGetProductInfoExA(prodcode, usersid,
6717                               MSIINSTALLCONTEXT_USERUNMANAGED,
6718                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6719     ok(r == ERROR_SUCCESS || broken(r == ERROR_UNKNOWN_PRODUCT), "Expected ERROR_SUCCESS, got %d\n", r);
6720     if (r == ERROR_UNKNOWN_PRODUCT)
6721     {
6722         win_skip("skipping remaining tests for MsiGetProductInfoEx\n");
6723         delete_key(prodkey, "", access);
6724         RegCloseKey(prodkey);
6725         return;
6726     }
6727     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
6728     ok(sz == 1, "Expected 1, got %d\n", sz);
6729 
6730     res = RegSetValueExA(prodkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
6731     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6732 
6733     /* HelpLink value exists */
6734     sz = MAX_PATH;
6735     lstrcpyA(buf, "apple");
6736     r = pMsiGetProductInfoExA(prodcode, usersid,
6737                               MSIINSTALLCONTEXT_USERUNMANAGED,
6738                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
6739     ok(r == ERROR_UNKNOWN_PROPERTY,
6740        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6741     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6742     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6743 
6744     res = RegSetValueExA(prodkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
6745     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6746 
6747     /* HelpTelephone value exists */
6748     sz = MAX_PATH;
6749     lstrcpyA(buf, "apple");
6750     r = pMsiGetProductInfoExA(prodcode, usersid,
6751                               MSIINSTALLCONTEXT_USERUNMANAGED,
6752                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
6753     ok(r == ERROR_UNKNOWN_PROPERTY,
6754        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6755     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6756     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6757 
6758     res = RegSetValueExA(prodkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
6759     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6760 
6761     /* InstallDate value exists */
6762     sz = MAX_PATH;
6763     lstrcpyA(buf, "apple");
6764     r = pMsiGetProductInfoExA(prodcode, usersid,
6765                               MSIINSTALLCONTEXT_USERUNMANAGED,
6766                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
6767     ok(r == ERROR_UNKNOWN_PROPERTY,
6768        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6769     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6770     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6771 
6772     res = RegSetValueExA(prodkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
6773     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6774 
6775     /* DisplayName value exists */
6776     sz = MAX_PATH;
6777     lstrcpyA(buf, "apple");
6778     r = pMsiGetProductInfoExA(prodcode, usersid,
6779                               MSIINSTALLCONTEXT_USERUNMANAGED,
6780                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
6781     ok(r == ERROR_UNKNOWN_PROPERTY,
6782        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6783     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6784     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6785 
6786     res = RegSetValueExA(prodkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
6787     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6788 
6789     /* InstallLocation value exists */
6790     sz = MAX_PATH;
6791     lstrcpyA(buf, "apple");
6792     r = pMsiGetProductInfoExA(prodcode, usersid,
6793                               MSIINSTALLCONTEXT_USERUNMANAGED,
6794                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
6795     ok(r == ERROR_UNKNOWN_PROPERTY,
6796        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6797     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6798     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6799 
6800     res = RegSetValueExA(prodkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
6801     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6802 
6803     /* InstallSource value exists */
6804     sz = MAX_PATH;
6805     lstrcpyA(buf, "apple");
6806     r = pMsiGetProductInfoExA(prodcode, usersid,
6807                               MSIINSTALLCONTEXT_USERUNMANAGED,
6808                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
6809     ok(r == ERROR_UNKNOWN_PROPERTY,
6810        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6811     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6812     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6813 
6814     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6815     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6816 
6817     /* LocalPackage value exists */
6818     sz = MAX_PATH;
6819     lstrcpyA(buf, "apple");
6820     r = pMsiGetProductInfoExA(prodcode, usersid,
6821                               MSIINSTALLCONTEXT_USERUNMANAGED,
6822                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
6823     ok(r == ERROR_UNKNOWN_PROPERTY,
6824        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6825     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6826     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6827 
6828     res = RegSetValueExA(prodkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
6829     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6830 
6831     /* Publisher value exists */
6832     sz = MAX_PATH;
6833     lstrcpyA(buf, "apple");
6834     r = pMsiGetProductInfoExA(prodcode, usersid,
6835                               MSIINSTALLCONTEXT_USERUNMANAGED,
6836                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
6837     ok(r == ERROR_UNKNOWN_PROPERTY,
6838        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6839     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6840     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6841 
6842     res = RegSetValueExA(prodkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
6843     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6844 
6845     /* URLInfoAbout value exists */
6846     sz = MAX_PATH;
6847     lstrcpyA(buf, "apple");
6848     r = pMsiGetProductInfoExA(prodcode, usersid,
6849                               MSIINSTALLCONTEXT_USERUNMANAGED,
6850                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
6851     ok(r == ERROR_UNKNOWN_PROPERTY,
6852        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6853     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6854     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6855 
6856     res = RegSetValueExA(prodkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
6857     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6858 
6859     /* URLUpdateInfo value exists */
6860     sz = MAX_PATH;
6861     lstrcpyA(buf, "apple");
6862     r = pMsiGetProductInfoExA(prodcode, usersid,
6863                               MSIINSTALLCONTEXT_USERUNMANAGED,
6864                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
6865     ok(r == ERROR_UNKNOWN_PROPERTY,
6866        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6867     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6868     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6869 
6870     res = RegSetValueExA(prodkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
6871     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6872 
6873     /* VersionMinor value exists */
6874     sz = MAX_PATH;
6875     lstrcpyA(buf, "apple");
6876     r = pMsiGetProductInfoExA(prodcode, usersid,
6877                               MSIINSTALLCONTEXT_USERUNMANAGED,
6878                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
6879     ok(r == ERROR_UNKNOWN_PROPERTY,
6880        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6881     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6882     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6883 
6884     res = RegSetValueExA(prodkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
6885     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6886 
6887     /* VersionMajor value exists */
6888     sz = MAX_PATH;
6889     lstrcpyA(buf, "apple");
6890     r = pMsiGetProductInfoExA(prodcode, usersid,
6891                               MSIINSTALLCONTEXT_USERUNMANAGED,
6892                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
6893     ok(r == ERROR_UNKNOWN_PROPERTY,
6894        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6895     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6896     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6897 
6898     res = RegSetValueExA(prodkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
6899     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6900 
6901     /* DisplayVersion value exists */
6902     sz = MAX_PATH;
6903     lstrcpyA(buf, "apple");
6904     r = pMsiGetProductInfoExA(prodcode, usersid,
6905                               MSIINSTALLCONTEXT_USERUNMANAGED,
6906                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
6907     ok(r == ERROR_UNKNOWN_PROPERTY,
6908        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6909     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6910     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6911 
6912     res = RegSetValueExA(prodkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
6913     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6914 
6915     /* ProductID value exists */
6916     sz = MAX_PATH;
6917     lstrcpyA(buf, "apple");
6918     r = pMsiGetProductInfoExA(prodcode, usersid,
6919                               MSIINSTALLCONTEXT_USERUNMANAGED,
6920                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
6921     ok(r == ERROR_UNKNOWN_PROPERTY,
6922        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6923     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6924     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6925 
6926     res = RegSetValueExA(prodkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
6927     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6928 
6929     /* RegCompany value exists */
6930     sz = MAX_PATH;
6931     lstrcpyA(buf, "apple");
6932     r = pMsiGetProductInfoExA(prodcode, usersid,
6933                               MSIINSTALLCONTEXT_USERUNMANAGED,
6934                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
6935     ok(r == ERROR_UNKNOWN_PROPERTY,
6936        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6937     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6938     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6939 
6940     res = RegSetValueExA(prodkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
6941     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6942 
6943     /* RegOwner value exists */
6944     sz = MAX_PATH;
6945     lstrcpyA(buf, "apple");
6946     r = pMsiGetProductInfoExA(prodcode, usersid,
6947                               MSIINSTALLCONTEXT_USERUNMANAGED,
6948                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
6949     ok(r == ERROR_UNKNOWN_PROPERTY,
6950        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6951     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6952     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6953 
6954     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
6955     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6956 
6957     /* Transforms value exists */
6958     sz = MAX_PATH;
6959     lstrcpyA(buf, "apple");
6960     r = pMsiGetProductInfoExA(prodcode, usersid,
6961                               MSIINSTALLCONTEXT_USERUNMANAGED,
6962                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
6963     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6964     ok(!lstrcmpA(buf, "trans"), "Expected \"trans\", got \"%s\"\n", buf);
6965     ok(sz == 5, "Expected 5, got %d\n", sz);
6966 
6967     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
6968     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6969 
6970     /* Language value exists */
6971     sz = MAX_PATH;
6972     lstrcpyA(buf, "apple");
6973     r = pMsiGetProductInfoExA(prodcode, usersid,
6974                               MSIINSTALLCONTEXT_USERUNMANAGED,
6975                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
6976     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6977     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
6978     ok(sz == 4, "Expected 4, got %d\n", sz);
6979 
6980     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
6981     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6982 
6983     /* ProductName value exists */
6984     sz = MAX_PATH;
6985     lstrcpyA(buf, "apple");
6986     r = pMsiGetProductInfoExA(prodcode, usersid,
6987                               MSIINSTALLCONTEXT_USERUNMANAGED,
6988                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
6989     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6990     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
6991     ok(sz == 4, "Expected 4, got %d\n", sz);
6992 
6993     res = RegSetValueExA(prodkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
6994     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6995 
6996     /* FIXME */
6997 
6998     /* AssignmentType value exists */
6999     sz = MAX_PATH;
7000     lstrcpyA(buf, "apple");
7001     r = pMsiGetProductInfoExA(prodcode, usersid,
7002                               MSIINSTALLCONTEXT_USERUNMANAGED,
7003                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
7004     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7005     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7006     ok(sz == 0, "Expected 0, got %d\n", sz);
7007 
7008     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
7009     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7010 
7011     /* FIXME */
7012 
7013     /* PackageCode value exists */
7014     sz = MAX_PATH;
7015     lstrcpyA(buf, "apple");
7016     r = pMsiGetProductInfoExA(prodcode, usersid,
7017                               MSIINSTALLCONTEXT_USERUNMANAGED,
7018                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
7019     todo_wine
7020     {
7021         ok(r == ERROR_BAD_CONFIGURATION,
7022            "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
7023         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7024         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7025     }
7026 
7027     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
7028     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7029 
7030     /* Version value exists */
7031     sz = MAX_PATH;
7032     lstrcpyA(buf, "apple");
7033     r = pMsiGetProductInfoExA(prodcode, usersid,
7034                               MSIINSTALLCONTEXT_USERUNMANAGED,
7035                               INSTALLPROPERTY_VERSIONA, buf, &sz);
7036     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7037     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
7038     ok(sz == 3, "Expected 3, got %d\n", sz);
7039 
7040     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
7041     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7042 
7043     /* ProductIcon value exists */
7044     sz = MAX_PATH;
7045     lstrcpyA(buf, "apple");
7046     r = pMsiGetProductInfoExA(prodcode, usersid,
7047                               MSIINSTALLCONTEXT_USERUNMANAGED,
7048                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
7049     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7050     ok(!lstrcmpA(buf, "icon"), "Expected \"icon\", got \"%s\"\n", buf);
7051     ok(sz == 4, "Expected 4, got %d\n", sz);
7052 
7053     res = RegSetValueExA(prodkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
7054     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7055 
7056     /* PackageName value exists */
7057     sz = MAX_PATH;
7058     lstrcpyA(buf, "apple");
7059     r = pMsiGetProductInfoExA(prodcode, usersid,
7060                               MSIINSTALLCONTEXT_USERUNMANAGED,
7061                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
7062     todo_wine
7063     {
7064         ok(r == ERROR_UNKNOWN_PRODUCT,
7065            "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7066         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7067         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7068     }
7069 
7070     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
7071     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7072 
7073     /* AuthorizedLUAApp value exists */
7074     sz = MAX_PATH;
7075     lstrcpyA(buf, "apple");
7076     r = pMsiGetProductInfoExA(prodcode, usersid,
7077                               MSIINSTALLCONTEXT_USERUNMANAGED,
7078                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
7079     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7080     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
7081     ok(sz == 4, "Expected 4, got %d\n", sz);
7082 
7083     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
7084     RegDeleteValueA(prodkey, "PackageName");
7085     RegDeleteValueA(prodkey, "ProductIcon");
7086     RegDeleteValueA(prodkey, "Version");
7087     RegDeleteValueA(prodkey, "PackageCode");
7088     RegDeleteValueA(prodkey, "AssignmentType");
7089     RegDeleteValueA(prodkey, "ProductName");
7090     RegDeleteValueA(prodkey, "Language");
7091     RegDeleteValueA(prodkey, "Transforms");
7092     RegDeleteValueA(prodkey, "RegOwner");
7093     RegDeleteValueA(prodkey, "RegCompany");
7094     RegDeleteValueA(prodkey, "ProductID");
7095     RegDeleteValueA(prodkey, "DisplayVersion");
7096     RegDeleteValueA(prodkey, "VersionMajor");
7097     RegDeleteValueA(prodkey, "VersionMinor");
7098     RegDeleteValueA(prodkey, "URLUpdateInfo");
7099     RegDeleteValueA(prodkey, "URLInfoAbout");
7100     RegDeleteValueA(prodkey, "Publisher");
7101     RegDeleteValueA(prodkey, "LocalPackage");
7102     RegDeleteValueA(prodkey, "InstallSource");
7103     RegDeleteValueA(prodkey, "InstallLocation");
7104     RegDeleteValueA(prodkey, "DisplayName");
7105     RegDeleteValueA(prodkey, "InstallDate");
7106     RegDeleteValueA(prodkey, "HelpTelephone");
7107     RegDeleteValueA(prodkey, "HelpLink");
7108     RegDeleteValueA(prodkey, "LocalPackage");
7109     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
7110     RegCloseKey(prodkey);
7111 
7112     /* MSIINSTALLCONTEXT_USERMANAGED */
7113 
7114     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
7115     lstrcatA(keypath, usersid);
7116     lstrcatA(keypath, "\\Products\\");
7117     lstrcatA(keypath, prod_squashed);
7118 
7119     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
7120     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7121 
7122     /* local user product key exists */
7123     sz = MAX_PATH;
7124     lstrcpyA(buf, "apple");
7125     r = pMsiGetProductInfoExA(prodcode, usersid,
7126                               MSIINSTALLCONTEXT_USERMANAGED,
7127                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7128     ok(r == ERROR_UNKNOWN_PRODUCT,
7129        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7130     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7131     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7132 
7133     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
7134     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7135 
7136     /* InstallProperties key exists */
7137     sz = MAX_PATH;
7138     lstrcpyA(buf, "apple");
7139     r = pMsiGetProductInfoExA(prodcode, usersid,
7140                               MSIINSTALLCONTEXT_USERMANAGED,
7141                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7142     ok(r == ERROR_UNKNOWN_PRODUCT,
7143        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7144     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7145     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7146 
7147     res = RegSetValueExA(propkey, "ManagedLocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
7148     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7149 
7150     /* ManagedLocalPackage value exists */
7151     sz = MAX_PATH;
7152     lstrcpyA(buf, "apple");
7153     r = pMsiGetProductInfoExA(prodcode, usersid,
7154                               MSIINSTALLCONTEXT_USERMANAGED,
7155                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7156     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7157     ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
7158     ok(sz == 1, "Expected 1, got %d\n", sz);
7159 
7160     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
7161     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7162 
7163     /* HelpLink value exists */
7164     sz = MAX_PATH;
7165     lstrcpyA(buf, "apple");
7166     r = pMsiGetProductInfoExA(prodcode, usersid,
7167                               MSIINSTALLCONTEXT_USERMANAGED,
7168                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
7169     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7170     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
7171     ok(sz == 4, "Expected 4, got %d\n", sz);
7172 
7173     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
7174     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7175 
7176     /* HelpTelephone value exists */
7177     sz = MAX_PATH;
7178     lstrcpyA(buf, "apple");
7179     r = pMsiGetProductInfoExA(prodcode, usersid,
7180                               MSIINSTALLCONTEXT_USERMANAGED,
7181                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
7182     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7183     ok(!lstrcmpA(buf, "phone"), "Expected \"phone\", got \"%s\"\n", buf);
7184     ok(sz == 5, "Expected 5, got %d\n", sz);
7185 
7186     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
7187     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7188 
7189     /* InstallDate value exists */
7190     sz = MAX_PATH;
7191     lstrcpyA(buf, "apple");
7192     r = pMsiGetProductInfoExA(prodcode, usersid,
7193                               MSIINSTALLCONTEXT_USERMANAGED,
7194                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
7195     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7196     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
7197     ok(sz == 4, "Expected 4, got %d\n", sz);
7198 
7199     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
7200     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7201 
7202     /* DisplayName value exists */
7203     sz = MAX_PATH;
7204     lstrcpyA(buf, "apple");
7205     r = pMsiGetProductInfoExA(prodcode, usersid,
7206                               MSIINSTALLCONTEXT_USERMANAGED,
7207                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
7208     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7209     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
7210     ok(sz == 4, "Expected 4, got %d\n", sz);
7211 
7212     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
7213     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7214 
7215     /* InstallLocation value exists */
7216     sz = MAX_PATH;
7217     lstrcpyA(buf, "apple");
7218     r = pMsiGetProductInfoExA(prodcode, usersid,
7219                               MSIINSTALLCONTEXT_USERMANAGED,
7220                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
7221     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7222     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
7223     ok(sz == 3, "Expected 3, got %d\n", sz);
7224 
7225     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
7226     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7227 
7228     /* InstallSource value exists */
7229     sz = MAX_PATH;
7230     lstrcpyA(buf, "apple");
7231     r = pMsiGetProductInfoExA(prodcode, usersid,
7232                               MSIINSTALLCONTEXT_USERMANAGED,
7233                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
7234     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7235     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
7236     ok(sz == 6, "Expected 6, got %d\n", sz);
7237 
7238     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
7239     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7240 
7241     /* LocalPackage value exists */
7242     sz = MAX_PATH;
7243     lstrcpyA(buf, "apple");
7244     r = pMsiGetProductInfoExA(prodcode, usersid,
7245                               MSIINSTALLCONTEXT_USERMANAGED,
7246                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
7247     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7248     ok(!lstrcmpA(buf, "local"), "Expected \"local\", got \"%s\"\n", buf);
7249     ok(sz == 5, "Expected 5, got %d\n", sz);
7250 
7251     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
7252     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7253 
7254     /* Publisher value exists */
7255     sz = MAX_PATH;
7256     lstrcpyA(buf, "apple");
7257     r = pMsiGetProductInfoExA(prodcode, usersid,
7258                               MSIINSTALLCONTEXT_USERMANAGED,
7259                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
7260     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7261     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
7262     ok(sz == 3, "Expected 3, got %d\n", sz);
7263 
7264     res = RegSetValueExA(propkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
7265     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7266 
7267     /* URLInfoAbout value exists */
7268     sz = MAX_PATH;
7269     lstrcpyA(buf, "apple");
7270     r = pMsiGetProductInfoExA(prodcode, usersid,
7271                               MSIINSTALLCONTEXT_USERMANAGED,
7272                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
7273     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7274     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
7275     ok(sz == 5, "Expected 5, got %d\n", sz);
7276 
7277     res = RegSetValueExA(propkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
7278     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7279 
7280     /* URLUpdateInfo value exists */
7281     sz = MAX_PATH;
7282     lstrcpyA(buf, "apple");
7283     r = pMsiGetProductInfoExA(prodcode, usersid,
7284                               MSIINSTALLCONTEXT_USERMANAGED,
7285                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
7286     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7287     ok(!lstrcmpA(buf, "update"), "Expected \"update\", got \"%s\"\n", buf);
7288     ok(sz == 6, "Expected 6, got %d\n", sz);
7289 
7290     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
7291     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7292 
7293     /* VersionMinor value exists */
7294     sz = MAX_PATH;
7295     lstrcpyA(buf, "apple");
7296     r = pMsiGetProductInfoExA(prodcode, usersid,
7297                               MSIINSTALLCONTEXT_USERMANAGED,
7298                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
7299     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7300     ok(!lstrcmpA(buf, "2"), "Expected \"2\", got \"%s\"\n", buf);
7301     ok(sz == 1, "Expected 1, got %d\n", sz);
7302 
7303     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
7304     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7305 
7306     /* VersionMajor value exists */
7307     sz = MAX_PATH;
7308     lstrcpyA(buf, "apple");
7309     r = pMsiGetProductInfoExA(prodcode, usersid,
7310                               MSIINSTALLCONTEXT_USERMANAGED,
7311                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
7312     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7313     ok(!lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
7314     ok(sz == 1, "Expected 1, got %d\n", sz);
7315 
7316     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
7317     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7318 
7319     /* DisplayVersion value exists */
7320     sz = MAX_PATH;
7321     lstrcpyA(buf, "apple");
7322     r = pMsiGetProductInfoExA(prodcode, usersid,
7323                               MSIINSTALLCONTEXT_USERMANAGED,
7324                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
7325     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7326     ok(!lstrcmpA(buf, "3.2.1"), "Expected \"3.2.1\", got \"%s\"\n", buf);
7327     ok(sz == 5, "Expected 5, got %d\n", sz);
7328 
7329     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
7330     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7331 
7332     /* ProductID value exists */
7333     sz = MAX_PATH;
7334     lstrcpyA(buf, "apple");
7335     r = pMsiGetProductInfoExA(prodcode, usersid,
7336                               MSIINSTALLCONTEXT_USERMANAGED,
7337                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
7338     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7339     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
7340     ok(sz == 2, "Expected 2, got %d\n", sz);
7341 
7342     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
7343     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7344 
7345     /* RegCompany value exists */
7346     sz = MAX_PATH;
7347     lstrcpyA(buf, "apple");
7348     r = pMsiGetProductInfoExA(prodcode, usersid,
7349                               MSIINSTALLCONTEXT_USERMANAGED,
7350                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
7351     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7352     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
7353     ok(sz == 4, "Expected 4, got %d\n", sz);
7354 
7355     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
7356     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7357 
7358     /* RegOwner value exists */
7359     sz = MAX_PATH;
7360     lstrcpyA(buf, "apple");
7361     r = pMsiGetProductInfoExA(prodcode, usersid,
7362                               MSIINSTALLCONTEXT_USERMANAGED,
7363                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
7364     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7365     ok(!lstrcmpA(buf, "owner"), "Expected \"owner\", got \"%s\"\n", buf);
7366     ok(sz == 5, "Expected 5, got %d\n", sz);
7367 
7368     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
7369     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7370 
7371     /* Transforms value exists */
7372     sz = MAX_PATH;
7373     lstrcpyA(buf, "apple");
7374     r = pMsiGetProductInfoExA(prodcode, usersid,
7375                               MSIINSTALLCONTEXT_USERMANAGED,
7376                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
7377     ok(r == ERROR_UNKNOWN_PRODUCT,
7378        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7379     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7380     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7381 
7382     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
7383     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7384 
7385     /* Language value exists */
7386     sz = MAX_PATH;
7387     lstrcpyA(buf, "apple");
7388     r = pMsiGetProductInfoExA(prodcode, usersid,
7389                               MSIINSTALLCONTEXT_USERMANAGED,
7390                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
7391     ok(r == ERROR_UNKNOWN_PRODUCT,
7392        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7393     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7394     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7395 
7396     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
7397     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7398 
7399     /* ProductName value exists */
7400     sz = MAX_PATH;
7401     lstrcpyA(buf, "apple");
7402     r = pMsiGetProductInfoExA(prodcode, usersid,
7403                               MSIINSTALLCONTEXT_USERMANAGED,
7404                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
7405     ok(r == ERROR_UNKNOWN_PRODUCT,
7406        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7407     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7408     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7409 
7410     res = RegSetValueExA(propkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
7411     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7412 
7413     /* FIXME */
7414 
7415     /* AssignmentType value exists */
7416     sz = MAX_PATH;
7417     lstrcpyA(buf, "apple");
7418     r = pMsiGetProductInfoExA(prodcode, usersid,
7419                               MSIINSTALLCONTEXT_USERMANAGED,
7420                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
7421     ok(r == ERROR_UNKNOWN_PRODUCT,
7422        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7423     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7424     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7425 
7426     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
7427     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7428 
7429     /* PackageCode value exists */
7430     sz = MAX_PATH;
7431     lstrcpyA(buf, "apple");
7432     r = pMsiGetProductInfoExA(prodcode, usersid,
7433                               MSIINSTALLCONTEXT_USERMANAGED,
7434                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
7435     ok(r == ERROR_UNKNOWN_PRODUCT,
7436        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7437     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7438     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7439 
7440     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
7441     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7442 
7443     /* Version value exists */
7444     sz = MAX_PATH;
7445     lstrcpyA(buf, "apple");
7446     r = pMsiGetProductInfoExA(prodcode, usersid,
7447                               MSIINSTALLCONTEXT_USERMANAGED,
7448                               INSTALLPROPERTY_VERSIONA, buf, &sz);
7449     ok(r == ERROR_UNKNOWN_PRODUCT,
7450        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7451     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7452     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7453 
7454     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
7455     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7456 
7457     /* ProductIcon value exists */
7458     sz = MAX_PATH;
7459     lstrcpyA(buf, "apple");
7460     r = pMsiGetProductInfoExA(prodcode, usersid,
7461                               MSIINSTALLCONTEXT_USERMANAGED,
7462                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
7463     ok(r == ERROR_UNKNOWN_PRODUCT,
7464        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7465     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7466     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7467 
7468     res = RegSetValueExA(propkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
7469     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7470 
7471     /* PackageName value exists */
7472     sz = MAX_PATH;
7473     lstrcpyA(buf, "apple");
7474     r = pMsiGetProductInfoExA(prodcode, usersid,
7475                               MSIINSTALLCONTEXT_USERMANAGED,
7476                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
7477     ok(r == ERROR_UNKNOWN_PRODUCT,
7478        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7479     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7480     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7481 
7482     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
7483     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7484 
7485     /* AuthorizedLUAApp value exists */
7486     sz = MAX_PATH;
7487     lstrcpyA(buf, "apple");
7488     r = pMsiGetProductInfoExA(prodcode, usersid,
7489                               MSIINSTALLCONTEXT_USERMANAGED,
7490                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
7491     ok(r == ERROR_UNKNOWN_PRODUCT,
7492        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7493     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7494     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7495 
7496     RegDeleteValueA(propkey, "AuthorizedLUAApp");
7497     RegDeleteValueA(propkey, "PackageName");
7498     RegDeleteValueA(propkey, "ProductIcon");
7499     RegDeleteValueA(propkey, "Version");
7500     RegDeleteValueA(propkey, "PackageCode");
7501     RegDeleteValueA(propkey, "AssignmentType");
7502     RegDeleteValueA(propkey, "ProductName");
7503     RegDeleteValueA(propkey, "Language");
7504     RegDeleteValueA(propkey, "Transforms");
7505     RegDeleteValueA(propkey, "RegOwner");
7506     RegDeleteValueA(propkey, "RegCompany");
7507     RegDeleteValueA(propkey, "ProductID");
7508     RegDeleteValueA(propkey, "DisplayVersion");
7509     RegDeleteValueA(propkey, "VersionMajor");
7510     RegDeleteValueA(propkey, "VersionMinor");
7511     RegDeleteValueA(propkey, "URLUpdateInfo");
7512     RegDeleteValueA(propkey, "URLInfoAbout");
7513     RegDeleteValueA(propkey, "Publisher");
7514     RegDeleteValueA(propkey, "LocalPackage");
7515     RegDeleteValueA(propkey, "InstallSource");
7516     RegDeleteValueA(propkey, "InstallLocation");
7517     RegDeleteValueA(propkey, "DisplayName");
7518     RegDeleteValueA(propkey, "InstallDate");
7519     RegDeleteValueA(propkey, "HelpTelephone");
7520     RegDeleteValueA(propkey, "HelpLink");
7521     RegDeleteValueA(propkey, "ManagedLocalPackage");
7522     delete_key(propkey, "", access & KEY_WOW64_64KEY);
7523     RegCloseKey(propkey);
7524     delete_key(localkey, "", access & KEY_WOW64_64KEY);
7525     RegCloseKey(localkey);
7526 
7527     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
7528     lstrcatA(keypath, usersid);
7529     lstrcatA(keypath, "\\Installer\\Products\\");
7530     lstrcatA(keypath, prod_squashed);
7531 
7532     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
7533     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7534 
7535     /* user product key exists */
7536     sz = MAX_PATH;
7537     lstrcpyA(buf, "apple");
7538     r = pMsiGetProductInfoExA(prodcode, usersid,
7539                               MSIINSTALLCONTEXT_USERMANAGED,
7540                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7541     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7542     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
7543     ok(sz == 1, "Expected 1, got %d\n", sz);
7544 
7545     delete_key(userkey, "", access & KEY_WOW64_64KEY);
7546     RegCloseKey(userkey);
7547 
7548     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
7549     lstrcatA(keypath, prod_squashed);
7550 
7551     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
7552     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7553 
7554     /* current user product key exists */
7555     sz = MAX_PATH;
7556     lstrcpyA(buf, "apple");
7557     r = pMsiGetProductInfoExA(prodcode, usersid,
7558                               MSIINSTALLCONTEXT_USERMANAGED,
7559                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7560     ok(r == ERROR_UNKNOWN_PRODUCT,
7561        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7562     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7563     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7564 
7565     res = RegSetValueExA(prodkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
7566     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7567 
7568     /* HelpLink value exists, user product key does not exist */
7569     sz = MAX_PATH;
7570     lstrcpyA(buf, "apple");
7571     r = pMsiGetProductInfoExA(prodcode, usersid,
7572                               MSIINSTALLCONTEXT_USERMANAGED,
7573                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
7574     ok(r == ERROR_UNKNOWN_PRODUCT,
7575        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7576     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7577     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7578 
7579     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
7580     lstrcatA(keypath, usersid);
7581     lstrcatA(keypath, "\\Installer\\Products\\");
7582     lstrcatA(keypath, prod_squashed);
7583 
7584     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
7585     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7586 
7587     res = RegSetValueExA(userkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
7588     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7589 
7590     /* HelpLink value exists, user product key does exist */
7591     sz = MAX_PATH;
7592     lstrcpyA(buf, "apple");
7593     r = pMsiGetProductInfoExA(prodcode, usersid,
7594                               MSIINSTALLCONTEXT_USERMANAGED,
7595                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
7596     ok(r == ERROR_UNKNOWN_PROPERTY,
7597        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7598     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7599     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7600 
7601     res = RegSetValueExA(userkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
7602     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7603 
7604     /* HelpTelephone value exists */
7605     sz = MAX_PATH;
7606     lstrcpyA(buf, "apple");
7607     r = pMsiGetProductInfoExA(prodcode, usersid,
7608                               MSIINSTALLCONTEXT_USERMANAGED,
7609                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
7610     ok(r == ERROR_UNKNOWN_PROPERTY,
7611        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7612     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7613     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7614 
7615     res = RegSetValueExA(userkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
7616     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7617 
7618     /* InstallDate value exists */
7619     sz = MAX_PATH;
7620     lstrcpyA(buf, "apple");
7621     r = pMsiGetProductInfoExA(prodcode, usersid,
7622                               MSIINSTALLCONTEXT_USERMANAGED,
7623                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
7624     ok(r == ERROR_UNKNOWN_PROPERTY,
7625        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7626     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7627     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7628 
7629     res = RegSetValueExA(userkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
7630     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7631 
7632     /* DisplayName value exists */
7633     sz = MAX_PATH;
7634     lstrcpyA(buf, "apple");
7635     r = pMsiGetProductInfoExA(prodcode, usersid,
7636                               MSIINSTALLCONTEXT_USERMANAGED,
7637                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
7638     ok(r == ERROR_UNKNOWN_PROPERTY,
7639        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7640     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7641     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7642 
7643     res = RegSetValueExA(userkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
7644     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7645 
7646     /* InstallLocation value exists */
7647     sz = MAX_PATH;
7648     lstrcpyA(buf, "apple");
7649     r = pMsiGetProductInfoExA(prodcode, usersid,
7650                               MSIINSTALLCONTEXT_USERMANAGED,
7651                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
7652     ok(r == ERROR_UNKNOWN_PROPERTY,
7653        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7654     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7655     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7656 
7657     res = RegSetValueExA(userkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
7658     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7659 
7660     /* InstallSource value exists */
7661     sz = MAX_PATH;
7662     lstrcpyA(buf, "apple");
7663     r = pMsiGetProductInfoExA(prodcode, usersid,
7664                               MSIINSTALLCONTEXT_USERMANAGED,
7665                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
7666     ok(r == ERROR_UNKNOWN_PROPERTY,
7667        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7668     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7669     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7670 
7671     res = RegSetValueExA(userkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
7672     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7673 
7674     /* LocalPackage value exists */
7675     sz = MAX_PATH;
7676     lstrcpyA(buf, "apple");
7677     r = pMsiGetProductInfoExA(prodcode, usersid,
7678                               MSIINSTALLCONTEXT_USERMANAGED,
7679                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
7680     ok(r == ERROR_UNKNOWN_PROPERTY,
7681        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7682     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7683     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7684 
7685     res = RegSetValueExA(userkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
7686     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7687 
7688     /* Publisher value exists */
7689     sz = MAX_PATH;
7690     lstrcpyA(buf, "apple");
7691     r = pMsiGetProductInfoExA(prodcode, usersid,
7692                               MSIINSTALLCONTEXT_USERMANAGED,
7693                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
7694     ok(r == ERROR_UNKNOWN_PROPERTY,
7695        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7696     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7697     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7698 
7699     res = RegSetValueExA(userkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
7700     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7701 
7702     /* URLInfoAbout value exists */
7703     sz = MAX_PATH;
7704     lstrcpyA(buf, "apple");
7705     r = pMsiGetProductInfoExA(prodcode, usersid,
7706                               MSIINSTALLCONTEXT_USERMANAGED,
7707                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
7708     ok(r == ERROR_UNKNOWN_PROPERTY,
7709        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7710     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7711     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7712 
7713     res = RegSetValueExA(userkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
7714     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7715 
7716     /* URLUpdateInfo value exists */
7717     sz = MAX_PATH;
7718     lstrcpyA(buf, "apple");
7719     r = pMsiGetProductInfoExA(prodcode, usersid,
7720                               MSIINSTALLCONTEXT_USERMANAGED,
7721                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
7722     ok(r == ERROR_UNKNOWN_PROPERTY,
7723        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7724     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7725     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7726 
7727     res = RegSetValueExA(userkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
7728     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7729 
7730     /* VersionMinor value exists */
7731     sz = MAX_PATH;
7732     lstrcpyA(buf, "apple");
7733     r = pMsiGetProductInfoExA(prodcode, usersid,
7734                               MSIINSTALLCONTEXT_USERMANAGED,
7735                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
7736     ok(r == ERROR_UNKNOWN_PROPERTY,
7737        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7738     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7739     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7740 
7741     res = RegSetValueExA(userkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
7742     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7743 
7744     /* VersionMajor value exists */
7745     sz = MAX_PATH;
7746     lstrcpyA(buf, "apple");
7747     r = pMsiGetProductInfoExA(prodcode, usersid,
7748                               MSIINSTALLCONTEXT_USERMANAGED,
7749                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
7750     ok(r == ERROR_UNKNOWN_PROPERTY,
7751        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7752     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7753     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7754 
7755     res = RegSetValueExA(userkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
7756     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7757 
7758     /* DisplayVersion value exists */
7759     sz = MAX_PATH;
7760     lstrcpyA(buf, "apple");
7761     r = pMsiGetProductInfoExA(prodcode, usersid,
7762                               MSIINSTALLCONTEXT_USERMANAGED,
7763                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
7764     ok(r == ERROR_UNKNOWN_PROPERTY,
7765        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7766     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7767     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7768 
7769     res = RegSetValueExA(userkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
7770     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7771 
7772     /* ProductID value exists */
7773     sz = MAX_PATH;
7774     lstrcpyA(buf, "apple");
7775     r = pMsiGetProductInfoExA(prodcode, usersid,
7776                               MSIINSTALLCONTEXT_USERMANAGED,
7777                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
7778     ok(r == ERROR_UNKNOWN_PROPERTY,
7779        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7780     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7781     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7782 
7783     res = RegSetValueExA(userkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
7784     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7785 
7786     /* RegCompany value exists */
7787     sz = MAX_PATH;
7788     lstrcpyA(buf, "apple");
7789     r = pMsiGetProductInfoExA(prodcode, usersid,
7790                               MSIINSTALLCONTEXT_USERMANAGED,
7791                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
7792     ok(r == ERROR_UNKNOWN_PROPERTY,
7793        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7794     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7795     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7796 
7797     res = RegSetValueExA(userkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
7798     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7799 
7800     /* RegOwner value exists */
7801     sz = MAX_PATH;
7802     lstrcpyA(buf, "apple");
7803     r = pMsiGetProductInfoExA(prodcode, usersid,
7804                               MSIINSTALLCONTEXT_USERMANAGED,
7805                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
7806     ok(r == ERROR_UNKNOWN_PROPERTY,
7807        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7808     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7809     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7810 
7811     res = RegSetValueExA(userkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
7812     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7813 
7814     /* Transforms value exists */
7815     sz = MAX_PATH;
7816     lstrcpyA(buf, "apple");
7817     r = pMsiGetProductInfoExA(prodcode, usersid,
7818                               MSIINSTALLCONTEXT_USERMANAGED,
7819                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
7820     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7821     ok(!lstrcmpA(buf, "trans"), "Expected \"trans\", got \"%s\"\n", buf);
7822     ok(sz == 5, "Expected 5, got %d\n", sz);
7823 
7824     res = RegSetValueExA(userkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
7825     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7826 
7827     /* Language value exists */
7828     sz = MAX_PATH;
7829     lstrcpyA(buf, "apple");
7830     r = pMsiGetProductInfoExA(prodcode, usersid,
7831                               MSIINSTALLCONTEXT_USERMANAGED,
7832                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
7833     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7834     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
7835     ok(sz == 4, "Expected 4, got %d\n", sz);
7836 
7837     res = RegSetValueExA(userkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
7838     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7839 
7840     /* ProductName value exists */
7841     sz = MAX_PATH;
7842     lstrcpyA(buf, "apple");
7843     r = pMsiGetProductInfoExA(prodcode, usersid,
7844                               MSIINSTALLCONTEXT_USERMANAGED,
7845                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
7846     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7847     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
7848     ok(sz == 4, "Expected 4, got %d\n", sz);
7849 
7850     res = RegSetValueExA(userkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
7851     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7852 
7853     /* FIXME */
7854 
7855     /* AssignmentType value exists */
7856     sz = MAX_PATH;
7857     lstrcpyA(buf, "apple");
7858     r = pMsiGetProductInfoExA(prodcode, usersid,
7859                               MSIINSTALLCONTEXT_USERMANAGED,
7860                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
7861     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7862     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7863     ok(sz == 0, "Expected 0, got %d\n", sz);
7864 
7865     res = RegSetValueExA(userkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
7866     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7867 
7868     /* FIXME */
7869 
7870     /* PackageCode value exists */
7871     sz = MAX_PATH;
7872     lstrcpyA(buf, "apple");
7873     r = pMsiGetProductInfoExA(prodcode, usersid,
7874                               MSIINSTALLCONTEXT_USERMANAGED,
7875                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
7876     todo_wine
7877     {
7878         ok(r == ERROR_BAD_CONFIGURATION,
7879            "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
7880         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7881         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7882     }
7883 
7884     res = RegSetValueExA(userkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
7885     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7886 
7887     /* Version value exists */
7888     sz = MAX_PATH;
7889     lstrcpyA(buf, "apple");
7890     r = pMsiGetProductInfoExA(prodcode, usersid,
7891                               MSIINSTALLCONTEXT_USERMANAGED,
7892                               INSTALLPROPERTY_VERSIONA, buf, &sz);
7893     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7894     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
7895     ok(sz == 3, "Expected 3, got %d\n", sz);
7896 
7897     res = RegSetValueExA(userkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
7898     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7899 
7900     /* ProductIcon value exists */
7901     sz = MAX_PATH;
7902     lstrcpyA(buf, "apple");
7903     r = pMsiGetProductInfoExA(prodcode, usersid,
7904                               MSIINSTALLCONTEXT_USERMANAGED,
7905                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
7906     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7907     ok(!lstrcmpA(buf, "icon"), "Expected \"icon\", got \"%s\"\n", buf);
7908     ok(sz == 4, "Expected 4, got %d\n", sz);
7909 
7910     res = RegSetValueExA(userkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
7911     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7912 
7913     /* PackageName value exists */
7914     sz = MAX_PATH;
7915     lstrcpyA(buf, "apple");
7916     r = pMsiGetProductInfoExA(prodcode, usersid,
7917                               MSIINSTALLCONTEXT_USERMANAGED,
7918                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
7919     todo_wine
7920     {
7921         ok(r == ERROR_UNKNOWN_PRODUCT,
7922            "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7923         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7924         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7925     }
7926 
7927     res = RegSetValueExA(userkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
7928     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7929 
7930     /* AuthorizedLUAApp value exists */
7931     sz = MAX_PATH;
7932     lstrcpyA(buf, "apple");
7933     r = pMsiGetProductInfoExA(prodcode, usersid,
7934                               MSIINSTALLCONTEXT_USERMANAGED,
7935                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
7936     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7937     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
7938     ok(sz == 4, "Expected 4, got %d\n", sz);
7939 
7940     RegDeleteValueA(userkey, "AuthorizedLUAApp");
7941     RegDeleteValueA(userkey, "PackageName");
7942     RegDeleteValueA(userkey, "ProductIcon");
7943     RegDeleteValueA(userkey, "Version");
7944     RegDeleteValueA(userkey, "PackageCode");
7945     RegDeleteValueA(userkey, "AssignmentType");
7946     RegDeleteValueA(userkey, "ProductName");
7947     RegDeleteValueA(userkey, "Language");
7948     RegDeleteValueA(userkey, "Transforms");
7949     RegDeleteValueA(userkey, "RegOwner");
7950     RegDeleteValueA(userkey, "RegCompany");
7951     RegDeleteValueA(userkey, "ProductID");
7952     RegDeleteValueA(userkey, "DisplayVersion");
7953     RegDeleteValueA(userkey, "VersionMajor");
7954     RegDeleteValueA(userkey, "VersionMinor");
7955     RegDeleteValueA(userkey, "URLUpdateInfo");
7956     RegDeleteValueA(userkey, "URLInfoAbout");
7957     RegDeleteValueA(userkey, "Publisher");
7958     RegDeleteValueA(userkey, "LocalPackage");
7959     RegDeleteValueA(userkey, "InstallSource");
7960     RegDeleteValueA(userkey, "InstallLocation");
7961     RegDeleteValueA(userkey, "DisplayName");
7962     RegDeleteValueA(userkey, "InstallDate");
7963     RegDeleteValueA(userkey, "HelpTelephone");
7964     RegDeleteValueA(userkey, "HelpLink");
7965     delete_key(userkey, "", access & KEY_WOW64_64KEY);
7966     RegCloseKey(userkey);
7967     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
7968     RegCloseKey(prodkey);
7969 
7970     /* MSIINSTALLCONTEXT_MACHINE */
7971 
7972     /* szUserSid is non-NULL */
7973     sz = MAX_PATH;
7974     lstrcpyA(buf, "apple");
7975     r = pMsiGetProductInfoExA(prodcode, usersid,
7976                               MSIINSTALLCONTEXT_MACHINE,
7977                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7978     ok(r == ERROR_INVALID_PARAMETER,
7979        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
7980     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7981     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7982 
7983     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\");
7984     lstrcatA(keypath, prod_squashed);
7985 
7986     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
7987     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7988 
7989     /* local system product key exists */
7990     sz = MAX_PATH;
7991     lstrcpyA(buf, "apple");
7992     r = pMsiGetProductInfoExA(prodcode, NULL,
7993                               MSIINSTALLCONTEXT_MACHINE,
7994                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7995     ok(r == ERROR_UNKNOWN_PRODUCT,
7996        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7997     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7998     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7999 
8000     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
8001     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8002 
8003     /* InstallProperties key exists */
8004     sz = MAX_PATH;
8005     lstrcpyA(buf, "apple");
8006     r = pMsiGetProductInfoExA(prodcode, NULL,
8007                               MSIINSTALLCONTEXT_MACHINE,
8008                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
8009     ok(r == ERROR_UNKNOWN_PRODUCT,
8010        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8011     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8012     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8013 
8014     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
8015     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8016 
8017     /* LocalPackage value exists */
8018     sz = MAX_PATH;
8019     lstrcpyA(buf, "apple");
8020     r = pMsiGetProductInfoExA(prodcode, NULL,
8021                               MSIINSTALLCONTEXT_MACHINE,
8022                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
8023     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8024     ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
8025     ok(sz == 1, "Expected 1, got %d\n", sz);
8026 
8027     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
8028     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8029 
8030     /* HelpLink value exists */
8031     sz = MAX_PATH;
8032     lstrcpyA(buf, "apple");
8033     r = pMsiGetProductInfoExA(prodcode, NULL,
8034                               MSIINSTALLCONTEXT_MACHINE,
8035                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
8036     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8037     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
8038     ok(sz == 4, "Expected 4, got %d\n", sz);
8039 
8040     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
8041     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8042 
8043     /* HelpTelephone value exists */
8044     sz = MAX_PATH;
8045     lstrcpyA(buf, "apple");
8046     r = pMsiGetProductInfoExA(prodcode, NULL,
8047                               MSIINSTALLCONTEXT_MACHINE,
8048                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
8049     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8050     ok(!lstrcmpA(buf, "phone"), "Expected \"phone\", got \"%s\"\n", buf);
8051     ok(sz == 5, "Expected 5, got %d\n", sz);
8052 
8053     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
8054     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8055 
8056     /* InstallDate value exists */
8057     sz = MAX_PATH;
8058     lstrcpyA(buf, "apple");
8059     r = pMsiGetProductInfoExA(prodcode, NULL,
8060                               MSIINSTALLCONTEXT_MACHINE,
8061                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
8062     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8063     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
8064     ok(sz == 4, "Expected 4, got %d\n", sz);
8065 
8066     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
8067     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8068 
8069     /* DisplayName value exists */
8070     sz = MAX_PATH;
8071     lstrcpyA(buf, "apple");
8072     r = pMsiGetProductInfoExA(prodcode, NULL,
8073                               MSIINSTALLCONTEXT_MACHINE,
8074                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
8075     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8076     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
8077     ok(sz == 4, "Expected 4, got %d\n", sz);
8078 
8079     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
8080     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8081 
8082     /* InstallLocation value exists */
8083     sz = MAX_PATH;
8084     lstrcpyA(buf, "apple");
8085     r = pMsiGetProductInfoExA(prodcode, NULL,
8086                               MSIINSTALLCONTEXT_MACHINE,
8087                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
8088     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8089     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
8090     ok(sz == 3, "Expected 3, got %d\n", sz);
8091 
8092     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
8093     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8094 
8095     /* InstallSource value exists */
8096     sz = MAX_PATH;
8097     lstrcpyA(buf, "apple");
8098     r = pMsiGetProductInfoExA(prodcode, NULL,
8099                               MSIINSTALLCONTEXT_MACHINE,
8100                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
8101     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8102     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
8103     ok(sz == 6, "Expected 6, got %d\n", sz);
8104 
8105     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
8106     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8107 
8108     /* LocalPackage value exists */
8109     sz = MAX_PATH;
8110     lstrcpyA(buf, "apple");
8111     r = pMsiGetProductInfoExA(prodcode, NULL,
8112                               MSIINSTALLCONTEXT_MACHINE,
8113                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
8114     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8115     ok(!lstrcmpA(buf, "local"), "Expected \"local\", got \"%s\"\n", buf);
8116     ok(sz == 5, "Expected 5, got %d\n", sz);
8117 
8118     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
8119     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8120 
8121     /* Publisher value exists */
8122     sz = MAX_PATH;
8123     lstrcpyA(buf, "apple");
8124     r = pMsiGetProductInfoExA(prodcode, NULL,
8125                               MSIINSTALLCONTEXT_MACHINE,
8126                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
8127     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8128     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
8129     ok(sz == 3, "Expected 3, got %d\n", sz);
8130 
8131     res = RegSetValueExA(propkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
8132     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8133 
8134     /* URLInfoAbout value exists */
8135     sz = MAX_PATH;
8136     lstrcpyA(buf, "apple");
8137     r = pMsiGetProductInfoExA(prodcode, NULL,
8138                               MSIINSTALLCONTEXT_MACHINE,
8139                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
8140     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8141     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
8142     ok(sz == 5, "Expected 5, got %d\n", sz);
8143 
8144     res = RegSetValueExA(propkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
8145     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8146 
8147     /* URLUpdateInfo value exists */
8148     sz = MAX_PATH;
8149     lstrcpyA(buf, "apple");
8150     r = pMsiGetProductInfoExA(prodcode, NULL,
8151                               MSIINSTALLCONTEXT_MACHINE,
8152                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
8153     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8154     ok(!lstrcmpA(buf, "update"), "Expected \"update\", got \"%s\"\n", buf);
8155     ok(sz == 6, "Expected 6, got %d\n", sz);
8156 
8157     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
8158     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8159 
8160     /* VersionMinor value exists */
8161     sz = MAX_PATH;
8162     lstrcpyA(buf, "apple");
8163     r = pMsiGetProductInfoExA(prodcode, NULL,
8164                               MSIINSTALLCONTEXT_MACHINE,
8165                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
8166     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8167     ok(!lstrcmpA(buf, "2"), "Expected \"2\", got \"%s\"\n", buf);
8168     ok(sz == 1, "Expected 1, got %d\n", sz);
8169 
8170     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
8171     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8172 
8173     /* VersionMajor value exists */
8174     sz = MAX_PATH;
8175     lstrcpyA(buf, "apple");
8176     r = pMsiGetProductInfoExA(prodcode, NULL,
8177                               MSIINSTALLCONTEXT_MACHINE,
8178                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
8179     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8180     ok(!lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
8181     ok(sz == 1, "Expected 1, got %d\n", sz);
8182 
8183     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
8184     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8185 
8186     /* DisplayVersion value exists */
8187     sz = MAX_PATH;
8188     lstrcpyA(buf, "apple");
8189     r = pMsiGetProductInfoExA(prodcode, NULL,
8190                               MSIINSTALLCONTEXT_MACHINE,
8191                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
8192     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8193     ok(!lstrcmpA(buf, "3.2.1"), "Expected \"3.2.1\", got \"%s\"\n", buf);
8194     ok(sz == 5, "Expected 5, got %d\n", sz);
8195 
8196     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
8197     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8198 
8199     /* ProductID value exists */
8200     sz = MAX_PATH;
8201     lstrcpyA(buf, "apple");
8202     r = pMsiGetProductInfoExA(prodcode, NULL,
8203                               MSIINSTALLCONTEXT_MACHINE,
8204                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
8205     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8206     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
8207     ok(sz == 2, "Expected 2, got %d\n", sz);
8208 
8209     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
8210     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8211 
8212     /* RegCompany value exists */
8213     sz = MAX_PATH;
8214     lstrcpyA(buf, "apple");
8215     r = pMsiGetProductInfoExA(prodcode, NULL,
8216                               MSIINSTALLCONTEXT_MACHINE,
8217                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
8218     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8219     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
8220     ok(sz == 4, "Expected 4, got %d\n", sz);
8221 
8222     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
8223     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8224 
8225     /* RegOwner value exists */
8226     sz = MAX_PATH;
8227     lstrcpyA(buf, "apple");
8228     r = pMsiGetProductInfoExA(prodcode, NULL,
8229                               MSIINSTALLCONTEXT_MACHINE,
8230                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
8231     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8232     ok(!lstrcmpA(buf, "owner"), "Expected \"owner\", got \"%s\"\n", buf);
8233     ok(sz == 5, "Expected 5, got %d\n", sz);
8234 
8235     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
8236     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8237 
8238     /* Transforms value exists */
8239     sz = MAX_PATH;
8240     lstrcpyA(buf, "apple");
8241     r = pMsiGetProductInfoExA(prodcode, NULL,
8242                               MSIINSTALLCONTEXT_MACHINE,
8243                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
8244     ok(r == ERROR_UNKNOWN_PRODUCT,
8245        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8246     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8247     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8248 
8249     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
8250     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8251 
8252     /* Language value exists */
8253     sz = MAX_PATH;
8254     lstrcpyA(buf, "apple");
8255     r = pMsiGetProductInfoExA(prodcode, NULL,
8256                               MSIINSTALLCONTEXT_MACHINE,
8257                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
8258     ok(r == ERROR_UNKNOWN_PRODUCT,
8259        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8260     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8261     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8262 
8263     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
8264     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8265 
8266     /* ProductName value exists */
8267     sz = MAX_PATH;
8268     lstrcpyA(buf, "apple");
8269     r = pMsiGetProductInfoExA(prodcode, NULL,
8270                               MSIINSTALLCONTEXT_MACHINE,
8271                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
8272     ok(r == ERROR_UNKNOWN_PRODUCT,
8273        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8274     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8275     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8276 
8277     res = RegSetValueExA(propkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
8278     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8279 
8280     /* FIXME */
8281 
8282     /* AssignmentType value exists */
8283     sz = MAX_PATH;
8284     lstrcpyA(buf, "apple");
8285     r = pMsiGetProductInfoExA(prodcode, NULL,
8286                               MSIINSTALLCONTEXT_MACHINE,
8287                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
8288     ok(r == ERROR_UNKNOWN_PRODUCT,
8289        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8290     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8291     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8292 
8293     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
8294     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8295 
8296     /* PackageCode value exists */
8297     sz = MAX_PATH;
8298     lstrcpyA(buf, "apple");
8299     r = pMsiGetProductInfoExA(prodcode, NULL,
8300                               MSIINSTALLCONTEXT_MACHINE,
8301                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
8302     ok(r == ERROR_UNKNOWN_PRODUCT,
8303        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8304     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8305     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8306 
8307     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
8308     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8309 
8310     /* Version value exists */
8311     sz = MAX_PATH;
8312     lstrcpyA(buf, "apple");
8313     r = pMsiGetProductInfoExA(prodcode, NULL,
8314                               MSIINSTALLCONTEXT_MACHINE,
8315                               INSTALLPROPERTY_VERSIONA, buf, &sz);
8316     ok(r == ERROR_UNKNOWN_PRODUCT,
8317        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8318     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8319     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8320 
8321     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
8322     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8323 
8324     /* ProductIcon value exists */
8325     sz = MAX_PATH;
8326     lstrcpyA(buf, "apple");
8327     r = pMsiGetProductInfoExA(prodcode, NULL,
8328                               MSIINSTALLCONTEXT_MACHINE,
8329                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
8330     ok(r == ERROR_UNKNOWN_PRODUCT,
8331        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8332     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8333     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8334 
8335     res = RegSetValueExA(propkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
8336     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8337 
8338     /* PackageName value exists */
8339     sz = MAX_PATH;
8340     lstrcpyA(buf, "apple");
8341     r = pMsiGetProductInfoExA(prodcode, NULL,
8342                               MSIINSTALLCONTEXT_MACHINE,
8343                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
8344     ok(r == ERROR_UNKNOWN_PRODUCT,
8345        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8346     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8347     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8348 
8349     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
8350     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8351 
8352     /* AuthorizedLUAApp value exists */
8353     sz = MAX_PATH;
8354     lstrcpyA(buf, "apple");
8355     r = pMsiGetProductInfoExA(prodcode, NULL,
8356                               MSIINSTALLCONTEXT_MACHINE,
8357                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
8358     ok(r == ERROR_UNKNOWN_PRODUCT,
8359        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8360     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8361     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8362 
8363     RegDeleteValueA(propkey, "AuthorizedLUAApp");
8364     RegDeleteValueA(propkey, "PackageName");
8365     RegDeleteValueA(propkey, "ProductIcon");
8366     RegDeleteValueA(propkey, "Version");
8367     RegDeleteValueA(propkey, "PackageCode");
8368     RegDeleteValueA(propkey, "AssignmentType");
8369     RegDeleteValueA(propkey, "ProductName");
8370     RegDeleteValueA(propkey, "Language");
8371     RegDeleteValueA(propkey, "Transforms");
8372     RegDeleteValueA(propkey, "RegOwner");
8373     RegDeleteValueA(propkey, "RegCompany");
8374     RegDeleteValueA(propkey, "ProductID");
8375     RegDeleteValueA(propkey, "DisplayVersion");
8376     RegDeleteValueA(propkey, "VersionMajor");
8377     RegDeleteValueA(propkey, "VersionMinor");
8378     RegDeleteValueA(propkey, "URLUpdateInfo");
8379     RegDeleteValueA(propkey, "URLInfoAbout");
8380     RegDeleteValueA(propkey, "Publisher");
8381     RegDeleteValueA(propkey, "LocalPackage");
8382     RegDeleteValueA(propkey, "InstallSource");
8383     RegDeleteValueA(propkey, "InstallLocation");
8384     RegDeleteValueA(propkey, "DisplayName");
8385     RegDeleteValueA(propkey, "InstallDate");
8386     RegDeleteValueA(propkey, "HelpTelephone");
8387     RegDeleteValueA(propkey, "HelpLink");
8388     RegDeleteValueA(propkey, "LocalPackage");
8389     delete_key(propkey, "", access & KEY_WOW64_64KEY);
8390     RegCloseKey(propkey);
8391     delete_key(localkey, "", access & KEY_WOW64_64KEY);
8392     RegCloseKey(localkey);
8393 
8394     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
8395     lstrcatA(keypath, prod_squashed);
8396 
8397     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8398     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8399 
8400     /* local classes product key exists */
8401     sz = MAX_PATH;
8402     lstrcpyA(buf, "apple");
8403     r = pMsiGetProductInfoExA(prodcode, NULL,
8404                               MSIINSTALLCONTEXT_MACHINE,
8405                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
8406     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8407     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
8408     ok(sz == 1, "Expected 1, got %d\n", sz);
8409 
8410     res = RegSetValueExA(prodkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
8411     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8412 
8413     /* HelpLink value exists */
8414     sz = MAX_PATH;
8415     lstrcpyA(buf, "apple");
8416     r = pMsiGetProductInfoExA(prodcode, NULL,
8417                               MSIINSTALLCONTEXT_MACHINE,
8418                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
8419     ok(r == ERROR_UNKNOWN_PROPERTY,
8420        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8421     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8422     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8423 
8424     res = RegSetValueExA(prodkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
8425     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8426 
8427     /* HelpTelephone value exists */
8428     sz = MAX_PATH;
8429     lstrcpyA(buf, "apple");
8430     r = pMsiGetProductInfoExA(prodcode, NULL,
8431                               MSIINSTALLCONTEXT_MACHINE,
8432                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
8433     ok(r == ERROR_UNKNOWN_PROPERTY,
8434        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8435     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8436     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8437 
8438     res = RegSetValueExA(prodkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
8439     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8440 
8441     /* InstallDate value exists */
8442     sz = MAX_PATH;
8443     lstrcpyA(buf, "apple");
8444     r = pMsiGetProductInfoExA(prodcode, NULL,
8445                               MSIINSTALLCONTEXT_MACHINE,
8446                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
8447     ok(r == ERROR_UNKNOWN_PROPERTY,
8448        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8449     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8450     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8451 
8452     res = RegSetValueExA(prodkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
8453     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8454 
8455     /* DisplayName value exists */
8456     sz = MAX_PATH;
8457     lstrcpyA(buf, "apple");
8458     r = pMsiGetProductInfoExA(prodcode, NULL,
8459                               MSIINSTALLCONTEXT_MACHINE,
8460                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
8461     ok(r == ERROR_UNKNOWN_PROPERTY,
8462        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8463     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8464     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8465 
8466     res = RegSetValueExA(prodkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
8467     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8468 
8469     /* InstallLocation value exists */
8470     sz = MAX_PATH;
8471     lstrcpyA(buf, "apple");
8472     r = pMsiGetProductInfoExA(prodcode, NULL,
8473                               MSIINSTALLCONTEXT_MACHINE,
8474                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
8475     ok(r == ERROR_UNKNOWN_PROPERTY,
8476        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8477     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8478     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8479 
8480     res = RegSetValueExA(prodkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
8481     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8482 
8483     /* InstallSource value exists */
8484     sz = MAX_PATH;
8485     lstrcpyA(buf, "apple");
8486     r = pMsiGetProductInfoExA(prodcode, NULL,
8487                               MSIINSTALLCONTEXT_MACHINE,
8488                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
8489     ok(r == ERROR_UNKNOWN_PROPERTY,
8490        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8491     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8492     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8493 
8494     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
8495     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8496 
8497     /* LocalPackage value exists */
8498     sz = MAX_PATH;
8499     lstrcpyA(buf, "apple");
8500     r = pMsiGetProductInfoExA(prodcode, NULL,
8501                               MSIINSTALLCONTEXT_MACHINE,
8502                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
8503     ok(r == ERROR_UNKNOWN_PROPERTY,
8504        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8505     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8506     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8507 
8508     res = RegSetValueExA(prodkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
8509     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8510 
8511     /* Publisher value exists */
8512     sz = MAX_PATH;
8513     lstrcpyA(buf, "apple");
8514     r = pMsiGetProductInfoExA(prodcode, NULL,
8515                               MSIINSTALLCONTEXT_MACHINE,
8516                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
8517     ok(r == ERROR_UNKNOWN_PROPERTY,
8518        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8519     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8520     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8521 
8522     res = RegSetValueExA(prodkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
8523     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8524 
8525     /* URLInfoAbout value exists */
8526     sz = MAX_PATH;
8527     lstrcpyA(buf, "apple");
8528     r = pMsiGetProductInfoExA(prodcode, NULL,
8529                               MSIINSTALLCONTEXT_MACHINE,
8530                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
8531     ok(r == ERROR_UNKNOWN_PROPERTY,
8532        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8533     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8534     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8535 
8536     res = RegSetValueExA(prodkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
8537     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8538 
8539     /* URLUpdateInfo value exists */
8540     sz = MAX_PATH;
8541     lstrcpyA(buf, "apple");
8542     r = pMsiGetProductInfoExA(prodcode, NULL,
8543                               MSIINSTALLCONTEXT_MACHINE,
8544                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
8545     ok(r == ERROR_UNKNOWN_PROPERTY,
8546        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8547     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8548     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8549 
8550     res = RegSetValueExA(prodkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
8551     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8552 
8553     /* VersionMinor value exists */
8554     sz = MAX_PATH;
8555     lstrcpyA(buf, "apple");
8556     r = pMsiGetProductInfoExA(prodcode, NULL,
8557                               MSIINSTALLCONTEXT_MACHINE,
8558                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
8559     ok(r == ERROR_UNKNOWN_PROPERTY,
8560        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8561     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8562     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8563 
8564     res = RegSetValueExA(prodkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
8565     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8566 
8567     /* VersionMajor value exists */
8568     sz = MAX_PATH;
8569     lstrcpyA(buf, "apple");
8570     r = pMsiGetProductInfoExA(prodcode, NULL,
8571                               MSIINSTALLCONTEXT_MACHINE,
8572                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
8573     ok(r == ERROR_UNKNOWN_PROPERTY,
8574        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8575     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8576     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8577 
8578     res = RegSetValueExA(prodkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
8579     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8580 
8581     /* DisplayVersion value exists */
8582     sz = MAX_PATH;
8583     lstrcpyA(buf, "apple");
8584     r = pMsiGetProductInfoExA(prodcode, NULL,
8585                               MSIINSTALLCONTEXT_MACHINE,
8586                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
8587     ok(r == ERROR_UNKNOWN_PROPERTY,
8588        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8589     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8590     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8591 
8592     res = RegSetValueExA(prodkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
8593     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8594 
8595     /* ProductID value exists */
8596     sz = MAX_PATH;
8597     lstrcpyA(buf, "apple");
8598     r = pMsiGetProductInfoExA(prodcode, NULL,
8599                               MSIINSTALLCONTEXT_MACHINE,
8600                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
8601     ok(r == ERROR_UNKNOWN_PROPERTY,
8602        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8603     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8604     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8605 
8606     res = RegSetValueExA(prodkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
8607     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8608 
8609     /* RegCompany value exists */
8610     sz = MAX_PATH;
8611     lstrcpyA(buf, "apple");
8612     r = pMsiGetProductInfoExA(prodcode, NULL,
8613                               MSIINSTALLCONTEXT_MACHINE,
8614                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
8615     ok(r == ERROR_UNKNOWN_PROPERTY,
8616        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8617     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8618     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8619 
8620     res = RegSetValueExA(prodkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
8621     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8622 
8623     /* RegOwner value exists */
8624     sz = MAX_PATH;
8625     lstrcpyA(buf, "apple");
8626     r = pMsiGetProductInfoExA(prodcode, NULL,
8627                               MSIINSTALLCONTEXT_MACHINE,
8628                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
8629     ok(r == ERROR_UNKNOWN_PROPERTY,
8630        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8631     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8632     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8633 
8634     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
8635     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8636 
8637     /* Transforms value exists */
8638     sz = MAX_PATH;
8639     lstrcpyA(buf, "apple");
8640     r = pMsiGetProductInfoExA(prodcode, NULL,
8641                               MSIINSTALLCONTEXT_MACHINE,
8642                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
8643     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8644     ok(!lstrcmpA(buf, "trans"), "Expected \"trans\", got \"%s\"\n", buf);
8645     ok(sz == 5, "Expected 5, got %d\n", sz);
8646 
8647     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
8648     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8649 
8650     /* Language value exists */
8651     sz = MAX_PATH;
8652     lstrcpyA(buf, "apple");
8653     r = pMsiGetProductInfoExA(prodcode, NULL,
8654                               MSIINSTALLCONTEXT_MACHINE,
8655                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
8656     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8657     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
8658     ok(sz == 4, "Expected 4, got %d\n", sz);
8659 
8660     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
8661     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8662 
8663     /* ProductName value exists */
8664     sz = MAX_PATH;
8665     lstrcpyA(buf, "apple");
8666     r = pMsiGetProductInfoExA(prodcode, NULL,
8667                               MSIINSTALLCONTEXT_MACHINE,
8668                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
8669     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8670     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
8671     ok(sz == 4, "Expected 4, got %d\n", sz);
8672 
8673     res = RegSetValueExA(prodkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
8674     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8675 
8676     /* FIXME */
8677 
8678     /* AssignmentType value exists */
8679     sz = MAX_PATH;
8680     lstrcpyA(buf, "apple");
8681     r = pMsiGetProductInfoExA(prodcode, NULL,
8682                               MSIINSTALLCONTEXT_MACHINE,
8683                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
8684     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8685     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
8686     ok(sz == 0, "Expected 0, got %d\n", sz);
8687 
8688     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
8689     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8690 
8691     /* FIXME */
8692 
8693     /* PackageCode value exists */
8694     sz = MAX_PATH;
8695     lstrcpyA(buf, "apple");
8696     r = pMsiGetProductInfoExA(prodcode, NULL,
8697                               MSIINSTALLCONTEXT_MACHINE,
8698                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
8699     todo_wine
8700     {
8701         ok(r == ERROR_BAD_CONFIGURATION,
8702            "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
8703         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8704         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8705     }
8706 
8707     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
8708     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8709 
8710     /* Version value exists */
8711     sz = MAX_PATH;
8712     lstrcpyA(buf, "apple");
8713     r = pMsiGetProductInfoExA(prodcode, NULL,
8714                               MSIINSTALLCONTEXT_MACHINE,
8715                               INSTALLPROPERTY_VERSIONA, buf, &sz);
8716     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8717     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
8718     ok(sz == 3, "Expected 3, got %d\n", sz);
8719 
8720     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
8721     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8722 
8723     /* ProductIcon value exists */
8724     sz = MAX_PATH;
8725     lstrcpyA(buf, "apple");
8726     r = pMsiGetProductInfoExA(prodcode, NULL,
8727                               MSIINSTALLCONTEXT_MACHINE,
8728                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
8729     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8730     ok(!lstrcmpA(buf, "icon"), "Expected \"icon\", got \"%s\"\n", buf);
8731     ok(sz == 4, "Expected 4, got %d\n", sz);
8732 
8733     res = RegSetValueExA(prodkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
8734     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8735 
8736     /* PackageName value exists */
8737     sz = MAX_PATH;
8738     lstrcpyA(buf, "apple");
8739     r = pMsiGetProductInfoExA(prodcode, NULL,
8740                               MSIINSTALLCONTEXT_MACHINE,
8741                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
8742     todo_wine
8743     {
8744         ok(r == ERROR_UNKNOWN_PRODUCT,
8745            "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8746         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8747         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8748     }
8749 
8750     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
8751     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8752 
8753     /* AuthorizedLUAApp value exists */
8754     sz = MAX_PATH;
8755     lstrcpyA(buf, "apple");
8756     r = pMsiGetProductInfoExA(prodcode, NULL,
8757                               MSIINSTALLCONTEXT_MACHINE,
8758                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
8759     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8760     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
8761     ok(sz == 4, "Expected 4, got %d\n", sz);
8762 
8763     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
8764     RegDeleteValueA(prodkey, "PackageName");
8765     RegDeleteValueA(prodkey, "ProductIcon");
8766     RegDeleteValueA(prodkey, "Version");
8767     RegDeleteValueA(prodkey, "PackageCode");
8768     RegDeleteValueA(prodkey, "AssignmentType");
8769     RegDeleteValueA(prodkey, "ProductName");
8770     RegDeleteValueA(prodkey, "Language");
8771     RegDeleteValueA(prodkey, "Transforms");
8772     RegDeleteValueA(prodkey, "RegOwner");
8773     RegDeleteValueA(prodkey, "RegCompany");
8774     RegDeleteValueA(prodkey, "ProductID");
8775     RegDeleteValueA(prodkey, "DisplayVersion");
8776     RegDeleteValueA(prodkey, "VersionMajor");
8777     RegDeleteValueA(prodkey, "VersionMinor");
8778     RegDeleteValueA(prodkey, "URLUpdateInfo");
8779     RegDeleteValueA(prodkey, "URLInfoAbout");
8780     RegDeleteValueA(prodkey, "Publisher");
8781     RegDeleteValueA(prodkey, "LocalPackage");
8782     RegDeleteValueA(prodkey, "InstallSource");
8783     RegDeleteValueA(prodkey, "InstallLocation");
8784     RegDeleteValueA(prodkey, "DisplayName");
8785     RegDeleteValueA(prodkey, "InstallDate");
8786     RegDeleteValueA(prodkey, "HelpTelephone");
8787     RegDeleteValueA(prodkey, "HelpLink");
8788     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
8789     RegCloseKey(prodkey);
8790     LocalFree(usersid);
8791 }
8792 
8793 #define INIT_USERINFO() \
8794     lstrcpyA(user, "apple"); \
8795     lstrcpyA(org, "orange"); \
8796     lstrcpyA(serial, "banana"); \
8797     usersz = orgsz = serialsz = MAX_PATH;
8798 
8799 static void test_MsiGetUserInfo(void)
8800 {
8801     USERINFOSTATE state;
8802     CHAR user[MAX_PATH];
8803     CHAR org[MAX_PATH];
8804     CHAR serial[MAX_PATH];
8805     DWORD usersz, orgsz, serialsz;
8806     CHAR keypath[MAX_PATH * 2];
8807     CHAR prodcode[MAX_PATH];
8808     CHAR prod_squashed[MAX_PATH];
8809     HKEY prodkey, userprod, props;
8810     LPSTR usersid;
8811     LONG res;
8812     REGSAM access = KEY_ALL_ACCESS;
8813 
8814     create_test_guid(prodcode, prod_squashed);
8815     usersid = get_user_sid();
8816 
8817     if (is_wow64)
8818         access |= KEY_WOW64_64KEY;
8819 
8820     /* NULL szProduct */
8821     INIT_USERINFO();
8822     state = MsiGetUserInfoA(NULL, user, &usersz, org, &orgsz, serial, &serialsz);
8823     ok(state == USERINFOSTATE_INVALIDARG,
8824        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8825     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8826     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8827     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8828     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8829     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8830     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8831 
8832     /* empty szProductCode */
8833     INIT_USERINFO();
8834     state = MsiGetUserInfoA("", user, &usersz, org, &orgsz, serial, &serialsz);
8835     ok(state == USERINFOSTATE_INVALIDARG,
8836        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8837     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8838     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8839     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8840     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8841     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8842     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8843 
8844     /* garbage szProductCode */
8845     INIT_USERINFO();
8846     state = MsiGetUserInfoA("garbage", user, &usersz, org, &orgsz, serial, &serialsz);
8847     ok(state == USERINFOSTATE_INVALIDARG,
8848        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8849     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8850     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8851     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8852     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8853     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8854     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8855 
8856     /* guid without brackets */
8857     INIT_USERINFO();
8858     state = MsiGetUserInfoA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
8859                             user, &usersz, org, &orgsz, serial, &serialsz);
8860     ok(state == USERINFOSTATE_INVALIDARG,
8861        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8862     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8863     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8864     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8865     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8866     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8867     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8868 
8869     /* guid with brackets */
8870     INIT_USERINFO();
8871     state = MsiGetUserInfoA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
8872                             user, &usersz, org, &orgsz, serial, &serialsz);
8873     ok(state == USERINFOSTATE_UNKNOWN,
8874        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8875     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
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 lpUserNameBuf */
8883     INIT_USERINFO();
8884     state = MsiGetUserInfoA(prodcode, NULL, &usersz, org, &orgsz, serial, &serialsz);
8885     ok(state == USERINFOSTATE_UNKNOWN,
8886        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8887     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8888     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8889     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
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     /* NULL pcchUserNameBuf */
8894     INIT_USERINFO();
8895     state = MsiGetUserInfoA(prodcode, user, NULL, org, &orgsz, serial, &serialsz);
8896     ok(state == USERINFOSTATE_INVALIDARG,
8897        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8898     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8899     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8900     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8901     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8902     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8903 
8904     /* both lpUserNameBuf and pcchUserNameBuf NULL */
8905     INIT_USERINFO();
8906     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
8907     ok(state == USERINFOSTATE_UNKNOWN,
8908        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8909     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8910     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
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 lpOrgNameBuf */
8915     INIT_USERINFO();
8916     state = MsiGetUserInfoA(prodcode, user, &usersz, NULL, &orgsz, serial, &serialsz);
8917     ok(state == USERINFOSTATE_UNKNOWN,
8918        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8919     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8920     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8921     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8922     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8923     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8924 
8925     /* NULL pcchOrgNameBuf */
8926     INIT_USERINFO();
8927     state = MsiGetUserInfoA(prodcode, user, &usersz, org, NULL, serial, &serialsz);
8928     ok(state == USERINFOSTATE_INVALIDARG,
8929        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8930     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8931     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8932     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8933     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8934     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8935 
8936     /* both lpOrgNameBuf and pcchOrgNameBuf NULL */
8937     INIT_USERINFO();
8938     state = MsiGetUserInfoA(prodcode, user, &usersz, NULL, NULL, serial, &serialsz);
8939     ok(state == USERINFOSTATE_UNKNOWN,
8940        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8941     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8942     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8943     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8944     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8945 
8946     /* NULL lpSerialBuf */
8947     INIT_USERINFO();
8948     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, NULL, &serialsz);
8949     ok(state == USERINFOSTATE_UNKNOWN,
8950        "Expected USERINFOSTATE_UNKNOWN, 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(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8954     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8955     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8956 
8957     /* NULL pcchSerialBuf */
8958     INIT_USERINFO();
8959     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, NULL);
8960     ok(state == USERINFOSTATE_INVALIDARG,
8961        "Expected USERINFOSTATE_INVALIDARG, 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(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8965     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8966     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8967 
8968     /* both lpSerialBuf and pcchSerialBuf NULL */
8969     INIT_USERINFO();
8970     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, NULL, NULL);
8971     ok(state == USERINFOSTATE_UNKNOWN,
8972        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8973     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8974     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8975     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8976     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8977 
8978     /* MSIINSTALLCONTEXT_USERMANAGED */
8979 
8980     /* create local system product key */
8981     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
8982     lstrcatA(keypath, usersid);
8983     lstrcatA(keypath, "\\Installer\\Products\\");
8984     lstrcatA(keypath, prod_squashed);
8985 
8986     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8987     if (res == ERROR_ACCESS_DENIED)
8988     {
8989         skip("Not enough rights to perform tests\n");
8990         LocalFree(usersid);
8991         return;
8992     }
8993     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8994 
8995     /* managed product key exists */
8996     INIT_USERINFO();
8997     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
8998     ok(state == USERINFOSTATE_ABSENT,
8999        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9000     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9001     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
9002     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9003     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
9004     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
9005     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
9006 
9007     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9008     lstrcatA(keypath, "Installer\\UserData\\");
9009     lstrcatA(keypath, usersid);
9010     lstrcatA(keypath, "\\Products\\");
9011     lstrcatA(keypath, prod_squashed);
9012 
9013     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL);
9014     if (res == ERROR_ACCESS_DENIED)
9015     {
9016         skip("Not enough rights to perform tests\n");
9017         LocalFree(usersid);
9018         return;
9019     }
9020     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9021 
9022     res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9023     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9024 
9025     /* InstallProperties key exists */
9026     INIT_USERINFO();
9027     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9028     ok(state == USERINFOSTATE_ABSENT,
9029        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9030     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9031     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
9032     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9033     ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", usersz);
9034     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
9035     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
9036 
9037     /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */
9038     INIT_USERINFO();
9039     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
9040     ok(state == USERINFOSTATE_ABSENT,
9041        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9042     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
9043     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9044     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
9045     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9046 
9047     /* RegOwner, RegCompany don't exist, out params are NULL */
9048     INIT_USERINFO();
9049     state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz);
9050     ok(state == USERINFOSTATE_ABSENT,
9051        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9052     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9053     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9054 
9055     res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
9056     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9057 
9058     /* RegOwner value exists */
9059     INIT_USERINFO();
9060     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9061     ok(state == USERINFOSTATE_ABSENT,
9062        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9063     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9064     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
9065     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9066     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9067     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
9068     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9069 
9070     res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8);
9071     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9072 
9073     /* RegCompany value exists */
9074     INIT_USERINFO();
9075     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9076     ok(state == USERINFOSTATE_ABSENT,
9077        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9078     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9079     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9080     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9081     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9082     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
9083     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9084 
9085     res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3);
9086     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9087 
9088     /* ProductID value exists */
9089     INIT_USERINFO();
9090     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9091     ok(state == USERINFOSTATE_PRESENT,
9092        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
9093     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9094     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9095     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
9096     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9097     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
9098     ok(serialsz == 2, "Expected 2, got %d\n", serialsz);
9099 
9100     /* pcchUserNameBuf is too small */
9101     INIT_USERINFO();
9102     usersz = 0;
9103     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9104     ok(state == USERINFOSTATE_MOREDATA,
9105        "Expected USERINFOSTATE_MOREDATA, got %d\n", state);
9106     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9107     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
9108     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9109     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9110     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
9111     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
9112 
9113     /* pcchUserNameBuf has no room for NULL terminator */
9114     INIT_USERINFO();
9115     usersz = 5;
9116     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9117     ok(state == USERINFOSTATE_MOREDATA,
9118        "Expected USERINFOSTATE_MOREDATA, got %d\n", state);
9119     todo_wine
9120     {
9121         ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9122     }
9123     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
9124     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9125     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9126     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
9127     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
9128 
9129     /* pcchUserNameBuf is too small, lpUserNameBuf is NULL */
9130     INIT_USERINFO();
9131     usersz = 0;
9132     state = MsiGetUserInfoA(prodcode, NULL, &usersz, org, &orgsz, serial, &serialsz);
9133     ok(state == USERINFOSTATE_PRESENT,
9134        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
9135     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9136     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9137     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
9138     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9139     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
9140     ok(serialsz == 2, "Expected 2, got %d\n", serialsz);
9141 
9142     RegDeleteValueA(props, "ProductID");
9143     RegDeleteValueA(props, "RegCompany");
9144     RegDeleteValueA(props, "RegOwner");
9145     delete_key(props, "", access & KEY_WOW64_64KEY);
9146     RegCloseKey(props);
9147     delete_key(userprod, "", access & KEY_WOW64_64KEY);
9148     RegCloseKey(userprod);
9149     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
9150     RegCloseKey(prodkey);
9151 
9152     /* MSIINSTALLCONTEXT_USERUNMANAGED */
9153 
9154     /* create local system product key */
9155     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
9156     lstrcatA(keypath, prod_squashed);
9157 
9158     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
9159     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9160 
9161     /* product key exists */
9162     INIT_USERINFO();
9163     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9164     ok(state == USERINFOSTATE_ABSENT,
9165        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9166     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9167     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
9168     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9169     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
9170     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
9171     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
9172 
9173     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9174     lstrcatA(keypath, "Installer\\UserData\\");
9175     lstrcatA(keypath, usersid);
9176     lstrcatA(keypath, "\\Products\\");
9177     lstrcatA(keypath, prod_squashed);
9178 
9179     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL);
9180     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9181 
9182     res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9183     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9184 
9185     /* InstallProperties key exists */
9186     INIT_USERINFO();
9187     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9188     ok(state == USERINFOSTATE_ABSENT,
9189        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9190     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9191     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
9192     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9193     ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", usersz);
9194     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
9195     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
9196 
9197     /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */
9198     INIT_USERINFO();
9199     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
9200     ok(state == USERINFOSTATE_ABSENT,
9201        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9202     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
9203     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9204     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
9205     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9206 
9207     /* RegOwner, RegCompany don't exist, out params are NULL */
9208     INIT_USERINFO();
9209     state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz);
9210     ok(state == USERINFOSTATE_ABSENT,
9211        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9212     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9213     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9214 
9215     res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
9216     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9217 
9218     /* RegOwner value exists */
9219     INIT_USERINFO();
9220     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9221     ok(state == USERINFOSTATE_ABSENT,
9222        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9223     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9224     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
9225     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9226     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9227     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
9228     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9229 
9230     res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8);
9231     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9232 
9233     /* RegCompany value exists */
9234     INIT_USERINFO();
9235     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9236     ok(state == USERINFOSTATE_ABSENT,
9237        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9238     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9239     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9240     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9241     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9242     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
9243     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9244 
9245     res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3);
9246     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9247 
9248     /* ProductID value exists */
9249     INIT_USERINFO();
9250     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9251     ok(state == USERINFOSTATE_PRESENT,
9252        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
9253     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9254     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9255     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
9256     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9257     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
9258     ok(serialsz == 2, "Expected 2, got %d\n", serialsz);
9259 
9260     RegDeleteValueA(props, "ProductID");
9261     RegDeleteValueA(props, "RegCompany");
9262     RegDeleteValueA(props, "RegOwner");
9263     delete_key(props, "", access & KEY_WOW64_64KEY);
9264     RegCloseKey(props);
9265     delete_key(userprod, "", access & KEY_WOW64_64KEY);
9266     RegCloseKey(userprod);
9267     RegDeleteKeyA(prodkey, "");
9268     RegCloseKey(prodkey);
9269 
9270     /* MSIINSTALLCONTEXT_MACHINE */
9271 
9272     /* create local system product key */
9273     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
9274     lstrcatA(keypath, prod_squashed);
9275 
9276     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
9277     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9278 
9279     /* product key exists */
9280     INIT_USERINFO();
9281     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9282     ok(state == USERINFOSTATE_ABSENT,
9283        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9284     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9285     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
9286     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9287     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
9288     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
9289     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
9290 
9291     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9292     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18");
9293     lstrcatA(keypath, "\\Products\\");
9294     lstrcatA(keypath, prod_squashed);
9295 
9296     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL);
9297     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9298 
9299     res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9300     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9301 
9302     /* InstallProperties key exists */
9303     INIT_USERINFO();
9304     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9305     ok(state == USERINFOSTATE_ABSENT,
9306        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9307     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9308     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
9309     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9310     ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", usersz);
9311     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
9312     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
9313 
9314     /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */
9315     INIT_USERINFO();
9316     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
9317     ok(state == USERINFOSTATE_ABSENT,
9318        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9319     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
9320     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9321     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
9322     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9323 
9324     /* RegOwner, RegCompany don't exist, out params are NULL */
9325     INIT_USERINFO();
9326     state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz);
9327     ok(state == USERINFOSTATE_ABSENT,
9328        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9329     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9330     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9331 
9332     res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
9333     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9334 
9335     /* RegOwner value exists */
9336     INIT_USERINFO();
9337     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9338     ok(state == USERINFOSTATE_ABSENT,
9339        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9340     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9341     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
9342     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9343     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9344     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
9345     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9346 
9347     res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8);
9348     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9349 
9350     /* RegCompany value exists */
9351     INIT_USERINFO();
9352     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9353     ok(state == USERINFOSTATE_ABSENT,
9354        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9355     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9356     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9357     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9358     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9359     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
9360     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9361 
9362     res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3);
9363     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9364 
9365     /* ProductID value exists */
9366     INIT_USERINFO();
9367     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9368     ok(state == USERINFOSTATE_PRESENT,
9369        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
9370     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9371     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9372     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
9373     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9374     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
9375     ok(serialsz == 2, "Expected 2, got %d\n", serialsz);
9376 
9377     RegDeleteValueA(props, "ProductID");
9378     RegDeleteValueA(props, "RegCompany");
9379     RegDeleteValueA(props, "RegOwner");
9380     delete_key(props, "", access & KEY_WOW64_64KEY);
9381     RegCloseKey(props);
9382     delete_key(userprod, "", access & KEY_WOW64_64KEY);
9383     RegCloseKey(userprod);
9384     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
9385     RegCloseKey(prodkey);
9386     LocalFree(usersid);
9387 }
9388 
9389 static void test_MsiOpenProduct(void)
9390 {
9391     MSIHANDLE hprod, hdb;
9392     CHAR val[MAX_PATH];
9393     CHAR path[MAX_PATH];
9394     CHAR keypath[MAX_PATH*2];
9395     CHAR prodcode[MAX_PATH];
9396     CHAR prod_squashed[MAX_PATH];
9397     HKEY prodkey, userkey, props;
9398     LPSTR usersid;
9399     DWORD size;
9400     LONG res;
9401     UINT r;
9402     REGSAM access = KEY_ALL_ACCESS;
9403 
9404     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
9405 
9406     GetCurrentDirectoryA(MAX_PATH, path);
9407     lstrcatA(path, "\\");
9408 
9409     create_test_guid(prodcode, prod_squashed);
9410     usersid = get_user_sid();
9411 
9412     if (is_wow64)
9413         access |= KEY_WOW64_64KEY;
9414 
9415     hdb = create_package_db(prodcode);
9416     MsiCloseHandle(hdb);
9417 
9418     /* NULL szProduct */
9419     hprod = 0xdeadbeef;
9420     r = MsiOpenProductA(NULL, &hprod);
9421     ok(r == ERROR_INVALID_PARAMETER,
9422        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9423     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9424 
9425     /* empty szProduct */
9426     hprod = 0xdeadbeef;
9427     r = MsiOpenProductA("", &hprod);
9428     ok(r == ERROR_INVALID_PARAMETER,
9429        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9430     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9431 
9432     /* garbage szProduct */
9433     hprod = 0xdeadbeef;
9434     r = MsiOpenProductA("garbage", &hprod);
9435     ok(r == ERROR_INVALID_PARAMETER,
9436        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9437     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9438 
9439     /* guid without brackets */
9440     hprod = 0xdeadbeef;
9441     r = MsiOpenProductA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", &hprod);
9442     ok(r == ERROR_INVALID_PARAMETER,
9443        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9444     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9445 
9446     /* guid with brackets */
9447     hprod = 0xdeadbeef;
9448     r = MsiOpenProductA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", &hprod);
9449     ok(r == ERROR_UNKNOWN_PRODUCT,
9450        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9451     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9452 
9453     /* same length as guid, but random */
9454     hprod = 0xdeadbeef;
9455     r = MsiOpenProductA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", &hprod);
9456     ok(r == ERROR_INVALID_PARAMETER,
9457        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9458     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9459 
9460     /* hProduct is NULL */
9461     hprod = 0xdeadbeef;
9462     r = MsiOpenProductA(prodcode, NULL);
9463     ok(r == ERROR_INVALID_PARAMETER,
9464        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9465     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9466 
9467     /* MSIINSTALLCONTEXT_USERMANAGED */
9468 
9469     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9470     lstrcatA(keypath, "Installer\\Managed\\");
9471     lstrcatA(keypath, usersid);
9472     lstrcatA(keypath, "\\Installer\\Products\\");
9473     lstrcatA(keypath, prod_squashed);
9474 
9475     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
9476     if (res == ERROR_ACCESS_DENIED)
9477     {
9478         skip("Not enough rights to perform tests\n");
9479         LocalFree(usersid);
9480         return;
9481     }
9482     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9483 
9484     /* managed product key exists */
9485     hprod = 0xdeadbeef;
9486     r = MsiOpenProductA(prodcode, &hprod);
9487     ok(r == ERROR_UNKNOWN_PRODUCT,
9488        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9489     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9490 
9491     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9492     lstrcatA(keypath, "Installer\\UserData\\");
9493     lstrcatA(keypath, usersid);
9494     lstrcatA(keypath, "\\Products\\");
9495     lstrcatA(keypath, prod_squashed);
9496 
9497     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
9498     if (res == ERROR_ACCESS_DENIED)
9499     {
9500         skip("Not enough rights to perform tests\n");
9501         LocalFree(usersid);
9502         return;
9503     }
9504     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9505 
9506     /* user product key exists */
9507     hprod = 0xdeadbeef;
9508     r = MsiOpenProductA(prodcode, &hprod);
9509     ok(r == ERROR_UNKNOWN_PRODUCT,
9510        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9511     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9512 
9513     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9514     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9515 
9516     /* InstallProperties key exists */
9517     hprod = 0xdeadbeef;
9518     r = MsiOpenProductA(prodcode, &hprod);
9519     ok(r == ERROR_UNKNOWN_PRODUCT,
9520        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9521     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9522 
9523     lstrcpyA(val, path);
9524     lstrcatA(val, "\\winetest.msi");
9525     res = RegSetValueExA(props, "ManagedLocalPackage", 0, REG_SZ,
9526                          (const BYTE *)val, lstrlenA(val) + 1);
9527     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9528 
9529     /* ManagedLocalPackage value exists */
9530     hprod = 0xdeadbeef;
9531     r = MsiOpenProductA(prodcode, &hprod);
9532     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9533     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
9534 
9535     size = MAX_PATH;
9536     r = MsiGetPropertyA(hprod, "ProductCode", val, &size);
9537     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9538     ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val);
9539     ok(size == lstrlenA(prodcode), "Expected %d, got %d\n", lstrlenA(prodcode), size);
9540 
9541     MsiCloseHandle(hprod);
9542 
9543     RegDeleteValueA(props, "ManagedLocalPackage");
9544     delete_key(props, "", access & KEY_WOW64_64KEY);
9545     RegCloseKey(props);
9546     delete_key(userkey, "", access & KEY_WOW64_64KEY);
9547     RegCloseKey(userkey);
9548     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
9549     RegCloseKey(prodkey);
9550 
9551     /* MSIINSTALLCONTEXT_USERUNMANAGED */
9552 
9553     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
9554     lstrcatA(keypath, prod_squashed);
9555 
9556     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
9557     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9558 
9559     /* unmanaged product key exists */
9560     hprod = 0xdeadbeef;
9561     r = MsiOpenProductA(prodcode, &hprod);
9562     ok(r == ERROR_UNKNOWN_PRODUCT,
9563        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9564     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9565 
9566     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9567     lstrcatA(keypath, "Installer\\UserData\\");
9568     lstrcatA(keypath, usersid);
9569     lstrcatA(keypath, "\\Products\\");
9570     lstrcatA(keypath, prod_squashed);
9571 
9572     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
9573     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9574 
9575     /* user product key exists */
9576     hprod = 0xdeadbeef;
9577     r = MsiOpenProductA(prodcode, &hprod);
9578     ok(r == ERROR_UNKNOWN_PRODUCT,
9579        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9580     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9581 
9582     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9583     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9584 
9585     /* InstallProperties key exists */
9586     hprod = 0xdeadbeef;
9587     r = MsiOpenProductA(prodcode, &hprod);
9588     ok(r == ERROR_UNKNOWN_PRODUCT,
9589        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9590     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9591 
9592     lstrcpyA(val, path);
9593     lstrcatA(val, "\\winetest.msi");
9594     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
9595                          (const BYTE *)val, lstrlenA(val) + 1);
9596     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9597 
9598     /* LocalPackage value exists */
9599     hprod = 0xdeadbeef;
9600     r = MsiOpenProductA(prodcode, &hprod);
9601     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9602     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
9603 
9604     size = MAX_PATH;
9605     r = MsiGetPropertyA(hprod, "ProductCode", val, &size);
9606     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9607     ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val);
9608     ok(size == lstrlenA(prodcode), "Expected %d, got %d\n", lstrlenA(prodcode), size);
9609 
9610     MsiCloseHandle(hprod);
9611 
9612     RegDeleteValueA(props, "LocalPackage");
9613     delete_key(props, "", access & KEY_WOW64_64KEY);
9614     RegCloseKey(props);
9615     delete_key(userkey, "", access & KEY_WOW64_64KEY);
9616     RegCloseKey(userkey);
9617     RegDeleteKeyA(prodkey, "");
9618     RegCloseKey(prodkey);
9619 
9620     /* MSIINSTALLCONTEXT_MACHINE */
9621 
9622     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
9623     lstrcatA(keypath, prod_squashed);
9624 
9625     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
9626     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9627 
9628     /* managed product key exists */
9629     hprod = 0xdeadbeef;
9630     r = MsiOpenProductA(prodcode, &hprod);
9631     ok(r == ERROR_UNKNOWN_PRODUCT,
9632        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9633     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9634 
9635     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9636     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
9637     lstrcatA(keypath, prod_squashed);
9638 
9639     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
9640     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9641 
9642     /* user product key exists */
9643     hprod = 0xdeadbeef;
9644     r = MsiOpenProductA(prodcode, &hprod);
9645     ok(r == ERROR_UNKNOWN_PRODUCT,
9646        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9647     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9648 
9649     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9650     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9651 
9652     /* InstallProperties key exists */
9653     hprod = 0xdeadbeef;
9654     r = MsiOpenProductA(prodcode, &hprod);
9655     ok(r == ERROR_UNKNOWN_PRODUCT,
9656        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9657     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9658 
9659     lstrcpyA(val, path);
9660     lstrcatA(val, "\\winetest.msi");
9661     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
9662                          (const BYTE *)val, lstrlenA(val) + 1);
9663     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9664 
9665     /* LocalPackage value exists */
9666     hprod = 0xdeadbeef;
9667     r = MsiOpenProductA(prodcode, &hprod);
9668     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9669     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
9670 
9671     size = MAX_PATH;
9672     r = MsiGetPropertyA(hprod, "ProductCode", val, &size);
9673     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9674     ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val);
9675     ok(size == lstrlenA(prodcode), "Expected %d, got %d\n", lstrlenA(prodcode), size);
9676 
9677     MsiCloseHandle(hprod);
9678 
9679     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
9680                          (const BYTE *)"winetest.msi", 13);
9681     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9682 
9683     lstrcpyA(val, path);
9684     lstrcatA(val, "\\winetest.msi");
9685     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
9686                          (const BYTE *)val, lstrlenA(val) + 1);
9687     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9688 
9689     DeleteFileA(msifile);
9690 
9691     /* local package does not exist */
9692     hprod = 0xdeadbeef;
9693     r = MsiOpenProductA(prodcode, &hprod);
9694     ok(r == ERROR_UNKNOWN_PRODUCT,
9695        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9696     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9697 
9698     RegDeleteValueA(props, "LocalPackage");
9699     delete_key(props, "", access & KEY_WOW64_64KEY);
9700     RegCloseKey(props);
9701     delete_key(userkey, "", access & KEY_WOW64_64KEY);
9702     RegCloseKey(userkey);
9703     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
9704     RegCloseKey(prodkey);
9705 
9706     DeleteFileA(msifile);
9707     LocalFree(usersid);
9708 }
9709 
9710 static void test_MsiEnumPatchesEx_usermanaged(LPCSTR usersid, LPCSTR expectedsid)
9711 {
9712     MSIINSTALLCONTEXT context;
9713     CHAR keypath[MAX_PATH], patch[MAX_PATH];
9714     CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
9715     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
9716     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
9717     HKEY prodkey, patches, udprod, udpatch, hpatch;
9718     DWORD size, data;
9719     LONG res;
9720     UINT r;
9721     REGSAM access = KEY_ALL_ACCESS;
9722 
9723     create_test_guid(prodcode, prod_squashed);
9724     create_test_guid(patch, patch_squashed);
9725 
9726     if (is_wow64)
9727         access |= KEY_WOW64_64KEY;
9728 
9729     /* MSIPATCHSTATE_APPLIED */
9730 
9731     lstrcpyA(patchcode, "apple");
9732     lstrcpyA(targetprod, "banana");
9733     context = 0xdeadbeef;
9734     lstrcpyA(targetsid, "kiwi");
9735     size = MAX_PATH;
9736     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9737                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9738                            &context, targetsid, &size);
9739     if (r == ERROR_ACCESS_DENIED)
9740     {
9741         skip("Not enough rights to perform tests\n");
9742         return;
9743     }
9744     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9745     ok(!lstrcmpA(patchcode, "apple"),
9746        "Expected patchcode to be unchanged, got %s\n", patchcode);
9747     ok(!lstrcmpA(targetprod, "banana"),
9748        "Expected targetprod to be unchanged, got %s\n", targetprod);
9749     ok(context == 0xdeadbeef,
9750        "Expected context to be unchanged, got %d\n", context);
9751     ok(!lstrcmpA(targetsid, "kiwi"),
9752        "Expected targetsid to be unchanged, got %s\n", targetsid);
9753     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9754 
9755     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
9756     lstrcatA(keypath, expectedsid);
9757     lstrcatA(keypath, "\\Installer\\Products\\");
9758     lstrcatA(keypath, prod_squashed);
9759 
9760     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
9761     if (res == ERROR_ACCESS_DENIED)
9762     {
9763         skip("Not enough rights to perform tests\n");
9764         return;
9765     }
9766     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9767 
9768     /* managed product key exists */
9769     lstrcpyA(patchcode, "apple");
9770     lstrcpyA(targetprod, "banana");
9771     context = 0xdeadbeef;
9772     lstrcpyA(targetsid, "kiwi");
9773     size = MAX_PATH;
9774     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9775                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9776                            &context, targetsid, &size);
9777     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9778     ok(!lstrcmpA(patchcode, "apple"),
9779        "Expected patchcode to be unchanged, got %s\n", patchcode);
9780     ok(!lstrcmpA(targetprod, "banana"),
9781        "Expected targetprod to be unchanged, got %s\n", targetprod);
9782     ok(context == 0xdeadbeef,
9783        "Expected context to be unchanged, got %d\n", context);
9784     ok(!lstrcmpA(targetsid, "kiwi"),
9785        "Expected targetsid to be unchanged, got %s\n", targetsid);
9786     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9787 
9788     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
9789     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9790 
9791     /* patches key exists */
9792     lstrcpyA(patchcode, "apple");
9793     lstrcpyA(targetprod, "banana");
9794     context = 0xdeadbeef;
9795     lstrcpyA(targetsid, "kiwi");
9796     size = MAX_PATH;
9797     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9798                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9799                            &context, targetsid, &size);
9800     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9801     ok(!lstrcmpA(patchcode, "apple"),
9802        "Expected patchcode to be unchanged, got %s\n", patchcode);
9803     ok(!lstrcmpA(targetprod, "banana"),
9804        "Expected targetprod to be unchanged, got %s\n", targetprod);
9805     ok(context == 0xdeadbeef,
9806        "Expected context to be unchanged, got %d\n", context);
9807     ok(!lstrcmpA(targetsid, "kiwi"),
9808        "Expected targetsid to be unchanged, got %s\n", targetsid);
9809     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9810 
9811     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
9812                          (const BYTE *)patch_squashed,
9813                          lstrlenA(patch_squashed) + 1);
9814     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9815 
9816     /* Patches value exists, is not REG_MULTI_SZ */
9817     lstrcpyA(patchcode, "apple");
9818     lstrcpyA(targetprod, "banana");
9819     context = 0xdeadbeef;
9820     lstrcpyA(targetsid, "kiwi");
9821     size = MAX_PATH;
9822     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9823                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9824                            &context, targetsid, &size);
9825     ok(r == ERROR_BAD_CONFIGURATION,
9826        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9827     ok(!lstrcmpA(patchcode, "apple"),
9828        "Expected patchcode to be unchanged, got %s\n", patchcode);
9829     ok(!lstrcmpA(targetprod, "banana"),
9830        "Expected targetprod to be unchanged, got %s\n", targetprod);
9831     ok(context == 0xdeadbeef,
9832        "Expected context to be unchanged, got %d\n", context);
9833     ok(!lstrcmpA(targetsid, "kiwi"),
9834        "Expected targetsid to be unchanged, got %s\n", targetsid);
9835     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9836 
9837     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
9838                          (const BYTE *)"a\0b\0c\0\0", 7);
9839     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9840 
9841     /* Patches value exists, is not a squashed guid */
9842     lstrcpyA(patchcode, "apple");
9843     lstrcpyA(targetprod, "banana");
9844     context = 0xdeadbeef;
9845     lstrcpyA(targetsid, "kiwi");
9846     size = MAX_PATH;
9847     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9848                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9849                            &context, targetsid, &size);
9850     ok(r == ERROR_BAD_CONFIGURATION,
9851        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9852     ok(!lstrcmpA(patchcode, "apple"),
9853        "Expected patchcode to be unchanged, got %s\n", patchcode);
9854     ok(!lstrcmpA(targetprod, "banana"),
9855        "Expected targetprod to be unchanged, got %s\n", targetprod);
9856     ok(context == 0xdeadbeef,
9857        "Expected context to be unchanged, got %d\n", context);
9858     ok(!lstrcmpA(targetsid, "kiwi"),
9859        "Expected targetsid to be unchanged, got %s\n", targetsid);
9860     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9861 
9862     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
9863     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
9864                          (const BYTE *)patch_squashed,
9865                          lstrlenA(patch_squashed) + 2);
9866     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9867 
9868     /* Patches value exists */
9869     lstrcpyA(patchcode, "apple");
9870     lstrcpyA(targetprod, "banana");
9871     context = 0xdeadbeef;
9872     lstrcpyA(targetsid, "kiwi");
9873     size = MAX_PATH;
9874     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9875                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9876                            &context, targetsid, &size);
9877     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9878     ok(!lstrcmpA(patchcode, "apple"),
9879        "Expected patchcode to be unchanged, got %s\n", patchcode);
9880     ok(!lstrcmpA(targetprod, "banana"),
9881        "Expected targetprod to be unchanged, got %s\n", targetprod);
9882     ok(context == 0xdeadbeef,
9883        "Expected context to be unchanged, got %d\n", context);
9884     ok(!lstrcmpA(targetsid, "kiwi"),
9885        "Expected targetsid to be unchanged, got %s\n", targetsid);
9886     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9887 
9888     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
9889                          (const BYTE *)"whatever", 9);
9890     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9891 
9892     /* patch squashed value exists */
9893     lstrcpyA(patchcode, "apple");
9894     lstrcpyA(targetprod, "banana");
9895     context = 0xdeadbeef;
9896     lstrcpyA(targetsid, "kiwi");
9897     size = MAX_PATH;
9898     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9899                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9900                            &context, targetsid, &size);
9901     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9902     ok(!lstrcmpA(patchcode, patch),
9903        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9904     ok(!lstrcmpA(targetprod, prodcode),
9905        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9906     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9907        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9908     ok(!lstrcmpA(targetsid, expectedsid),
9909        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9910     ok(size == lstrlenA(expectedsid),
9911        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9912 
9913     /* increase the index */
9914     lstrcpyA(patchcode, "apple");
9915     lstrcpyA(targetprod, "banana");
9916     context = 0xdeadbeef;
9917     lstrcpyA(targetsid, "kiwi");
9918     size = MAX_PATH;
9919     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9920                            MSIPATCHSTATE_APPLIED, 1, patchcode, targetprod,
9921                            &context, targetsid, &size);
9922     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9923     ok(!lstrcmpA(patchcode, "apple"),
9924        "Expected patchcode to be unchanged, got %s\n", patchcode);
9925     ok(!lstrcmpA(targetprod, "banana"),
9926        "Expected targetprod to be unchanged, got %s\n", targetprod);
9927     ok(context == 0xdeadbeef,
9928        "Expected context to be unchanged, got %d\n", context);
9929     ok(!lstrcmpA(targetsid, "kiwi"),
9930        "Expected targetsid to be unchanged, got %s\n", targetsid);
9931     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9932 
9933     /* increase again */
9934     lstrcpyA(patchcode, "apple");
9935     lstrcpyA(targetprod, "banana");
9936     context = 0xdeadbeef;
9937     lstrcpyA(targetsid, "kiwi");
9938     size = MAX_PATH;
9939     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9940                            MSIPATCHSTATE_APPLIED, 2, patchcode, targetprod,
9941                            &context, targetsid, &size);
9942     ok(r == ERROR_INVALID_PARAMETER,
9943        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9944     ok(!lstrcmpA(patchcode, "apple"),
9945        "Expected patchcode to be unchanged, got %s\n", patchcode);
9946     ok(!lstrcmpA(targetprod, "banana"),
9947        "Expected targetprod to be unchanged, got %s\n", targetprod);
9948     ok(context == 0xdeadbeef,
9949        "Expected context to be unchanged, got %d\n", context);
9950     ok(!lstrcmpA(targetsid, "kiwi"),
9951        "Expected targetsid to be unchanged, got %s\n", targetsid);
9952     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9953 
9954     /* szPatchCode is NULL */
9955     lstrcpyA(targetprod, "banana");
9956     context = 0xdeadbeef;
9957     lstrcpyA(targetsid, "kiwi");
9958     size = MAX_PATH;
9959     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9960                            MSIPATCHSTATE_APPLIED, 0, NULL, targetprod,
9961                            &context, targetsid, &size);
9962     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9963     ok(!lstrcmpA(targetprod, prodcode),
9964        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9965     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9966        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9967     ok(!lstrcmpA(targetsid, expectedsid),
9968        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9969     ok(size == lstrlenA(expectedsid),
9970        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9971 
9972     /* szTargetProductCode is NULL */
9973     lstrcpyA(patchcode, "apple");
9974     context = 0xdeadbeef;
9975     lstrcpyA(targetsid, "kiwi");
9976     size = MAX_PATH;
9977     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9978                            MSIPATCHSTATE_APPLIED, 0, patchcode, NULL,
9979                            &context, targetsid, &size);
9980     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9981     ok(!lstrcmpA(patchcode, patch),
9982        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9983     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9984        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9985     ok(!lstrcmpA(targetsid, expectedsid),
9986        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9987     ok(size == lstrlenA(expectedsid),
9988        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9989 
9990     /* pdwTargetProductContext is NULL */
9991     lstrcpyA(patchcode, "apple");
9992     lstrcpyA(targetprod, "banana");
9993     lstrcpyA(targetsid, "kiwi");
9994     size = MAX_PATH;
9995     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9996                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9997                            NULL, targetsid, &size);
9998     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9999     ok(!lstrcmpA(patchcode, patch),
10000        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10001     ok(!lstrcmpA(targetprod, prodcode),
10002        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10003     ok(!lstrcmpA(targetsid, expectedsid),
10004        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10005     ok(size == lstrlenA(expectedsid),
10006        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10007 
10008     /* szTargetUserSid is NULL */
10009     lstrcpyA(patchcode, "apple");
10010     lstrcpyA(targetprod, "banana");
10011     context = 0xdeadbeef;
10012     size = MAX_PATH;
10013     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10014                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10015                            &context, NULL, &size);
10016     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10017     ok(!lstrcmpA(patchcode, patch),
10018        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10019     ok(!lstrcmpA(targetprod, prodcode),
10020        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10021     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
10022        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
10023     ok(size == lstrlenA(expectedsid) * sizeof(WCHAR),
10024        "Expected %d*sizeof(WCHAR), got %d\n", lstrlenA(expectedsid), size);
10025 
10026     /* pcchTargetUserSid is exactly the length of szTargetUserSid */
10027     lstrcpyA(patchcode, "apple");
10028     lstrcpyA(targetprod, "banana");
10029     context = 0xdeadbeef;
10030     lstrcpyA(targetsid, "kiwi");
10031     size = lstrlenA(expectedsid);
10032     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10033                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10034                            &context, targetsid, &size);
10035     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
10036     ok(!lstrcmpA(patchcode, patch),
10037        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10038     ok(!lstrcmpA(targetprod, prodcode),
10039        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10040     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
10041        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
10042     ok(!strncmp(targetsid, expectedsid, lstrlenA(expectedsid) - 1),
10043        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10044     ok(size == lstrlenA(expectedsid) * sizeof(WCHAR),
10045        "Expected %d*sizeof(WCHAR), got %d\n", lstrlenA(expectedsid), size);
10046 
10047     /* pcchTargetUserSid has enough room for NULL terminator */
10048     lstrcpyA(patchcode, "apple");
10049     lstrcpyA(targetprod, "banana");
10050     context = 0xdeadbeef;
10051     lstrcpyA(targetsid, "kiwi");
10052     size = lstrlenA(expectedsid) + 1;
10053     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10054                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10055                            &context, targetsid, &size);
10056     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10057     ok(!lstrcmpA(patchcode, patch),
10058        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10059     ok(!lstrcmpA(targetprod, prodcode),
10060        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10061     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
10062        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
10063     ok(!lstrcmpA(targetsid, expectedsid),
10064        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10065     ok(size == lstrlenA(expectedsid),
10066        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10067 
10068     /* both szTargetuserSid and pcchTargetUserSid are NULL */
10069     lstrcpyA(patchcode, "apple");
10070     lstrcpyA(targetprod, "banana");
10071     context = 0xdeadbeef;
10072     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10073                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10074                            &context, NULL, NULL);
10075     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10076     ok(!lstrcmpA(patchcode, patch),
10077        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10078     ok(!lstrcmpA(targetprod, prodcode),
10079        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10080     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
10081        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
10082 
10083     /* MSIPATCHSTATE_SUPERSEDED */
10084 
10085     lstrcpyA(patchcode, "apple");
10086     lstrcpyA(targetprod, "banana");
10087     context = 0xdeadbeef;
10088     lstrcpyA(targetsid, "kiwi");
10089     size = MAX_PATH;
10090     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10091                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10092                            &context, targetsid, &size);
10093     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10094     ok(!lstrcmpA(patchcode, "apple"),
10095        "Expected patchcode to be unchanged, got %s\n", patchcode);
10096     ok(!lstrcmpA(targetprod, "banana"),
10097        "Expected targetprod to be unchanged, got %s\n", targetprod);
10098     ok(context == 0xdeadbeef,
10099        "Expected context to be unchanged, got %d\n", context);
10100     ok(!lstrcmpA(targetsid, "kiwi"),
10101        "Expected targetsid to be unchanged, got %s\n", targetsid);
10102     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10103 
10104     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
10105     lstrcatA(keypath, expectedsid);
10106     lstrcatA(keypath, "\\Products\\");
10107     lstrcatA(keypath, prod_squashed);
10108 
10109     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
10110     if (res == ERROR_ACCESS_DENIED)
10111     {
10112         skip("Not enough rights to perform tests\n");
10113         return;
10114     }
10115     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10116 
10117     /* UserData product key exists */
10118     lstrcpyA(patchcode, "apple");
10119     lstrcpyA(targetprod, "banana");
10120     context = 0xdeadbeef;
10121     lstrcpyA(targetsid, "kiwi");
10122     size = MAX_PATH;
10123     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10124                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10125                            &context, targetsid, &size);
10126     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10127     ok(!lstrcmpA(patchcode, "apple"),
10128        "Expected patchcode to be unchanged, got %s\n", patchcode);
10129     ok(!lstrcmpA(targetprod, "banana"),
10130        "Expected targetprod to be unchanged, got %s\n", targetprod);
10131     ok(context == 0xdeadbeef,
10132        "Expected context to be unchanged, got %d\n", context);
10133     ok(!lstrcmpA(targetsid, "kiwi"),
10134        "Expected targetsid to be unchanged, got %s\n", targetsid);
10135     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10136 
10137     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
10138     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10139 
10140     /* UserData patches key exists */
10141     lstrcpyA(patchcode, "apple");
10142     lstrcpyA(targetprod, "banana");
10143     context = 0xdeadbeef;
10144     lstrcpyA(targetsid, "kiwi");
10145     size = MAX_PATH;
10146     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10147                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10148                            &context, targetsid, &size);
10149     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10150     ok(!lstrcmpA(patchcode, "apple"),
10151        "Expected patchcode to be unchanged, got %s\n", patchcode);
10152     ok(!lstrcmpA(targetprod, "banana"),
10153        "Expected targetprod to be unchanged, got %s\n", targetprod);
10154     ok(context == 0xdeadbeef,
10155        "Expected context to be unchanged, got %d\n", context);
10156     ok(!lstrcmpA(targetsid, "kiwi"),
10157        "Expected targetsid to be unchanged, got %s\n", targetsid);
10158     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10159 
10160     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
10161     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10162 
10163     /* specific UserData patch key exists */
10164     lstrcpyA(patchcode, "apple");
10165     lstrcpyA(targetprod, "banana");
10166     context = 0xdeadbeef;
10167     lstrcpyA(targetsid, "kiwi");
10168     size = MAX_PATH;
10169     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10170                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10171                            &context, targetsid, &size);
10172     ok(r == ERROR_BAD_CONFIGURATION,
10173        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10174     ok(!lstrcmpA(patchcode, "apple"),
10175        "Expected patchcode to be unchanged, got %s\n", patchcode);
10176     ok(!lstrcmpA(targetprod, "banana"),
10177        "Expected targetprod to be unchanged, got %s\n", targetprod);
10178     ok(context == 0xdeadbeef,
10179        "Expected context to be unchanged, got %d\n", context);
10180     ok(!lstrcmpA(targetsid, "kiwi"),
10181        "Expected targetsid to be unchanged, got %s\n", targetsid);
10182     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10183 
10184     data = MSIPATCHSTATE_SUPERSEDED;
10185     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10186                          (const BYTE *)&data, sizeof(DWORD));
10187     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10188 
10189     /* State value exists */
10190     lstrcpyA(patchcode, "apple");
10191     lstrcpyA(targetprod, "banana");
10192     context = 0xdeadbeef;
10193     lstrcpyA(targetsid, "kiwi");
10194     size = MAX_PATH;
10195     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10196                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10197                            &context, targetsid, &size);
10198     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10199     ok(!lstrcmpA(patchcode, patch),
10200        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10201     ok(!lstrcmpA(targetprod, prodcode),
10202        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10203     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
10204        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
10205     ok(!lstrcmpA(targetsid, expectedsid),
10206        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10207     ok(size == lstrlenA(expectedsid),
10208        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10209 
10210     /* MSIPATCHSTATE_OBSOLETED */
10211 
10212     lstrcpyA(patchcode, "apple");
10213     lstrcpyA(targetprod, "banana");
10214     context = 0xdeadbeef;
10215     lstrcpyA(targetsid, "kiwi");
10216     size = MAX_PATH;
10217     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10218                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
10219                            &context, targetsid, &size);
10220     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10221     ok(!lstrcmpA(patchcode, "apple"),
10222        "Expected patchcode to be unchanged, got %s\n", patchcode);
10223     ok(!lstrcmpA(targetprod, "banana"),
10224        "Expected targetprod to be unchanged, got %s\n", targetprod);
10225     ok(context == 0xdeadbeef,
10226        "Expected context to be unchanged, got %d\n", context);
10227     ok(!lstrcmpA(targetsid, "kiwi"),
10228        "Expected targetsid to be unchanged, got %s\n", targetsid);
10229     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10230 
10231     data = MSIPATCHSTATE_OBSOLETED;
10232     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10233                          (const BYTE *)&data, sizeof(DWORD));
10234     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10235 
10236     /* State value is obsoleted */
10237     lstrcpyA(patchcode, "apple");
10238     lstrcpyA(targetprod, "banana");
10239     context = 0xdeadbeef;
10240     lstrcpyA(targetsid, "kiwi");
10241     size = MAX_PATH;
10242     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10243                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
10244                            &context, targetsid, &size);
10245     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10246     ok(!lstrcmpA(patchcode, patch),
10247        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10248     ok(!lstrcmpA(targetprod, prodcode),
10249        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10250     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
10251        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
10252     ok(!lstrcmpA(targetsid, expectedsid),
10253        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10254     ok(size == lstrlenA(expectedsid),
10255        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10256 
10257     /* MSIPATCHSTATE_REGISTERED */
10258     /* FIXME */
10259 
10260     /* MSIPATCHSTATE_ALL */
10261 
10262     /* 1st */
10263     lstrcpyA(patchcode, "apple");
10264     lstrcpyA(targetprod, "banana");
10265     context = 0xdeadbeef;
10266     lstrcpyA(targetsid, "kiwi");
10267     size = MAX_PATH;
10268     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10269                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
10270                            &context, targetsid, &size);
10271     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10272     ok(!lstrcmpA(patchcode, patch),
10273        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10274     ok(!lstrcmpA(targetprod, prodcode),
10275        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10276     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
10277        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
10278     ok(!lstrcmpA(targetsid, expectedsid),
10279        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10280     ok(size == lstrlenA(expectedsid),
10281        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10282 
10283     /* same patch in multiple places, only one is enumerated */
10284     lstrcpyA(patchcode, "apple");
10285     lstrcpyA(targetprod, "banana");
10286     context = 0xdeadbeef;
10287     lstrcpyA(targetsid, "kiwi");
10288     size = MAX_PATH;
10289     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10290                            MSIPATCHSTATE_ALL, 1, patchcode, targetprod,
10291                            &context, targetsid, &size);
10292     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10293     ok(!lstrcmpA(patchcode, "apple"),
10294        "Expected patchcode to be unchanged, got %s\n", patchcode);
10295     ok(!lstrcmpA(targetprod, "banana"),
10296        "Expected targetprod to be unchanged, got %s\n", targetprod);
10297     ok(context == 0xdeadbeef,
10298        "Expected context to be unchanged, got %d\n", context);
10299     ok(!lstrcmpA(targetsid, "kiwi"),
10300        "Expected targetsid to be unchanged, got %s\n", targetsid);
10301     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10302 
10303     RegDeleteValueA(hpatch, "State");
10304     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
10305     RegCloseKey(hpatch);
10306     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
10307     RegCloseKey(udpatch);
10308     delete_key(udprod, "", access & KEY_WOW64_64KEY);
10309     RegCloseKey(udprod);
10310     RegDeleteValueA(patches, "Patches");
10311     delete_key(patches, "", access & KEY_WOW64_64KEY);
10312     RegCloseKey(patches);
10313     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
10314     RegCloseKey(prodkey);
10315 }
10316 
10317 static void test_MsiEnumPatchesEx_userunmanaged(LPCSTR usersid, LPCSTR expectedsid)
10318 {
10319     MSIINSTALLCONTEXT context;
10320     CHAR keypath[MAX_PATH], patch[MAX_PATH];
10321     CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
10322     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
10323     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
10324     HKEY prodkey, patches, udprod, udpatch;
10325     HKEY userkey, hpatch;
10326     DWORD size, data;
10327     LONG res;
10328     UINT r;
10329     REGSAM access = KEY_ALL_ACCESS;
10330 
10331     create_test_guid(prodcode, prod_squashed);
10332     create_test_guid(patch, patch_squashed);
10333 
10334     if (is_wow64)
10335         access |= KEY_WOW64_64KEY;
10336 
10337     /* MSIPATCHSTATE_APPLIED */
10338 
10339     lstrcpyA(patchcode, "apple");
10340     lstrcpyA(targetprod, "banana");
10341     context = 0xdeadbeef;
10342     lstrcpyA(targetsid, "kiwi");
10343     size = MAX_PATH;
10344     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10345                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10346                            &context, targetsid, &size);
10347     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10348     ok(!lstrcmpA(patchcode, "apple"),
10349        "Expected patchcode to be unchanged, got %s\n", patchcode);
10350     ok(!lstrcmpA(targetprod, "banana"),
10351        "Expected targetprod to be unchanged, got %s\n", targetprod);
10352     ok(context == 0xdeadbeef,
10353        "Expected context to be unchanged, got %d\n", context);
10354     ok(!lstrcmpA(targetsid, "kiwi"),
10355        "Expected targetsid to be unchanged, got %s\n", targetsid);
10356     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10357 
10358     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
10359     lstrcatA(keypath, prod_squashed);
10360 
10361     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
10362     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10363 
10364     /* current user product key exists */
10365     lstrcpyA(patchcode, "apple");
10366     lstrcpyA(targetprod, "banana");
10367     context = 0xdeadbeef;
10368     lstrcpyA(targetsid, "kiwi");
10369     size = MAX_PATH;
10370     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10371                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10372                            &context, targetsid, &size);
10373     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10374     ok(!lstrcmpA(patchcode, "apple"),
10375        "Expected patchcode to be unchanged, got %s\n", patchcode);
10376     ok(!lstrcmpA(targetprod, "banana"),
10377        "Expected targetprod to be unchanged, got %s\n", targetprod);
10378     ok(context == 0xdeadbeef,
10379        "Expected context to be unchanged, got %d\n", context);
10380     ok(!lstrcmpA(targetsid, "kiwi"),
10381        "Expected targetsid to be unchanged, got %s\n", targetsid);
10382     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10383 
10384     res = RegCreateKeyA(prodkey, "Patches", &patches);
10385     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10386 
10387     /* Patches key exists */
10388     lstrcpyA(patchcode, "apple");
10389     lstrcpyA(targetprod, "banana");
10390     context = 0xdeadbeef;
10391     lstrcpyA(targetsid, "kiwi");
10392     size = MAX_PATH;
10393     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10394                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10395                            &context, targetsid, &size);
10396     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10397     ok(!lstrcmpA(patchcode, "apple"),
10398        "Expected patchcode to be unchanged, got %s\n", patchcode);
10399     ok(!lstrcmpA(targetprod, "banana"),
10400        "Expected targetprod to be unchanged, got %s\n", targetprod);
10401     ok(context == 0xdeadbeef,
10402        "Expected context to be unchanged, got %d\n", context);
10403     ok(!lstrcmpA(targetsid, "kiwi"),
10404        "Expected targetsid to be unchanged, got %s\n", targetsid);
10405     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10406 
10407     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
10408                          (const BYTE *)patch_squashed,
10409                          lstrlenA(patch_squashed) + 1);
10410     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10411 
10412     /* Patches value exists, is not REG_MULTI_SZ */
10413     lstrcpyA(patchcode, "apple");
10414     lstrcpyA(targetprod, "banana");
10415     context = 0xdeadbeef;
10416     lstrcpyA(targetsid, "kiwi");
10417     size = MAX_PATH;
10418     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10419                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10420                            &context, targetsid, &size);
10421     ok(r == ERROR_BAD_CONFIGURATION,
10422        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10423     ok(!lstrcmpA(patchcode, "apple"),
10424        "Expected patchcode to be unchanged, got %s\n", patchcode);
10425     ok(!lstrcmpA(targetprod, "banana"),
10426        "Expected targetprod to be unchanged, got %s\n", targetprod);
10427     ok(context == 0xdeadbeef,
10428        "Expected context to be unchanged, got %d\n", context);
10429     ok(!lstrcmpA(targetsid, "kiwi"),
10430        "Expected targetsid to be unchanged, got %s\n", targetsid);
10431     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10432 
10433     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10434                          (const BYTE *)"a\0b\0c\0\0", 7);
10435     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10436 
10437     /* Patches value exists, is not a squashed guid */
10438     lstrcpyA(patchcode, "apple");
10439     lstrcpyA(targetprod, "banana");
10440     context = 0xdeadbeef;
10441     lstrcpyA(targetsid, "kiwi");
10442     size = MAX_PATH;
10443     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10444                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10445                            &context, targetsid, &size);
10446     ok(r == ERROR_BAD_CONFIGURATION,
10447        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10448     ok(!lstrcmpA(patchcode, "apple"),
10449        "Expected patchcode to be unchanged, got %s\n", patchcode);
10450     ok(!lstrcmpA(targetprod, "banana"),
10451        "Expected targetprod to be unchanged, got %s\n", targetprod);
10452     ok(context == 0xdeadbeef,
10453        "Expected context to be unchanged, got %d\n", context);
10454     ok(!lstrcmpA(targetsid, "kiwi"),
10455        "Expected targetsid to be unchanged, got %s\n", targetsid);
10456     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10457 
10458     patch_squashed[lstrlenA(patch_squashed) + 1] = 0;
10459     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10460                          (const BYTE *)patch_squashed,
10461                          lstrlenA(patch_squashed) + 2);
10462     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10463 
10464     /* Patches value exists */
10465     lstrcpyA(patchcode, "apple");
10466     lstrcpyA(targetprod, "banana");
10467     context = 0xdeadbeef;
10468     lstrcpyA(targetsid, "kiwi");
10469     size = MAX_PATH;
10470     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10471                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10472                            &context, targetsid, &size);
10473     ok(r == ERROR_NO_MORE_ITEMS ||
10474        broken(r == ERROR_BAD_CONFIGURATION), /* Windows Installer 3.0 */
10475        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10476     ok(!lstrcmpA(patchcode, "apple"),
10477        "Expected patchcode to be unchanged, got %s\n", patchcode);
10478     ok(!lstrcmpA(targetprod, "banana"),
10479        "Expected targetprod to be unchanged, got %s\n", targetprod);
10480     ok(context == 0xdeadbeef,
10481        "Expected context to be unchanged, got %d\n", context);
10482     ok(!lstrcmpA(targetsid, "kiwi"),
10483        "Expected targetsid to be unchanged, got %s\n", targetsid);
10484     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10485 
10486     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
10487                          (const BYTE *)"whatever", 9);
10488     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10489 
10490     /* patch code value exists */
10491     lstrcpyA(patchcode, "apple");
10492     lstrcpyA(targetprod, "banana");
10493     context = 0xdeadbeef;
10494     lstrcpyA(targetsid, "kiwi");
10495     size = MAX_PATH;
10496     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10497                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10498                            &context, targetsid, &size);
10499     ok(r == ERROR_NO_MORE_ITEMS ||
10500        broken(r == ERROR_BAD_CONFIGURATION), /* Windows Installer 3.0 */
10501        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10502     ok(!lstrcmpA(patchcode, "apple"),
10503        "Expected patchcode to be unchanged, got %s\n", patchcode);
10504     ok(!lstrcmpA(targetprod, "banana"),
10505        "Expected targetprod to be unchanged, got %s\n", targetprod);
10506     ok(context == 0xdeadbeef,
10507        "Expected context to be unchanged, got %d\n", context);
10508     ok(!lstrcmpA(targetsid, "kiwi"),
10509        "Expected targetsid to be unchanged, got %s\n", targetsid);
10510     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10511 
10512     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
10513     lstrcatA(keypath, expectedsid);
10514     lstrcatA(keypath, "\\Patches\\");
10515     lstrcatA(keypath, patch_squashed);
10516 
10517     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
10518     if (res == ERROR_ACCESS_DENIED)
10519     {
10520         skip("Not enough rights to perform tests\n");
10521         goto error;
10522     }
10523     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10524 
10525     /* userdata patch key exists */
10526     lstrcpyA(patchcode, "apple");
10527     lstrcpyA(targetprod, "banana");
10528     context = 0xdeadbeef;
10529     lstrcpyA(targetsid, "kiwi");
10530     size = MAX_PATH;
10531     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10532                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10533                            &context, targetsid, &size);
10534     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10535     ok(!lstrcmpA(patchcode, patch),
10536        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10537     ok(!lstrcmpA(targetprod, prodcode),
10538        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10539     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
10540        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
10541     ok(!lstrcmpA(targetsid, expectedsid),
10542        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10543     ok(size == lstrlenA(expectedsid),
10544        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10545 
10546     /* MSIPATCHSTATE_SUPERSEDED */
10547 
10548     lstrcpyA(patchcode, "apple");
10549     lstrcpyA(targetprod, "banana");
10550     context = 0xdeadbeef;
10551     lstrcpyA(targetsid, "kiwi");
10552     size = MAX_PATH;
10553     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10554                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10555                            &context, targetsid, &size);
10556     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10557     ok(!lstrcmpA(patchcode, "apple"),
10558        "Expected patchcode to be unchanged, got %s\n", patchcode);
10559     ok(!lstrcmpA(targetprod, "banana"),
10560        "Expected targetprod to be unchanged, got %s\n", targetprod);
10561     ok(context == 0xdeadbeef,
10562        "Expected context to be unchanged, got %d\n", context);
10563     ok(!lstrcmpA(targetsid, "kiwi"),
10564        "Expected targetsid to be unchanged, got %s\n", targetsid);
10565     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10566 
10567     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
10568     lstrcatA(keypath, expectedsid);
10569     lstrcatA(keypath, "\\Products\\");
10570     lstrcatA(keypath, prod_squashed);
10571 
10572     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
10573     if (res == ERROR_ACCESS_DENIED)
10574     {
10575         skip("Not enough rights to perform tests\n");
10576         goto error;
10577     }
10578     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10579 
10580     /* UserData product key exists */
10581     lstrcpyA(patchcode, "apple");
10582     lstrcpyA(targetprod, "banana");
10583     context = 0xdeadbeef;
10584     lstrcpyA(targetsid, "kiwi");
10585     size = MAX_PATH;
10586     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10587                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10588                            &context, targetsid, &size);
10589     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10590     ok(!lstrcmpA(patchcode, "apple"),
10591        "Expected patchcode to be unchanged, got %s\n", patchcode);
10592     ok(!lstrcmpA(targetprod, "banana"),
10593        "Expected targetprod to be unchanged, got %s\n", targetprod);
10594     ok(context == 0xdeadbeef,
10595        "Expected context to be unchanged, got %d\n", context);
10596     ok(!lstrcmpA(targetsid, "kiwi"),
10597        "Expected targetsid to be unchanged, got %s\n", targetsid);
10598     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10599 
10600     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
10601     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10602 
10603     /* UserData patches key exists */
10604     lstrcpyA(patchcode, "apple");
10605     lstrcpyA(targetprod, "banana");
10606     context = 0xdeadbeef;
10607     lstrcpyA(targetsid, "kiwi");
10608     size = MAX_PATH;
10609     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10610                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10611                            &context, targetsid, &size);
10612     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10613     ok(!lstrcmpA(patchcode, "apple"),
10614        "Expected patchcode to be unchanged, got %s\n", patchcode);
10615     ok(!lstrcmpA(targetprod, "banana"),
10616        "Expected targetprod to be unchanged, got %s\n", targetprod);
10617     ok(context == 0xdeadbeef,
10618        "Expected context to be unchanged, got %d\n", context);
10619     ok(!lstrcmpA(targetsid, "kiwi"),
10620        "Expected targetsid to be unchanged, got %s\n", targetsid);
10621     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10622 
10623     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
10624     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10625 
10626     /* specific UserData patch key exists */
10627     lstrcpyA(patchcode, "apple");
10628     lstrcpyA(targetprod, "banana");
10629     context = 0xdeadbeef;
10630     lstrcpyA(targetsid, "kiwi");
10631     size = MAX_PATH;
10632     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10633                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10634                            &context, targetsid, &size);
10635     ok(r == ERROR_BAD_CONFIGURATION,
10636        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10637     ok(!lstrcmpA(patchcode, "apple"),
10638        "Expected patchcode to be unchanged, got %s\n", patchcode);
10639     ok(!lstrcmpA(targetprod, "banana"),
10640        "Expected targetprod to be unchanged, got %s\n", targetprod);
10641     ok(context == 0xdeadbeef,
10642        "Expected context to be unchanged, got %d\n", context);
10643     ok(!lstrcmpA(targetsid, "kiwi"),
10644        "Expected targetsid to be unchanged, got %s\n", targetsid);
10645     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10646 
10647     data = MSIPATCHSTATE_SUPERSEDED;
10648     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10649                          (const BYTE *)&data, sizeof(DWORD));
10650     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10651 
10652     /* State value exists */
10653     lstrcpyA(patchcode, "apple");
10654     lstrcpyA(targetprod, "banana");
10655     context = 0xdeadbeef;
10656     lstrcpyA(targetsid, "kiwi");
10657     size = MAX_PATH;
10658     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10659                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10660                            &context, targetsid, &size);
10661     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10662     ok(!lstrcmpA(patchcode, patch),
10663        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10664     ok(!lstrcmpA(targetprod, prodcode),
10665        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10666     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
10667        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
10668     ok(!lstrcmpA(targetsid, expectedsid),
10669        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10670     ok(size == lstrlenA(expectedsid),
10671        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10672 
10673     /* MSIPATCHSTATE_OBSOLETED */
10674 
10675     lstrcpyA(patchcode, "apple");
10676     lstrcpyA(targetprod, "banana");
10677     context = 0xdeadbeef;
10678     lstrcpyA(targetsid, "kiwi");
10679     size = MAX_PATH;
10680     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10681                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
10682                            &context, targetsid, &size);
10683     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10684     ok(!lstrcmpA(patchcode, "apple"),
10685        "Expected patchcode to be unchanged, got %s\n", patchcode);
10686     ok(!lstrcmpA(targetprod, "banana"),
10687        "Expected targetprod to be unchanged, got %s\n", targetprod);
10688     ok(context == 0xdeadbeef,
10689        "Expected context to be unchanged, got %d\n", context);
10690     ok(!lstrcmpA(targetsid, "kiwi"),
10691        "Expected targetsid to be unchanged, got %s\n", targetsid);
10692     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10693 
10694     data = MSIPATCHSTATE_OBSOLETED;
10695     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10696                          (const BYTE *)&data, sizeof(DWORD));
10697     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10698 
10699     /* State value is obsoleted */
10700     lstrcpyA(patchcode, "apple");
10701     lstrcpyA(targetprod, "banana");
10702     context = 0xdeadbeef;
10703     lstrcpyA(targetsid, "kiwi");
10704     size = MAX_PATH;
10705     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10706                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
10707                            &context, targetsid, &size);
10708     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10709     ok(!lstrcmpA(patchcode, patch),
10710        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10711     ok(!lstrcmpA(targetprod, prodcode),
10712        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10713     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
10714        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
10715     ok(!lstrcmpA(targetsid, expectedsid),
10716        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10717     ok(size == lstrlenA(expectedsid),
10718        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10719 
10720     /* MSIPATCHSTATE_REGISTERED */
10721     /* FIXME */
10722 
10723     /* MSIPATCHSTATE_ALL */
10724 
10725     /* 1st */
10726     lstrcpyA(patchcode, "apple");
10727     lstrcpyA(targetprod, "banana");
10728     context = 0xdeadbeef;
10729     lstrcpyA(targetsid, "kiwi");
10730     size = MAX_PATH;
10731     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10732                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
10733                            &context, targetsid, &size);
10734     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10735     ok(!lstrcmpA(patchcode, patch),
10736        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10737     ok(!lstrcmpA(targetprod, prodcode),
10738        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10739     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
10740        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
10741     ok(!lstrcmpA(targetsid, expectedsid),
10742        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10743     ok(size == lstrlenA(expectedsid),
10744        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10745 
10746     /* same patch in multiple places, only one is enumerated */
10747     lstrcpyA(patchcode, "apple");
10748     lstrcpyA(targetprod, "banana");
10749     context = 0xdeadbeef;
10750     lstrcpyA(targetsid, "kiwi");
10751     size = MAX_PATH;
10752     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10753                            MSIPATCHSTATE_ALL, 1, patchcode, targetprod,
10754                            &context, targetsid, &size);
10755     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10756     ok(!lstrcmpA(patchcode, "apple"),
10757        "Expected patchcode to be unchanged, got %s\n", patchcode);
10758     ok(!lstrcmpA(targetprod, "banana"),
10759        "Expected targetprod to be unchanged, got %s\n", targetprod);
10760     ok(context == 0xdeadbeef,
10761        "Expected context to be unchanged, got %d\n", context);
10762     ok(!lstrcmpA(targetsid, "kiwi"),
10763        "Expected targetsid to be unchanged, got %s\n", targetsid);
10764     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10765 
10766     RegDeleteValueA(hpatch, "State");
10767     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
10768     RegCloseKey(hpatch);
10769     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
10770     RegCloseKey(udpatch);
10771     delete_key(udprod, "", access & KEY_WOW64_64KEY);
10772     RegCloseKey(udprod);
10773     delete_key(userkey, "", access & KEY_WOW64_64KEY);
10774     RegCloseKey(userkey);
10775     RegDeleteValueA(patches, patch_squashed);
10776     RegDeleteValueA(patches, "Patches");
10777 
10778 error:
10779     RegDeleteKeyA(patches, "");
10780     RegCloseKey(patches);
10781     RegDeleteKeyA(prodkey, "");
10782     RegCloseKey(prodkey);
10783 }
10784 
10785 static void test_MsiEnumPatchesEx_machine(void)
10786 {
10787     CHAR keypath[MAX_PATH], patch[MAX_PATH];
10788     CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
10789     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
10790     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
10791     HKEY prodkey, patches, udprod, udpatch;
10792     HKEY hpatch;
10793     MSIINSTALLCONTEXT context;
10794     DWORD size, data;
10795     LONG res;
10796     UINT r;
10797     REGSAM access = KEY_ALL_ACCESS;
10798 
10799     create_test_guid(prodcode, prod_squashed);
10800     create_test_guid(patch, patch_squashed);
10801 
10802     if (is_wow64)
10803         access |= KEY_WOW64_64KEY;
10804 
10805     /* MSIPATCHSTATE_APPLIED */
10806 
10807     lstrcpyA(patchcode, "apple");
10808     lstrcpyA(targetprod, "banana");
10809     context = 0xdeadbeef;
10810     lstrcpyA(targetsid, "kiwi");
10811     size = MAX_PATH;
10812     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10813                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10814                            &context, targetsid, &size);
10815     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10816     ok(!lstrcmpA(patchcode, "apple"),
10817        "Expected patchcode to be unchanged, got %s\n", patchcode);
10818     ok(!lstrcmpA(targetprod, "banana"),
10819        "Expected targetprod to be unchanged, got %s\n", targetprod);
10820     ok(context == 0xdeadbeef,
10821        "Expected context to be unchanged, got %d\n", context);
10822     ok(!lstrcmpA(targetsid, "kiwi"),
10823        "Expected targetsid to be unchanged, got %s\n", targetsid);
10824     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10825 
10826     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
10827     lstrcatA(keypath, prod_squashed);
10828 
10829     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
10830     if (res == ERROR_ACCESS_DENIED)
10831     {
10832         skip("Not enough rights to perform tests\n");
10833         return;
10834     }
10835     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10836 
10837     /* local product key exists */
10838     lstrcpyA(patchcode, "apple");
10839     lstrcpyA(targetprod, "banana");
10840     context = 0xdeadbeef;
10841     lstrcpyA(targetsid, "kiwi");
10842     size = MAX_PATH;
10843     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10844                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10845                            &context, targetsid, &size);
10846     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10847     ok(!lstrcmpA(patchcode, "apple"),
10848        "Expected patchcode to be unchanged, got %s\n", patchcode);
10849     ok(!lstrcmpA(targetprod, "banana"),
10850        "Expected targetprod to be unchanged, got %s\n", targetprod);
10851     ok(context == 0xdeadbeef,
10852        "Expected context to be unchanged, got %d\n", context);
10853     ok(!lstrcmpA(targetsid, "kiwi"),
10854        "Expected targetsid to be unchanged, got %s\n", targetsid);
10855     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10856 
10857     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
10858     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10859 
10860     /* Patches key exists */
10861     lstrcpyA(patchcode, "apple");
10862     lstrcpyA(targetprod, "banana");
10863     context = 0xdeadbeef;
10864     lstrcpyA(targetsid, "kiwi");
10865     size = MAX_PATH;
10866     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10867                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10868                            &context, targetsid, &size);
10869     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10870     ok(!lstrcmpA(patchcode, "apple"),
10871        "Expected patchcode to be unchanged, got %s\n", patchcode);
10872     ok(!lstrcmpA(targetprod, "banana"),
10873        "Expected targetprod to be unchanged, got %s\n", targetprod);
10874     ok(context == 0xdeadbeef,
10875        "Expected context to be unchanged, got %d\n", context);
10876     ok(!lstrcmpA(targetsid, "kiwi"),
10877        "Expected targetsid to be unchanged, got %s\n", targetsid);
10878     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10879 
10880     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
10881                          (const BYTE *)patch_squashed,
10882                          lstrlenA(patch_squashed) + 1);
10883     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10884 
10885     /* Patches value exists, is not REG_MULTI_SZ */
10886     lstrcpyA(patchcode, "apple");
10887     lstrcpyA(targetprod, "banana");
10888     context = 0xdeadbeef;
10889     lstrcpyA(targetsid, "kiwi");
10890     size = MAX_PATH;
10891     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10892                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10893                            &context, targetsid, &size);
10894     ok(r == ERROR_BAD_CONFIGURATION,
10895        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10896     ok(!lstrcmpA(patchcode, "apple"),
10897        "Expected patchcode to be unchanged, got %s\n", patchcode);
10898     ok(!lstrcmpA(targetprod, "banana"),
10899        "Expected targetprod to be unchanged, got %s\n", targetprod);
10900     ok(context == 0xdeadbeef,
10901        "Expected context to be unchanged, got %d\n", context);
10902     ok(!lstrcmpA(targetsid, "kiwi"),
10903        "Expected targetsid to be unchanged, got %s\n", targetsid);
10904     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10905 
10906     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10907                          (const BYTE *)"a\0b\0c\0\0", 7);
10908     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10909 
10910     /* Patches value exists, is not a squashed guid */
10911     lstrcpyA(patchcode, "apple");
10912     lstrcpyA(targetprod, "banana");
10913     context = 0xdeadbeef;
10914     lstrcpyA(targetsid, "kiwi");
10915     size = MAX_PATH;
10916     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10917                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10918                            &context, targetsid, &size);
10919     ok(r == ERROR_BAD_CONFIGURATION,
10920        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10921     ok(!lstrcmpA(patchcode, "apple"),
10922        "Expected patchcode to be unchanged, got %s\n", patchcode);
10923     ok(!lstrcmpA(targetprod, "banana"),
10924        "Expected targetprod to be unchanged, got %s\n", targetprod);
10925     ok(context == 0xdeadbeef,
10926        "Expected context to be unchanged, got %d\n", context);
10927     ok(!lstrcmpA(targetsid, "kiwi"),
10928        "Expected targetsid to be unchanged, got %s\n", targetsid);
10929     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10930 
10931     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
10932     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10933                          (const BYTE *)patch_squashed,
10934                          lstrlenA(patch_squashed) + 2);
10935     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10936 
10937     /* Patches value exists */
10938     lstrcpyA(patchcode, "apple");
10939     lstrcpyA(targetprod, "banana");
10940     context = 0xdeadbeef;
10941     lstrcpyA(targetsid, "kiwi");
10942     size = MAX_PATH;
10943     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10944                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10945                            &context, targetsid, &size);
10946     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10947     ok(!lstrcmpA(patchcode, "apple"),
10948        "Expected patchcode to be unchanged, got %s\n", patchcode);
10949     ok(!lstrcmpA(targetprod, "banana"),
10950        "Expected targetprod to be unchanged, got %s\n", targetprod);
10951     ok(context == 0xdeadbeef,
10952        "Expected context to be unchanged, got %d\n", context);
10953     ok(!lstrcmpA(targetsid, "kiwi"),
10954        "Expected targetsid to be unchanged, got %s\n", targetsid);
10955     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10956 
10957     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
10958                          (const BYTE *)"whatever", 9);
10959     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10960 
10961     /* patch code value exists */
10962     lstrcpyA(patchcode, "apple");
10963     lstrcpyA(targetprod, "banana");
10964     context = 0xdeadbeef;
10965     lstrcpyA(targetsid, "kiwi");
10966     size = MAX_PATH;
10967     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10968                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10969                            &context, targetsid, &size);
10970     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10971     ok(!lstrcmpA(patchcode, patch),
10972        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10973     ok(!lstrcmpA(targetprod, prodcode),
10974        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10975     ok(context == MSIINSTALLCONTEXT_MACHINE,
10976        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10977     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
10978     ok(size == 0, "Expected 0, got %d\n", size);
10979 
10980     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
10981     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
10982     lstrcatA(keypath, prod_squashed);
10983 
10984     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
10985     if (res == ERROR_ACCESS_DENIED)
10986     {
10987         skip("Not enough rights to perform tests\n");
10988         goto done;
10989     }
10990     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10991 
10992     /* local UserData product key exists */
10993     lstrcpyA(patchcode, "apple");
10994     lstrcpyA(targetprod, "banana");
10995     context = 0xdeadbeef;
10996     lstrcpyA(targetsid, "kiwi");
10997     size = MAX_PATH;
10998     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10999                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
11000                            &context, targetsid, &size);
11001     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11002     ok(!lstrcmpA(patchcode, patch),
11003        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
11004     ok(!lstrcmpA(targetprod, prodcode),
11005        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
11006     ok(context == MSIINSTALLCONTEXT_MACHINE,
11007        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
11008     ok(!lstrcmpA(targetsid, ""),
11009        "Expected \"\", got \"%s\"\n", targetsid);
11010     ok(size == 0, "Expected 0, got %d\n", size);
11011 
11012     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
11013     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11014 
11015     /* local UserData Patches key exists */
11016     lstrcpyA(patchcode, "apple");
11017     lstrcpyA(targetprod, "banana");
11018     context = 0xdeadbeef;
11019     lstrcpyA(targetsid, "kiwi");
11020     size = MAX_PATH;
11021     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11022                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
11023                            &context, targetsid, &size);
11024     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11025     ok(!lstrcmpA(patchcode, patch),
11026        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
11027     ok(!lstrcmpA(targetprod, prodcode),
11028        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
11029     ok(context == MSIINSTALLCONTEXT_MACHINE,
11030        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
11031     ok(!lstrcmpA(targetsid, ""),
11032        "Expected \"\", got \"%s\"\n", targetsid);
11033     ok(size == 0, "Expected 0, got %d\n", size);
11034 
11035     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
11036     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11037 
11038     /* local UserData Product patch key exists */
11039     lstrcpyA(patchcode, "apple");
11040     lstrcpyA(targetprod, "banana");
11041     context = 0xdeadbeef;
11042     lstrcpyA(targetsid, "kiwi");
11043     size = MAX_PATH;
11044     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11045                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
11046                            &context, targetsid, &size);
11047     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11048     ok(!lstrcmpA(patchcode, "apple"),
11049        "Expected patchcode to be unchanged, got %s\n", patchcode);
11050     ok(!lstrcmpA(targetprod, "banana"),
11051        "Expected targetprod to be unchanged, got %s\n", targetprod);
11052     ok(context == 0xdeadbeef,
11053        "Expected context to be unchanged, got %d\n", context);
11054     ok(!lstrcmpA(targetsid, "kiwi"),
11055        "Expected targetsid to be unchanged, got %s\n", targetsid);
11056     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11057 
11058     data = MSIPATCHSTATE_APPLIED;
11059     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
11060                          (const BYTE *)&data, sizeof(DWORD));
11061     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11062 
11063     /* State value exists */
11064     lstrcpyA(patchcode, "apple");
11065     lstrcpyA(targetprod, "banana");
11066     context = 0xdeadbeef;
11067     lstrcpyA(targetsid, "kiwi");
11068     size = MAX_PATH;
11069     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11070                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
11071                            &context, targetsid, &size);
11072     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11073     ok(!lstrcmpA(patchcode, patch),
11074        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
11075     ok(!lstrcmpA(targetprod, prodcode),
11076        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
11077     ok(context == MSIINSTALLCONTEXT_MACHINE,
11078        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
11079     ok(!lstrcmpA(targetsid, ""),
11080        "Expected \"\", got \"%s\"\n", targetsid);
11081     ok(size == 0, "Expected 0, got %d\n", size);
11082 
11083     /* MSIPATCHSTATE_SUPERSEDED */
11084 
11085     lstrcpyA(patchcode, "apple");
11086     lstrcpyA(targetprod, "banana");
11087     context = 0xdeadbeef;
11088     lstrcpyA(targetsid, "kiwi");
11089     size = MAX_PATH;
11090     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11091                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
11092                            &context, targetsid, &size);
11093     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11094     ok(!lstrcmpA(patchcode, "apple"),
11095        "Expected patchcode to be unchanged, got %s\n", patchcode);
11096     ok(!lstrcmpA(targetprod, "banana"),
11097        "Expected targetprod to be unchanged, got %s\n", targetprod);
11098     ok(context == 0xdeadbeef,
11099        "Expected context to be unchanged, got %d\n", context);
11100     ok(!lstrcmpA(targetsid, "kiwi"),
11101        "Expected targetsid to be unchanged, got %s\n", targetsid);
11102     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11103 
11104     data = MSIPATCHSTATE_SUPERSEDED;
11105     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
11106                          (const BYTE *)&data, sizeof(DWORD));
11107     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11108 
11109     /* State value is MSIPATCHSTATE_SUPERSEDED */
11110     lstrcpyA(patchcode, "apple");
11111     lstrcpyA(targetprod, "banana");
11112     context = 0xdeadbeef;
11113     lstrcpyA(targetsid, "kiwi");
11114     size = MAX_PATH;
11115     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11116                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
11117                            &context, targetsid, &size);
11118     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11119     ok(!lstrcmpA(patchcode, patch),
11120        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
11121     ok(!lstrcmpA(targetprod, prodcode),
11122        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
11123     ok(context == MSIINSTALLCONTEXT_MACHINE,
11124        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
11125     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
11126     ok(size == 0, "Expected 0, got %d\n", size);
11127 
11128     /* MSIPATCHSTATE_OBSOLETED */
11129 
11130     lstrcpyA(patchcode, "apple");
11131     lstrcpyA(targetprod, "banana");
11132     context = 0xdeadbeef;
11133     lstrcpyA(targetsid, "kiwi");
11134     size = MAX_PATH;
11135     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11136                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
11137                            &context, targetsid, &size);
11138     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11139     ok(!lstrcmpA(patchcode, "apple"),
11140        "Expected patchcode to be unchanged, got %s\n", patchcode);
11141     ok(!lstrcmpA(targetprod, "banana"),
11142        "Expected targetprod to be unchanged, got %s\n", targetprod);
11143     ok(context == 0xdeadbeef,
11144        "Expected context to be unchanged, got %d\n", context);
11145     ok(!lstrcmpA(targetsid, "kiwi"),
11146        "Expected targetsid to be unchanged, got %s\n", targetsid);
11147     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11148 
11149     data = MSIPATCHSTATE_OBSOLETED;
11150     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
11151                          (const BYTE *)&data, sizeof(DWORD));
11152     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11153 
11154     /* State value is obsoleted */
11155     lstrcpyA(patchcode, "apple");
11156     lstrcpyA(targetprod, "banana");
11157     context = 0xdeadbeef;
11158     lstrcpyA(targetsid, "kiwi");
11159     size = MAX_PATH;
11160     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11161                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
11162                            &context, targetsid, &size);
11163     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11164     ok(!lstrcmpA(patchcode, patch),
11165        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
11166     ok(!lstrcmpA(targetprod, prodcode),
11167        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
11168     ok(context == MSIINSTALLCONTEXT_MACHINE,
11169        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
11170     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
11171     ok(size == 0, "Expected 0, got %d\n", size);
11172 
11173     /* MSIPATCHSTATE_REGISTERED */
11174     /* FIXME */
11175 
11176     /* MSIPATCHSTATE_ALL */
11177 
11178     /* 1st */
11179     lstrcpyA(patchcode, "apple");
11180     lstrcpyA(targetprod, "banana");
11181     context = 0xdeadbeef;
11182     lstrcpyA(targetsid, "kiwi");
11183     size = MAX_PATH;
11184     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11185                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
11186                            &context, targetsid, &size);
11187     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11188     ok(!lstrcmpA(patchcode, patch),
11189        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
11190     ok(!lstrcmpA(targetprod, prodcode),
11191        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
11192     ok(context == MSIINSTALLCONTEXT_MACHINE,
11193        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
11194     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
11195     ok(size == 0, "Expected 0, got %d\n", size);
11196 
11197     /* same patch in multiple places, only one is enumerated */
11198     lstrcpyA(patchcode, "apple");
11199     lstrcpyA(targetprod, "banana");
11200     context = 0xdeadbeef;
11201     lstrcpyA(targetsid, "kiwi");
11202     size = MAX_PATH;
11203     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11204                            MSIPATCHSTATE_ALL, 1, patchcode, targetprod,
11205                            &context, targetsid, &size);
11206     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11207     ok(!lstrcmpA(patchcode, "apple"),
11208        "Expected patchcode to be unchanged, got %s\n", patchcode);
11209     ok(!lstrcmpA(targetprod, "banana"),
11210        "Expected targetprod to be unchanged, got %s\n", targetprod);
11211     ok(context == 0xdeadbeef,
11212        "Expected context to be unchanged, got %d\n", context);
11213     ok(!lstrcmpA(targetsid, "kiwi"),
11214        "Expected targetsid to be unchanged, got %s\n", targetsid);
11215     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11216 
11217     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
11218     RegDeleteValueA(hpatch, "State");
11219     RegCloseKey(hpatch);
11220     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
11221     RegCloseKey(udpatch);
11222     delete_key(udprod, "", access & KEY_WOW64_64KEY);
11223     RegCloseKey(udprod);
11224 
11225 done:
11226     RegDeleteValueA(patches, patch_squashed);
11227     RegDeleteValueA(patches, "Patches");
11228     delete_key(patches, "", access & KEY_WOW64_64KEY);
11229     RegCloseKey(patches);
11230     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
11231     RegCloseKey(prodkey);
11232 }
11233 
11234 static void test_MsiEnumPatchesEx(void)
11235 {
11236     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
11237     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
11238     CHAR patchcode[MAX_PATH];
11239     MSIINSTALLCONTEXT context;
11240     LPSTR usersid;
11241     DWORD size;
11242     UINT r;
11243 
11244     if (!pMsiEnumPatchesExA)
11245     {
11246         win_skip("MsiEnumPatchesExA not implemented\n");
11247         return;
11248     }
11249 
11250     create_test_guid(prodcode, prod_squashed);
11251     usersid = get_user_sid();
11252 
11253     /* empty szProductCode */
11254     lstrcpyA(patchcode, "apple");
11255     lstrcpyA(targetprod, "banana");
11256     context = 0xdeadbeef;
11257     lstrcpyA(targetsid, "kiwi");
11258     size = MAX_PATH;
11259     r = pMsiEnumPatchesExA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
11260                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod, &context,
11261                            targetsid, &size);
11262     ok(r == ERROR_INVALID_PARAMETER,
11263        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11264     ok(!lstrcmpA(patchcode, "apple"),
11265        "Expected patchcode to be unchanged, got %s\n", patchcode);
11266     ok(!lstrcmpA(targetprod, "banana"),
11267        "Expected targetprod to be unchanged, got %s\n", targetprod);
11268     ok(context == 0xdeadbeef,
11269        "Expected context to be unchanged, got %d\n", context);
11270     ok(!lstrcmpA(targetsid, "kiwi"),
11271        "Expected targetsid to be unchanged, got %s\n", targetsid);
11272     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11273 
11274     /* garbage szProductCode */
11275     lstrcpyA(patchcode, "apple");
11276     lstrcpyA(targetprod, "banana");
11277     context = 0xdeadbeef;
11278     lstrcpyA(targetsid, "kiwi");
11279     size = MAX_PATH;
11280     r = pMsiEnumPatchesExA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
11281                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod, &context,
11282                            targetsid, &size);
11283     ok(r == ERROR_INVALID_PARAMETER,
11284        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11285     ok(!lstrcmpA(patchcode, "apple"),
11286        "Expected patchcode to be unchanged, got %s\n", patchcode);
11287     ok(!lstrcmpA(targetprod, "banana"),
11288        "Expected targetprod to be unchanged, got %s\n", targetprod);
11289     ok(context == 0xdeadbeef,
11290        "Expected context to be unchanged, got %d\n", context);
11291     ok(!lstrcmpA(targetsid, "kiwi"),
11292        "Expected targetsid to be unchanged, got %s\n", targetsid);
11293     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11294 
11295     /* guid without brackets */
11296     lstrcpyA(patchcode, "apple");
11297     lstrcpyA(targetprod, "banana");
11298     context = 0xdeadbeef;
11299     lstrcpyA(targetsid, "kiwi");
11300     size = MAX_PATH;
11301     r = pMsiEnumPatchesExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", usersid,
11302                            MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
11303                            0, patchcode, targetprod, &context,
11304                            targetsid, &size);
11305     ok(r == ERROR_INVALID_PARAMETER,
11306        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11307     ok(!lstrcmpA(patchcode, "apple"),
11308        "Expected patchcode to be unchanged, got %s\n", patchcode);
11309     ok(!lstrcmpA(targetprod, "banana"),
11310        "Expected targetprod to be unchanged, got %s\n", targetprod);
11311     ok(context == 0xdeadbeef,
11312        "Expected context to be unchanged, got %d\n", context);
11313     ok(!lstrcmpA(targetsid, "kiwi"),
11314        "Expected targetsid to be unchanged, got %s\n", targetsid);
11315     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11316 
11317     /* guid with brackets */
11318     lstrcpyA(patchcode, "apple");
11319     lstrcpyA(targetprod, "banana");
11320     context = 0xdeadbeef;
11321     lstrcpyA(targetsid, "kiwi");
11322     size = MAX_PATH;
11323     r = pMsiEnumPatchesExA("{6700E8CF-95AB-4D9C-BC2C-15840DDA7A5D}", usersid,
11324                            MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
11325                            0, patchcode, targetprod, &context,
11326                            targetsid, &size);
11327     ok(r == ERROR_NO_MORE_ITEMS,
11328        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11329     ok(!lstrcmpA(patchcode, "apple"),
11330        "Expected patchcode to be unchanged, got %s\n", patchcode);
11331     ok(!lstrcmpA(targetprod, "banana"),
11332        "Expected targetprod to be unchanged, got %s\n", targetprod);
11333     ok(context == 0xdeadbeef,
11334        "Expected context to be unchanged, got %d\n", context);
11335     ok(!lstrcmpA(targetsid, "kiwi"),
11336        "Expected targetsid to be unchanged, got %s\n", targetsid);
11337     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11338 
11339     /* szUserSid is S-1-5-18 */
11340     lstrcpyA(patchcode, "apple");
11341     lstrcpyA(targetprod, "banana");
11342     context = 0xdeadbeef;
11343     lstrcpyA(targetsid, "kiwi");
11344     size = MAX_PATH;
11345     r = pMsiEnumPatchesExA(prodcode, "S-1-5-18",
11346                            MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
11347                            0, patchcode, targetprod, &context,
11348                            targetsid, &size);
11349     ok(r == ERROR_INVALID_PARAMETER,
11350        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11351     ok(!lstrcmpA(patchcode, "apple"),
11352        "Expected patchcode to be unchanged, got %s\n", patchcode);
11353     ok(!lstrcmpA(targetprod, "banana"),
11354        "Expected targetprod to be unchanged, got %s\n", targetprod);
11355     ok(context == 0xdeadbeef,
11356        "Expected context to be unchanged, got %d\n", context);
11357     ok(!lstrcmpA(targetsid, "kiwi"),
11358        "Expected targetsid to be unchanged, got %s\n", targetsid);
11359     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11360 
11361     /* dwContext is MSIINSTALLCONTEXT_MACHINE, but szUserSid is non-NULL */
11362     lstrcpyA(patchcode, "apple");
11363     lstrcpyA(targetprod, "banana");
11364     context = 0xdeadbeef;
11365     lstrcpyA(targetsid, "kiwi");
11366     size = MAX_PATH;
11367     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_MACHINE,
11368                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
11369                            &context, targetsid, &size);
11370     ok(r == ERROR_INVALID_PARAMETER,
11371        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11372     ok(!lstrcmpA(patchcode, "apple"),
11373        "Expected patchcode to be unchanged, got %s\n", patchcode);
11374     ok(!lstrcmpA(targetprod, "banana"),
11375        "Expected targetprod to be unchanged, got %s\n", targetprod);
11376     ok(context == 0xdeadbeef,
11377        "Expected context to be unchanged, got %d\n", context);
11378     ok(!lstrcmpA(targetsid, "kiwi"),
11379        "Expected targetsid to be unchanged, got %s\n", targetsid);
11380     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11381 
11382     /* dwContext is out of bounds */
11383     lstrcpyA(patchcode, "apple");
11384     lstrcpyA(targetprod, "banana");
11385     context = 0xdeadbeef;
11386     lstrcpyA(targetsid, "kiwi");
11387     size = MAX_PATH;
11388     r = pMsiEnumPatchesExA(prodcode, usersid, 0,
11389                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
11390                            &context, targetsid, &size);
11391     ok(r == ERROR_INVALID_PARAMETER,
11392        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11393     ok(!lstrcmpA(patchcode, "apple"),
11394        "Expected patchcode to be unchanged, got %s\n", patchcode);
11395     ok(!lstrcmpA(targetprod, "banana"),
11396        "Expected targetprod to be unchanged, got %s\n", targetprod);
11397     ok(context == 0xdeadbeef,
11398        "Expected context to be unchanged, got %d\n", context);
11399     ok(!lstrcmpA(targetsid, "kiwi"),
11400        "Expected targetsid to be unchanged, got %s\n", targetsid);
11401     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11402 
11403     /* dwContext is out of bounds */
11404     lstrcpyA(patchcode, "apple");
11405     lstrcpyA(targetprod, "banana");
11406     context = 0xdeadbeef;
11407     lstrcpyA(targetsid, "kiwi");
11408     size = MAX_PATH;
11409     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_ALL + 1,
11410                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
11411                            &context, targetsid, &size);
11412     ok(r == ERROR_INVALID_PARAMETER,
11413        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11414     ok(!lstrcmpA(patchcode, "apple"),
11415        "Expected patchcode to be unchanged, got %s\n", patchcode);
11416     ok(!lstrcmpA(targetprod, "banana"),
11417        "Expected targetprod to be unchanged, got %s\n", targetprod);
11418     ok(context == 0xdeadbeef,
11419        "Expected context to be unchanged, got %d\n", context);
11420     ok(!lstrcmpA(targetsid, "kiwi"),
11421        "Expected targetsid to be unchanged, got %s\n", targetsid);
11422     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11423 
11424     /* dwFilter is out of bounds */
11425     lstrcpyA(patchcode, "apple");
11426     lstrcpyA(targetprod, "banana");
11427     context = 0xdeadbeef;
11428     lstrcpyA(targetsid, "kiwi");
11429     size = MAX_PATH;
11430     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
11431                            MSIPATCHSTATE_INVALID, 0, patchcode, targetprod,
11432                            &context, targetsid, &size);
11433     ok(r == ERROR_INVALID_PARAMETER,
11434        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11435     ok(!lstrcmpA(patchcode, "apple"),
11436        "Expected patchcode to be unchanged, got %s\n", patchcode);
11437     ok(!lstrcmpA(targetprod, "banana"),
11438        "Expected targetprod to be unchanged, got %s\n", targetprod);
11439     ok(context == 0xdeadbeef,
11440        "Expected context to be unchanged, got %d\n", context);
11441     ok(!lstrcmpA(targetsid, "kiwi"),
11442        "Expected targetsid to be unchanged, got %s\n", targetsid);
11443     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11444 
11445     /* dwFilter is out of bounds */
11446     lstrcpyA(patchcode, "apple");
11447     lstrcpyA(targetprod, "banana");
11448     context = 0xdeadbeef;
11449     lstrcpyA(targetsid, "kiwi");
11450     size = MAX_PATH;
11451     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
11452                            MSIPATCHSTATE_ALL + 1, 0, patchcode, targetprod,
11453                            &context, targetsid, &size);
11454     ok(r == ERROR_INVALID_PARAMETER,
11455        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11456     ok(!lstrcmpA(patchcode, "apple"),
11457        "Expected patchcode to be unchanged, got %s\n", patchcode);
11458     ok(!lstrcmpA(targetprod, "banana"),
11459        "Expected targetprod to be unchanged, got %s\n", targetprod);
11460     ok(context == 0xdeadbeef,
11461        "Expected context to be unchanged, got %d\n", context);
11462     ok(!lstrcmpA(targetsid, "kiwi"),
11463        "Expected targetsid to be unchanged, got %s\n", targetsid);
11464     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11465 
11466     /* pcchTargetUserSid is NULL while szTargetUserSid is non-NULL */
11467     lstrcpyA(patchcode, "apple");
11468     lstrcpyA(targetprod, "banana");
11469     context = 0xdeadbeef;
11470     lstrcpyA(targetsid, "kiwi");
11471     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
11472                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
11473                            &context, targetsid, NULL);
11474     ok(r == ERROR_INVALID_PARAMETER,
11475        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11476     ok(!lstrcmpA(patchcode, "apple"),
11477        "Expected patchcode to be unchanged, got %s\n", patchcode);
11478     ok(!lstrcmpA(targetprod, "banana"),
11479        "Expected targetprod to be unchanged, got %s\n", targetprod);
11480     ok(context == 0xdeadbeef,
11481        "Expected context to be unchanged, got %d\n", context);
11482     ok(!lstrcmpA(targetsid, "kiwi"),
11483        "Expected targetsid to be unchanged, got %s\n", targetsid);
11484 
11485     test_MsiEnumPatchesEx_usermanaged(usersid, usersid);
11486     test_MsiEnumPatchesEx_usermanaged(NULL, usersid);
11487     test_MsiEnumPatchesEx_usermanaged("S-1-2-34", "S-1-2-34");
11488     test_MsiEnumPatchesEx_userunmanaged(usersid, usersid);
11489     test_MsiEnumPatchesEx_userunmanaged(NULL, usersid);
11490     /* FIXME: Successfully test userunmanaged with a different user */
11491     test_MsiEnumPatchesEx_machine();
11492     LocalFree(usersid);
11493 }
11494 
11495 static void test_MsiEnumPatches(void)
11496 {
11497     CHAR keypath[MAX_PATH], patch[MAX_PATH];
11498     CHAR patchcode[MAX_PATH], patch_squashed[MAX_PATH];
11499     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
11500     CHAR transforms[MAX_PATH];
11501     WCHAR patchW[MAX_PATH], prodcodeW[MAX_PATH], transformsW[MAX_PATH];
11502     HKEY prodkey, patches, udprod;
11503     HKEY userkey, hpatch, udpatch;
11504     DWORD size, data;
11505     LPSTR usersid;
11506     LONG res;
11507     UINT r;
11508     REGSAM access = KEY_ALL_ACCESS;
11509 
11510     create_test_guid(prodcode, prod_squashed);
11511     create_test_guid(patchcode, patch_squashed);
11512     usersid = get_user_sid();
11513 
11514     if (is_wow64)
11515         access |= KEY_WOW64_64KEY;
11516 
11517     /* NULL szProduct */
11518     size = MAX_PATH;
11519     lstrcpyA(patch, "apple");
11520     lstrcpyA(transforms, "banana");
11521     r = MsiEnumPatchesA(NULL, 0, patch, transforms, &size);
11522     ok(r == ERROR_INVALID_PARAMETER,
11523        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11524     ok(!lstrcmpA(patch, "apple"),
11525        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11526     ok(!lstrcmpA(transforms, "banana"),
11527        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11528     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11529 
11530     /* empty szProduct */
11531     size = MAX_PATH;
11532     lstrcpyA(patch, "apple");
11533     lstrcpyA(transforms, "banana");
11534     r = MsiEnumPatchesA("", 0, patch, transforms, &size);
11535     ok(r == ERROR_INVALID_PARAMETER,
11536        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11537     ok(!lstrcmpA(patch, "apple"),
11538        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11539     ok(!lstrcmpA(transforms, "banana"),
11540        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11541     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11542 
11543     /* garbage szProduct */
11544     size = MAX_PATH;
11545     lstrcpyA(patch, "apple");
11546     lstrcpyA(transforms, "banana");
11547     r = MsiEnumPatchesA("garbage", 0, patch, transforms, &size);
11548     ok(r == ERROR_INVALID_PARAMETER,
11549        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11550     ok(!lstrcmpA(patch, "apple"),
11551        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11552     ok(!lstrcmpA(transforms, "banana"),
11553        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11554     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11555 
11556     /* guid without brackets */
11557     size = MAX_PATH;
11558     lstrcpyA(patch, "apple");
11559     lstrcpyA(transforms, "banana");
11560     r = MsiEnumPatchesA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", 0, patch,
11561                         transforms, &size);
11562     ok(r == ERROR_INVALID_PARAMETER,
11563        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11564     ok(!lstrcmpA(patch, "apple"),
11565        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11566     ok(!lstrcmpA(transforms, "banana"),
11567        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11568     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11569 
11570     /* guid with brackets */
11571     size = MAX_PATH;
11572     lstrcpyA(patch, "apple");
11573     lstrcpyA(transforms, "banana");
11574     r = MsiEnumPatchesA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", 0, patch,
11575                         transforms, &size);
11576     ok(r == ERROR_UNKNOWN_PRODUCT,
11577        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11578     ok(!lstrcmpA(patch, "apple"),
11579        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11580     ok(!lstrcmpA(transforms, "banana"),
11581        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11582     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11583 
11584     /* same length as guid, but random */
11585     size = MAX_PATH;
11586     lstrcpyA(patch, "apple");
11587     lstrcpyA(transforms, "banana");
11588     r = MsiEnumPatchesA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", 0, patch,
11589                         transforms, &size);
11590     ok(r == ERROR_INVALID_PARAMETER,
11591        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11592     ok(!lstrcmpA(patch, "apple"),
11593        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11594     ok(!lstrcmpA(transforms, "banana"),
11595        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11596     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11597 
11598     /* MSIINSTALLCONTEXT_USERMANAGED */
11599 
11600     size = MAX_PATH;
11601     lstrcpyA(patch, "apple");
11602     lstrcpyA(transforms, "banana");
11603     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11604     ok(r == ERROR_UNKNOWN_PRODUCT,
11605        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11606     ok(!lstrcmpA(patch, "apple"),
11607        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11608     ok(!lstrcmpA(transforms, "banana"),
11609        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11610     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11611 
11612     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
11613     lstrcatA(keypath, usersid);
11614     lstrcatA(keypath, "\\Installer\\Products\\");
11615     lstrcatA(keypath, prod_squashed);
11616 
11617     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
11618     if (res == ERROR_ACCESS_DENIED)
11619     {
11620         skip("Not enough rights to perform tests\n");
11621         LocalFree(usersid);
11622         return;
11623     }
11624     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11625 
11626     /* managed product key exists */
11627     size = MAX_PATH;
11628     lstrcpyA(patch, "apple");
11629     lstrcpyA(transforms, "banana");
11630     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11631     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11632     ok(!lstrcmpA(patch, "apple"),
11633        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11634     ok(!lstrcmpA(transforms, "banana"),
11635        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11636     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11637 
11638     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
11639     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11640 
11641     /* patches key exists */
11642     size = MAX_PATH;
11643     lstrcpyA(patch, "apple");
11644     lstrcpyA(transforms, "banana");
11645     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11646     ok(r == ERROR_NO_MORE_ITEMS ||
11647        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11648        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11649     ok(!lstrcmpA(patch, "apple"),
11650        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11651     ok(!lstrcmpA(transforms, "banana"),
11652        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11653     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11654 
11655     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
11656                          (const BYTE *)patch_squashed,
11657                          lstrlenA(patch_squashed) + 1);
11658     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11659 
11660     /* Patches value exists, is not REG_MULTI_SZ */
11661     size = MAX_PATH;
11662     lstrcpyA(patch, "apple");
11663     lstrcpyA(transforms, "banana");
11664     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11665     ok(r == ERROR_BAD_CONFIGURATION ||
11666        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
11667        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11668     ok(!lstrcmpA(patch, "apple"),
11669        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11670     ok(!lstrcmpA(transforms, "banana"),
11671        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11672     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11673 
11674     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11675                          (const BYTE *)"a\0b\0c\0\0", 7);
11676     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11677 
11678     /* Patches value exists, is not a squashed guid */
11679     size = MAX_PATH;
11680     lstrcpyA(patch, "apple");
11681     lstrcpyA(transforms, "banana");
11682     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11683     ok(r == ERROR_BAD_CONFIGURATION,
11684        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11685     ok(!lstrcmpA(patch, "apple"),
11686        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11687     ok(!lstrcmpA(transforms, "banana"),
11688        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11689     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11690 
11691     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
11692     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11693                          (const BYTE *)patch_squashed,
11694                          lstrlenA(patch_squashed) + 2);
11695     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11696 
11697     /* Patches value exists */
11698     size = MAX_PATH;
11699     lstrcpyA(patch, "apple");
11700     lstrcpyA(transforms, "banana");
11701     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11702     ok(r == ERROR_NO_MORE_ITEMS ||
11703        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11704        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11705     ok(!lstrcmpA(patch, "apple") ||
11706        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
11707        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11708     ok(!lstrcmpA(transforms, "banana"),
11709        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11710     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11711 
11712     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
11713                          (const BYTE *)"whatever", 9);
11714     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11715 
11716     /* patch squashed value exists */
11717     size = MAX_PATH;
11718     lstrcpyA(patch, "apple");
11719     lstrcpyA(transforms, "banana");
11720     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11721     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11722     ok(!lstrcmpA(patch, patchcode),
11723        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11724     ok(!lstrcmpA(transforms, "whatever"),
11725        "Expected \"whatever\", got \"%s\"\n", transforms);
11726     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
11727 
11728     /* lpPatchBuf is NULL */
11729     size = MAX_PATH;
11730     lstrcpyA(transforms, "banana");
11731     r = MsiEnumPatchesA(prodcode, 0, NULL, transforms, &size);
11732     ok(r == ERROR_INVALID_PARAMETER,
11733        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11734     ok(!lstrcmpA(transforms, "banana"),
11735        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11736     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11737 
11738     /* lpTransformsBuf is NULL, pcchTransformsBuf is not */
11739     size = MAX_PATH;
11740     lstrcpyA(patch, "apple");
11741     r = MsiEnumPatchesA(prodcode, 0, patch, NULL, &size);
11742     ok(r == ERROR_INVALID_PARAMETER,
11743        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11744     ok(!lstrcmpA(patch, "apple"),
11745        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11746     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11747 
11748     /* pcchTransformsBuf is NULL, lpTransformsBuf is not */
11749     lstrcpyA(patch, "apple");
11750     lstrcpyA(transforms, "banana");
11751     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, NULL);
11752     ok(r == ERROR_INVALID_PARAMETER,
11753        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11754     ok(!lstrcmpA(patch, "apple"),
11755        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11756     ok(!lstrcmpA(transforms, "banana"),
11757        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11758 
11759     /* pcchTransformsBuf is too small */
11760     size = 6;
11761     lstrcpyA(patch, "apple");
11762     lstrcpyA(transforms, "banana");
11763     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11764     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
11765     ok(!lstrcmpA(patch, patchcode),
11766        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11767     ok(!lstrcmpA(transforms, "whate") ||
11768        broken(!lstrcmpA(transforms, "banana")), /* Windows Installer < 3.0 */
11769        "Expected \"whate\", got \"%s\"\n", transforms);
11770     ok(size == 8 || size == 16, "Expected 8 or 16, got %d\n", size);
11771 
11772     /* increase the index */
11773     size = MAX_PATH;
11774     lstrcpyA(patch, "apple");
11775     lstrcpyA(transforms, "banana");
11776     r = MsiEnumPatchesA(prodcode, 1, patch, transforms, &size);
11777     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11778     ok(!lstrcmpA(patch, "apple"),
11779        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11780     ok(!lstrcmpA(transforms, "banana"),
11781        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11782     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11783 
11784     /* increase again */
11785     size = MAX_PATH;
11786     lstrcpyA(patch, "apple");
11787     lstrcpyA(transforms, "banana");
11788     r = MsiEnumPatchesA(prodcode, 2, patch, transforms, &size);
11789     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11790     ok(!lstrcmpA(patch, "apple"),
11791        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11792     ok(!lstrcmpA(transforms, "banana"),
11793        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11794     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11795 
11796     RegDeleteValueA(patches, "Patches");
11797     delete_key(patches, "", access & KEY_WOW64_64KEY);
11798     RegCloseKey(patches);
11799     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
11800     RegCloseKey(prodkey);
11801 
11802     /* MSIINSTALLCONTEXT_USERUNMANAGED */
11803 
11804     size = MAX_PATH;
11805     lstrcpyA(patch, "apple");
11806     lstrcpyA(transforms, "banana");
11807     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11808     ok(r == ERROR_UNKNOWN_PRODUCT,
11809        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11810     ok(!lstrcmpA(patch, "apple"),
11811        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11812     ok(!lstrcmpA(transforms, "banana"),
11813        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11814     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11815 
11816     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
11817     lstrcatA(keypath, prod_squashed);
11818 
11819     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
11820     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11821 
11822     /* current user product key exists */
11823     size = MAX_PATH;
11824     lstrcpyA(patch, "apple");
11825     lstrcpyA(transforms, "banana");
11826     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11827     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11828     ok(!lstrcmpA(patch, "apple"),
11829        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11830     ok(!lstrcmpA(transforms, "banana"),
11831        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11832     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11833 
11834     res = RegCreateKeyA(prodkey, "Patches", &patches);
11835     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11836 
11837     /* Patches key exists */
11838     size = MAX_PATH;
11839     lstrcpyA(patch, "apple");
11840     lstrcpyA(transforms, "banana");
11841     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11842     ok(r == ERROR_NO_MORE_ITEMS ||
11843        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11844        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11845     ok(!lstrcmpA(patch, "apple"),
11846        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11847     ok(!lstrcmpA(transforms, "banana"),
11848        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11849     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11850 
11851     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
11852                          (const BYTE *)patch_squashed,
11853                          lstrlenA(patch_squashed) + 1);
11854     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11855 
11856     /* Patches value exists, is not REG_MULTI_SZ */
11857     size = MAX_PATH;
11858     lstrcpyA(patch, "apple");
11859     lstrcpyA(transforms, "banana");
11860     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11861     ok(r == ERROR_BAD_CONFIGURATION ||
11862        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
11863        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11864     ok(!lstrcmpA(patch, "apple"),
11865        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11866     ok(!lstrcmpA(transforms, "banana"),
11867        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11868     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11869 
11870     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11871                          (const BYTE *)"a\0b\0c\0\0", 7);
11872     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11873 
11874     /* Patches value exists, is not a squashed guid */
11875     size = MAX_PATH;
11876     lstrcpyA(patch, "apple");
11877     lstrcpyA(transforms, "banana");
11878     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11879     ok(r == ERROR_BAD_CONFIGURATION,
11880        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11881     ok(!lstrcmpA(patch, "apple"),
11882        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11883     ok(!lstrcmpA(transforms, "banana"),
11884        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11885     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11886 
11887     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
11888     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11889                          (const BYTE *)patch_squashed,
11890                          lstrlenA(patch_squashed) + 2);
11891     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11892 
11893     /* Patches value exists */
11894     size = MAX_PATH;
11895     lstrcpyA(patch, "apple");
11896     lstrcpyA(transforms, "banana");
11897     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11898     ok(r == ERROR_NO_MORE_ITEMS ||
11899        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11900        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11901     ok(!lstrcmpA(patch, "apple") ||
11902        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
11903        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11904     ok(!lstrcmpA(transforms, "banana"),
11905        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11906     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11907 
11908     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
11909                          (const BYTE *)"whatever", 9);
11910     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11911 
11912     /* patch code value exists */
11913     size = MAX_PATH;
11914     lstrcpyA(patch, "apple");
11915     lstrcpyA(transforms, "banana");
11916     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11917     ok(r == ERROR_NO_MORE_ITEMS ||
11918        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
11919        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11920     ok(!lstrcmpA(patch, "apple") ||
11921        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
11922        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11923     ok(!lstrcmpA(transforms, "banana") ||
11924        broken(!lstrcmpA(transforms, "whatever")), /* Windows Installer < 3.0 */
11925        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11926     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11927 
11928     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
11929     lstrcatA(keypath, usersid);
11930     lstrcatA(keypath, "\\Patches\\");
11931     lstrcatA(keypath, patch_squashed);
11932 
11933     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
11934     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11935 
11936     /* userdata patch key exists */
11937     size = MAX_PATH;
11938     lstrcpyA(patch, "apple");
11939     lstrcpyA(transforms, "banana");
11940     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11941     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11942     ok(!lstrcmpA(patch, patchcode),
11943        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11944     ok(!lstrcmpA(transforms, "whatever"),
11945        "Expected \"whatever\", got \"%s\"\n", transforms);
11946     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
11947 
11948     delete_key(userkey, "", access & KEY_WOW64_64KEY);
11949     RegCloseKey(userkey);
11950     RegDeleteValueA(patches, patch_squashed);
11951     RegDeleteValueA(patches, "Patches");
11952     RegDeleteKeyA(patches, "");
11953     RegCloseKey(patches);
11954     RegDeleteKeyA(prodkey, "");
11955     RegCloseKey(prodkey);
11956 
11957     /* MSIINSTALLCONTEXT_MACHINE */
11958 
11959     size = MAX_PATH;
11960     lstrcpyA(patch, "apple");
11961     lstrcpyA(transforms, "banana");
11962     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11963     ok(r == ERROR_UNKNOWN_PRODUCT,
11964        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11965     ok(!lstrcmpA(patch, "apple"),
11966        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11967     ok(!lstrcmpA(transforms, "banana"),
11968        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11969     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11970 
11971     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
11972     lstrcatA(keypath, prod_squashed);
11973 
11974     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
11975     if (res == ERROR_ACCESS_DENIED)
11976     {
11977         skip("Not enough rights to perform tests\n");
11978         LocalFree(usersid);
11979         return;
11980     }
11981     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11982 
11983     /* local product key exists */
11984     size = MAX_PATH;
11985     lstrcpyA(patch, "apple");
11986     lstrcpyA(transforms, "banana");
11987     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11988     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11989     ok(!lstrcmpA(patch, "apple"),
11990        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11991     ok(!lstrcmpA(transforms, "banana"),
11992        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11993     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11994 
11995     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
11996     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11997 
11998     /* Patches key exists */
11999     size = MAX_PATH;
12000     lstrcpyA(patch, "apple");
12001     lstrcpyA(transforms, "banana");
12002     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12003     ok(r == ERROR_NO_MORE_ITEMS ||
12004        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
12005        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
12006     ok(!lstrcmpA(patch, "apple"),
12007        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
12008     ok(!lstrcmpA(transforms, "banana"),
12009        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
12010     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12011 
12012     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
12013                          (const BYTE *)patch_squashed,
12014                          lstrlenA(patch_squashed) + 1);
12015     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12016 
12017     /* Patches value exists, is not REG_MULTI_SZ */
12018     size = MAX_PATH;
12019     lstrcpyA(patch, "apple");
12020     lstrcpyA(transforms, "banana");
12021     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12022     ok(r == ERROR_BAD_CONFIGURATION ||
12023        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
12024        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
12025     ok(!lstrcmpA(patch, "apple"),
12026        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
12027     ok(!lstrcmpA(transforms, "banana"),
12028        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
12029     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12030 
12031     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
12032                          (const BYTE *)"a\0b\0c\0\0", 7);
12033     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12034 
12035     /* Patches value exists, is not a squashed guid */
12036     size = MAX_PATH;
12037     lstrcpyA(patch, "apple");
12038     lstrcpyA(transforms, "banana");
12039     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12040     ok(r == ERROR_BAD_CONFIGURATION,
12041        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
12042     ok(!lstrcmpA(patch, "apple"),
12043        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
12044     ok(!lstrcmpA(transforms, "banana"),
12045        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
12046     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12047 
12048     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
12049     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
12050                          (const BYTE *)patch_squashed,
12051                          lstrlenA(patch_squashed) + 2);
12052     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12053 
12054     /* Patches value exists */
12055     size = MAX_PATH;
12056     lstrcpyA(patch, "apple");
12057     lstrcpyA(transforms, "banana");
12058     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12059     ok(r == ERROR_NO_MORE_ITEMS ||
12060        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
12061        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
12062     ok(!lstrcmpA(patch, "apple") ||
12063        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
12064        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
12065     ok(!lstrcmpA(transforms, "banana"),
12066        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
12067     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12068 
12069     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
12070                          (const BYTE *)"whatever", 9);
12071     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12072 
12073     /* patch code value exists */
12074     size = MAX_PATH;
12075     lstrcpyA(patch, "apple");
12076     lstrcpyA(transforms, "banana");
12077     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12078     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12079     ok(!lstrcmpA(patch, patchcode),
12080        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
12081     ok(!lstrcmpA(transforms, "whatever"),
12082        "Expected \"whatever\", got \"%s\"\n", transforms);
12083     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
12084 
12085     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
12086     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
12087     lstrcatA(keypath, prod_squashed);
12088 
12089     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
12090     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12091 
12092     /* local UserData product key exists */
12093     size = MAX_PATH;
12094     lstrcpyA(patch, "apple");
12095     lstrcpyA(transforms, "banana");
12096     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12097     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12098     ok(!lstrcmpA(patch, patchcode),
12099        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
12100     ok(!lstrcmpA(transforms, "whatever"),
12101        "Expected \"whatever\", got \"%s\"\n", transforms);
12102     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
12103 
12104     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
12105     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12106 
12107     /* local UserData Patches key exists */
12108     size = MAX_PATH;
12109     lstrcpyA(patch, "apple");
12110     lstrcpyA(transforms, "banana");
12111     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12112     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12113     ok(!lstrcmpA(patch, patchcode),
12114        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
12115     ok(!lstrcmpA(transforms, "whatever"),
12116        "Expected \"whatever\", got \"%s\"\n", transforms);
12117     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
12118 
12119     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
12120     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12121 
12122     /* local UserData Product patch key exists */
12123     size = MAX_PATH;
12124     lstrcpyA(patch, "apple");
12125     lstrcpyA(transforms, "banana");
12126     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12127     ok(r == ERROR_NO_MORE_ITEMS ||
12128        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
12129        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
12130     ok(!lstrcmpA(patch, "apple") ||
12131        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
12132        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
12133     ok(!lstrcmpA(transforms, "banana") ||
12134        broken(!lstrcmpA(transforms, "whatever")), /* Windows Installer < 3.0 */
12135        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
12136     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12137 
12138     data = MSIPATCHSTATE_APPLIED;
12139     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
12140                          (const BYTE *)&data, sizeof(DWORD));
12141     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12142 
12143     /* State value exists */
12144     size = MAX_PATH;
12145     lstrcpyA(patch, "apple");
12146     lstrcpyA(transforms, "banana");
12147     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12148     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12149     ok(!lstrcmpA(patch, patchcode),
12150        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
12151     ok(!lstrcmpA(transforms, "whatever"),
12152        "Expected \"whatever\", got \"%s\"\n", transforms);
12153     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
12154 
12155     /* now duplicate some of the tests for the W version */
12156 
12157     /* pcchTransformsBuf is too small */
12158     size = 6;
12159     MultiByteToWideChar( CP_ACP, 0, prodcode, -1, prodcodeW, MAX_PATH );
12160     MultiByteToWideChar( CP_ACP, 0, "apple", -1, patchW, MAX_PATH );
12161     MultiByteToWideChar( CP_ACP, 0, "banana", -1, transformsW, MAX_PATH );
12162     r = MsiEnumPatchesW(prodcodeW, 0, patchW, transformsW, &size);
12163     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
12164     WideCharToMultiByte( CP_ACP, 0, patchW, -1, patch, MAX_PATH, NULL, NULL );
12165     WideCharToMultiByte( CP_ACP, 0, transformsW, -1, transforms, MAX_PATH, NULL, NULL );
12166     ok(!lstrcmpA(patch, patchcode),
12167        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
12168     ok(!lstrcmpA(transforms, "whate") ||
12169        broken(!lstrcmpA(transforms, "banana")), /* Windows Installer < 3.0 */
12170        "Expected \"whate\", got \"%s\"\n", transforms);
12171     ok(size == 8, "Expected 8, got %d\n", size);
12172 
12173     /* patch code value exists */
12174     size = MAX_PATH;
12175     MultiByteToWideChar( CP_ACP, 0, "apple", -1, patchW, MAX_PATH );
12176     MultiByteToWideChar( CP_ACP, 0, "banana", -1, transformsW, MAX_PATH );
12177     r = MsiEnumPatchesW(prodcodeW, 0, patchW, transformsW, &size);
12178     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12179     WideCharToMultiByte( CP_ACP, 0, patchW, -1, patch, MAX_PATH, NULL, NULL );
12180     WideCharToMultiByte( CP_ACP, 0, transformsW, -1, transforms, MAX_PATH, NULL, NULL );
12181     ok(!lstrcmpA(patch, patchcode),
12182        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
12183     ok(!lstrcmpA(transforms, "whatever"),
12184        "Expected \"whatever\", got \"%s\"\n", transforms);
12185     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
12186 
12187     RegDeleteValueA(patches, patch_squashed);
12188     RegDeleteValueA(patches, "Patches");
12189     delete_key(patches, "", access & KEY_WOW64_64KEY);
12190     RegCloseKey(patches);
12191     RegDeleteValueA(hpatch, "State");
12192     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
12193     RegCloseKey(hpatch);
12194     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
12195     RegCloseKey(udpatch);
12196     delete_key(udprod, "", access & KEY_WOW64_64KEY);
12197     RegCloseKey(udprod);
12198     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
12199     RegCloseKey(prodkey);
12200     LocalFree(usersid);
12201 }
12202 
12203 static void test_MsiGetPatchInfoEx(void)
12204 {
12205     CHAR keypath[MAX_PATH], val[MAX_PATH];
12206     CHAR patchcode[MAX_PATH], patch_squashed[MAX_PATH];
12207     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
12208     HKEY prodkey, patches, udprod, props;
12209     HKEY hpatch, udpatch, prodpatches;
12210     LPSTR usersid;
12211     DWORD size;
12212     LONG res;
12213     UINT r;
12214     REGSAM access = KEY_ALL_ACCESS;
12215 
12216     if (!pMsiGetPatchInfoExA)
12217     {
12218         win_skip("MsiGetPatchInfoEx not implemented\n");
12219         return;
12220     }
12221 
12222     create_test_guid(prodcode, prod_squashed);
12223     create_test_guid(patchcode, patch_squashed);
12224     usersid = get_user_sid();
12225 
12226     if (is_wow64)
12227         access |= KEY_WOW64_64KEY;
12228 
12229     /* NULL szPatchCode */
12230     lstrcpyA(val, "apple");
12231     size = MAX_PATH;
12232     r = pMsiGetPatchInfoExA(NULL, 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     /* empty szPatchCode */
12241     size = MAX_PATH;
12242     lstrcpyA(val, "apple");
12243     r = pMsiGetPatchInfoExA("", prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED,
12244                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12245     ok(r == ERROR_INVALID_PARAMETER,
12246        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12247     ok(!lstrcmpA(val, "apple"),
12248        "Expected val to be unchanged, got \"%s\"\n", val);
12249     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12250 
12251     /* garbage szPatchCode */
12252     size = MAX_PATH;
12253     lstrcpyA(val, "apple");
12254     r = pMsiGetPatchInfoExA("garbage", prodcode, NULL,
12255                             MSIINSTALLCONTEXT_USERMANAGED,
12256                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12257     ok(r == ERROR_INVALID_PARAMETER,
12258        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12259     ok(!lstrcmpA(val, "apple"),
12260        "Expected val to be unchanged, got \"%s\"\n", val);
12261     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12262 
12263     /* guid without brackets */
12264     size = MAX_PATH;
12265     lstrcpyA(val, "apple");
12266     r = pMsiGetPatchInfoExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", prodcode,
12267                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
12268                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12269     ok(r == ERROR_INVALID_PARAMETER,
12270        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12271     ok(!lstrcmpA(val, "apple"),
12272        "Expected val to be unchanged, got \"%s\"\n", val);
12273     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12274 
12275     /* guid with brackets */
12276     size = MAX_PATH;
12277     lstrcpyA(val, "apple");
12278     r = pMsiGetPatchInfoExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", prodcode,
12279                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
12280                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12281     ok(r == ERROR_UNKNOWN_PRODUCT,
12282        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12283     ok(!lstrcmpA(val, "apple"),
12284        "Expected val to be unchanged, got \"%s\"\n", val);
12285     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12286 
12287     /* same length as guid, but random */
12288     size = MAX_PATH;
12289     lstrcpyA(val, "apple");
12290     r = pMsiGetPatchInfoExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", prodcode,
12291                             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     /* NULL szProductCode */
12300     lstrcpyA(val, "apple");
12301     size = MAX_PATH;
12302     r = pMsiGetPatchInfoExA(patchcode, NULL, 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     /* empty szProductCode */
12311     size = MAX_PATH;
12312     lstrcpyA(val, "apple");
12313     r = pMsiGetPatchInfoExA(patchcode, "", NULL, MSIINSTALLCONTEXT_USERMANAGED,
12314                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12315     ok(r == ERROR_INVALID_PARAMETER,
12316        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12317     ok(!lstrcmpA(val, "apple"),
12318        "Expected val to be unchanged, got \"%s\"\n", val);
12319     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12320 
12321     /* garbage szProductCode */
12322     size = MAX_PATH;
12323     lstrcpyA(val, "apple");
12324     r = pMsiGetPatchInfoExA(patchcode, "garbage", NULL,
12325                             MSIINSTALLCONTEXT_USERMANAGED,
12326                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12327     ok(r == ERROR_INVALID_PARAMETER,
12328        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12329     ok(!lstrcmpA(val, "apple"),
12330        "Expected val to be unchanged, got \"%s\"\n", val);
12331     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12332 
12333     /* guid without brackets */
12334     size = MAX_PATH;
12335     lstrcpyA(val, "apple");
12336     r = pMsiGetPatchInfoExA(patchcode, "6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
12337                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
12338                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12339     ok(r == ERROR_INVALID_PARAMETER,
12340        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12341     ok(!lstrcmpA(val, "apple"),
12342        "Expected val to be unchanged, got \"%s\"\n", val);
12343     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12344 
12345     /* guid with brackets */
12346     size = MAX_PATH;
12347     lstrcpyA(val, "apple");
12348     r = pMsiGetPatchInfoExA(patchcode, "{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
12349                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
12350                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12351     ok(r == ERROR_UNKNOWN_PRODUCT,
12352        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12353     ok(!lstrcmpA(val, "apple"),
12354        "Expected val to be unchanged, got \"%s\"\n", val);
12355     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12356 
12357     /* same length as guid, but random */
12358     size = MAX_PATH;
12359     lstrcpyA(val, "apple");
12360     r = pMsiGetPatchInfoExA(patchcode, "A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
12361                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
12362                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12363     ok(r == ERROR_INVALID_PARAMETER,
12364        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12365     ok(!lstrcmpA(val, "apple"),
12366        "Expected val to be unchanged, got \"%s\"\n", val);
12367     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12368 
12369     /* szUserSid cannot be S-1-5-18 for MSIINSTALLCONTEXT_USERMANAGED */
12370     size = MAX_PATH;
12371     lstrcpyA(val, "apple");
12372     r = pMsiGetPatchInfoExA(patchcode, prodcode, "S-1-5-18",
12373                             MSIINSTALLCONTEXT_USERMANAGED,
12374                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12375     ok(r == ERROR_INVALID_PARAMETER,
12376        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12377     ok(!lstrcmpA(val, "apple"),
12378        "Expected val to be unchanged, got \"%s\"\n", val);
12379     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12380 
12381     /* szUserSid cannot be S-1-5-18 for MSIINSTALLCONTEXT_USERUNMANAGED */
12382     size = MAX_PATH;
12383     lstrcpyA(val, "apple");
12384     r = pMsiGetPatchInfoExA(patchcode, prodcode, "S-1-5-18",
12385                             MSIINSTALLCONTEXT_USERUNMANAGED,
12386                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12387     ok(r == ERROR_INVALID_PARAMETER,
12388        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12389     ok(!lstrcmpA(val, "apple"),
12390        "Expected val to be unchanged, got \"%s\"\n", val);
12391     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12392 
12393     /* szUserSid cannot be S-1-5-18 for MSIINSTALLCONTEXT_MACHINE */
12394     size = MAX_PATH;
12395     lstrcpyA(val, "apple");
12396     r = pMsiGetPatchInfoExA(patchcode, prodcode, "S-1-5-18",
12397                             MSIINSTALLCONTEXT_MACHINE,
12398                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12399     ok(r == ERROR_INVALID_PARAMETER,
12400        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12401     ok(!lstrcmpA(val, "apple"),
12402        "Expected val to be unchanged, got \"%s\"\n", val);
12403     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12404 
12405     /* szUserSid must be NULL for MSIINSTALLCONTEXT_MACHINE */
12406     size = MAX_PATH;
12407     lstrcpyA(val, "apple");
12408     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12409                             MSIINSTALLCONTEXT_MACHINE,
12410                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12411     ok(r == ERROR_INVALID_PARAMETER,
12412        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12413     ok(!lstrcmpA(val, "apple"),
12414        "Expected val to be unchanged, got \"%s\"\n", val);
12415     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12416 
12417     /* dwContext is out of range */
12418     size = MAX_PATH;
12419     lstrcpyA(val, "apple");
12420     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12421                             MSIINSTALLCONTEXT_NONE,
12422                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12423     ok(r == ERROR_INVALID_PARAMETER,
12424        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12425     ok(!lstrcmpA(val, "apple"),
12426        "Expected val to be unchanged, got \"%s\"\n", val);
12427     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12428 
12429     /* dwContext is out of range */
12430     size = MAX_PATH;
12431     lstrcpyA(val, "apple");
12432     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12433                             MSIINSTALLCONTEXT_ALL,
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     /* dwContext is invalid */
12442     size = MAX_PATH;
12443     lstrcpyA(val, "apple");
12444     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid, 3,
12445                            INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12446     ok(r == ERROR_INVALID_PARAMETER,
12447        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12448     ok(!lstrcmpA(val, "apple"),
12449        "Expected val to be unchanged, got \"%s\"\n", val);
12450     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12451 
12452     /* MSIINSTALLCONTEXT_USERMANAGED */
12453 
12454     size = MAX_PATH;
12455     lstrcpyA(val, "apple");
12456     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12457                             MSIINSTALLCONTEXT_USERMANAGED,
12458                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12459     ok(r == ERROR_UNKNOWN_PRODUCT,
12460        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12461     ok(!lstrcmpA(val, "apple"),
12462        "Expected val to be unchanged, got \"%s\"\n", val);
12463     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12464 
12465     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
12466     lstrcatA(keypath, usersid);
12467     lstrcatA(keypath, "\\Products\\");
12468     lstrcatA(keypath, prod_squashed);
12469 
12470     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
12471     if (res == ERROR_ACCESS_DENIED)
12472     {
12473         skip("Not enough rights to perform tests\n");
12474         LocalFree(usersid);
12475         return;
12476     }
12477     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12478 
12479     /* local UserData product key exists */
12480     size = MAX_PATH;
12481     lstrcpyA(val, "apple");
12482     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12483                             MSIINSTALLCONTEXT_USERMANAGED,
12484                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12485     ok(r == ERROR_UNKNOWN_PRODUCT,
12486        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12487     ok(!lstrcmpA(val, "apple"),
12488        "Expected val to be unchanged, got \"%s\"\n", val);
12489     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12490 
12491     res = RegCreateKeyExA(udprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
12492     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12493 
12494     /* InstallProperties key exists */
12495     size = MAX_PATH;
12496     lstrcpyA(val, "apple");
12497     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12498                             MSIINSTALLCONTEXT_USERMANAGED,
12499                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12500     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12501     ok(!lstrcmpA(val, "apple"),
12502        "Expected val to be unchanged, got \"%s\"\n", val);
12503     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12504 
12505     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
12506     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12507 
12508     /* Patches key exists */
12509     size = MAX_PATH;
12510     lstrcpyA(val, "apple");
12511     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12512                             MSIINSTALLCONTEXT_USERMANAGED,
12513                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12514     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCHA, got %d\n", r);
12515     ok(!lstrcmpA(val, "apple"),
12516        "Expected val to be unchanged, got \"%s\"\n", val);
12517     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12518 
12519     res = RegCreateKeyExA(patches, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
12520     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12521 
12522     /* Patches key exists */
12523     size = MAX_PATH;
12524     lstrcpyA(val, "apple");
12525     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12526                             MSIINSTALLCONTEXT_USERMANAGED,
12527                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12528     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12529     ok(!lstrcmpA(val, "apple"),
12530        "Expected val to be unchanged, got \"%s\"\n", val);
12531     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12532 
12533     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
12534     lstrcatA(keypath, usersid);
12535     lstrcatA(keypath, "\\Installer\\Products\\");
12536     lstrcatA(keypath, prod_squashed);
12537 
12538     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
12539     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12540 
12541     /* managed product key exists */
12542     size = MAX_PATH;
12543     lstrcpyA(val, "apple");
12544     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12545                             MSIINSTALLCONTEXT_USERMANAGED,
12546                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12547     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12548     ok(!lstrcmpA(val, "apple"),
12549        "Expected val to be unchanged, got \"%s\"\n", val);
12550     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12551 
12552     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &prodpatches, NULL);
12553     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12554 
12555     /* Patches key exists */
12556     size = MAX_PATH;
12557     lstrcpyA(val, "apple");
12558     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12559                             MSIINSTALLCONTEXT_USERMANAGED,
12560                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12561     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12562     ok(!lstrcmpA(val, "apple"),
12563        "Expected val to be unchanged, got \"%s\"\n", val);
12564     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12565 
12566     res = RegSetValueExA(prodpatches, patch_squashed, 0, REG_SZ,
12567                          (const BYTE *)"transforms", 11);
12568     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12569 
12570     /* specific patch value exists */
12571     size = MAX_PATH;
12572     lstrcpyA(val, "apple");
12573     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12574                             MSIINSTALLCONTEXT_USERMANAGED,
12575                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12576     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12577     ok(!lstrcmpA(val, "apple"),
12578        "Expected val to be unchanged, got \"%s\"\n", val);
12579     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12580 
12581     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
12582     lstrcatA(keypath, usersid);
12583     lstrcatA(keypath, "\\Patches\\");
12584     lstrcatA(keypath, patch_squashed);
12585 
12586     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udpatch, NULL);
12587     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12588 
12589     /* UserData Patches key exists */
12590     size = MAX_PATH;
12591     lstrcpyA(val, "apple");
12592     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12593                             MSIINSTALLCONTEXT_USERMANAGED,
12594                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12595     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12596     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
12597     ok(size == 0, "Expected 0, got %d\n", size);
12598 
12599     res = RegSetValueExA(udpatch, "ManagedLocalPackage", 0, REG_SZ,
12600                          (const BYTE *)"pack", 5);
12601     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12602 
12603     /* ManagedLocalPatch value exists */
12604     size = MAX_PATH;
12605     lstrcpyA(val, "apple");
12606     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12607                             MSIINSTALLCONTEXT_USERMANAGED,
12608                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12609     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12610     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12611     ok(size == 4, "Expected 4, got %d\n", size);
12612 
12613     size = MAX_PATH;
12614     lstrcpyA(val, "apple");
12615     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12616                             MSIINSTALLCONTEXT_USERMANAGED,
12617                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12618     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12619     ok(!lstrcmpA(val, "transforms"), "Expected \"transforms\", got \"%s\"\n", val);
12620     ok(size == 10, "Expected 10, got %d\n", size);
12621 
12622     res = RegSetValueExA(hpatch, "Installed", 0, REG_SZ,
12623                          (const BYTE *)"mydate", 7);
12624     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12625 
12626     /* Installed value exists */
12627     size = MAX_PATH;
12628     lstrcpyA(val, "apple");
12629     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12630                             MSIINSTALLCONTEXT_USERMANAGED,
12631                             INSTALLPROPERTY_INSTALLDATEA, val, &size);
12632     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12633     ok(!lstrcmpA(val, "mydate"), "Expected \"mydate\", got \"%s\"\n", val);
12634     ok(size == 6, "Expected 6, got %d\n", size);
12635 
12636     res = RegSetValueExA(hpatch, "Uninstallable", 0, REG_SZ,
12637                          (const BYTE *)"yes", 4);
12638     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12639 
12640     /* Uninstallable value exists */
12641     size = MAX_PATH;
12642     lstrcpyA(val, "apple");
12643     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12644                             MSIINSTALLCONTEXT_USERMANAGED,
12645                             INSTALLPROPERTY_UNINSTALLABLEA, val, &size);
12646     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12647     ok(!lstrcmpA(val, "yes"), "Expected \"yes\", got \"%s\"\n", val);
12648     ok(size == 3, "Expected 3, got %d\n", size);
12649 
12650     res = RegSetValueExA(hpatch, "State", 0, REG_SZ,
12651                          (const BYTE *)"good", 5);
12652     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12653 
12654     /* State value exists */
12655     size = MAX_PATH;
12656     lstrcpyA(val, "apple");
12657     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12658                             MSIINSTALLCONTEXT_USERMANAGED,
12659                             INSTALLPROPERTY_PATCHSTATEA, val, &size);
12660     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12661     ok(!lstrcmpA(val, "good"), "Expected \"good\", got \"%s\"\n", val);
12662     ok(size == 4, "Expected 4, got %d\n", size);
12663 
12664     size = 1;
12665     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
12666                          (const BYTE *)&size, sizeof(DWORD));
12667     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12668 
12669     /* State value exists */
12670     size = MAX_PATH;
12671     lstrcpyA(val, "apple");
12672     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12673                             MSIINSTALLCONTEXT_USERMANAGED,
12674                             INSTALLPROPERTY_PATCHSTATEA, val, &size);
12675     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12676     ok(!lstrcmpA(val, "1"), "Expected \"1\", got \"%s\"\n", val);
12677     ok(size == 1, "Expected 1, got %d\n", size);
12678 
12679     size = 1;
12680     res = RegSetValueExA(hpatch, "Uninstallable", 0, REG_DWORD,
12681                          (const BYTE *)&size, sizeof(DWORD));
12682     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12683 
12684     /* Uninstallable value exists */
12685     size = MAX_PATH;
12686     lstrcpyA(val, "apple");
12687     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12688                             MSIINSTALLCONTEXT_USERMANAGED,
12689                             INSTALLPROPERTY_UNINSTALLABLEA, val, &size);
12690     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12691     ok(!lstrcmpA(val, "1"), "Expected \"1\", got \"%s\"\n", val);
12692     ok(size == 1, "Expected 1, got %d\n", size);
12693 
12694     res = RegSetValueExA(hpatch, "DisplayName", 0, REG_SZ,
12695                          (const BYTE *)"display", 8);
12696     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12697 
12698     /* DisplayName value exists */
12699     size = MAX_PATH;
12700     lstrcpyA(val, "apple");
12701     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12702                             MSIINSTALLCONTEXT_USERMANAGED,
12703                             INSTALLPROPERTY_DISPLAYNAMEA, val, &size);
12704     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12705     ok(!lstrcmpA(val, "display"), "Expected \"display\", got \"%s\"\n", val);
12706     ok(size == 7, "Expected 7, got %d\n", size);
12707 
12708     res = RegSetValueExA(hpatch, "MoreInfoURL", 0, REG_SZ,
12709                          (const BYTE *)"moreinfo", 9);
12710     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12711 
12712     /* MoreInfoURL value exists */
12713     size = MAX_PATH;
12714     lstrcpyA(val, "apple");
12715     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12716                             MSIINSTALLCONTEXT_USERMANAGED,
12717                             INSTALLPROPERTY_MOREINFOURLA, val, &size);
12718     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12719     ok(!lstrcmpA(val, "moreinfo"), "Expected \"moreinfo\", got \"%s\"\n", val);
12720     ok(size == 8, "Expected 8, got %d\n", size);
12721 
12722     /* szProperty is invalid */
12723     size = MAX_PATH;
12724     lstrcpyA(val, "apple");
12725     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12726                             MSIINSTALLCONTEXT_USERMANAGED,
12727                             "IDontExist", val, &size);
12728     ok(r == ERROR_UNKNOWN_PROPERTY,
12729        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
12730     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
12731     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
12732 
12733     /* lpValue is NULL, while pcchValue is non-NULL */
12734     size = MAX_PATH;
12735     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12736                             MSIINSTALLCONTEXT_USERMANAGED,
12737                             INSTALLPROPERTY_MOREINFOURLA, NULL, &size);
12738     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12739     ok(size == 16, "Expected 16, got %d\n", size);
12740 
12741     /* pcchValue is NULL, while lpValue is non-NULL */
12742     lstrcpyA(val, "apple");
12743     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12744                             MSIINSTALLCONTEXT_USERMANAGED,
12745                             INSTALLPROPERTY_MOREINFOURLA, val, NULL);
12746     ok(r == ERROR_INVALID_PARAMETER,
12747        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12748     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
12749 
12750     /* both lpValue and pcchValue are NULL */
12751     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12752                             MSIINSTALLCONTEXT_USERMANAGED,
12753                             INSTALLPROPERTY_MOREINFOURLA, NULL, NULL);
12754     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12755 
12756     /* pcchValue doesn't have enough room for NULL terminator */
12757     size = 8;
12758     lstrcpyA(val, "apple");
12759     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12760                             MSIINSTALLCONTEXT_USERMANAGED,
12761                             INSTALLPROPERTY_MOREINFOURLA, val, &size);
12762     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
12763     ok(!lstrcmpA(val, "moreinf"),
12764        "Expected \"moreinf\", got \"%s\"\n", val);
12765     ok(size == 16, "Expected 16, got %d\n", size);
12766 
12767     /* pcchValue has exactly enough room for NULL terminator */
12768     size = 9;
12769     lstrcpyA(val, "apple");
12770     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12771                             MSIINSTALLCONTEXT_USERMANAGED,
12772                             INSTALLPROPERTY_MOREINFOURLA, val, &size);
12773     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12774     ok(!lstrcmpA(val, "moreinfo"),
12775        "Expected \"moreinfo\", got \"%s\"\n", val);
12776     ok(size == 8, "Expected 8, got %d\n", size);
12777 
12778     /* pcchValue is too small, lpValue is NULL */
12779     size = 0;
12780     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12781                             MSIINSTALLCONTEXT_USERMANAGED,
12782                             INSTALLPROPERTY_MOREINFOURLA, NULL, &size);
12783     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12784     ok(size == 16, "Expected 16, got %d\n", size);
12785 
12786     RegDeleteValueA(prodpatches, patch_squashed);
12787     delete_key(prodpatches, "", access & KEY_WOW64_64KEY);
12788     RegCloseKey(prodpatches);
12789     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
12790     RegCloseKey(prodkey);
12791 
12792     /* UserData is sufficient for all properties
12793      * except INSTALLPROPERTY_TRANSFORMS
12794      */
12795     size = MAX_PATH;
12796     lstrcpyA(val, "apple");
12797     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12798                             MSIINSTALLCONTEXT_USERMANAGED,
12799                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12800     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12801     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12802     ok(size == 4, "Expected 4, got %d\n", size);
12803 
12804     /* UserData is sufficient for all properties
12805      * except INSTALLPROPERTY_TRANSFORMS
12806      */
12807     size = MAX_PATH;
12808     lstrcpyA(val, "apple");
12809     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12810                             MSIINSTALLCONTEXT_USERMANAGED,
12811                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12812     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12813     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
12814     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
12815 
12816     RegDeleteValueA(hpatch, "MoreInfoURL");
12817     RegDeleteValueA(hpatch, "Display");
12818     RegDeleteValueA(hpatch, "State");
12819     RegDeleteValueA(hpatch, "Uninstallable");
12820     RegDeleteValueA(hpatch, "Installed");
12821     RegDeleteValueA(udpatch, "ManagedLocalPackage");
12822     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
12823     RegCloseKey(udpatch);
12824     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
12825     RegCloseKey(hpatch);
12826     delete_key(patches, "", access & KEY_WOW64_64KEY);
12827     RegCloseKey(patches);
12828     delete_key(props, "", access & KEY_WOW64_64KEY);
12829     RegCloseKey(props);
12830     delete_key(udprod, "", access & KEY_WOW64_64KEY);
12831     RegCloseKey(udprod);
12832 
12833     /* MSIINSTALLCONTEXT_USERUNMANAGED */
12834 
12835     size = MAX_PATH;
12836     lstrcpyA(val, "apple");
12837     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12838                             MSIINSTALLCONTEXT_USERUNMANAGED,
12839                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12840     ok(r == ERROR_UNKNOWN_PRODUCT,
12841        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12842     ok(!lstrcmpA(val, "apple"),
12843        "Expected val to be unchanged, got \"%s\"\n", val);
12844     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12845 
12846     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
12847     lstrcatA(keypath, usersid);
12848     lstrcatA(keypath, "\\Products\\");
12849     lstrcatA(keypath, prod_squashed);
12850 
12851     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
12852     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12853 
12854     /* local UserData product key exists */
12855     size = MAX_PATH;
12856     lstrcpyA(val, "apple");
12857     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12858                             MSIINSTALLCONTEXT_USERUNMANAGED,
12859                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12860     ok(r == ERROR_UNKNOWN_PRODUCT,
12861        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12862     ok(!lstrcmpA(val, "apple"),
12863        "Expected val to be unchanged, got \"%s\"\n", val);
12864     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12865 
12866     res = RegCreateKeyExA(udprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
12867     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12868 
12869     /* InstallProperties key exists */
12870     size = MAX_PATH;
12871     lstrcpyA(val, "apple");
12872     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12873                             MSIINSTALLCONTEXT_USERUNMANAGED,
12874                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12875     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12876     ok(!lstrcmpA(val, "apple"),
12877        "Expected val to be unchanged, got \"%s\"\n", val);
12878     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12879 
12880     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
12881     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12882 
12883     /* Patches key exists */
12884     size = MAX_PATH;
12885     lstrcpyA(val, "apple");
12886     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12887                             MSIINSTALLCONTEXT_USERUNMANAGED,
12888                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12889     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12890     ok(!lstrcmpA(val, "apple"),
12891        "Expected val to be unchanged, got \"%s\"\n", val);
12892     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12893 
12894     res = RegCreateKeyExA(patches, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
12895     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12896 
12897     /* Patches key exists */
12898     size = MAX_PATH;
12899     lstrcpyA(val, "apple");
12900     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12901                             MSIINSTALLCONTEXT_USERUNMANAGED,
12902                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12903     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12904     ok(!lstrcmpA(val, "apple"),
12905        "Expected val to be unchanged, got \"%s\"\n", val);
12906     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12907 
12908     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
12909     lstrcatA(keypath, prod_squashed);
12910 
12911     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
12912     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12913 
12914     /* current user product key exists */
12915     size = MAX_PATH;
12916     lstrcpyA(val, "apple");
12917     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12918                             MSIINSTALLCONTEXT_USERUNMANAGED,
12919                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12920     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12921     ok(!lstrcmpA(val, "apple"),
12922        "Expected val to be unchanged, got \"%s\"\n", val);
12923     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12924 
12925     res = RegCreateKeyA(prodkey, "Patches", &prodpatches);
12926     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12927 
12928     /* Patches key exists */
12929     size = MAX_PATH;
12930     lstrcpyA(val, "apple");
12931     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12932                             MSIINSTALLCONTEXT_USERUNMANAGED,
12933                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12934     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12935     ok(!lstrcmpA(val, "apple"),
12936        "Expected val to be unchanged, got \"%s\"\n", val);
12937     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12938 
12939     res = RegSetValueExA(prodpatches, patch_squashed, 0, REG_SZ,
12940                          (const BYTE *)"transforms", 11);
12941     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12942 
12943     /* specific patch value exists */
12944     size = MAX_PATH;
12945     lstrcpyA(val, "apple");
12946     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12947                             MSIINSTALLCONTEXT_USERUNMANAGED,
12948                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12949     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12950     ok(!lstrcmpA(val, "apple"),
12951        "Expected val to be unchanged, got \"%s\"\n", val);
12952     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12953 
12954     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
12955     lstrcatA(keypath, usersid);
12956     lstrcatA(keypath, "\\Patches\\");
12957     lstrcatA(keypath, patch_squashed);
12958 
12959     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udpatch, NULL);
12960     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12961 
12962     /* UserData Patches key exists */
12963     size = MAX_PATH;
12964     lstrcpyA(val, "apple");
12965     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12966                             MSIINSTALLCONTEXT_USERUNMANAGED,
12967                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12968     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12969     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
12970     ok(size == 0, "Expected 0, got %d\n", size);
12971 
12972     res = RegSetValueExA(udpatch, "LocalPackage", 0, REG_SZ,
12973                          (const BYTE *)"pack", 5);
12974     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12975 
12976     /* LocalPatch value exists */
12977     size = MAX_PATH;
12978     lstrcpyA(val, "apple");
12979     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12980                             MSIINSTALLCONTEXT_USERUNMANAGED,
12981                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12982     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12983     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12984     ok(size == 4, "Expected 4, got %d\n", size);
12985 
12986     size = MAX_PATH;
12987     lstrcpyA(val, "apple");
12988     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12989                             MSIINSTALLCONTEXT_USERUNMANAGED,
12990                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12991     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12992     ok(!lstrcmpA(val, "transforms"), "Expected \"transforms\", got \"%s\"\n", val);
12993     ok(size == 10, "Expected 10, got %d\n", size);
12994 
12995     RegDeleteValueA(prodpatches, patch_squashed);
12996     delete_key(prodpatches, "", access & KEY_WOW64_64KEY);
12997     RegCloseKey(prodpatches);
12998     RegDeleteKeyA(prodkey, "");
12999     RegCloseKey(prodkey);
13000 
13001     /* UserData is sufficient for all properties
13002      * except INSTALLPROPERTY_TRANSFORMS
13003      */
13004     size = MAX_PATH;
13005     lstrcpyA(val, "apple");
13006     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
13007                             MSIINSTALLCONTEXT_USERUNMANAGED,
13008                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13009     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13010     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
13011     ok(size == 4, "Expected 4, got %d\n", size);
13012 
13013     /* UserData is sufficient for all properties
13014      * except INSTALLPROPERTY_TRANSFORMS
13015      */
13016     size = MAX_PATH;
13017     lstrcpyA(val, "apple");
13018     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
13019                             MSIINSTALLCONTEXT_USERUNMANAGED,
13020                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
13021     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
13022     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
13023     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
13024 
13025     RegDeleteValueA(udpatch, "LocalPackage");
13026     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
13027     RegCloseKey(udpatch);
13028     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
13029     RegCloseKey(hpatch);
13030     delete_key(patches, "", access & KEY_WOW64_64KEY);
13031     RegCloseKey(patches);
13032     delete_key(props, "", access & KEY_WOW64_64KEY);
13033     RegCloseKey(props);
13034     delete_key(udprod, "", access & KEY_WOW64_64KEY);
13035     RegCloseKey(udprod);
13036 
13037     /* MSIINSTALLCONTEXT_MACHINE */
13038 
13039     size = MAX_PATH;
13040     lstrcpyA(val, "apple");
13041     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13042                             MSIINSTALLCONTEXT_MACHINE,
13043                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13044     ok(r == ERROR_UNKNOWN_PRODUCT,
13045        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
13046     ok(!lstrcmpA(val, "apple"),
13047        "Expected val to be unchanged, got \"%s\"\n", val);
13048     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
13049 
13050     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
13051     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Products\\");
13052     lstrcatA(keypath, prod_squashed);
13053 
13054     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
13055     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13056 
13057     /* local UserData product key exists */
13058     size = MAX_PATH;
13059     lstrcpyA(val, "apple");
13060     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13061                             MSIINSTALLCONTEXT_MACHINE,
13062                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13063     ok(r == ERROR_UNKNOWN_PRODUCT,
13064        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
13065     ok(!lstrcmpA(val, "apple"),
13066        "Expected val to be unchanged, got \"%s\"\n", val);
13067     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
13068 
13069     res = RegCreateKeyExA(udprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
13070     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13071 
13072     /* InstallProperties key exists */
13073     size = MAX_PATH;
13074     lstrcpyA(val, "apple");
13075     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13076                             MSIINSTALLCONTEXT_MACHINE,
13077                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13078     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
13079     ok(!lstrcmpA(val, "apple"),
13080        "Expected val to be unchanged, got \"%s\"\n", val);
13081     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
13082 
13083     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
13084     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13085 
13086     /* Patches key exists */
13087     size = MAX_PATH;
13088     lstrcpyA(val, "apple");
13089     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13090                             MSIINSTALLCONTEXT_MACHINE,
13091                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13092     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
13093     ok(!lstrcmpA(val, "apple"),
13094        "Expected val to be unchanged, got \"%s\"\n", val);
13095     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
13096 
13097     res = RegCreateKeyExA(patches, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
13098     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13099 
13100     /* Patches key exists */
13101     size = MAX_PATH;
13102     lstrcpyA(val, "apple");
13103     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13104                             MSIINSTALLCONTEXT_MACHINE,
13105                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13106     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
13107     ok(!lstrcmpA(val, "apple"),
13108        "Expected val to be unchanged, got \"%s\"\n", val);
13109     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
13110 
13111     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
13112     lstrcatA(keypath, prod_squashed);
13113 
13114     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
13115     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13116 
13117     /* local product key exists */
13118     size = MAX_PATH;
13119     lstrcpyA(val, "apple");
13120     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13121                             MSIINSTALLCONTEXT_MACHINE,
13122                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13123     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
13124     ok(!lstrcmpA(val, "apple"),
13125        "Expected val to be unchanged, got \"%s\"\n", val);
13126     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
13127 
13128     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &prodpatches, NULL);
13129     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13130 
13131     /* Patches key exists */
13132     size = MAX_PATH;
13133     lstrcpyA(val, "apple");
13134     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13135                             MSIINSTALLCONTEXT_MACHINE,
13136                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13137     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
13138     ok(!lstrcmpA(val, "apple"),
13139        "Expected val to be unchanged, got \"%s\"\n", val);
13140     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
13141 
13142     res = RegSetValueExA(prodpatches, patch_squashed, 0, REG_SZ,
13143                          (const BYTE *)"transforms", 11);
13144     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13145 
13146     /* specific patch value exists */
13147     size = MAX_PATH;
13148     lstrcpyA(val, "apple");
13149     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13150                             MSIINSTALLCONTEXT_MACHINE,
13151                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13152     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
13153     ok(!lstrcmpA(val, "apple"),
13154        "Expected val to be unchanged, got \"%s\"\n", val);
13155     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
13156 
13157     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
13158     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Patches\\");
13159     lstrcatA(keypath, patch_squashed);
13160 
13161     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udpatch, NULL);
13162     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13163 
13164     /* UserData Patches key exists */
13165     size = MAX_PATH;
13166     lstrcpyA(val, "apple");
13167     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13168                             MSIINSTALLCONTEXT_MACHINE,
13169                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13170     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13171     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
13172     ok(size == 0, "Expected 0, got %d\n", size);
13173 
13174     res = RegSetValueExA(udpatch, "LocalPackage", 0, REG_SZ,
13175                          (const BYTE *)"pack", 5);
13176     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13177 
13178     /* LocalPatch value exists */
13179     size = MAX_PATH;
13180     lstrcpyA(val, "apple");
13181     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13182                             MSIINSTALLCONTEXT_MACHINE,
13183                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13184     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13185     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
13186     ok(size == 4, "Expected 4, got %d\n", size);
13187 
13188     size = MAX_PATH;
13189     lstrcpyA(val, "apple");
13190     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13191                             MSIINSTALLCONTEXT_MACHINE,
13192                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
13193     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13194     ok(!lstrcmpA(val, "transforms"), "Expected \"transforms\", got \"%s\"\n", val);
13195     ok(size == 10, "Expected 10, got %d\n", size);
13196 
13197     RegDeleteValueA(prodpatches, patch_squashed);
13198     delete_key(prodpatches, "", access & KEY_WOW64_64KEY);
13199     RegCloseKey(prodpatches);
13200     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
13201     RegCloseKey(prodkey);
13202 
13203     /* UserData is sufficient for all properties
13204      * except INSTALLPROPERTY_TRANSFORMS
13205      */
13206     size = MAX_PATH;
13207     lstrcpyA(val, "apple");
13208     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13209                             MSIINSTALLCONTEXT_MACHINE,
13210                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13211     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13212     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
13213     ok(size == 4, "Expected 4, got %d\n", size);
13214 
13215     /* UserData is sufficient for all properties
13216      * except INSTALLPROPERTY_TRANSFORMS
13217      */
13218     size = MAX_PATH;
13219     lstrcpyA(val, "apple");
13220     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13221                             MSIINSTALLCONTEXT_MACHINE,
13222                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
13223     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
13224     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
13225     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
13226 
13227     RegDeleteValueA(udpatch, "LocalPackage");
13228     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
13229     RegCloseKey(udpatch);
13230     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
13231     RegCloseKey(hpatch);
13232     delete_key(patches, "", access & KEY_WOW64_64KEY);
13233     RegCloseKey(patches);
13234     delete_key(props, "", access & KEY_WOW64_64KEY);
13235     RegCloseKey(props);
13236     delete_key(udprod, "", access & KEY_WOW64_64KEY);
13237     RegCloseKey(udprod);
13238     LocalFree(usersid);
13239 }
13240 
13241 static void test_MsiGetPatchInfo(void)
13242 {
13243     UINT r;
13244     char prod_code[MAX_PATH], prod_squashed[MAX_PATH], val[MAX_PATH];
13245     char patch_code[MAX_PATH], patch_squashed[MAX_PATH], keypath[MAX_PATH];
13246     WCHAR valW[MAX_PATH], patch_codeW[MAX_PATH];
13247     HKEY hkey_product, hkey_patch, hkey_patches, hkey_udprops, hkey_udproduct;
13248     HKEY hkey_udpatch, hkey_udpatches, hkey_udproductpatches, hkey_udproductpatch;
13249     DWORD size;
13250     LONG res;
13251     REGSAM access = KEY_ALL_ACCESS;
13252 
13253     create_test_guid(patch_code, patch_squashed);
13254     create_test_guid(prod_code, prod_squashed);
13255     MultiByteToWideChar(CP_ACP, 0, patch_code, -1, patch_codeW, MAX_PATH);
13256 
13257     if (is_wow64)
13258         access |= KEY_WOW64_64KEY;
13259 
13260     r = MsiGetPatchInfoA(NULL, NULL, NULL, NULL);
13261     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
13262 
13263     r = MsiGetPatchInfoA(patch_code, NULL, NULL, NULL);
13264     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
13265 
13266     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, NULL, NULL);
13267     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
13268 
13269     size = 0;
13270     r = MsiGetPatchInfoA(patch_code, NULL, NULL, &size);
13271     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
13272 
13273     r = MsiGetPatchInfoA(patch_code, "", NULL, &size);
13274     ok(r == ERROR_UNKNOWN_PROPERTY, "expected ERROR_UNKNOWN_PROPERTY, got %u\n", r);
13275 
13276     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
13277     lstrcatA(keypath, prod_squashed);
13278 
13279     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey_product, NULL);
13280     if (res == ERROR_ACCESS_DENIED)
13281     {
13282         skip("Not enough rights to perform tests\n");
13283         return;
13284     }
13285     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13286 
13287     /* product 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_product, "Patches", 0, NULL, 0, access, NULL, &hkey_patches, NULL);
13296     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13297 
13298     /* patches 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     res = RegCreateKeyExA(hkey_patches, patch_squashed, 0, NULL, 0, access, NULL, &hkey_patch, NULL);
13307     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13308 
13309     /* patch key exists */
13310     size = MAX_PATH;
13311     lstrcpyA(val, "apple");
13312     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13313     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13314     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
13315     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
13316 
13317     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
13318     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Products\\");
13319     lstrcatA(keypath, prod_squashed);
13320 
13321     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey_udproduct, NULL);
13322     if (res == ERROR_ACCESS_DENIED)
13323     {
13324         skip("Not enough rights to perform tests\n");
13325         goto done;
13326     }
13327     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
13328 
13329     /* UserData product 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, "InstallProperties", 0, NULL, 0, access, NULL, &hkey_udprops, NULL);
13338     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13339 
13340     /* InstallProperties 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_udpatches, NULL);
13349     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13350 
13351     /* UserData Patches key exists */
13352     size = MAX_PATH;
13353     lstrcpyA(val, "apple");
13354     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13355     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13356     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
13357     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
13358 
13359     res = RegCreateKeyExA(hkey_udproduct, "Patches", 0, NULL, 0, access, NULL, &hkey_udproductpatches, NULL);
13360     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13361 
13362     res = RegCreateKeyExA(hkey_udproductpatches, patch_squashed, 0, NULL, 0, access, NULL, &hkey_udproductpatch, NULL);
13363     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13364 
13365     /* UserData product patch key exists */
13366     size = MAX_PATH;
13367     lstrcpyA(val, "apple");
13368     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13369     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13370     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
13371     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
13372 
13373     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
13374     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Patches\\");
13375     lstrcatA(keypath, patch_squashed);
13376 
13377     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey_udpatch, NULL);
13378     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13379 
13380     res = RegSetValueExA(hkey_udpatch, "LocalPackage", 0, REG_SZ, (const BYTE *)"c:\\test.msp", 12);
13381     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13382 
13383     /* UserData Patch key exists */
13384     size = 0;
13385     lstrcpyA(val, "apple");
13386     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13387     ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", r);
13388     ok(!lstrcmpA(val, "apple"), "expected \"apple\", got \"%s\"\n", val);
13389     ok(size == 11, "expected 11 got %u\n", size);
13390 
13391     size = MAX_PATH;
13392     lstrcpyA(val, "apple");
13393     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13394     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS got %u\n", r);
13395     ok(!lstrcmpA(val, "c:\\test.msp"), "expected \"c:\\test.msp\", got \"%s\"\n", val);
13396     ok(size == 11, "expected 11 got %u\n", size);
13397 
13398     size = 0;
13399     valW[0] = 0;
13400     r = MsiGetPatchInfoW(patch_codeW, INSTALLPROPERTY_LOCALPACKAGEW, valW, &size);
13401     ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", r);
13402     ok(!valW[0], "expected 0 got %u\n", valW[0]);
13403     ok(size == 11, "expected 11 got %u\n", size);
13404 
13405     size = MAX_PATH;
13406     valW[0] = 0;
13407     r = MsiGetPatchInfoW(patch_codeW, INSTALLPROPERTY_LOCALPACKAGEW, valW, &size);
13408     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS got %u\n", r);
13409     ok(valW[0], "expected > 0 got %u\n", valW[0]);
13410     ok(size == 11, "expected 11 got %u\n", size);
13411 
13412     delete_key(hkey_udproductpatch, "", access & KEY_WOW64_64KEY);
13413     RegCloseKey(hkey_udproductpatch);
13414     delete_key(hkey_udproductpatches, "", access & KEY_WOW64_64KEY);
13415     RegCloseKey(hkey_udproductpatches);
13416     delete_key(hkey_udpatch, "", access & KEY_WOW64_64KEY);
13417     RegCloseKey(hkey_udpatch);
13418     delete_key(hkey_udpatches, "", access & KEY_WOW64_64KEY);
13419     RegCloseKey(hkey_udpatches);
13420     delete_key(hkey_udprops, "", access & KEY_WOW64_64KEY);
13421     RegCloseKey(hkey_udprops);
13422     delete_key(hkey_udproduct, "", access & KEY_WOW64_64KEY);
13423     RegCloseKey(hkey_udproduct);
13424 
13425 done:
13426     delete_key(hkey_patches, "", access & KEY_WOW64_64KEY);
13427     RegCloseKey(hkey_patches);
13428     delete_key(hkey_product, "", access & KEY_WOW64_64KEY);
13429     RegCloseKey(hkey_product);
13430     delete_key(hkey_patch, "", access & KEY_WOW64_64KEY);
13431     RegCloseKey(hkey_patch);
13432 }
13433 
13434 static void test_MsiEnumProducts(void)
13435 {
13436     UINT r;
13437     BOOL found1, found2, found3;
13438     DWORD index;
13439     char product1[39], product2[39], product3[39], guid[39];
13440     char product_squashed1[33], product_squashed2[33], product_squashed3[33];
13441     char keypath1[MAX_PATH], keypath2[MAX_PATH], keypath3[MAX_PATH];
13442     char *usersid;
13443     HKEY key1, key2, key3;
13444     REGSAM access = KEY_ALL_ACCESS;
13445 
13446     create_test_guid(product1, product_squashed1);
13447     create_test_guid(product2, product_squashed2);
13448     create_test_guid(product3, product_squashed3);
13449     usersid = get_user_sid();
13450 
13451     if (is_wow64)
13452         access |= KEY_WOW64_64KEY;
13453 
13454     strcpy(keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
13455     strcat(keypath2, usersid);
13456     strcat(keypath2, "\\Installer\\Products\\");
13457     strcat(keypath2, product_squashed2);
13458 
13459     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL);
13460     if (r == ERROR_ACCESS_DENIED)
13461     {
13462         skip("Not enough rights to perform tests\n");
13463         LocalFree(usersid);
13464         return;
13465     }
13466     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13467 
13468     strcpy(keypath1, "Software\\Classes\\Installer\\Products\\");
13469     strcat(keypath1, product_squashed1);
13470 
13471     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL);
13472     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13473 
13474     strcpy(keypath3, "Software\\Microsoft\\Installer\\Products\\");
13475     strcat(keypath3, product_squashed3);
13476 
13477     r = RegCreateKeyA(HKEY_CURRENT_USER, keypath3, &key3);
13478     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\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     r = MsiEnumProductsA(index, NULL);
13485     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
13486 
13487     index = 2;
13488     r = MsiEnumProductsA(index, guid);
13489     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
13490 
13491     index = 0;
13492     r = MsiEnumProductsA(index, guid);
13493     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13494 
13495     found1 = found2 = found3 = FALSE;
13496     while ((r = MsiEnumProductsA(index, guid)) == ERROR_SUCCESS)
13497     {
13498         if (!strcmp(product1, guid)) found1 = TRUE;
13499         if (!strcmp(product2, guid)) found2 = TRUE;
13500         if (!strcmp(product3, guid)) found3 = TRUE;
13501         index++;
13502     }
13503     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %u\n", r);
13504     ok(found1, "product1 not found\n");
13505     ok(found2, "product2 not found\n");
13506     ok(found3, "product3 not found\n");
13507 
13508     delete_key(key1, "", access & KEY_WOW64_64KEY);
13509     delete_key(key2, "", access & KEY_WOW64_64KEY);
13510     RegDeleteKeyA(key3, "");
13511     RegCloseKey(key1);
13512     RegCloseKey(key2);
13513     RegCloseKey(key3);
13514     LocalFree(usersid);
13515 }
13516 
13517 static void test_MsiGetFileSignatureInformation(void)
13518 {
13519     HRESULT hr;
13520     const CERT_CONTEXT *cert;
13521     DWORD len;
13522 
13523     hr = MsiGetFileSignatureInformationA( NULL, 0, NULL, NULL, NULL );
13524     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13525 
13526     hr = MsiGetFileSignatureInformationA( NULL, 0, NULL, NULL, &len );
13527     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13528 
13529     hr = MsiGetFileSignatureInformationA( NULL, 0, &cert, NULL, &len );
13530     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13531 
13532     hr = MsiGetFileSignatureInformationA( "", 0, NULL, NULL, NULL );
13533     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
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     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, &cert, NULL, &len );
13542     todo_wine ok(hr == CRYPT_E_FILE_ERROR, "expected CRYPT_E_FILE_ERROR got 0x%08x\n", hr);
13543 
13544     create_file( "signature.bin", "signature", sizeof("signature") );
13545 
13546     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, NULL );
13547     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13548 
13549     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, &len );
13550     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13551 
13552     cert = (const CERT_CONTEXT *)0xdeadbeef;
13553     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, &cert, NULL, &len );
13554     todo_wine ok(hr == HRESULT_FROM_WIN32(ERROR_FUNCTION_FAILED), "got 0x%08x\n", hr);
13555     ok(cert == NULL, "got %p\n", cert);
13556 
13557     DeleteFileA( "signature.bin" );
13558 }
13559 
13560 static void test_MsiEnumProductsEx(void)
13561 {
13562     UINT r;
13563     DWORD len, index;
13564     MSIINSTALLCONTEXT context;
13565     char product0[39], product1[39], product2[39], product3[39], guid[39], sid[128];
13566     char product_squashed1[33], product_squashed2[33], product_squashed3[33];
13567     char keypath1[MAX_PATH], keypath2[MAX_PATH], keypath3[MAX_PATH];
13568     HKEY key1 = NULL, key2 = NULL, key3 = NULL;
13569     REGSAM access = KEY_ALL_ACCESS;
13570     char *usersid = get_user_sid();
13571 
13572     if (!pMsiEnumProductsExA)
13573     {
13574         win_skip("MsiEnumProductsExA not implemented\n");
13575         return;
13576     }
13577 
13578     create_test_guid( product0, NULL );
13579     create_test_guid( product1, product_squashed1 );
13580     create_test_guid( product2, product_squashed2 );
13581     create_test_guid( product3, product_squashed3 );
13582 
13583     if (is_wow64) access |= KEY_WOW64_64KEY;
13584 
13585     strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\" );
13586     strcat( keypath2, usersid );
13587     strcat( keypath2, "\\Installer\\Products\\" );
13588     strcat( keypath2, product_squashed2 );
13589 
13590     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
13591     if (r == ERROR_ACCESS_DENIED)
13592     {
13593         skip( "insufficient rights\n" );
13594         goto done;
13595     }
13596     ok( r == ERROR_SUCCESS, "got %u\n", r );
13597 
13598     strcpy( keypath1, "Software\\Classes\\Installer\\Products\\" );
13599     strcat( keypath1, product_squashed1 );
13600 
13601     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
13602     ok( r == ERROR_SUCCESS, "got %u\n", r );
13603 
13604     strcpy( keypath3, usersid );
13605     strcat( keypath3, "\\Software\\Microsoft\\Installer\\Products\\" );
13606     strcat( keypath3, product_squashed3 );
13607 
13608     r = RegCreateKeyExA( HKEY_USERS, keypath3, 0, NULL, 0, access, NULL, &key3, NULL );
13609     ok( r == ERROR_SUCCESS, "got %u\n", r );
13610 
13611     r = pMsiEnumProductsExA( NULL, NULL, 0, 0, NULL, NULL, NULL, NULL );
13612     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13613 
13614     len = sizeof(sid);
13615     r = pMsiEnumProductsExA( NULL, NULL, 0, 0, NULL, NULL, NULL, &len );
13616     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13617     ok( len == sizeof(sid), "got %u\n", len );
13618 
13619     r = pMsiEnumProductsExA( NULL, NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, NULL, NULL );
13620     ok( r == ERROR_SUCCESS, "got %u\n", r );
13621 
13622     sid[0] = 0;
13623     len = sizeof(sid);
13624     r = pMsiEnumProductsExA( product0, NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, &len );
13625     ok( r == ERROR_NO_MORE_ITEMS, "got %u\n", r );
13626     ok( len == sizeof(sid), "got %u\n", len );
13627     ok( !sid[0], "got %s\n", sid );
13628 
13629     sid[0] = 0;
13630     len = sizeof(sid);
13631     r = pMsiEnumProductsExA( product0, usersid, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, &len );
13632     ok( r == ERROR_NO_MORE_ITEMS, "got %u\n", r );
13633     ok( len == sizeof(sid), "got %u\n", len );
13634     ok( !sid[0], "got %s\n", sid );
13635 
13636     sid[0] = 0;
13637     len = 0;
13638     r = pMsiEnumProductsExA( NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, 0, NULL, NULL, sid, &len );
13639     ok( r == ERROR_MORE_DATA, "got %u\n", r );
13640     ok( len, "length unchanged\n" );
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, NULL, 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, usersid, MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
13659     ok( r == ERROR_SUCCESS, "got %u\n", r );
13660     ok( guid[0], "empty guid\n" );
13661     ok( context != 0xdeadbeef, "context unchanged\n" );
13662     ok( !len, "got %u\n", len );
13663     ok( !sid[0], "got %s\n", sid );
13664 
13665     guid[0] = 0;
13666     context = 0xdeadbeef;
13667     sid[0] = 0;
13668     len = sizeof(sid);
13669     r = pMsiEnumProductsExA( NULL, "S-1-1-0", MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
13670     if (r == ERROR_ACCESS_DENIED)
13671     {
13672         skip( "insufficient rights\n" );
13673         goto done;
13674     }
13675     ok( r == ERROR_SUCCESS, "got %u\n", r );
13676     ok( guid[0], "empty guid\n" );
13677     ok( context != 0xdeadbeef, "context unchanged\n" );
13678     ok( !len, "got %u\n", len );
13679     ok( !sid[0], "got %s\n", sid );
13680 
13681     index = 0;
13682     guid[0] = 0;
13683     context = 0xdeadbeef;
13684     sid[0] = 0;
13685     len = sizeof(sid);
13686     while (!pMsiEnumProductsExA( NULL, "S-1-1-0", MSIINSTALLCONTEXT_ALL, index, guid, &context, sid, &len ))
13687     {
13688         if (!strcmp( product1, guid ))
13689         {
13690             ok( context == MSIINSTALLCONTEXT_MACHINE, "got %u\n", context );
13691             ok( !sid[0], "got \"%s\"\n", sid );
13692             ok( !len, "unexpected length %u\n", len );
13693         }
13694         if (!strcmp( product2, guid ))
13695         {
13696             ok( context == MSIINSTALLCONTEXT_USERMANAGED, "got %u\n", context );
13697             ok( sid[0], "empty sid\n" );
13698             ok( len == strlen(sid), "unexpected length %u\n", len );
13699         }
13700         if (!strcmp( product3, guid ))
13701         {
13702             ok( context == MSIINSTALLCONTEXT_USERUNMANAGED, "got %u\n", context );
13703             ok( sid[0], "empty sid\n" );
13704             ok( len == strlen(sid), "unexpected length %u\n", len );
13705         }
13706         index++;
13707         guid[0] = 0;
13708         context = 0xdeadbeef;
13709         sid[0] = 0;
13710         len = sizeof(sid);
13711     }
13712 
13713 done:
13714     delete_key( key1, "", access );
13715     delete_key( key2, "", access );
13716     delete_key( key3, "", access );
13717     RegCloseKey( key1 );
13718     RegCloseKey( key2 );
13719     RegCloseKey( key3 );
13720     LocalFree( usersid );
13721 }
13722 
13723 static void test_MsiEnumComponents(void)
13724 {
13725     UINT r;
13726     BOOL found1, found2;
13727     DWORD index;
13728     char comp1[39], comp2[39], guid[39];
13729     char comp_squashed1[33], comp_squashed2[33];
13730     char keypath1[MAX_PATH], keypath2[MAX_PATH];
13731     REGSAM access = KEY_ALL_ACCESS;
13732     char *usersid = get_user_sid();
13733     HKEY key1 = NULL, key2 = NULL;
13734 
13735     create_test_guid( comp1, comp_squashed1 );
13736     create_test_guid( comp2, comp_squashed2 );
13737 
13738     if (is_wow64) access |= KEY_WOW64_64KEY;
13739 
13740     strcpy( keypath1, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
13741     strcat( keypath1, "S-1-5-18\\Components\\" );
13742     strcat( keypath1, comp_squashed1 );
13743 
13744     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
13745     if (r == ERROR_ACCESS_DENIED)
13746     {
13747         skip( "insufficient rights\n" );
13748         goto done;
13749     }
13750     ok( r == ERROR_SUCCESS, "got %u\n", r );
13751 
13752     strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
13753     strcat( keypath2, usersid );
13754     strcat( keypath2, "\\Components\\" );
13755     strcat( keypath2, comp_squashed2 );
13756 
13757     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
13758     if (r == ERROR_ACCESS_DENIED)
13759     {
13760         skip( "insufficient rights\n" );
13761         goto done;
13762     }
13763 
13764     r = MsiEnumComponentsA( 0, NULL );
13765     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13766 
13767     index = 0;
13768     guid[0] = 0;
13769     found1 = found2 = FALSE;
13770     while (!MsiEnumComponentsA( index, guid ))
13771     {
13772         if (!strcmp( guid, comp1 )) found1 = TRUE;
13773         if (!strcmp( guid, comp2 )) found2 = TRUE;
13774         ok( guid[0], "empty guid\n" );
13775         guid[0] = 0;
13776         index++;
13777     }
13778     ok( found1, "comp1 not found\n" );
13779     ok( found2, "comp2 not found\n" );
13780 
13781 done:
13782     delete_key( key1, "", access );
13783     delete_key( key2, "", access );
13784     RegCloseKey( key1 );
13785     RegCloseKey( key2 );
13786     LocalFree( usersid );
13787 }
13788 
13789 static void test_MsiEnumComponentsEx(void)
13790 {
13791     UINT r;
13792     BOOL found1, found2;
13793     DWORD len, index;
13794     MSIINSTALLCONTEXT context;
13795     char comp1[39], comp2[39], guid[39], sid[128];
13796     char comp_squashed1[33], comp_squashed2[33];
13797     char keypath1[MAX_PATH], keypath2[MAX_PATH];
13798     HKEY key1 = NULL, key2 = NULL;
13799     REGSAM access = KEY_ALL_ACCESS;
13800     char *usersid = get_user_sid();
13801 
13802     if (!pMsiEnumComponentsExA)
13803     {
13804         win_skip( "MsiEnumComponentsExA not implemented\n" );
13805         return;
13806     }
13807     create_test_guid( comp1, comp_squashed1 );
13808     create_test_guid( comp2, comp_squashed2 );
13809 
13810     if (is_wow64) access |= KEY_WOW64_64KEY;
13811 
13812     strcpy( keypath1, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
13813     strcat( keypath1, "S-1-5-18\\Components\\" );
13814     strcat( keypath1, comp_squashed1 );
13815 
13816     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
13817     if (r == ERROR_ACCESS_DENIED)
13818     {
13819         skip( "insufficient rights\n" );
13820         goto done;
13821     }
13822     ok( r == ERROR_SUCCESS, "got %u\n", r );
13823 
13824     strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
13825     strcat( keypath2, usersid );
13826     strcat( keypath2, "\\Components\\" );
13827     strcat( keypath2, comp_squashed2 );
13828 
13829     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
13830     if (r == ERROR_ACCESS_DENIED)
13831     {
13832         skip( "insufficient rights\n" );
13833         goto done;
13834     }
13835     ok( r == ERROR_SUCCESS, "got %u\n", r );
13836     r = RegSetValueExA( key2, comp_squashed2, 0, REG_SZ, (const BYTE *)"c:\\doesnotexist",
13837                         sizeof("c:\\doesnotexist"));
13838     ok( r == ERROR_SUCCESS, "got %u\n", r );
13839 
13840     index = 0;
13841     guid[0] = 0;
13842     context = 0xdeadbeef;
13843     sid[0] = 0;
13844     len = sizeof(sid);
13845     found1 = found2 = FALSE;
13846     while (!pMsiEnumComponentsExA( "S-1-1-0", MSIINSTALLCONTEXT_ALL, index, guid, &context, sid, &len ))
13847     {
13848         if (!strcmp( comp1, guid ))
13849         {
13850             ok( context == MSIINSTALLCONTEXT_MACHINE, "got %u\n", context );
13851             ok( !sid[0], "got \"%s\"\n", sid );
13852             ok( !len, "unexpected length %u\n", len );
13853             found1 = TRUE;
13854         }
13855         if (!strcmp( comp2, guid ))
13856         {
13857             ok( context == MSIINSTALLCONTEXT_USERUNMANAGED, "got %u\n", context );
13858             ok( sid[0], "empty sid\n" );
13859             ok( len == strlen(sid), "unexpected length %u\n", len );
13860             found2 = TRUE;
13861         }
13862         index++;
13863         guid[0] = 0;
13864         context = 0xdeadbeef;
13865         sid[0] = 0;
13866         len = sizeof(sid);
13867     }
13868     ok( found1, "comp1 not found\n" );
13869     ok( found2, "comp2 not found\n" );
13870 
13871     r = pMsiEnumComponentsExA( NULL, 0, 0, NULL, NULL, NULL, NULL );
13872     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13873 
13874     r = pMsiEnumComponentsExA( NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, NULL );
13875     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13876 
13877 done:
13878     RegDeleteValueA( key2, comp_squashed2 );
13879     delete_key( key1, "", access );
13880     delete_key( key2, "", access );
13881     RegCloseKey( key1 );
13882     RegCloseKey( key2 );
13883     LocalFree( usersid );
13884 }
13885 
13886 static void test_MsiConfigureProductEx(void)
13887 {
13888     UINT r;
13889     LONG res;
13890     DWORD type, size;
13891     HKEY props, source;
13892     CHAR keypath[MAX_PATH * 2], localpackage[MAX_PATH], packagename[MAX_PATH];
13893     REGSAM access = KEY_ALL_ACCESS;
13894 
13895     if (is_process_limited())
13896     {
13897         skip("process is limited\n");
13898         return;
13899     }
13900 
13901     CreateDirectoryA("msitest", NULL);
13902     create_file("msitest\\hydrogen", "hydrogen", 500);
13903     create_file("msitest\\helium", "helium", 500);
13904     create_file("msitest\\lithium", "lithium", 500);
13905 
13906     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
13907 
13908     if (is_wow64)
13909         access |= KEY_WOW64_64KEY;
13910 
13911     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
13912 
13913     /* NULL szProduct */
13914     r = MsiConfigureProductExA(NULL, INSTALLLEVEL_DEFAULT,
13915                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
13916     ok(r == ERROR_INVALID_PARAMETER,
13917        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
13918 
13919     /* empty szProduct */
13920     r = MsiConfigureProductExA("", INSTALLLEVEL_DEFAULT,
13921                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
13922     ok(r == ERROR_INVALID_PARAMETER,
13923        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
13924 
13925     /* garbage szProduct */
13926     r = MsiConfigureProductExA("garbage", INSTALLLEVEL_DEFAULT,
13927                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
13928     ok(r == ERROR_INVALID_PARAMETER,
13929        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
13930 
13931     /* guid without brackets */
13932     r = MsiConfigureProductExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
13933                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13934                                "PROPVAR=42");
13935     ok(r == ERROR_INVALID_PARAMETER,
13936        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
13937 
13938     /* guid with brackets */
13939     r = MsiConfigureProductExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
13940                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13941                                "PROPVAR=42");
13942     ok(r == ERROR_UNKNOWN_PRODUCT,
13943        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
13944 
13945     /* same length as guid, but random */
13946     r = MsiConfigureProductExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
13947                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13948                                "PROPVAR=42");
13949     ok(r == ERROR_UNKNOWN_PRODUCT,
13950        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
13951 
13952     /* product not installed yet */
13953     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
13954                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13955                                "PROPVAR=42");
13956     ok(r == ERROR_UNKNOWN_PRODUCT,
13957        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
13958 
13959     /* install the product, per-user unmanaged */
13960     r = MsiInstallProductA(msifile, "INSTALLLEVEL=10 PROPVAR=42");
13961     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
13962     {
13963         skip("Not enough rights to perform tests\n");
13964         goto error;
13965     }
13966     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13967     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13968     ok(pf_exists("msitest\\helium"), "File not installed\n");
13969     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13970     ok(pf_exists("msitest"), "File not installed\n");
13971 
13972     /* product is installed per-user managed, remove it */
13973     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13974                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13975                                "PROPVAR=42");
13976     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13977     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
13978     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
13979     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
13980     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
13981 
13982     /* product has been removed */
13983     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13984                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13985                                "PROPVAR=42");
13986     ok(r == ERROR_UNKNOWN_PRODUCT,
13987        "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
13988 
13989     /* install the product, machine */
13990     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
13991     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13992     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13993     ok(pf_exists("msitest\\helium"), "File not installed\n");
13994     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13995     ok(pf_exists("msitest"), "File not installed\n");
13996 
13997     /* product is installed machine, remove it */
13998     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13999                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
14000                                "PROPVAR=42");
14001     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
14002     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
14003     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
14004     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
14005     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
14006 
14007     /* product has been removed */
14008     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
14009                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
14010                                "PROPVAR=42");
14011     ok(r == ERROR_UNKNOWN_PRODUCT,
14012        "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14013 
14014     /* install the product, machine */
14015     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
14016     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14017     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
14018     ok(pf_exists("msitest\\helium"), "File not installed\n");
14019     ok(pf_exists("msitest\\lithium"), "File not installed\n");
14020     ok(pf_exists("msitest"), "File not installed\n");
14021 
14022     DeleteFileA(msifile);
14023 
14024     /* msifile is removed */
14025     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
14026                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
14027                                "PROPVAR=42");
14028     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
14029     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
14030     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
14031     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
14032     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
14033 
14034     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
14035 
14036     /* install the product, machine */
14037     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
14038     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14039     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
14040     ok(pf_exists("msitest\\helium"), "File not installed\n");
14041     ok(pf_exists("msitest\\lithium"), "File not installed\n");
14042     ok(pf_exists("msitest"), "File not installed\n");
14043 
14044     DeleteFileA(msifile);
14045 
14046     lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
14047     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
14048     lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\InstallProperties");
14049 
14050     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &props);
14051     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14052 
14053     type = REG_SZ;
14054     size = MAX_PATH;
14055     res = RegQueryValueExA(props, "LocalPackage", NULL, &type,
14056                            (LPBYTE)localpackage, &size);
14057     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14058 
14059     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
14060                          (const BYTE *)"C:\\idontexist.msi", 18);
14061     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14062 
14063     /* LocalPackage is used to find the cached msi package */
14064     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
14065                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
14066                                "PROPVAR=42");
14067     ok(r == ERROR_INSTALL_SOURCE_ABSENT,
14068        "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
14069     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
14070     ok(pf_exists("msitest\\helium"), "File not installed\n");
14071     ok(pf_exists("msitest\\lithium"), "File not installed\n");
14072     ok(pf_exists("msitest"), "File not installed\n");
14073 
14074     RegCloseKey(props);
14075     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
14076 
14077     /* LastUsedSource can be used as a last resort */
14078     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
14079                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
14080                                "PROPVAR=42");
14081     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
14082     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
14083     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
14084     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
14085     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
14086     DeleteFileA( localpackage );
14087 
14088     /* install the product, machine */
14089     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
14090     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14091     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
14092     ok(pf_exists("msitest\\helium"), "File not installed\n");
14093     ok(pf_exists("msitest\\lithium"), "File not installed\n");
14094     ok(pf_exists("msitest"), "File not installed\n");
14095 
14096     lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
14097     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
14098     lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\InstallProperties");
14099 
14100     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &props);
14101     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14102 
14103     type = REG_SZ;
14104     size = MAX_PATH;
14105     res = RegQueryValueExA(props, "LocalPackage", NULL, &type,
14106                            (LPBYTE)localpackage, &size);
14107     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14108 
14109     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
14110                          (const BYTE *)"C:\\idontexist.msi", 18);
14111     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14112 
14113     lstrcpyA(keypath, "SOFTWARE\\Classes\\Installer\\Products\\");
14114     lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\SourceList");
14115 
14116     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &source);
14117     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14118 
14119     type = REG_SZ;
14120     size = MAX_PATH;
14121     res = RegQueryValueExA(source, "PackageName", NULL, &type,
14122                            (LPBYTE)packagename, &size);
14123     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14124 
14125     res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
14126                          (const BYTE *)"idontexist.msi", 15);
14127     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14128 
14129     /* SourceList is altered */
14130     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
14131                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
14132                                "PROPVAR=42");
14133     ok(r == ERROR_INSTALL_SOURCE_ABSENT,
14134        "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
14135     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
14136     ok(pf_exists("msitest\\helium"), "File not installed\n");
14137     ok(pf_exists("msitest\\lithium"), "File not installed\n");
14138     ok(pf_exists("msitest"), "File not installed\n");
14139 
14140     /* restore PackageName */
14141     res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
14142                          (const BYTE *)packagename, lstrlenA(packagename) + 1);
14143     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14144 
14145     /* restore LocalPackage */
14146     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
14147                          (const BYTE *)localpackage, lstrlenA(localpackage) + 1);
14148     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14149 
14150     /* finally remove the product */
14151     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
14152                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
14153                                "PROPVAR=42");
14154     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
14155     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
14156     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
14157     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
14158     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
14159 
14160     RegCloseKey(source);
14161     RegCloseKey(props);
14162 
14163 error:
14164     DeleteFileA("msitest\\hydrogen");
14165     DeleteFileA("msitest\\helium");
14166     DeleteFileA("msitest\\lithium");
14167     RemoveDirectoryA("msitest");
14168     DeleteFileA(msifile);
14169 }
14170 
14171 static void test_MsiSetFeatureAttributes(void)
14172 {
14173     UINT r;
14174     DWORD attrs;
14175     char path[MAX_PATH];
14176     MSIHANDLE package;
14177 
14178     if (is_process_limited())
14179     {
14180         skip("process is limited\n");
14181         return;
14182     }
14183     create_database( msifile, tables, sizeof(tables) / sizeof(tables[0]) );
14184 
14185     strcpy( path, CURR_DIR );
14186     strcat( path, "\\" );
14187     strcat( path, msifile );
14188 
14189     r = MsiOpenPackageA( path, &package );
14190     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14191     {
14192         skip("Not enough rights to perform tests\n");
14193         DeleteFileA( msifile );
14194         return;
14195     }
14196     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14197 
14198     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
14199     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %u\n", r);
14200 
14201     r = MsiDoActionA( package, "CostInitialize" );
14202     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14203 
14204     r = MsiSetFeatureAttributesA( 0, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
14205     ok(r == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", r);
14206 
14207     r = MsiSetFeatureAttributesA( package, "", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
14208     ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
14209 
14210     r = MsiSetFeatureAttributesA( package, NULL, INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
14211     ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
14212 
14213     r = MsiSetFeatureAttributesA( package, "One", 0 );
14214     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14215 
14216     attrs = 0xdeadbeef;
14217     r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL );
14218     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14219     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL,
14220        "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got 0x%08x\n", attrs);
14221 
14222     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
14223     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14224 
14225     attrs = 0;
14226     r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL );
14227     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14228     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL,
14229        "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got 0x%08x\n", attrs);
14230 
14231     r = MsiDoActionA( package, "FileCost" );
14232     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14233 
14234     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORSOURCE );
14235     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14236 
14237     attrs = 0;
14238     r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL );
14239     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14240     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORSOURCE,
14241        "expected INSTALLFEATUREATTRIBUTE_FAVORSOURCE, got 0x%08x\n", attrs);
14242 
14243     r = MsiDoActionA( package, "CostFinalize" );
14244     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14245 
14246     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
14247     ok(r == ERROR_FUNCTION_FAILED, "expected ERROR_FUNCTION_FAILED, got %u\n", r);
14248 
14249     MsiCloseHandle( package );
14250     DeleteFileA( msifile );
14251 }
14252 
14253 static void test_MsiGetFeatureInfo(void)
14254 {
14255     UINT r;
14256     MSIHANDLE package;
14257     char title[32], help[32], path[MAX_PATH];
14258     DWORD attrs, title_len, help_len;
14259 
14260     if (is_process_limited())
14261     {
14262         skip("process is limited\n");
14263         return;
14264     }
14265     create_database( msifile, tables, sizeof(tables) / sizeof(tables[0]) );
14266 
14267     strcpy( path, CURR_DIR );
14268     strcat( path, "\\" );
14269     strcat( path, msifile );
14270 
14271     r = MsiOpenPackageA( path, &package );
14272     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14273     {
14274         skip("Not enough rights to perform tests\n");
14275         DeleteFileA( msifile );
14276         return;
14277     }
14278     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14279 
14280     r = MsiGetFeatureInfoA( 0, NULL, NULL, NULL, NULL, NULL, NULL );
14281     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
14282 
14283     r = MsiGetFeatureInfoA( package, NULL, NULL, NULL, NULL, NULL, NULL );
14284     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
14285 
14286     r = MsiGetFeatureInfoA( package, "", NULL, NULL, NULL, NULL, NULL );
14287     ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
14288 
14289     r = MsiGetFeatureInfoA( package, "One", NULL, NULL, NULL, NULL, NULL );
14290     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14291 
14292     r = MsiGetFeatureInfoA( 0, "One", NULL, NULL, NULL, NULL, NULL );
14293     ok(r == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", r);
14294 
14295     title_len = help_len = 0;
14296     r = MsiGetFeatureInfoA( package, "One", NULL, NULL, &title_len, NULL, &help_len );
14297     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14298     ok(title_len == 3, "expected 3, got %u\n", title_len);
14299     ok(help_len == 3, "expected 3, got %u\n", help_len);
14300 
14301     title[0] = help[0] = 0;
14302     title_len = help_len = 0;
14303     r = MsiGetFeatureInfoA( package, "One", NULL, title, &title_len, help, &help_len );
14304     ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %u\n", r);
14305     ok(title_len == 3, "expected 3, got %u\n", title_len);
14306     ok(help_len == 3, "expected 3, got %u\n", help_len);
14307 
14308     attrs = 0;
14309     title[0] = help[0] = 0;
14310     title_len = sizeof(title);
14311     help_len = sizeof(help);
14312     r = MsiGetFeatureInfoA( package, "One", &attrs, title, &title_len, help, &help_len );
14313     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14314     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %u\n", attrs);
14315     ok(title_len == 3, "expected 3, got %u\n", title_len);
14316     ok(help_len == 3, "expected 3, got %u\n", help_len);
14317     ok(!strcmp(title, "One"), "expected \"One\", got \"%s\"\n", title);
14318     ok(!strcmp(help, "One"), "expected \"One\", got \"%s\"\n", help);
14319 
14320     attrs = 0;
14321     title[0] = help[0] = 0;
14322     title_len = sizeof(title);
14323     help_len = sizeof(help);
14324     r = MsiGetFeatureInfoA( package, "Two", &attrs, title, &title_len, help, &help_len );
14325     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14326     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %u\n", attrs);
14327     ok(!title_len, "expected 0, got %u\n", title_len);
14328     ok(!help_len, "expected 0, got %u\n", help_len);
14329     ok(!title[0], "expected \"\", got \"%s\"\n", title);
14330     ok(!help[0], "expected \"\", got \"%s\"\n", help);
14331 
14332     MsiCloseHandle( package );
14333     DeleteFileA( msifile );
14334 }
14335 
14336 static INT CALLBACK handler_a(LPVOID context, UINT type, LPCSTR msg)
14337 {
14338     return IDOK;
14339 }
14340 
14341 static INT CALLBACK handler_w(LPVOID context, UINT type, LPCWSTR msg)
14342 {
14343     return IDOK;
14344 }
14345 
14346 static INT CALLBACK handler_record(LPVOID context, UINT type, MSIHANDLE record)
14347 {
14348     return IDOK;
14349 }
14350 
14351 static void test_MsiSetExternalUI(void)
14352 {
14353     INSTALLUI_HANDLERA ret_a;
14354     INSTALLUI_HANDLERW ret_w;
14355     INSTALLUI_HANDLER_RECORD prev;
14356     UINT error;
14357 
14358     ret_a = MsiSetExternalUIA(handler_a, INSTALLLOGMODE_ERROR, NULL);
14359     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
14360 
14361     ret_a = MsiSetExternalUIA(NULL, 0, NULL);
14362     ok(ret_a == handler_a, "expected %p, got %p\n", handler_a, ret_a);
14363 
14364     /* Not present before Installer 3.1 */
14365     if (!pMsiSetExternalUIRecord) {
14366         win_skip("MsiSetExternalUIRecord is not available\n");
14367         return;
14368     }
14369 
14370     error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, &prev);
14371     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14372     ok(prev == NULL, "expected NULL, got %p\n", prev);
14373 
14374     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
14375     error = pMsiSetExternalUIRecord(NULL, INSTALLLOGMODE_ERROR, NULL, &prev);
14376     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14377     ok(prev == handler_record, "expected %p, got %p\n", handler_record, prev);
14378 
14379     ret_w = MsiSetExternalUIW(handler_w, INSTALLLOGMODE_ERROR, NULL);
14380     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
14381 
14382     ret_w = MsiSetExternalUIW(NULL, 0, NULL);
14383     ok(ret_w == handler_w, "expected %p, got %p\n", handler_w, ret_w);
14384 
14385     ret_a = MsiSetExternalUIA(handler_a, INSTALLLOGMODE_ERROR, NULL);
14386     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
14387 
14388     ret_w = MsiSetExternalUIW(handler_w, INSTALLLOGMODE_ERROR, NULL);
14389     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
14390 
14391     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
14392     error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, &prev);
14393     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14394     ok(prev == NULL, "expected NULL, got %p\n", prev);
14395 
14396     ret_a = MsiSetExternalUIA(NULL, 0, NULL);
14397     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
14398 
14399     ret_w = MsiSetExternalUIW(NULL, 0, NULL);
14400     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
14401 
14402     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
14403     error = pMsiSetExternalUIRecord(NULL, 0, NULL, &prev);
14404     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14405     ok(prev == handler_record, "expected %p, got %p\n", handler_record, prev);
14406 
14407     error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, NULL);
14408     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14409 
14410     error = pMsiSetExternalUIRecord(NULL, 0, NULL, NULL);
14411     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14412 }
14413 
14414 static void test_lastusedsource(void)
14415 {
14416     static const char prodcode[] = "{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}";
14417     char value[MAX_PATH], path[MAX_PATH];
14418     DWORD size;
14419     UINT r;
14420 
14421     if (!pMsiSourceListGetInfoA)
14422     {
14423         win_skip("MsiSourceListGetInfoA is not available\n");
14424         return;
14425     }
14426 
14427     CreateDirectoryA("msitest", NULL);
14428     create_file("maximus", "maximus", 500);
14429     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
14430     DeleteFileA("maximus");
14431 
14432     create_database("msifile0.msi", lus0_tables, sizeof(lus0_tables) / sizeof(msi_table));
14433     create_database("msifile1.msi", lus1_tables, sizeof(lus1_tables) / sizeof(msi_table));
14434     create_database("msifile2.msi", lus2_tables, sizeof(lus2_tables) / sizeof(msi_table));
14435 
14436     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
14437 
14438     /* no cabinet file */
14439 
14440     size = MAX_PATH;
14441     lstrcpyA(value, "aaa");
14442     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14443                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14444     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14445     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
14446 
14447     r = MsiInstallProductA("msifile0.msi", "PUBLISH_PRODUCT=1");
14448     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14449     {
14450         skip("Not enough rights to perform tests\n");
14451         goto error;
14452     }
14453     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14454 
14455     lstrcpyA(path, CURR_DIR);
14456     lstrcatA(path, "\\");
14457 
14458     size = MAX_PATH;
14459     lstrcpyA(value, "aaa");
14460     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14461                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14462     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14463     ok(!lstrcmpA(value, path), "expected \"%s\", got \"%s\"\n", path, value);
14464     ok(size == lstrlenA(path), "expected %d, got %d\n", lstrlenA(path), size);
14465 
14466     r = MsiInstallProductA("msifile0.msi", "REMOVE=ALL");
14467     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14468 
14469     /* separate cabinet file */
14470 
14471     size = MAX_PATH;
14472     lstrcpyA(value, "aaa");
14473     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14474                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14475     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14476     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
14477 
14478     r = MsiInstallProductA("msifile1.msi", "PUBLISH_PRODUCT=1");
14479     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14480 
14481     lstrcpyA(path, CURR_DIR);
14482     lstrcatA(path, "\\");
14483 
14484     size = MAX_PATH;
14485     lstrcpyA(value, "aaa");
14486     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14487                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14488     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14489     ok(!lstrcmpA(value, path), "expected \"%s\", got \"%s\"\n", path, value);
14490     ok(size == lstrlenA(path), "expected %d, got %d\n", lstrlenA(path), size);
14491 
14492     r = MsiInstallProductA("msifile1.msi", "REMOVE=ALL");
14493     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14494 
14495     size = MAX_PATH;
14496     lstrcpyA(value, "aaa");
14497     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14498                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14499     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14500     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
14501 
14502     /* embedded cabinet stream */
14503 
14504     add_cabinet_storage("msifile2.msi", "test1.cab");
14505 
14506     r = MsiInstallProductA("msifile2.msi", "PUBLISH_PRODUCT=1");
14507     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14508 
14509     size = MAX_PATH;
14510     lstrcpyA(value, "aaa");
14511     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14512                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14513     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14514     ok(!lstrcmpA(value, path), "expected \"%s\", got \"%s\"\n", path, value);
14515     ok(size == lstrlenA(path), "expected %d, got %d\n", lstrlenA(path), size);
14516 
14517     r = MsiInstallProductA("msifile2.msi", "REMOVE=ALL");
14518     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14519 
14520     size = MAX_PATH;
14521     lstrcpyA(value, "aaa");
14522     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14523                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14524     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14525     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
14526 
14527 error:
14528     delete_cab_files();
14529     DeleteFileA("msitest\\maximus");
14530     RemoveDirectoryA("msitest");
14531     DeleteFileA("msifile0.msi");
14532     DeleteFileA("msifile1.msi");
14533     DeleteFileA("msifile2.msi");
14534 }
14535 
14536 static void test_setpropertyfolder(void)
14537 {
14538     UINT r;
14539     CHAR path[MAX_PATH];
14540     DWORD attr;
14541 
14542     if (is_process_limited())
14543     {
14544         skip("process is limited\n");
14545         return;
14546     }
14547 
14548     lstrcpyA(path, PROG_FILES_DIR);
14549     lstrcatA(path, "\\msitest\\added");
14550 
14551     CreateDirectoryA("msitest", NULL);
14552     create_file("msitest\\maximus", "msitest\\maximus", 500);
14553 
14554     create_database(msifile, spf_tables, sizeof(spf_tables) / sizeof(msi_table));
14555 
14556     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
14557 
14558     r = MsiInstallProductA(msifile, NULL);
14559     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14560     {
14561         skip("Not enough rights to perform tests\n");
14562         goto error;
14563     }
14564     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14565     attr = GetFileAttributesA(path);
14566     if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY))
14567     {
14568         ok(delete_pf("msitest\\added\\maximus", TRUE), "File not installed\n");
14569         ok(delete_pf("msitest\\added", FALSE), "Directory not created\n");
14570         ok(delete_pf("msitest", FALSE), "Directory not created\n");
14571     }
14572     else
14573     {
14574         trace("changing folder property not supported\n");
14575         ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
14576         ok(delete_pf("msitest", FALSE), "Directory not created\n");
14577     }
14578 
14579 error:
14580     DeleteFileA(msifile);
14581     DeleteFileA("msitest\\maximus");
14582     RemoveDirectoryA("msitest");
14583 }
14584 
14585 static void test_sourcedir_props(void)
14586 {
14587     UINT r;
14588 
14589     if (is_process_limited())
14590     {
14591         skip("process is limited\n");
14592         return;
14593     }
14594 
14595     create_test_files();
14596     create_file("msitest\\sourcedir.txt", "msitest\\sourcedir.txt", 1000);
14597     create_database(msifile, sd_tables, sizeof(sd_tables) / sizeof(msi_table));
14598 
14599     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
14600 
14601     /* full UI, no ResolveSource action */
14602     r = MsiInstallProductA(msifile, NULL);
14603     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14604 
14605     r = MsiInstallProductA(msifile, "REMOVE=ALL");
14606     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14607 
14608     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
14609     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
14610 
14611     /* full UI, ResolveSource action */
14612     r = MsiInstallProductA(msifile, "ResolveSource=1");
14613     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14614 
14615     r = MsiInstallProductA(msifile, "REMOVE=ALL");
14616     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14617 
14618     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
14619     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
14620 
14621     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
14622 
14623     /* no UI, no ResolveSource action */
14624     r = MsiInstallProductA(msifile, NULL);
14625     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14626 
14627     r = MsiInstallProductA(msifile, "REMOVE=ALL");
14628     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14629 
14630     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
14631     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
14632 
14633     /* no UI, ResolveSource action */
14634     r = MsiInstallProductA(msifile, "ResolveSource=1");
14635     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14636 
14637     r = MsiInstallProductA(msifile, "REMOVE=ALL");
14638     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14639 
14640     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
14641     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
14642 
14643     DeleteFileA("msitest\\sourcedir.txt");
14644     delete_test_files();
14645     DeleteFileA(msifile);
14646 }
14647 
14648 static void test_concurrentinstall(void)
14649 {
14650     UINT r;
14651     CHAR path[MAX_PATH];
14652 
14653     if (is_process_limited())
14654     {
14655         skip("process is limited\n");
14656         return;
14657     }
14658 
14659     CreateDirectoryA("msitest", NULL);
14660     CreateDirectoryA("msitest\\msitest", NULL);
14661     create_file("msitest\\maximus", "msitest\\maximus", 500);
14662     create_file("msitest\\msitest\\augustus", "msitest\\msitest\\augustus", 500);
14663 
14664     create_database(msifile, ci_tables, sizeof(ci_tables) / sizeof(msi_table));
14665 
14666     lstrcpyA(path, CURR_DIR);
14667     lstrcatA(path, "\\msitest\\concurrent.msi");
14668     create_database(path, ci2_tables, sizeof(ci2_tables) / sizeof(msi_table));
14669 
14670     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
14671 
14672     r = MsiInstallProductA(msifile, NULL);
14673     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14674     {
14675         skip("Not enough rights to perform tests\n");
14676         goto error;
14677     }
14678     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14679     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
14680     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
14681     ok(delete_pf("msitest", FALSE), "Directory not created\n");
14682 
14683     r = MsiConfigureProductA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", INSTALLLEVEL_DEFAULT,
14684                              INSTALLSTATE_ABSENT);
14685     ok(r == ERROR_SUCCESS, "got %u\n", r);
14686 
14687     r = MsiConfigureProductA("{FF4AFE9C-6AC2-44F9-A060-9EA6BD16C75E}", INSTALLLEVEL_DEFAULT,
14688                              INSTALLSTATE_ABSENT);
14689     ok(r == ERROR_SUCCESS, "got %u\n", r);
14690 
14691 error:
14692     DeleteFileA(path);
14693     DeleteFileA(msifile);
14694     DeleteFileA("msitest\\msitest\\augustus");
14695     DeleteFileA("msitest\\maximus");
14696     RemoveDirectoryA("msitest\\msitest");
14697     RemoveDirectoryA("msitest");
14698 }
14699 
14700 static void test_command_line_parsing(void)
14701 {
14702     UINT r;
14703     const char *cmd;
14704 
14705     if (is_process_limited())
14706     {
14707         skip("process is limited\n");
14708         return;
14709     }
14710 
14711     create_test_files();
14712     create_database(msifile, cl_tables, sizeof(cl_tables)/sizeof(msi_table));
14713 
14714     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
14715 
14716     cmd = " ";
14717     r = MsiInstallProductA(msifile, cmd);
14718     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14719 
14720     cmd = "=";
14721     r = MsiInstallProductA(msifile, cmd);
14722     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14723 
14724     cmd = "==";
14725     r = MsiInstallProductA(msifile, cmd);
14726     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14727 
14728     cmd = "one";
14729     r = MsiInstallProductA(msifile, cmd);
14730     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14731 
14732     cmd = "=one";
14733     r = MsiInstallProductA(msifile, cmd);
14734     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14735 
14736     cmd = "P=";
14737     r = MsiInstallProductA(msifile, cmd);
14738     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14739 
14740     cmd = "  P=";
14741     r = MsiInstallProductA(msifile, cmd);
14742     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14743 
14744     cmd = "P=  ";
14745     r = MsiInstallProductA(msifile, cmd);
14746     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14747 
14748     cmd = "P=\"";
14749     r = MsiInstallProductA(msifile, cmd);
14750     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14751 
14752     cmd = "P=\"\"";
14753     r = MsiInstallProductA(msifile, cmd);
14754     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14755 
14756     cmd = "P=\"\"\"";
14757     r = MsiInstallProductA(msifile, cmd);
14758     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14759 
14760     cmd = "P=\"\"\"\"";
14761     r = MsiInstallProductA(msifile, cmd);
14762     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14763 
14764     cmd = "P=\" ";
14765     r = MsiInstallProductA(msifile, cmd);
14766     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14767 
14768     cmd = "P= \"";
14769     r = MsiInstallProductA(msifile, cmd);
14770     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14771 
14772     cmd = "P= \"\" ";
14773     r = MsiInstallProductA(msifile, cmd);
14774     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14775 
14776     cmd = "P=\"  \"";
14777     r = MsiInstallProductA(msifile, cmd);
14778     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14779 
14780     cmd = "P=one";
14781     r = MsiInstallProductA(msifile, cmd);
14782     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14783 
14784     cmd = "P= one";
14785     r = MsiInstallProductA(msifile, cmd);
14786     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14787 
14788     cmd = "P=\"one";
14789     r = MsiInstallProductA(msifile, cmd);
14790     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14791 
14792     cmd = "P=one\"";
14793     r = MsiInstallProductA(msifile, cmd);
14794     todo_wine ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14795 
14796     cmd = "P=\"one\"";
14797     r = MsiInstallProductA(msifile, cmd);
14798     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14799 
14800     cmd = "P= \"one\" ";
14801     r = MsiInstallProductA(msifile, cmd);
14802     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14803 
14804     cmd = "P=\"one\"\"";
14805     r = MsiInstallProductA(msifile, cmd);
14806     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14807 
14808     cmd = "P=\"\"one\"";
14809     r = MsiInstallProductA(msifile, cmd);
14810     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14811 
14812     cmd = "P=\"\"one\"\"";
14813     r = MsiInstallProductA(msifile, cmd);
14814     todo_wine ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14815 
14816     cmd = "P=\"one two\"";
14817     r = MsiInstallProductA(msifile, cmd);
14818     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14819 
14820     cmd = "P=\"\"\"one\"\" two\"";
14821     r = MsiInstallProductA(msifile, cmd);
14822     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14823 
14824     cmd = "P=\"\"\"one\"\" two\" Q=three";
14825     r = MsiInstallProductA(msifile, cmd);
14826     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14827 
14828     cmd = "P=\"\" Q=\"two\"";
14829     r = MsiInstallProductA(msifile, cmd);
14830     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14831 
14832     cmd = "P=\"one\" Q=\"two\"";
14833     r = MsiInstallProductA(msifile, cmd);
14834     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14835 
14836     cmd = "P=\"one=two\"";
14837     r = MsiInstallProductA(msifile, cmd);
14838     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14839 
14840     cmd = "Q=\"\" P=\"one\"";
14841     r = MsiInstallProductA(msifile, cmd);
14842     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14843 
14844     cmd = "P=\"\"\"one\"\"\" Q=\"two\"";
14845     r = MsiInstallProductA(msifile, cmd);
14846     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14847 
14848     cmd = "P=\"one \"\"two\"\"\" Q=\"three\"";
14849     r = MsiInstallProductA(msifile, cmd);
14850     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14851 
14852     cmd = "P=\"\"\"one\"\" two\" Q=\"three\"";
14853     r = MsiInstallProductA(msifile, cmd);
14854     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14855 
14856     DeleteFileA(msifile);
14857     delete_test_files();
14858 }
14859 
14860 START_TEST(msi)
14861 {
14862     DWORD len;
14863     char temp_path[MAX_PATH], prev_path[MAX_PATH];
14864 
14865 #ifdef __REACTOS__
14866     if (!winetest_interactive &&
14867         !strcmp(winetest_platform, "windows"))
14868     {
14869         skip("ROSTESTS-180: Skipping msi_winetest:msi because it hangs on WHS-Testbot. Set winetest_interactive to run it anyway.\n");
14870         return;
14871     }
14872 #endif
14873 
14874     init_functionpointers();
14875 
14876     if (pIsWow64Process)
14877         pIsWow64Process(GetCurrentProcess(), &is_wow64);
14878 
14879     GetCurrentDirectoryA(MAX_PATH, prev_path);
14880     GetTempPathA(MAX_PATH, temp_path);
14881     SetCurrentDirectoryA(temp_path);
14882 
14883     lstrcpyA(CURR_DIR, temp_path);
14884     len = lstrlenA(CURR_DIR);
14885 
14886     if(len && (CURR_DIR[len - 1] == '\\'))
14887         CURR_DIR[len - 1] = 0;
14888 
14889     ok(get_system_dirs(), "failed to retrieve system dirs\n");
14890 
14891     test_usefeature();
14892     test_null();
14893     test_getcomponentpath();
14894     test_MsiGetFileHash();
14895 
14896     if (!pConvertSidToStringSidA)
14897         win_skip("ConvertSidToStringSidA not implemented\n");
14898     else
14899     {
14900         /* These tests rely on get_user_sid that needs ConvertSidToStringSidA */
14901         test_MsiQueryProductState();
14902         test_MsiQueryFeatureState();
14903         test_MsiQueryComponentState();
14904         test_MsiGetComponentPath();
14905         test_MsiGetComponentPathEx();
14906         test_MsiProvideComponent();
14907         test_MsiGetProductCode();
14908         test_MsiEnumClients();
14909         test_MsiGetProductInfo();
14910         test_MsiGetProductInfoEx();
14911         test_MsiGetUserInfo();
14912         test_MsiOpenProduct();
14913         test_MsiEnumPatchesEx();
14914         test_MsiEnumPatches();
14915         test_MsiGetPatchInfoEx();
14916         test_MsiGetPatchInfo();
14917         test_MsiEnumProducts();
14918         test_MsiEnumProductsEx();
14919         test_MsiEnumComponents();
14920         test_MsiEnumComponentsEx();
14921     }
14922     test_MsiGetFileVersion();
14923     test_MsiGetFileSignatureInformation();
14924     test_MsiConfigureProductEx();
14925     test_MsiSetFeatureAttributes();
14926     test_MsiGetFeatureInfo();
14927     test_MsiSetExternalUI();
14928     test_lastusedsource();
14929     test_setpropertyfolder();
14930     test_sourcedir_props();
14931     if (pMsiGetComponentPathExA)
14932         test_concurrentinstall();
14933     test_command_line_parsing();
14934     test_MsiProvideQualifiedComponentEx();
14935 
14936     SetCurrentDirectoryA(prev_path);
14937 }
14938