xref: /reactos/modules/rostests/winetests/msi/msi.c (revision 3435c3b5)
1 /*
2  * tests for Microsoft Installer functionality
3  *
4  * Copyright 2005 Mike McCormack for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #define _WIN32_MSI 300
22 #define COBJMACROS
23 
24 #include <stdio.h>
25 #include <windows.h>
26 #include <msi.h>
27 #include <msiquery.h>
28 #include <msidefs.h>
29 #include <sddl.h>
30 #include <fci.h>
31 #include <shellapi.h>
32 #include <objidl.h>
33 
34 #include "wine/test.h"
35 
36 static BOOL is_wow64;
37 static const char msifile[] = "winetest.msi";
38 static const WCHAR msifileW[] = {'w','i','n','e','t','e','s','t','.','m','s','i',0};
39 static char CURR_DIR[MAX_PATH];
40 static char PROG_FILES_DIR[MAX_PATH];
41 static char PROG_FILES_DIR_NATIVE[MAX_PATH];
42 static char COMMON_FILES_DIR[MAX_PATH];
43 static char WINDOWS_DIR[MAX_PATH];
44 
45 static BOOL (WINAPI *pCheckTokenMembership)(HANDLE,PSID,PBOOL);
46 static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
47 static BOOL (WINAPI *pOpenProcessToken)( HANDLE, DWORD, PHANDLE );
48 static LONG (WINAPI *pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD);
49 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
50 
51 static INSTALLSTATE (WINAPI *pMsiGetComponentPathA)
52     (LPCSTR, LPCSTR, LPSTR, DWORD*);
53 static INSTALLSTATE (WINAPI *pMsiGetComponentPathExA)
54     (LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPSTR, LPDWORD);
55 static INSTALLSTATE (WINAPI *pMsiProvideComponentA)
56     (LPCSTR, LPCSTR, LPCSTR, DWORD, LPSTR, LPDWORD);
57 static INSTALLSTATE (WINAPI *pMsiProvideComponentW)
58     (LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPWSTR, LPDWORD);
59 static UINT (WINAPI *pMsiGetFileHashA)
60     (LPCSTR, DWORD, PMSIFILEHASHINFO);
61 static UINT (WINAPI *pMsiGetProductInfoExA)
62     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, LPSTR, LPDWORD);
63 static UINT (WINAPI *pMsiOpenPackageExA)
64     (LPCSTR, DWORD, MSIHANDLE*);
65 static UINT (WINAPI *pMsiOpenPackageExW)
66     (LPCWSTR, DWORD, MSIHANDLE*);
67 static UINT (WINAPI *pMsiEnumPatchesExA)
68     (LPCSTR, LPCSTR, DWORD, DWORD, DWORD, LPSTR, LPSTR,
69     MSIINSTALLCONTEXT*, LPSTR, LPDWORD);
70 static UINT (WINAPI *pMsiQueryComponentStateA)
71     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, INSTALLSTATE*);
72 static INSTALLSTATE (WINAPI *pMsiUseFeatureExA)
73     (LPCSTR, LPCSTR ,DWORD, DWORD);
74 static UINT (WINAPI *pMsiGetPatchInfoExA)
75     (LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, LPSTR, DWORD *);
76 static UINT (WINAPI *pMsiEnumProductsExA)
77     (LPCSTR, LPCSTR, DWORD, DWORD, CHAR[39], MSIINSTALLCONTEXT *, LPSTR, LPDWORD);
78 static UINT (WINAPI *pMsiEnumComponentsExA)
79     (LPCSTR, DWORD, DWORD, CHAR[39], MSIINSTALLCONTEXT *, LPSTR, LPDWORD);
80 static UINT (WINAPI *pMsiSetExternalUIRecord)
81     (INSTALLUI_HANDLER_RECORD, DWORD, LPVOID, PINSTALLUI_HANDLER_RECORD);
82 static UINT (WINAPI *pMsiSourceListGetInfoA)
83     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, LPSTR, LPDWORD);
84 
85 static void init_functionpointers(void)
86 {
87     HMODULE hmsi = GetModuleHandleA("msi.dll");
88     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
89     HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
90 
91 #define GET_PROC(dll, func) \
92     p ## func = (void *)GetProcAddress(dll, #func); \
93     if(!p ## func) \
94       trace("GetProcAddress(%s) failed\n", #func);
95 
96     GET_PROC(hmsi, MsiGetComponentPathA)
97     GET_PROC(hmsi, MsiGetComponentPathExA);
98     GET_PROC(hmsi, MsiProvideComponentA)
99     GET_PROC(hmsi, MsiProvideComponentW)
100     GET_PROC(hmsi, MsiGetFileHashA)
101     GET_PROC(hmsi, MsiGetProductInfoExA)
102     GET_PROC(hmsi, MsiOpenPackageExA)
103     GET_PROC(hmsi, MsiOpenPackageExW)
104     GET_PROC(hmsi, MsiEnumPatchesExA)
105     GET_PROC(hmsi, MsiQueryComponentStateA)
106     GET_PROC(hmsi, MsiSetExternalUIRecord)
107     GET_PROC(hmsi, MsiUseFeatureExA)
108     GET_PROC(hmsi, MsiGetPatchInfoExA)
109     GET_PROC(hmsi, MsiEnumProductsExA)
110     GET_PROC(hmsi, MsiEnumComponentsExA)
111     GET_PROC(hmsi, MsiSourceListGetInfoA)
112 
113     GET_PROC(hadvapi32, CheckTokenMembership);
114     GET_PROC(hadvapi32, ConvertSidToStringSidA)
115     GET_PROC(hadvapi32, OpenProcessToken);
116     GET_PROC(hadvapi32, RegDeleteKeyExA)
117     GET_PROC(hkernel32, IsWow64Process)
118 
119 #undef GET_PROC
120 }
121 
122 static BOOL get_system_dirs(void)
123 {
124     HKEY hkey;
125     DWORD type, size;
126 
127     if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", &hkey))
128         return FALSE;
129 
130     size = MAX_PATH;
131     if (RegQueryValueExA(hkey, "ProgramFilesDir (x86)", 0, &type, (LPBYTE)PROG_FILES_DIR, &size) &&
132         RegQueryValueExA(hkey, "ProgramFilesDir", 0, &type, (LPBYTE)PROG_FILES_DIR, &size))
133     {
134         RegCloseKey(hkey);
135         return FALSE;
136     }
137     size = MAX_PATH;
138     if (RegQueryValueExA(hkey, "CommonFilesDir (x86)", 0, &type, (LPBYTE)COMMON_FILES_DIR, &size) &&
139         RegQueryValueExA(hkey, "CommonFilesDir", 0, &type, (LPBYTE)COMMON_FILES_DIR, &size))
140     {
141         RegCloseKey(hkey);
142         return FALSE;
143     }
144     size = MAX_PATH;
145     if (RegQueryValueExA(hkey, "ProgramFilesDir", 0, &type, (LPBYTE)PROG_FILES_DIR_NATIVE, &size))
146     {
147         RegCloseKey(hkey);
148         return FALSE;
149     }
150     RegCloseKey(hkey);
151     if (!GetWindowsDirectoryA(WINDOWS_DIR, MAX_PATH)) return FALSE;
152     return TRUE;
153 }
154 
155 static BOOL file_exists(const char *file)
156 {
157     return GetFileAttributesA(file) != INVALID_FILE_ATTRIBUTES;
158 }
159 
160 static BOOL pf_exists(const char *file)
161 {
162     char path[MAX_PATH];
163 
164     lstrcpyA(path, PROG_FILES_DIR);
165     lstrcatA(path, "\\");
166     lstrcatA(path, file);
167     return file_exists(path);
168 }
169 
170 static BOOL delete_pf(const char *rel_path, BOOL is_file)
171 {
172     char path[MAX_PATH];
173 
174     lstrcpyA(path, PROG_FILES_DIR);
175     lstrcatA(path, "\\");
176     lstrcatA(path, rel_path);
177 
178     if (is_file)
179         return DeleteFileA(path);
180     else
181         return RemoveDirectoryA(path);
182 }
183 
184 static BOOL is_process_limited(void)
185 {
186     SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
187     PSID Group = NULL;
188     BOOL IsInGroup;
189     HANDLE token;
190 
191     if (!pCheckTokenMembership || !pOpenProcessToken) return FALSE;
192 
193     if (!AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
194                                   DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &Group) ||
195         !pCheckTokenMembership(NULL, Group, &IsInGroup))
196     {
197         trace("Could not check if the current user is an administrator\n");
198         FreeSid(Group);
199         return FALSE;
200     }
201     FreeSid(Group);
202 
203     if (!IsInGroup)
204     {
205         /* Only administrators have enough privileges for these tests */
206         return TRUE;
207     }
208 
209     if (pOpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
210     {
211         BOOL ret;
212         TOKEN_ELEVATION_TYPE type = TokenElevationTypeDefault;
213         DWORD size;
214 
215         ret = GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &size);
216         CloseHandle(token);
217         return (ret && type == TokenElevationTypeLimited);
218     }
219     return FALSE;
220 }
221 
222 /* cabinet definitions */
223 
224 /* make the max size large so there is only one cab file */
225 #define MEDIA_SIZE          0x7FFFFFFF
226 #define FOLDER_THRESHOLD    900000
227 
228 /* the FCI callbacks */
229 
230 static void * CDECL mem_alloc(ULONG cb)
231 {
232     return HeapAlloc(GetProcessHeap(), 0, cb);
233 }
234 
235 static void CDECL mem_free(void *memory)
236 {
237     HeapFree(GetProcessHeap(), 0, memory);
238 }
239 
240 static BOOL CDECL get_next_cabinet(PCCAB pccab, ULONG  cbPrevCab, void *pv)
241 {
242     sprintf(pccab->szCab, pv, pccab->iCab);
243     return TRUE;
244 }
245 
246 static LONG CDECL progress(UINT typeStatus, ULONG cb1, ULONG cb2, void *pv)
247 {
248     return 0;
249 }
250 
251 static int CDECL file_placed(PCCAB pccab, char *pszFile, LONG cbFile,
252                              BOOL fContinuation, void *pv)
253 {
254     return 0;
255 }
256 
257 static INT_PTR CDECL fci_open(char *pszFile, int oflag, int pmode, int *err, void *pv)
258 {
259     HANDLE handle;
260     DWORD dwAccess = 0;
261     DWORD dwShareMode = 0;
262     DWORD dwCreateDisposition = OPEN_EXISTING;
263 
264     dwAccess = GENERIC_READ | GENERIC_WRITE;
265     /* FILE_SHARE_DELETE is not supported by Windows Me/98/95 */
266     dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
267 
268     if (GetFileAttributesA(pszFile) != INVALID_FILE_ATTRIBUTES)
269         dwCreateDisposition = OPEN_EXISTING;
270     else
271         dwCreateDisposition = CREATE_NEW;
272 
273     handle = CreateFileA(pszFile, dwAccess, dwShareMode, NULL,
274                          dwCreateDisposition, 0, NULL);
275 
276     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszFile);
277 
278     return (INT_PTR)handle;
279 }
280 
281 static UINT CDECL fci_read(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
282 {
283     HANDLE handle = (HANDLE)hf;
284     DWORD dwRead;
285     BOOL res;
286 
287     res = ReadFile(handle, memory, cb, &dwRead, NULL);
288     ok(res, "Failed to ReadFile\n");
289 
290     return dwRead;
291 }
292 
293 static UINT CDECL fci_write(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
294 {
295     HANDLE handle = (HANDLE)hf;
296     DWORD dwWritten;
297     BOOL res;
298 
299     res = WriteFile(handle, memory, cb, &dwWritten, NULL);
300     ok(res, "Failed to WriteFile\n");
301 
302     return dwWritten;
303 }
304 
305 static int CDECL fci_close(INT_PTR hf, int *err, void *pv)
306 {
307     HANDLE handle = (HANDLE)hf;
308     ok(CloseHandle(handle), "Failed to CloseHandle\n");
309 
310     return 0;
311 }
312 
313 static LONG CDECL fci_seek(INT_PTR hf, LONG dist, int seektype, int *err, void *pv)
314 {
315     HANDLE handle = (HANDLE)hf;
316     DWORD ret;
317 
318     ret = SetFilePointer(handle, dist, NULL, seektype);
319     ok(ret != INVALID_SET_FILE_POINTER, "Failed to SetFilePointer\n");
320 
321     return ret;
322 }
323 
324 static int CDECL fci_delete(char *pszFile, int *err, void *pv)
325 {
326     BOOL ret = DeleteFileA(pszFile);
327     ok(ret, "Failed to DeleteFile %s\n", pszFile);
328 
329     return 0;
330 }
331 
332 static BOOL CDECL get_temp_file(char *pszTempName, int cbTempName, void *pv)
333 {
334     LPSTR tempname;
335 
336     tempname = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
337     GetTempFileNameA(".", "xx", 0, tempname);
338 
339     if (tempname && (strlen(tempname) < (unsigned)cbTempName))
340     {
341         lstrcpyA(pszTempName, tempname);
342         HeapFree(GetProcessHeap(), 0, tempname);
343         return TRUE;
344     }
345 
346     HeapFree(GetProcessHeap(), 0, tempname);
347 
348     return FALSE;
349 }
350 
351 static INT_PTR CDECL get_open_info(char *pszName, USHORT *pdate, USHORT *ptime,
352                                    USHORT *pattribs, int *err, void *pv)
353 {
354     BY_HANDLE_FILE_INFORMATION finfo;
355     FILETIME filetime;
356     HANDLE handle;
357     DWORD attrs;
358     BOOL res;
359 
360     handle = CreateFileA(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
361                          OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
362     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszName);
363 
364     res = GetFileInformationByHandle(handle, &finfo);
365     ok(res, "Expected GetFileInformationByHandle to succeed\n");
366 
367     FileTimeToLocalFileTime(&finfo.ftLastWriteTime, &filetime);
368     FileTimeToDosDateTime(&filetime, pdate, ptime);
369 
370     attrs = GetFileAttributesA(pszName);
371     ok(attrs != INVALID_FILE_ATTRIBUTES, "Failed to GetFileAttributes\n");
372 
373     return (INT_PTR)handle;
374 }
375 
376 static BOOL add_file(HFCI hfci, const char *file, TCOMP compress)
377 {
378     char path[MAX_PATH];
379     char filename[MAX_PATH];
380 
381     lstrcpyA(path, CURR_DIR);
382     lstrcatA(path, "\\");
383     lstrcatA(path, file);
384 
385     lstrcpyA(filename, file);
386 
387     return FCIAddFile(hfci, path, filename, FALSE, get_next_cabinet,
388                       progress, get_open_info, compress);
389 }
390 
391 static void set_cab_parameters(PCCAB pCabParams, const CHAR *name, DWORD max_size)
392 {
393     ZeroMemory(pCabParams, sizeof(CCAB));
394 
395     pCabParams->cb = max_size;
396     pCabParams->cbFolderThresh = FOLDER_THRESHOLD;
397     pCabParams->setID = 0xbeef;
398     pCabParams->iCab = 1;
399     lstrcpyA(pCabParams->szCabPath, CURR_DIR);
400     lstrcatA(pCabParams->szCabPath, "\\");
401     lstrcpyA(pCabParams->szCab, name);
402 }
403 
404 static void create_cab_file(const CHAR *name, DWORD max_size, const CHAR *files)
405 {
406     CCAB cabParams;
407     LPCSTR ptr;
408     HFCI hfci;
409     ERF erf;
410     BOOL res;
411 
412     set_cab_parameters(&cabParams, name, max_size);
413 
414     hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
415                       fci_read, fci_write, fci_close, fci_seek, fci_delete,
416                       get_temp_file, &cabParams, NULL);
417 
418     ok(hfci != NULL, "Failed to create an FCI context\n");
419 
420     ptr = files;
421     while (*ptr)
422     {
423         res = add_file(hfci, ptr, tcompTYPE_MSZIP);
424         ok(res, "Failed to add file: %s\n", ptr);
425         ptr += lstrlenA(ptr) + 1;
426     }
427 
428     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
429     ok(res, "Failed to flush the cabinet\n");
430 
431     res = FCIDestroy(hfci);
432     ok(res, "Failed to destroy the cabinet\n");
433 }
434 
435 static BOOL add_cabinet_storage(LPCSTR db, LPCSTR cabinet)
436 {
437     WCHAR dbW[MAX_PATH], cabinetW[MAX_PATH];
438     IStorage *stg;
439     IStream *stm;
440     HRESULT hr;
441     HANDLE handle;
442 
443     MultiByteToWideChar(CP_ACP, 0, db, -1, dbW, MAX_PATH);
444     hr = StgOpenStorage(dbW, NULL, STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
445     if (FAILED(hr))
446         return FALSE;
447 
448     MultiByteToWideChar(CP_ACP, 0, cabinet, -1, cabinetW, MAX_PATH);
449     hr = IStorage_CreateStream(stg, cabinetW, STGM_WRITE|STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
450     if (FAILED(hr))
451     {
452         IStorage_Release(stg);
453         return FALSE;
454     }
455 
456     handle = CreateFileW(cabinetW, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
457     if (handle != INVALID_HANDLE_VALUE)
458     {
459         DWORD count;
460         char buffer[1024];
461         if (ReadFile(handle, buffer, sizeof(buffer), &count, NULL))
462             IStream_Write(stm, buffer, count, &count);
463         CloseHandle(handle);
464     }
465 
466     IStream_Release(stm);
467     IStorage_Release(stg);
468 
469     return TRUE;
470 }
471 
472 static void delete_cab_files(void)
473 {
474     SHFILEOPSTRUCTA shfl;
475     CHAR path[MAX_PATH+10];
476 
477     lstrcpyA(path, CURR_DIR);
478     lstrcatA(path, "\\*.cab");
479     path[strlen(path) + 1] = '\0';
480 
481     shfl.hwnd = NULL;
482     shfl.wFunc = FO_DELETE;
483     shfl.pFrom = path;
484     shfl.pTo = NULL;
485     shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
486 
487     SHFileOperationA(&shfl);
488 }
489 
490 /* msi database data */
491 
492 static const char directory_dat[] =
493     "Directory\tDirectory_Parent\tDefaultDir\n"
494     "s72\tS72\tl255\n"
495     "Directory\tDirectory\n"
496     "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
497     "ProgramFilesFolder\tTARGETDIR\t.\n"
498     "TARGETDIR\t\tSourceDir";
499 
500 static const char component_dat[] =
501     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
502     "s72\tS38\ts72\ti2\tS255\tS72\n"
503     "Component\tComponent\n"
504     "One\t{8F5BAEEF-DD92-40AC-9397-BE3CF9F97C81}\tMSITESTDIR\t2\tNOT REINSTALL\tone.txt\n";
505 
506 static const char feature_dat[] =
507     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
508     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
509     "Feature\tFeature\n"
510     "One\t\tOne\tOne\t1\t3\tMSITESTDIR\t0\n"
511     "Two\t\t\t\t2\t1\tTARGETDIR\t0\n";
512 
513 static const char feature_comp_dat[] =
514     "Feature_\tComponent_\n"
515     "s38\ts72\n"
516     "FeatureComponents\tFeature_\tComponent_\n"
517     "One\tOne\n";
518 
519 static const char file_dat[] =
520     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
521     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
522     "File\tFile\n"
523     "one.txt\tOne\tone.txt\t1000\t\t\t0\t1\n";
524 
525 static const char install_exec_seq_dat[] =
526     "Action\tCondition\tSequence\n"
527     "s72\tS255\tI2\n"
528     "InstallExecuteSequence\tAction\n"
529     "ValidateProductID\t\t700\n"
530     "CostInitialize\t\t800\n"
531     "FileCost\t\t900\n"
532     "CostFinalize\t\t1000\n"
533     "InstallValidate\t\t1400\n"
534     "InstallInitialize\t\t1500\n"
535     "ProcessComponents\t\t1600\n"
536     "UnpublishFeatures\t\t1800\n"
537     "RemoveFiles\t\t3500\n"
538     "InstallFiles\t\t4000\n"
539     "RegisterProduct\t\t6100\n"
540     "PublishFeatures\t\t6300\n"
541     "PublishProduct\t\t6400\n"
542     "InstallFinalize\t\t6600";
543 
544 static const char media_dat[] =
545     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
546     "i2\ti4\tL64\tS255\tS32\tS72\n"
547     "Media\tDiskId\n"
548     "1\t1\t\t\tDISK1\t\n";
549 
550 static const char property_dat[] =
551     "Property\tValue\n"
552     "s72\tl0\n"
553     "Property\tProperty\n"
554     "INSTALLLEVEL\t3\n"
555     "Manufacturer\tWine\n"
556     "ProductCode\t{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}\n"
557     "ProductName\tMSITEST\n"
558     "ProductVersion\t1.1.1\n"
559     "UpgradeCode\t{9574448F-9B86-4E07-B6F6-8D199DA12127}\n"
560     "MSIFASTINSTALL\t1\n";
561 
562 static const char ci2_property_dat[] =
563     "Property\tValue\n"
564     "s72\tl0\n"
565     "Property\tProperty\n"
566     "INSTALLLEVEL\t3\n"
567     "Manufacturer\tWine\n"
568     "ProductCode\t{FF4AFE9C-6AC2-44F9-A060-9EA6BD16C75E}\n"
569     "ProductName\tMSITEST2\n"
570     "ProductVersion\t1.1.1\n"
571     "UpgradeCode\t{6B60C3CA-B8CA-4FB7-A395-092D98FF5D2A}\n"
572     "MSIFASTINSTALL\t1\n";
573 
574 static const char mcp_component_dat[] =
575     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
576     "s72\tS38\ts72\ti2\tS255\tS72\n"
577     "Component\tComponent\n"
578     "hydrogen\t{C844BD1E-1907-4C00-8BC9-150BD70DF0A1}\tMSITESTDIR\t2\t\thydrogen\n"
579     "helium\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t2\t\thelium\n"
580     "lithium\t{4AF28FFC-71C7-4307-BDE4-B77C5338F56F}\tMSITESTDIR\t2\tPROPVAR=42\tlithium\n";
581 
582 static const char mcp_feature_dat[] =
583     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
584     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
585     "Feature\tFeature\n"
586     "hydroxyl\t\thydroxyl\thydroxyl\t2\t1\tTARGETDIR\t0\n"
587     "heliox\t\theliox\theliox\t2\t5\tTARGETDIR\t0\n"
588     "lithia\t\tlithia\tlithia\t2\t10\tTARGETDIR\t0";
589 
590 static const char mcp_feature_comp_dat[] =
591     "Feature_\tComponent_\n"
592     "s38\ts72\n"
593     "FeatureComponents\tFeature_\tComponent_\n"
594     "hydroxyl\thydrogen\n"
595     "heliox\thelium\n"
596     "lithia\tlithium";
597 
598 static const char mcp_file_dat[] =
599     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
600     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
601     "File\tFile\n"
602     "hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n"
603     "helium\thelium\thelium\t0\t\t\t8192\t1\n"
604     "lithium\tlithium\tlithium\t0\t\t\t8192\t1";
605 
606 static const char lus_component_dat[] =
607     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
608     "s72\tS38\ts72\ti2\tS255\tS72\n"
609     "Component\tComponent\n"
610     "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
611 
612 static const char lus_feature_dat[] =
613     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
614     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
615     "Feature\tFeature\n"
616     "feature\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0\n"
617     "montecristo\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0";
618 
619 static const char lus_file_dat[] =
620     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
621     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
622     "File\tFile\n"
623     "maximus\tmaximus\tmaximus\t500\t\t\t8192\t1";
624 
625 static const char lus_feature_comp_dat[] =
626     "Feature_\tComponent_\n"
627     "s38\ts72\n"
628     "FeatureComponents\tFeature_\tComponent_\n"
629     "feature\tmaximus\n"
630     "montecristo\tmaximus";
631 
632 static const char lus_install_exec_seq_dat[] =
633     "Action\tCondition\tSequence\n"
634     "s72\tS255\tI2\n"
635     "InstallExecuteSequence\tAction\n"
636     "ValidateProductID\t\t700\n"
637     "CostInitialize\t\t800\n"
638     "FileCost\t\t900\n"
639     "CostFinalize\t\t1000\n"
640     "InstallValidate\t\t1400\n"
641     "InstallInitialize\t\t1500\n"
642     "ProcessComponents\tPROCESS_COMPONENTS=1 Or FULL=1\t1600\n"
643     "UnpublishFeatures\tUNPUBLISH_FEATURES=1 Or FULL=1\t1800\n"
644     "RemoveFiles\t\t3500\n"
645     "InstallFiles\t\t4000\n"
646     "RegisterUser\tREGISTER_USER=1 Or FULL=1\t6000\n"
647     "RegisterProduct\tREGISTER_PRODUCT=1 Or FULL=1\t6100\n"
648     "PublishFeatures\tPUBLISH_FEATURES=1 Or FULL=1\t6300\n"
649     "PublishProduct\tPUBLISH_PRODUCT=1 Or FULL=1\t6400\n"
650     "InstallFinalize\t\t6600";
651 
652 static const char lus0_media_dat[] =
653     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
654     "i2\ti4\tL64\tS255\tS32\tS72\n"
655     "Media\tDiskId\n"
656     "1\t1\t\t\tDISK1\t\n";
657 
658 static const char lus1_media_dat[] =
659     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
660     "i2\ti4\tL64\tS255\tS32\tS72\n"
661     "Media\tDiskId\n"
662     "1\t1\t\ttest1.cab\tDISK1\t\n";
663 
664 static const char lus2_media_dat[] =
665     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
666     "i2\ti4\tL64\tS255\tS32\tS72\n"
667     "Media\tDiskId\n"
668     "1\t1\t\t#test1.cab\tDISK1\t\n";
669 
670 static const char spf_custom_action_dat[] =
671     "Action\tType\tSource\tTarget\tISComments\n"
672     "s72\ti2\tS64\tS0\tS255\n"
673     "CustomAction\tAction\n"
674     "SetFolderProp\t51\tMSITESTDIR\t[ProgramFilesFolder]\\msitest\\added\t\n";
675 
676 static const char spf_install_exec_seq_dat[] =
677     "Action\tCondition\tSequence\n"
678     "s72\tS255\tI2\n"
679     "InstallExecuteSequence\tAction\n"
680     "CostFinalize\t\t1000\n"
681     "CostInitialize\t\t800\n"
682     "FileCost\t\t900\n"
683     "SetFolderProp\t\t950\n"
684     "InstallFiles\t\t4000\n"
685     "InstallServices\t\t5000\n"
686     "InstallFinalize\t\t6600\n"
687     "InstallInitialize\t\t1500\n"
688     "InstallValidate\t\t1400\n"
689     "LaunchConditions\t\t100";
690 
691 static const char spf_install_ui_seq_dat[] =
692     "Action\tCondition\tSequence\n"
693     "s72\tS255\tI2\n"
694     "InstallUISequence\tAction\n"
695     "CostInitialize\t\t800\n"
696     "FileCost\t\t900\n"
697     "CostFinalize\t\t1000\n"
698     "ExecuteAction\t\t1100\n";
699 
700 static const char sd_file_dat[] =
701     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
702     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
703     "File\tFile\n"
704     "sourcedir.txt\tsourcedir\tsourcedir.txt\t1000\t\t\t8192\t1\n";
705 
706 static const char sd_feature_dat[] =
707     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
708     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
709     "Feature\tFeature\n"
710     "sourcedir\t\t\tsourcedir feature\t1\t2\tMSITESTDIR\t0\n";
711 
712 static const char sd_feature_comp_dat[] =
713     "Feature_\tComponent_\n"
714     "s38\ts72\n"
715     "FeatureComponents\tFeature_\tComponent_\n"
716     "sourcedir\tsourcedir\n";
717 
718 static const char sd_component_dat[] =
719     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
720     "s72\tS38\ts72\ti2\tS255\tS72\n"
721     "Component\tComponent\n"
722     "sourcedir\t{DD422F92-3ED8-49B5-A0B7-F266F98357DF}\tMSITESTDIR\t0\t\tsourcedir.txt\n";
723 
724 static const char sd_install_ui_seq_dat[] =
725     "Action\tCondition\tSequence\n"
726     "s72\tS255\tI2\n"
727     "InstallUISequence\tAction\n"
728     "TestSourceDirProp1\tnot SourceDir and not SOURCEDIR and not Installed\t99\n"
729     "AppSearch\t\t100\n"
730     "TestSourceDirProp2\tnot SourceDir and not SOURCEDIR and not Installed\t101\n"
731     "LaunchConditions\tnot Installed \t110\n"
732     "TestSourceDirProp3\tnot SourceDir and not SOURCEDIR and not Installed\t111\n"
733     "FindRelatedProducts\t\t120\n"
734     "TestSourceDirProp4\tnot SourceDir and not SOURCEDIR and not Installed\t121\n"
735     "CCPSearch\t\t130\n"
736     "TestSourceDirProp5\tnot SourceDir and not SOURCEDIR and not Installed\t131\n"
737     "RMCCPSearch\t\t140\n"
738     "TestSourceDirProp6\tnot SourceDir and not SOURCEDIR and not Installed\t141\n"
739     "ValidateProductID\t\t150\n"
740     "TestSourceDirProp7\tnot SourceDir and not SOURCEDIR and not Installed\t151\n"
741     "CostInitialize\t\t800\n"
742     "TestSourceDirProp8\tnot SourceDir and not SOURCEDIR and not Installed\t801\n"
743     "FileCost\t\t900\n"
744     "TestSourceDirProp9\tnot SourceDir and not SOURCEDIR and not Installed\t901\n"
745     "IsolateComponents\t\t1000\n"
746     "TestSourceDirProp10\tnot SourceDir and not SOURCEDIR and not Installed\t1001\n"
747     "CostFinalize\t\t1100\n"
748     "TestSourceDirProp11\tnot SourceDir and not SOURCEDIR and not Installed\t1101\n"
749     "MigrateFeatureStates\t\t1200\n"
750     "TestSourceDirProp12\tnot SourceDir and not SOURCEDIR and not Installed\t1201\n"
751     "ExecuteAction\t\t1300\n"
752     "TestSourceDirProp13\tnot SourceDir and not SOURCEDIR and not Installed\t1301\n";
753 
754 static const char sd_install_exec_seq_dat[] =
755     "Action\tCondition\tSequence\n"
756     "s72\tS255\tI2\n"
757     "InstallExecuteSequence\tAction\n"
758     "TestSourceDirProp14\tSourceDir and SOURCEDIR and not Installed\t99\n"
759     "LaunchConditions\t\t100\n"
760     "TestSourceDirProp15\tSourceDir and SOURCEDIR and not Installed\t101\n"
761     "ValidateProductID\t\t700\n"
762     "TestSourceDirProp16\tSourceDir and SOURCEDIR and not Installed\t701\n"
763     "CostInitialize\t\t800\n"
764     "TestSourceDirProp17\tSourceDir and SOURCEDIR and not Installed\t801\n"
765     "ResolveSource\tResolveSource and not Installed\t850\n"
766     "TestSourceDirProp18\tResolveSource and not SourceDir and not SOURCEDIR and not Installed\t851\n"
767     "TestSourceDirProp19\tnot ResolveSource and SourceDir and SOURCEDIR and not Installed\t852\n"
768     "FileCost\t\t900\n"
769     "TestSourceDirProp20\tSourceDir and SOURCEDIR and not Installed\t901\n"
770     "IsolateComponents\t\t1000\n"
771     "TestSourceDirProp21\tSourceDir and SOURCEDIR and not Installed\t1001\n"
772     "CostFinalize\t\t1100\n"
773     "TestSourceDirProp22\tSourceDir and SOURCEDIR and not Installed\t1101\n"
774     "MigrateFeatureStates\t\t1200\n"
775     "TestSourceDirProp23\tSourceDir and SOURCEDIR and not Installed\t1201\n"
776     "InstallValidate\t\t1400\n"
777     "TestSourceDirProp24\tSourceDir and SOURCEDIR and not Installed\t1401\n"
778     "InstallInitialize\t\t1500\n"
779     "TestSourceDirProp25\tSourceDir and SOURCEDIR and not Installed\t1501\n"
780     "ProcessComponents\t\t1600\n"
781     "TestSourceDirProp26\tnot SourceDir and not SOURCEDIR and not Installed\t1601\n"
782     "UnpublishFeatures\t\t1800\n"
783     "TestSourceDirProp27\tnot SourceDir and not SOURCEDIR and not Installed\t1801\n"
784     "RemoveFiles\t\t3500\n"
785     "TestSourceDirProp28\tnot SourceDir and not SOURCEDIR and not Installed\t3501\n"
786     "InstallFiles\t\t4000\n"
787     "TestSourceDirProp29\tnot SourceDir and not SOURCEDIR and not Installed\t4001\n"
788     "RegisterUser\t\t6000\n"
789     "TestSourceDirProp30\tnot SourceDir and not SOURCEDIR and not Installed\t6001\n"
790     "RegisterProduct\t\t6100\n"
791     "TestSourceDirProp31\tnot SourceDir and not SOURCEDIR and not Installed\t6101\n"
792     "PublishFeatures\t\t6300\n"
793     "TestSourceDirProp32\tnot SourceDir and not SOURCEDIR and not Installed\t6301\n"
794     "PublishProduct\t\t6400\n"
795     "TestSourceDirProp33\tnot SourceDir and not SOURCEDIR and not Installed\t6401\n"
796     "InstallExecute\t\t6500\n"
797     "TestSourceDirProp34\tnot SourceDir and not SOURCEDIR and not Installed\t6501\n"
798     "InstallFinalize\t\t6600\n"
799     "TestSourceDirProp35\tnot SourceDir and not SOURCEDIR and not Installed\t6601\n";
800 
801 static const char sd_custom_action_dat[] =
802     "Action\tType\tSource\tTarget\tISComments\n"
803     "s72\ti2\tS64\tS0\tS255\n"
804     "CustomAction\tAction\n"
805     "TestSourceDirProp1\t19\t\tTest 1 failed\t\n"
806     "TestSourceDirProp2\t19\t\tTest 2 failed\t\n"
807     "TestSourceDirProp3\t19\t\tTest 3 failed\t\n"
808     "TestSourceDirProp4\t19\t\tTest 4 failed\t\n"
809     "TestSourceDirProp5\t19\t\tTest 5 failed\t\n"
810     "TestSourceDirProp6\t19\t\tTest 6 failed\t\n"
811     "TestSourceDirProp7\t19\t\tTest 7 failed\t\n"
812     "TestSourceDirProp8\t19\t\tTest 8 failed\t\n"
813     "TestSourceDirProp9\t19\t\tTest 9 failed\t\n"
814     "TestSourceDirProp10\t19\t\tTest 10 failed\t\n"
815     "TestSourceDirProp11\t19\t\tTest 11 failed\t\n"
816     "TestSourceDirProp12\t19\t\tTest 12 failed\t\n"
817     "TestSourceDirProp13\t19\t\tTest 13 failed\t\n"
818     "TestSourceDirProp14\t19\t\tTest 14 failed\t\n"
819     "TestSourceDirProp15\t19\t\tTest 15 failed\t\n"
820     "TestSourceDirProp16\t19\t\tTest 16 failed\t\n"
821     "TestSourceDirProp17\t19\t\tTest 17 failed\t\n"
822     "TestSourceDirProp18\t19\t\tTest 18 failed\t\n"
823     "TestSourceDirProp19\t19\t\tTest 19 failed\t\n"
824     "TestSourceDirProp20\t19\t\tTest 20 failed\t\n"
825     "TestSourceDirProp21\t19\t\tTest 21 failed\t\n"
826     "TestSourceDirProp22\t19\t\tTest 22 failed\t\n"
827     "TestSourceDirProp23\t19\t\tTest 23 failed\t\n"
828     "TestSourceDirProp24\t19\t\tTest 24 failed\t\n"
829     "TestSourceDirProp25\t19\t\tTest 25 failed\t\n"
830     "TestSourceDirProp26\t19\t\tTest 26 failed\t\n"
831     "TestSourceDirProp27\t19\t\tTest 27 failed\t\n"
832     "TestSourceDirProp28\t19\t\tTest 28 failed\t\n"
833     "TestSourceDirProp29\t19\t\tTest 29 failed\t\n"
834     "TestSourceDirProp30\t19\t\tTest 30 failed\t\n"
835     "TestSourceDirProp31\t19\t\tTest 31 failed\t\n"
836     "TestSourceDirProp32\t19\t\tTest 32 failed\t\n"
837     "TestSourceDirProp33\t19\t\tTest 33 failed\t\n"
838     "TestSourceDirProp34\t19\t\tTest 34 failed\t\n"
839     "TestSourceDirProp35\t19\t\tTest 35 failed\t\n";
840 
841 static const char ci_install_exec_seq_dat[] =
842     "Action\tCondition\tSequence\n"
843     "s72\tS255\tI2\n"
844     "InstallExecuteSequence\tAction\n"
845     "CostInitialize\t\t800\n"
846     "FileCost\t\t900\n"
847     "CostFinalize\t\t1000\n"
848     "InstallValidate\t\t1400\n"
849     "InstallInitialize\t\t1500\n"
850     "RunInstall\tnot Installed\t1550\n"
851     "ProcessComponents\t\t1600\n"
852     "UnpublishFeatures\t\t1800\n"
853     "RemoveFiles\t\t3500\n"
854     "InstallFiles\t\t4000\n"
855     "RegisterProduct\t\t6100\n"
856     "PublishFeatures\t\t6300\n"
857     "PublishProduct\t\t6400\n"
858     "InstallFinalize\t\t6600\n";
859 
860 static const char ci_custom_action_dat[] =
861     "Action\tType\tSource\tTarget\tISComments\n"
862     "s72\ti2\tS64\tS0\tS255\n"
863     "CustomAction\tAction\n"
864     "RunInstall\t23\tmsitest\\concurrent.msi\tMYPROP=[UILevel]\t\n";
865 
866 static const char ci_component_dat[] =
867     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
868     "s72\tS38\ts72\ti2\tS255\tS72\n"
869     "Component\tComponent\n"
870     "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
871 
872 static const char ci2_component_dat[] =
873     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
874     "s72\tS38\ts72\ti2\tS255\tS72\n"
875     "Component\tComponent\n"
876     "augustus\t\tMSITESTDIR\t0\tUILevel=3 AND MYPROP=5\taugustus\n";
877 
878 static const char ci2_feature_comp_dat[] =
879     "Feature_\tComponent_\n"
880     "s38\ts72\n"
881     "FeatureComponents\tFeature_\tComponent_\n"
882     "feature\taugustus";
883 
884 static const char ci2_file_dat[] =
885     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
886     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
887     "File\tFile\n"
888     "augustus\taugustus\taugustus\t500\t\t\t8192\t1";
889 
890 static const char cl_custom_action_dat[] =
891     "Action\tType\tSource\tTarget\tISComments\n"
892     "s72\ti2\tS64\tS0\tS255\n"
893     "CustomAction\tAction\n"
894     "TestCommandlineProp\t19\t\tTest1\t\n";
895 
896 static const char cl_install_exec_seq_dat[] =
897     "Action\tCondition\tSequence\n"
898     "s72\tS255\tI2\n"
899     "InstallExecuteSequence\tAction\n"
900     "LaunchConditions\t\t100\n"
901     "ValidateProductID\t\t700\n"
902     "CostInitialize\t\t800\n"
903     "FileCost\t\t900\n"
904     "CostFinalize\t\t1000\n"
905     "TestCommandlineProp\tP=\"one\"\t1100\n"
906     "InstallInitialize\t\t1500\n"
907     "ProcessComponents\t\t1600\n"
908     "InstallValidate\t\t1400\n"
909     "InstallFinalize\t\t5000\n";
910 
911 typedef struct _msi_table
912 {
913     const CHAR *filename;
914     const CHAR *data;
915     int size;
916 } msi_table;
917 
918 #define ADD_TABLE(x) {#x".idt", x##_dat, sizeof(x##_dat)}
919 
920 static const msi_table tables[] =
921 {
922     ADD_TABLE(directory),
923     ADD_TABLE(component),
924     ADD_TABLE(feature),
925     ADD_TABLE(feature_comp),
926     ADD_TABLE(file),
927     ADD_TABLE(install_exec_seq),
928     ADD_TABLE(media),
929     ADD_TABLE(property),
930 };
931 
932 static const msi_table mcp_tables[] =
933 {
934     ADD_TABLE(directory),
935     ADD_TABLE(mcp_component),
936     ADD_TABLE(mcp_feature),
937     ADD_TABLE(mcp_feature_comp),
938     ADD_TABLE(mcp_file),
939     ADD_TABLE(install_exec_seq),
940     ADD_TABLE(media),
941     ADD_TABLE(property)
942 };
943 
944 static const msi_table lus0_tables[] =
945 {
946     ADD_TABLE(lus_component),
947     ADD_TABLE(directory),
948     ADD_TABLE(lus_feature),
949     ADD_TABLE(lus_feature_comp),
950     ADD_TABLE(lus_file),
951     ADD_TABLE(lus_install_exec_seq),
952     ADD_TABLE(lus0_media),
953     ADD_TABLE(property)
954 };
955 
956 static const msi_table lus1_tables[] =
957 {
958     ADD_TABLE(lus_component),
959     ADD_TABLE(directory),
960     ADD_TABLE(lus_feature),
961     ADD_TABLE(lus_feature_comp),
962     ADD_TABLE(lus_file),
963     ADD_TABLE(lus_install_exec_seq),
964     ADD_TABLE(lus1_media),
965     ADD_TABLE(property)
966 };
967 
968 static const msi_table lus2_tables[] =
969 {
970     ADD_TABLE(lus_component),
971     ADD_TABLE(directory),
972     ADD_TABLE(lus_feature),
973     ADD_TABLE(lus_feature_comp),
974     ADD_TABLE(lus_file),
975     ADD_TABLE(lus_install_exec_seq),
976     ADD_TABLE(lus2_media),
977     ADD_TABLE(property)
978 };
979 
980 static const msi_table spf_tables[] =
981 {
982     ADD_TABLE(lus_component),
983     ADD_TABLE(directory),
984     ADD_TABLE(lus_feature),
985     ADD_TABLE(lus_feature_comp),
986     ADD_TABLE(lus_file),
987     ADD_TABLE(lus0_media),
988     ADD_TABLE(property),
989     ADD_TABLE(spf_custom_action),
990     ADD_TABLE(spf_install_exec_seq),
991     ADD_TABLE(spf_install_ui_seq)
992 };
993 
994 static const msi_table sd_tables[] =
995 {
996     ADD_TABLE(directory),
997     ADD_TABLE(sd_component),
998     ADD_TABLE(sd_feature),
999     ADD_TABLE(sd_feature_comp),
1000     ADD_TABLE(sd_file),
1001     ADD_TABLE(sd_install_exec_seq),
1002     ADD_TABLE(sd_install_ui_seq),
1003     ADD_TABLE(sd_custom_action),
1004     ADD_TABLE(media),
1005     ADD_TABLE(property)
1006 };
1007 
1008 static const msi_table ci_tables[] =
1009 {
1010     ADD_TABLE(ci_component),
1011     ADD_TABLE(directory),
1012     ADD_TABLE(lus_feature),
1013     ADD_TABLE(lus_feature_comp),
1014     ADD_TABLE(lus_file),
1015     ADD_TABLE(ci_install_exec_seq),
1016     ADD_TABLE(lus0_media),
1017     ADD_TABLE(property),
1018     ADD_TABLE(ci_custom_action),
1019 };
1020 
1021 static const msi_table ci2_tables[] =
1022 {
1023     ADD_TABLE(ci2_component),
1024     ADD_TABLE(directory),
1025     ADD_TABLE(lus_feature),
1026     ADD_TABLE(ci2_feature_comp),
1027     ADD_TABLE(ci2_file),
1028     ADD_TABLE(install_exec_seq),
1029     ADD_TABLE(lus0_media),
1030     ADD_TABLE(ci2_property),
1031 };
1032 
1033 static const msi_table cl_tables[] =
1034 {
1035     ADD_TABLE(component),
1036     ADD_TABLE(directory),
1037     ADD_TABLE(feature),
1038     ADD_TABLE(feature_comp),
1039     ADD_TABLE(file),
1040     ADD_TABLE(cl_custom_action),
1041     ADD_TABLE(cl_install_exec_seq),
1042     ADD_TABLE(media),
1043     ADD_TABLE(property)
1044 };
1045 
1046 static void write_file(const CHAR *filename, const char *data, int data_size)
1047 {
1048     DWORD size;
1049 
1050     HANDLE hf = CreateFileA(filename, GENERIC_WRITE, 0, NULL,
1051                             CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1052     WriteFile(hf, data, data_size, &size, NULL);
1053     CloseHandle(hf);
1054 }
1055 
1056 static void write_msi_summary_info(MSIHANDLE db, INT version, INT wordcount, const char *template)
1057 {
1058     MSIHANDLE summary;
1059     UINT r;
1060 
1061     r = MsiGetSummaryInformationA(db, NULL, 5, &summary);
1062     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1063 
1064     r = MsiSummaryInfoSetPropertyA(summary, PID_TEMPLATE, VT_LPSTR, 0, NULL, template);
1065     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1066 
1067     r = MsiSummaryInfoSetPropertyA(summary, PID_REVNUMBER, VT_LPSTR, 0, NULL,
1068                                    "{004757CA-5092-49C2-AD20-28E1CE0DF5F2}");
1069     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1070 
1071     r = MsiSummaryInfoSetPropertyA(summary, PID_PAGECOUNT, VT_I4, version, NULL, NULL);
1072     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1073 
1074     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, wordcount, NULL, NULL);
1075     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1076 
1077     r = MsiSummaryInfoSetPropertyA(summary, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
1078     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1079 
1080     /* write the summary changes back to the stream */
1081     r = MsiSummaryInfoPersist(summary);
1082     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1083 
1084     MsiCloseHandle(summary);
1085 }
1086 
1087 #define create_database(name, tables, num_tables) \
1088     create_database_wordcount(name, tables, num_tables, 100, 0, ";1033");
1089 
1090 #define create_database_template(name, tables, num_tables, version, template) \
1091     create_database_wordcount(name, tables, num_tables, version, 0, template);
1092 
1093 static void create_database_wordcount(const CHAR *name, const msi_table *tables,
1094                                       int num_tables, INT version, INT wordcount,
1095                                       const char *template)
1096 {
1097     MSIHANDLE db;
1098     UINT r;
1099     WCHAR *nameW;
1100     int j, len;
1101 
1102     len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 );
1103     if (!(nameW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return;
1104     MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, len );
1105 
1106     r = MsiOpenDatabaseW(nameW, MSIDBOPEN_CREATE, &db);
1107     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1108 
1109     /* import the tables into the database */
1110     for (j = 0; j < num_tables; j++)
1111     {
1112         const msi_table *table = &tables[j];
1113 
1114         write_file(table->filename, table->data, (table->size - 1) * sizeof(char));
1115 
1116         r = MsiDatabaseImportA(db, CURR_DIR, table->filename);
1117         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1118 
1119         DeleteFileA(table->filename);
1120     }
1121 
1122     write_msi_summary_info(db, version, wordcount, template);
1123 
1124     r = MsiDatabaseCommit(db);
1125     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1126 
1127     MsiCloseHandle(db);
1128     HeapFree( GetProcessHeap(), 0, nameW );
1129 }
1130 
1131 static UINT run_query(MSIHANDLE hdb, const char *query)
1132 {
1133     MSIHANDLE hview = 0;
1134     UINT r;
1135 
1136     r = MsiDatabaseOpenViewA(hdb, query, &hview);
1137     if (r != ERROR_SUCCESS)
1138         return r;
1139 
1140     r = MsiViewExecute(hview, 0);
1141     if (r == ERROR_SUCCESS)
1142         r = MsiViewClose(hview);
1143     MsiCloseHandle(hview);
1144     return r;
1145 }
1146 
1147 static UINT set_summary_info(MSIHANDLE hdb, LPSTR prodcode)
1148 {
1149     UINT res;
1150     MSIHANDLE suminfo;
1151 
1152     /* build summary info */
1153     res = MsiGetSummaryInformationA(hdb, NULL, 7, &suminfo);
1154     ok(res == ERROR_SUCCESS, "Failed to open summaryinfo\n");
1155 
1156     res = MsiSummaryInfoSetPropertyA(suminfo, 2, VT_LPSTR, 0, NULL,
1157                                     "Installation Database");
1158     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1159 
1160     res = MsiSummaryInfoSetPropertyA(suminfo, 3, VT_LPSTR, 0, NULL,
1161                                     "Installation Database");
1162     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1163 
1164     res = MsiSummaryInfoSetPropertyA(suminfo, 4, VT_LPSTR, 0, NULL,
1165                                     "Wine Hackers");
1166     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1167 
1168     res = MsiSummaryInfoSetPropertyA(suminfo, 7, VT_LPSTR, 0, NULL,
1169                                     ";1033");
1170     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1171 
1172     res = MsiSummaryInfoSetPropertyA(suminfo, PID_REVNUMBER, VT_LPSTR, 0, NULL,
1173                                     "{A2078D65-94D6-4205-8DEE-F68D6FD622AA}");
1174     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1175 
1176     res = MsiSummaryInfoSetPropertyA(suminfo, 14, VT_I4, 100, NULL, NULL);
1177     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1178 
1179     res = MsiSummaryInfoSetPropertyA(suminfo, 15, VT_I4, 0, NULL, NULL);
1180     ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1181 
1182     res = MsiSummaryInfoPersist(suminfo);
1183     ok(res == ERROR_SUCCESS, "Failed to make summary info persist\n");
1184 
1185     res = MsiCloseHandle(suminfo);
1186     ok(res == ERROR_SUCCESS, "Failed to close suminfo\n");
1187 
1188     return res;
1189 }
1190 
1191 static MSIHANDLE create_package_db(LPSTR prodcode)
1192 {
1193     MSIHANDLE hdb = 0;
1194     CHAR query[MAX_PATH];
1195     UINT res;
1196 
1197     DeleteFileA(msifile);
1198 
1199     /* create an empty database */
1200     res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
1201     ok( res == ERROR_SUCCESS , "Failed to create database\n" );
1202     if (res != ERROR_SUCCESS)
1203         return hdb;
1204 
1205     res = MsiDatabaseCommit(hdb);
1206     ok(res == ERROR_SUCCESS, "Failed to commit database\n");
1207 
1208     set_summary_info(hdb, prodcode);
1209 
1210     res = run_query(hdb,
1211             "CREATE TABLE `Directory` ( "
1212             "`Directory` CHAR(255) NOT NULL, "
1213             "`Directory_Parent` CHAR(255), "
1214             "`DefaultDir` CHAR(255) NOT NULL "
1215             "PRIMARY KEY `Directory`)");
1216     ok(res == ERROR_SUCCESS , "Failed to create directory table\n");
1217 
1218     res = run_query(hdb,
1219             "CREATE TABLE `Property` ( "
1220             "`Property` CHAR(72) NOT NULL, "
1221             "`Value` CHAR(255) "
1222             "PRIMARY KEY `Property`)");
1223     ok(res == ERROR_SUCCESS , "Failed to create directory table\n");
1224 
1225     sprintf(query, "INSERT INTO `Property` "
1226             "(`Property`, `Value`) "
1227             "VALUES( 'ProductCode', '%s' )", prodcode);
1228     res = run_query(hdb, query);
1229     ok(res == ERROR_SUCCESS , "Failed\n");
1230 
1231     res = MsiDatabaseCommit(hdb);
1232     ok(res == ERROR_SUCCESS, "Failed to commit database\n");
1233 
1234     return hdb;
1235 }
1236 
1237 static void test_usefeature(void)
1238 {
1239     INSTALLSTATE r;
1240 
1241     if (!pMsiUseFeatureExA)
1242     {
1243         win_skip("MsiUseFeatureExA not implemented\n");
1244         return;
1245     }
1246 
1247     r = MsiQueryFeatureStateA(NULL, NULL);
1248     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1249 
1250     r = MsiQueryFeatureStateA("{9085040-6000-11d3-8cfe-0150048383c9}" ,NULL);
1251     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1252 
1253     r = pMsiUseFeatureExA(NULL,NULL,0,0);
1254     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1255 
1256     r = pMsiUseFeatureExA(NULL, "WORDVIEWFiles", -2, 1 );
1257     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1258 
1259     r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}",
1260                          NULL, -2, 0 );
1261     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1262 
1263     r = pMsiUseFeatureExA("{9085040-6000-11d3-8cfe-0150048383c9}",
1264                          "WORDVIEWFiles", -2, 0 );
1265     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1266 
1267     r = pMsiUseFeatureExA("{0085040-6000-11d3-8cfe-0150048383c9}",
1268                          "WORDVIEWFiles", -2, 0 );
1269     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1270 
1271     r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}",
1272                          "WORDVIEWFiles", -2, 1 );
1273     ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1274 }
1275 
1276 static LONG delete_key( HKEY key, LPCSTR subkey, REGSAM access )
1277 {
1278     if (pRegDeleteKeyExA)
1279         return pRegDeleteKeyExA( key, subkey, access, 0 );
1280     return RegDeleteKeyA( key, subkey );
1281 }
1282 
1283 static void test_null(void)
1284 {
1285     MSIHANDLE hpkg;
1286     UINT r;
1287     HKEY hkey;
1288     DWORD dwType, cbData;
1289     LPBYTE lpData = NULL;
1290     INSTALLSTATE state;
1291     REGSAM access = KEY_ALL_ACCESS;
1292 
1293     if (is_wow64)
1294         access |= KEY_WOW64_64KEY;
1295 
1296     r = pMsiOpenPackageExW(NULL, 0, &hpkg);
1297     ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
1298 
1299     state = MsiQueryProductStateW(NULL);
1300     ok( state == INSTALLSTATE_INVALIDARG, "wrong return\n");
1301 
1302     r = MsiEnumFeaturesW(NULL,0,NULL,NULL);
1303     ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
1304 
1305     r = MsiConfigureFeatureW(NULL, NULL, 0);
1306     ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
1307 
1308     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", NULL, 0);
1309     ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
1310 
1311     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000001}", "foo", 0);
1312     ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
1313 
1314     r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000002}", "foo", INSTALLSTATE_DEFAULT);
1315     ok( r == ERROR_UNKNOWN_PRODUCT, "wrong error %d\n", r);
1316 
1317     /* make sure empty string to MsiGetProductInfo is not a handle to default registry value, saving and restoring the
1318      * necessary registry values */
1319 
1320     /* empty product string */
1321     r = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", 0, access, &hkey);
1322     if (r == ERROR_ACCESS_DENIED)
1323     {
1324         skip("Not enough rights to perform tests\n");
1325         return;
1326     }
1327     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1328 
1329     r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
1330     ok ( r == ERROR_SUCCESS || r == ERROR_FILE_NOT_FOUND, "wrong error %d\n", r);
1331     if ( r == ERROR_SUCCESS )
1332     {
1333         lpData = HeapAlloc(GetProcessHeap(), 0, cbData);
1334         if (!lpData)
1335             skip("Out of memory\n");
1336         else
1337         {
1338             r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
1339             ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
1340         }
1341     }
1342 
1343     r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
1344     if (r == ERROR_ACCESS_DENIED)
1345     {
1346         skip("Not enough rights to perform tests\n");
1347         HeapFree(GetProcessHeap(), 0, lpData);
1348         RegCloseKey(hkey);
1349         return;
1350     }
1351     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1352 
1353     r = MsiGetProductInfoA("", "", NULL, NULL);
1354     ok ( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
1355 
1356     if (lpData)
1357     {
1358         r = RegSetValueExA(hkey, NULL, 0, dwType, lpData, cbData);
1359         ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
1360 
1361         HeapFree(GetProcessHeap(), 0, lpData);
1362     }
1363     else
1364     {
1365         r = RegDeleteValueA(hkey, NULL);
1366         ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
1367     }
1368 
1369     r = RegCloseKey(hkey);
1370     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1371 
1372     /* empty attribute */
1373     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}",
1374                         0, NULL, 0, access, NULL, &hkey, NULL);
1375     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1376 
1377     r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
1378     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1379 
1380     r = MsiGetProductInfoA("{F1C3AF50-8B56-4A69-A00C-00773FE42F30}", "", NULL, NULL);
1381     ok ( r == ERROR_UNKNOWN_PROPERTY, "wrong error %d\n", r);
1382 
1383     r = RegCloseKey(hkey);
1384     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1385 
1386     r = delete_key(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}",
1387                    access & KEY_WOW64_64KEY);
1388     ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1389 }
1390 
1391 static void test_getcomponentpath(void)
1392 {
1393     INSTALLSTATE r;
1394     char buffer[0x100];
1395     DWORD sz;
1396 
1397     if(!pMsiGetComponentPathA)
1398         return;
1399 
1400     r = pMsiGetComponentPathA( NULL, NULL, NULL, NULL );
1401     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1402 
1403     r = pMsiGetComponentPathA( "bogus", "bogus", NULL, NULL );
1404     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1405 
1406     r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", NULL, NULL );
1407     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1408 
1409     sz = sizeof buffer;
1410     buffer[0]=0;
1411     r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", buffer, &sz );
1412     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1413 
1414     r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C998E7}",
1415         "{00000000-0000-0000-0000-000000000000}", buffer, &sz );
1416     ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
1417 
1418     r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
1419         "{00000000-0000-0000-0000-00000000}", buffer, &sz );
1420     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1421 
1422     r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
1423         "{029E403D-A86A-1D11-5B5B0006799C897E}", buffer, &sz );
1424     ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1425 
1426     r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C9987e}",
1427                             "{00000000-A68A-11d1-5B5B-0006799C897E}", buffer, &sz );
1428     ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
1429 }
1430 
1431 static void create_file(LPCSTR name, LPCSTR data, DWORD size)
1432 {
1433     HANDLE file;
1434     DWORD written;
1435 
1436     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1437     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
1438     WriteFile(file, data, strlen(data), &written, NULL);
1439 
1440     if (size)
1441     {
1442         SetFilePointer(file, size, NULL, FILE_BEGIN);
1443         SetEndOfFile(file);
1444     }
1445 
1446     CloseHandle(file);
1447 }
1448 
1449 static void create_test_files(void)
1450 {
1451     CreateDirectoryA("msitest", NULL);
1452     create_file("msitest\\one.txt", "msitest\\one.txt", 100);
1453     CreateDirectoryA("msitest\\first", NULL);
1454     create_file("msitest\\first\\two.txt", "msitest\\first\\two.txt", 100);
1455     CreateDirectoryA("msitest\\second", NULL);
1456     create_file("msitest\\second\\three.txt", "msitest\\second\\three.txt", 100);
1457 
1458     create_file("four.txt", "four.txt", 100);
1459     create_file("five.txt", "five.txt", 100);
1460     create_cab_file("msitest.cab", MEDIA_SIZE, "four.txt\0five.txt\0");
1461 
1462     create_file("msitest\\filename", "msitest\\filename", 100);
1463     create_file("msitest\\service.exe", "msitest\\service.exe", 100);
1464 
1465     DeleteFileA("four.txt");
1466     DeleteFileA("five.txt");
1467 }
1468 
1469 static void delete_test_files(void)
1470 {
1471     DeleteFileA("msitest.msi");
1472     DeleteFileA("msitest.cab");
1473     DeleteFileA("msitest\\second\\three.txt");
1474     DeleteFileA("msitest\\first\\two.txt");
1475     DeleteFileA("msitest\\one.txt");
1476     DeleteFileA("msitest\\service.exe");
1477     DeleteFileA("msitest\\filename");
1478     RemoveDirectoryA("msitest\\second");
1479     RemoveDirectoryA("msitest\\first");
1480     RemoveDirectoryA("msitest");
1481 }
1482 
1483 #define HASHSIZE sizeof(MSIFILEHASHINFO)
1484 
1485 static const struct
1486 {
1487     LPCSTR data;
1488     DWORD size;
1489     MSIFILEHASHINFO hash;
1490 } hash_data[] =
1491 {
1492     { "", 0,
1493       { HASHSIZE,
1494         { 0, 0, 0, 0 },
1495       },
1496     },
1497 
1498     { "abc", 0,
1499       { HASHSIZE,
1500         { 0x98500190, 0xb04fd23c, 0x7d3f96d6, 0x727fe128 },
1501       },
1502     },
1503 
1504     { "C:\\Program Files\\msitest\\caesar\n", 0,
1505       { HASHSIZE,
1506         { 0x2b566794, 0xfd42181b, 0x2514d6e4, 0x5768b4e2 },
1507       },
1508     },
1509 
1510     { "C:\\Program Files\\msitest\\caesar\n", 500,
1511       { HASHSIZE,
1512         { 0x58095058, 0x805efeff, 0x10f3483e, 0x0147d653 },
1513       },
1514     },
1515 };
1516 
1517 static void test_MsiGetFileHash(void)
1518 {
1519     const char name[] = "msitest.bin";
1520     UINT r;
1521     MSIFILEHASHINFO hash;
1522     DWORD i;
1523 
1524     if (!pMsiGetFileHashA)
1525     {
1526         win_skip("MsiGetFileHash not implemented\n");
1527         return;
1528     }
1529 
1530     hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
1531 
1532     /* szFilePath is NULL */
1533     r = pMsiGetFileHashA(NULL, 0, &hash);
1534     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1535 
1536     /* szFilePath is empty */
1537     r = pMsiGetFileHashA("", 0, &hash);
1538     ok(r == ERROR_PATH_NOT_FOUND || r == ERROR_BAD_PATHNAME,
1539        "Expected ERROR_PATH_NOT_FOUND or ERROR_BAD_PATHNAME, got %d\n", r);
1540 
1541     /* szFilePath is nonexistent */
1542     r = pMsiGetFileHashA(name, 0, &hash);
1543     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
1544 
1545     /* dwOptions is non-zero */
1546     r = pMsiGetFileHashA(name, 1, &hash);
1547     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1548 
1549     /* pHash.dwFileHashInfoSize is not correct */
1550     hash.dwFileHashInfoSize = 0;
1551     r = pMsiGetFileHashA(name, 0, &hash);
1552     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1553 
1554     /* pHash is NULL */
1555     r = pMsiGetFileHashA(name, 0, NULL);
1556     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1557 
1558     for (i = 0; i < sizeof(hash_data) / sizeof(hash_data[0]); i++)
1559     {
1560         int ret;
1561 
1562         create_file(name, hash_data[i].data, hash_data[i].size);
1563 
1564         memset(&hash, 0, sizeof(MSIFILEHASHINFO));
1565         hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
1566 
1567         r = pMsiGetFileHashA(name, 0, &hash);
1568         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1569 
1570         ret = memcmp(&hash, &hash_data[i].hash, HASHSIZE);
1571         ok(!ret, "Hash incorrect\n");
1572 
1573         DeleteFileA(name);
1574     }
1575 }
1576 
1577 /* copied from dlls/msi/registry.c */
1578 static BOOL squash_guid(LPCWSTR in, LPWSTR out)
1579 {
1580     DWORD i,n=1;
1581     GUID guid;
1582 
1583     if (FAILED(CLSIDFromString((LPCOLESTR)in, &guid)))
1584         return FALSE;
1585 
1586     for(i=0; i<8; i++)
1587         out[7-i] = in[n++];
1588     n++;
1589     for(i=0; i<4; i++)
1590         out[11-i] = in[n++];
1591     n++;
1592     for(i=0; i<4; i++)
1593         out[15-i] = in[n++];
1594     n++;
1595     for(i=0; i<2; i++)
1596     {
1597         out[17+i*2] = in[n++];
1598         out[16+i*2] = in[n++];
1599     }
1600     n++;
1601     for( ; i<8; i++)
1602     {
1603         out[17+i*2] = in[n++];
1604         out[16+i*2] = in[n++];
1605     }
1606     out[32]=0;
1607     return TRUE;
1608 }
1609 
1610 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
1611 {
1612     WCHAR guidW[MAX_PATH];
1613     WCHAR squashedW[MAX_PATH];
1614     GUID guid;
1615     HRESULT hr;
1616     int size;
1617 
1618     hr = CoCreateGuid(&guid);
1619     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
1620 
1621     size = StringFromGUID2(&guid, guidW, MAX_PATH);
1622     ok(size == 39, "Expected 39, got %d\n", hr);
1623 
1624     WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
1625     if (squashed)
1626     {
1627         squash_guid(guidW, squashedW);
1628         WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
1629     }
1630 }
1631 
1632 static char *get_user_sid(void)
1633 {
1634     HANDLE token;
1635     DWORD size = 0;
1636     TOKEN_USER *user;
1637     char *usersid = NULL;
1638 
1639     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
1640     GetTokenInformation(token, TokenUser, NULL, size, &size);
1641 
1642     user = HeapAlloc(GetProcessHeap(), 0, size);
1643     GetTokenInformation(token, TokenUser, user, size, &size);
1644     pConvertSidToStringSidA(user->User.Sid, &usersid);
1645     HeapFree(GetProcessHeap(), 0, user);
1646 
1647     CloseHandle(token);
1648     return usersid;
1649 }
1650 
1651 static void test_MsiQueryProductState(void)
1652 {
1653     CHAR prodcode[MAX_PATH];
1654     CHAR prod_squashed[MAX_PATH];
1655     CHAR keypath[MAX_PATH*2];
1656     LPSTR usersid;
1657     INSTALLSTATE state;
1658     LONG res;
1659     HKEY userkey, localkey, props;
1660     HKEY prodkey;
1661     DWORD data, error;
1662     REGSAM access = KEY_ALL_ACCESS;
1663 
1664     create_test_guid(prodcode, prod_squashed);
1665     usersid = get_user_sid();
1666 
1667     if (is_wow64)
1668         access |= KEY_WOW64_64KEY;
1669 
1670     /* NULL prodcode */
1671     SetLastError(0xdeadbeef);
1672     state = MsiQueryProductStateA(NULL);
1673     error = GetLastError();
1674     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1675     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1676 
1677     /* empty prodcode */
1678     SetLastError(0xdeadbeef);
1679     state = MsiQueryProductStateA("");
1680     error = GetLastError();
1681     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1682     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1683 
1684     /* garbage prodcode */
1685     SetLastError(0xdeadbeef);
1686     state = MsiQueryProductStateA("garbage");
1687     error = GetLastError();
1688     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1689     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1690 
1691     /* guid without brackets */
1692     SetLastError(0xdeadbeef);
1693     state = MsiQueryProductStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D");
1694     error = GetLastError();
1695     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1696     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1697 
1698     /* guid with brackets */
1699     SetLastError(0xdeadbeef);
1700     state = MsiQueryProductStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}");
1701     error = GetLastError();
1702     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1703     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1704        "expected ERROR_SUCCESS, got %u\n", error);
1705 
1706     /* same length as guid, but random */
1707     SetLastError(0xdeadbeef);
1708     state = MsiQueryProductStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93");
1709     error = GetLastError();
1710     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1711     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1712 
1713     /* MSIINSTALLCONTEXT_USERUNMANAGED */
1714 
1715     SetLastError(0xdeadbeef);
1716     state = MsiQueryProductStateA(prodcode);
1717     error = GetLastError();
1718     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1719     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1720        "expected ERROR_SUCCESS, got %u\n", error);
1721 
1722     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
1723     lstrcatA(keypath, prod_squashed);
1724 
1725     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
1726     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1727 
1728     /* user product key exists */
1729     SetLastError(0xdeadbeef);
1730     state = MsiQueryProductStateA(prodcode);
1731     error = GetLastError();
1732     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1733     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1734        "expected ERROR_SUCCESS, got %u\n", error);
1735 
1736     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
1737     lstrcatA(keypath, prodcode);
1738 
1739     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1740     if (res == ERROR_ACCESS_DENIED)
1741     {
1742         skip("Not enough rights to perform tests\n");
1743         RegDeleteKeyA(userkey, "");
1744         RegCloseKey(userkey);
1745         LocalFree(usersid);
1746         return;
1747     }
1748     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1749 
1750     /* local uninstall key exists */
1751     SetLastError(0xdeadbeef);
1752     state = MsiQueryProductStateA(prodcode);
1753     error = GetLastError();
1754     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1755     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1756        "expected ERROR_SUCCESS, got %u\n", error);
1757 
1758     data = 1;
1759     res = RegSetValueExA(localkey, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1760     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1761 
1762     /* WindowsInstaller value exists */
1763     SetLastError(0xdeadbeef);
1764     state = MsiQueryProductStateA(prodcode);
1765     error = GetLastError();
1766     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1767     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1768        "expected ERROR_SUCCESS, got %u\n", error);
1769 
1770     RegDeleteValueA(localkey, "WindowsInstaller");
1771     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1772 
1773     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1774     lstrcatA(keypath, usersid);
1775     lstrcatA(keypath, "\\Products\\");
1776     lstrcatA(keypath, prod_squashed);
1777 
1778     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1779     if (res == ERROR_ACCESS_DENIED)
1780     {
1781         skip("Not enough rights to perform tests\n");
1782         RegDeleteKeyA(userkey, "");
1783         RegCloseKey(userkey);
1784         LocalFree(usersid);
1785         return;
1786     }
1787     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1788 
1789     /* local product key exists */
1790     SetLastError(0xdeadbeef);
1791     state = MsiQueryProductStateA(prodcode);
1792     error = GetLastError();
1793     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1794     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1795        "expected ERROR_SUCCESS, got %u\n", error);
1796 
1797     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1798     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1799 
1800     /* install properties key exists */
1801     SetLastError(0xdeadbeef);
1802     state = MsiQueryProductStateA(prodcode);
1803     error = GetLastError();
1804     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1805     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1806        "expected ERROR_SUCCESS, got %u\n", error);
1807 
1808     data = 1;
1809     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1810     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1811 
1812     /* WindowsInstaller value exists */
1813     SetLastError(0xdeadbeef);
1814     state = MsiQueryProductStateA(prodcode);
1815     error = GetLastError();
1816     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1817     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1818        "expected ERROR_SUCCESS, got %u\n", error);
1819 
1820     data = 2;
1821     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1822     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1823 
1824     /* WindowsInstaller value is not 1 */
1825     SetLastError(0xdeadbeef);
1826     state = MsiQueryProductStateA(prodcode);
1827     error = GetLastError();
1828     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1829     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1830        "expected ERROR_SUCCESS, got %u\n", error);
1831 
1832     RegDeleteKeyA(userkey, "");
1833 
1834     /* user product key does not exist */
1835     SetLastError(0xdeadbeef);
1836     state = MsiQueryProductStateA(prodcode);
1837     error = GetLastError();
1838     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1839     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1840        "expected ERROR_SUCCESS, got %u\n", error);
1841 
1842     RegDeleteValueA(props, "WindowsInstaller");
1843     delete_key(props, "", access & KEY_WOW64_64KEY);
1844     RegCloseKey(props);
1845     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1846     RegCloseKey(localkey);
1847     RegDeleteKeyA(userkey, "");
1848     RegCloseKey(userkey);
1849 
1850     /* MSIINSTALLCONTEXT_USERMANAGED */
1851 
1852     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
1853     lstrcatA(keypath, usersid);
1854     lstrcatA(keypath, "\\Installer\\Products\\");
1855     lstrcatA(keypath, prod_squashed);
1856 
1857     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
1858     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1859 
1860     state = MsiQueryProductStateA(prodcode);
1861     ok(state == INSTALLSTATE_ADVERTISED,
1862        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1863 
1864     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1865     lstrcatA(keypath, usersid);
1866     lstrcatA(keypath, "\\Products\\");
1867     lstrcatA(keypath, prod_squashed);
1868 
1869     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1870     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1871 
1872     state = MsiQueryProductStateA(prodcode);
1873     ok(state == INSTALLSTATE_ADVERTISED,
1874        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1875 
1876     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1877     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1878 
1879     state = MsiQueryProductStateA(prodcode);
1880     ok(state == INSTALLSTATE_ADVERTISED,
1881        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1882 
1883     data = 1;
1884     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1885     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1886 
1887     /* WindowsInstaller value exists */
1888     state = MsiQueryProductStateA(prodcode);
1889     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1890 
1891     RegDeleteValueA(props, "WindowsInstaller");
1892     delete_key(props, "", access & KEY_WOW64_64KEY);
1893     RegCloseKey(props);
1894     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1895     RegCloseKey(localkey);
1896     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
1897     RegCloseKey(prodkey);
1898 
1899     /* MSIINSTALLCONTEXT_MACHINE */
1900 
1901     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
1902     lstrcatA(keypath, prod_squashed);
1903 
1904     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
1905     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1906 
1907     state = MsiQueryProductStateA(prodcode);
1908     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1909 
1910     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1911     lstrcatA(keypath, "S-1-5-18\\Products\\");
1912     lstrcatA(keypath, prod_squashed);
1913 
1914     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1915     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1916 
1917     state = MsiQueryProductStateA(prodcode);
1918     ok(state == INSTALLSTATE_ADVERTISED,
1919        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1920 
1921     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1922     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1923 
1924     state = MsiQueryProductStateA(prodcode);
1925     ok(state == INSTALLSTATE_ADVERTISED,
1926        "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1927 
1928     data = 1;
1929     res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1930     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1931 
1932     /* WindowsInstaller value exists */
1933     state = MsiQueryProductStateA(prodcode);
1934     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1935 
1936     RegDeleteValueA(props, "WindowsInstaller");
1937     delete_key(props, "", access & KEY_WOW64_64KEY);
1938     RegCloseKey(props);
1939     delete_key(localkey, "", access & KEY_WOW64_64KEY);
1940     RegCloseKey(localkey);
1941     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
1942     RegCloseKey(prodkey);
1943 
1944     LocalFree(usersid);
1945 }
1946 
1947 static const char table_enc85[] =
1948 "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
1949 "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
1950 "yz{}~";
1951 
1952 /*
1953  *  Encodes a base85 guid given a GUID pointer
1954  *  Caller should provide a 21 character buffer for the encoded string.
1955  */
1956 static void encode_base85_guid( GUID *guid, LPWSTR str )
1957 {
1958     unsigned int x, *p, i;
1959 
1960     p = (unsigned int*) guid;
1961     for( i=0; i<4; i++ )
1962     {
1963         x = p[i];
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         x = x/85;
1972         *str++ = table_enc85[x%85];
1973     }
1974     *str = 0;
1975 }
1976 
1977 static void compose_base85_guid(LPSTR component, LPSTR comp_base85, LPSTR squashed)
1978 {
1979     WCHAR guidW[MAX_PATH];
1980     WCHAR base85W[MAX_PATH];
1981     WCHAR squashedW[MAX_PATH];
1982     GUID guid;
1983     HRESULT hr;
1984     int size;
1985 
1986     hr = CoCreateGuid(&guid);
1987     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
1988 
1989     size = StringFromGUID2(&guid, guidW, MAX_PATH);
1990     ok(size == 39, "Expected 39, got %d\n", hr);
1991 
1992     WideCharToMultiByte(CP_ACP, 0, guidW, size, component, MAX_PATH, NULL, NULL);
1993     encode_base85_guid(&guid, base85W);
1994     WideCharToMultiByte(CP_ACP, 0, base85W, -1, comp_base85, MAX_PATH, NULL, NULL);
1995     squash_guid(guidW, squashedW);
1996     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
1997 }
1998 
1999 static void test_MsiQueryFeatureState(void)
2000 {
2001     HKEY userkey, localkey, compkey, compkey2;
2002     CHAR prodcode[MAX_PATH];
2003     CHAR prod_squashed[MAX_PATH];
2004     CHAR component[MAX_PATH];
2005     CHAR comp_base85[MAX_PATH];
2006     CHAR comp_squashed[MAX_PATH], comp_squashed2[MAX_PATH];
2007     CHAR keypath[MAX_PATH*2];
2008     INSTALLSTATE state;
2009     LPSTR usersid;
2010     LONG res;
2011     REGSAM access = KEY_ALL_ACCESS;
2012     DWORD error;
2013 
2014     create_test_guid(prodcode, prod_squashed);
2015     compose_base85_guid(component, comp_base85, comp_squashed);
2016     compose_base85_guid(component, comp_base85 + 20, comp_squashed2);
2017     usersid = get_user_sid();
2018 
2019     if (is_wow64)
2020         access |= KEY_WOW64_64KEY;
2021 
2022     /* NULL prodcode */
2023     SetLastError(0xdeadbeef);
2024     state = MsiQueryFeatureStateA(NULL, "feature");
2025     error = GetLastError();
2026     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2027     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2028 
2029     /* empty prodcode */
2030     SetLastError(0xdeadbeef);
2031     state = MsiQueryFeatureStateA("", "feature");
2032     error = GetLastError();
2033     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2034     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2035 
2036     /* garbage prodcode */
2037     SetLastError(0xdeadbeef);
2038     state = MsiQueryFeatureStateA("garbage", "feature");
2039     error = GetLastError();
2040     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2041     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2042 
2043     /* guid without brackets */
2044     SetLastError(0xdeadbeef);
2045     state = MsiQueryFeatureStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", "feature");
2046     error = GetLastError();
2047     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2048     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2049 
2050     /* guid with brackets */
2051     SetLastError(0xdeadbeef);
2052     state = MsiQueryFeatureStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", "feature");
2053     error = GetLastError();
2054     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2055     ok(error == ERROR_SUCCESS || broken(error == ERROR_ALREADY_EXISTS) /* win2k */,
2056        "expected ERROR_SUCCESS, got %u\n", error);
2057 
2058     /* same length as guid, but random */
2059     SetLastError(0xdeadbeef);
2060     state = MsiQueryFeatureStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", "feature");
2061     error = GetLastError();
2062     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2063     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2064 
2065     /* NULL szFeature */
2066     SetLastError(0xdeadbeef);
2067     state = MsiQueryFeatureStateA(prodcode, NULL);
2068     error = GetLastError();
2069     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2070     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2071 
2072     /* empty szFeature */
2073     SetLastError(0xdeadbeef);
2074     state = MsiQueryFeatureStateA(prodcode, "");
2075     error = GetLastError();
2076     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2077     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2078        "expected ERROR_SUCCESS, got %u\n", error);
2079 
2080     /* feature key does not exist yet */
2081     SetLastError(0xdeadbeef);
2082     state = MsiQueryFeatureStateA(prodcode, "feature");
2083     error = GetLastError();
2084     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2085     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2086        "expected ERROR_SUCCESS, got %u\n", error);
2087 
2088     /* MSIINSTALLCONTEXT_USERUNMANAGED */
2089 
2090     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Features\\");
2091     lstrcatA(keypath, prod_squashed);
2092 
2093     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
2094     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2095 
2096     /* feature key exists */
2097     SetLastError(0xdeadbeef);
2098     state = MsiQueryFeatureStateA(prodcode, "feature");
2099     error = GetLastError();
2100     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2101     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2102        "expected ERROR_SUCCESS, got %u\n", error);
2103 
2104     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 2);
2105     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2106 
2107     /* feature value exists */
2108     SetLastError(0xdeadbeef);
2109     state = MsiQueryFeatureStateA(prodcode, "feature");
2110     error = GetLastError();
2111     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2112     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2113        "expected ERROR_SUCCESS, got %u\n", error);
2114 
2115     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2116     lstrcatA(keypath, usersid);
2117     lstrcatA(keypath, "\\Products\\");
2118     lstrcatA(keypath, prod_squashed);
2119     lstrcatA(keypath, "\\Features");
2120 
2121     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
2122     if (res == ERROR_ACCESS_DENIED)
2123     {
2124         skip("Not enough rights to perform tests\n");
2125         RegDeleteKeyA(userkey, "");
2126         RegCloseKey(userkey);
2127         LocalFree(usersid);
2128         return;
2129     }
2130     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2131 
2132     /* userdata features key exists */
2133     SetLastError(0xdeadbeef);
2134     state = MsiQueryFeatureStateA(prodcode, "feature");
2135     error = GetLastError();
2136     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2137     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2138        "expected ERROR_SUCCESS, got %u\n", error);
2139 
2140     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
2141     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2142 
2143     SetLastError(0xdeadbeef);
2144     state = MsiQueryFeatureStateA(prodcode, "feature");
2145     error = GetLastError();
2146     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
2147     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2148        "expected ERROR_SUCCESS, got %u\n", error);
2149 
2150     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
2151     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2152 
2153     SetLastError(0xdeadbeef);
2154     state = MsiQueryFeatureStateA(prodcode, "feature");
2155     error = GetLastError();
2156     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2157     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2158        "expected ERROR_SUCCESS, got %u\n", error);
2159 
2160     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
2161     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2162 
2163     SetLastError(0xdeadbeef);
2164     state = MsiQueryFeatureStateA(prodcode, "feature");
2165     error = GetLastError();
2166     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2167     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2168        "expected ERROR_SUCCESS, got %u\n", error);
2169 
2170     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
2171     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2172 
2173     SetLastError(0xdeadbeef);
2174     state = MsiQueryFeatureStateA(prodcode, "feature");
2175     error = GetLastError();
2176     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2177     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2178        "expected ERROR_SUCCESS, got %u\n", error);
2179 
2180     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2181     lstrcatA(keypath, usersid);
2182     lstrcatA(keypath, "\\Components\\");
2183     lstrcatA(keypath, comp_squashed);
2184 
2185     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2186     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2187 
2188     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2189     lstrcatA(keypath, usersid);
2190     lstrcatA(keypath, "\\Components\\");
2191     lstrcatA(keypath, comp_squashed2);
2192 
2193     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
2194     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2195 
2196     SetLastError(0xdeadbeef);
2197     state = MsiQueryFeatureStateA(prodcode, "feature");
2198     error = GetLastError();
2199     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2200     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2201        "expected ERROR_SUCCESS, got %u\n", error);
2202 
2203     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
2204     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2205 
2206     SetLastError(0xdeadbeef);
2207     state = MsiQueryFeatureStateA(prodcode, "feature");
2208     error = GetLastError();
2209     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2210     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2211        "expected ERROR_SUCCESS, got %u\n", error);
2212 
2213     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
2214     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2215 
2216     SetLastError(0xdeadbeef);
2217     state = MsiQueryFeatureStateA(prodcode, "feature");
2218     error = GetLastError();
2219     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2220     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2221        "expected ERROR_SUCCESS, got %u\n", error);
2222 
2223     res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
2224     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2225 
2226     /* INSTALLSTATE_LOCAL */
2227     SetLastError(0xdeadbeef);
2228     state = MsiQueryFeatureStateA(prodcode, "feature");
2229     error = GetLastError();
2230     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2231     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2232        "expected ERROR_SUCCESS, got %u\n", error);
2233 
2234     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01\\", 4);
2235     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2236 
2237     /* INSTALLSTATE_SOURCE */
2238     SetLastError(0xdeadbeef);
2239     state = MsiQueryFeatureStateA(prodcode, "feature");
2240     error = GetLastError();
2241     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2242     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2243        "expected ERROR_SUCCESS, got %u\n", error);
2244 
2245     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
2246     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2247 
2248     /* bad INSTALLSTATE_SOURCE */
2249     SetLastError(0xdeadbeef);
2250     state = MsiQueryFeatureStateA(prodcode, "feature");
2251     error = GetLastError();
2252     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2253     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2254        "expected ERROR_SUCCESS, got %u\n", error);
2255 
2256     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01a", 4);
2257     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2258 
2259     /* INSTALLSTATE_SOURCE */
2260     SetLastError(0xdeadbeef);
2261     state = MsiQueryFeatureStateA(prodcode, "feature");
2262     error = GetLastError();
2263     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2264     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2265        "expected ERROR_SUCCESS, got %u\n", error);
2266 
2267     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
2268     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2269 
2270     /* bad INSTALLSTATE_SOURCE */
2271     SetLastError(0xdeadbeef);
2272     state = MsiQueryFeatureStateA(prodcode, "feature");
2273     error = GetLastError();
2274     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2275     ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2276        "expected ERROR_SUCCESS, got %u\n", error);
2277 
2278     RegDeleteValueA(compkey, prod_squashed);
2279     RegDeleteValueA(compkey2, prod_squashed);
2280     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2281     delete_key(compkey2, "", access & KEY_WOW64_64KEY);
2282     RegDeleteValueA(localkey, "feature");
2283     RegDeleteValueA(userkey, "feature");
2284     RegDeleteKeyA(userkey, "");
2285     RegCloseKey(compkey);
2286     RegCloseKey(compkey2);
2287     RegCloseKey(localkey);
2288     RegCloseKey(userkey);
2289 
2290     /* MSIINSTALLCONTEXT_USERMANAGED */
2291 
2292     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
2293     lstrcatA(keypath, usersid);
2294     lstrcatA(keypath, "\\Installer\\Features\\");
2295     lstrcatA(keypath, prod_squashed);
2296 
2297     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
2298     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2299 
2300     /* feature key exists */
2301     state = MsiQueryFeatureStateA(prodcode, "feature");
2302     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2303 
2304     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 1);
2305     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2306 
2307     /* feature value exists */
2308     state = MsiQueryFeatureStateA(prodcode, "feature");
2309     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2310 
2311     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2312     lstrcatA(keypath, usersid);
2313     lstrcatA(keypath, "\\Products\\");
2314     lstrcatA(keypath, prod_squashed);
2315     lstrcatA(keypath, "\\Features");
2316 
2317     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
2318     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2319 
2320     /* userdata features key exists */
2321     state = MsiQueryFeatureStateA(prodcode, "feature");
2322     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2323 
2324     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
2325     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2326 
2327     state = MsiQueryFeatureStateA(prodcode, "feature");
2328     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
2329 
2330     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
2331     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2332 
2333     state = MsiQueryFeatureStateA(prodcode, "feature");
2334     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2335 
2336     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
2337     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2338 
2339     state = MsiQueryFeatureStateA(prodcode, "feature");
2340     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2341 
2342     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
2343     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2344 
2345     state = MsiQueryFeatureStateA(prodcode, "feature");
2346     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2347 
2348     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2349     lstrcatA(keypath, usersid);
2350     lstrcatA(keypath, "\\Components\\");
2351     lstrcatA(keypath, comp_squashed);
2352 
2353     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2354     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2355 
2356     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2357     lstrcatA(keypath, usersid);
2358     lstrcatA(keypath, "\\Components\\");
2359     lstrcatA(keypath, comp_squashed2);
2360 
2361     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
2362     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2363 
2364     state = MsiQueryFeatureStateA(prodcode, "feature");
2365     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2366 
2367     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
2368     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2369 
2370     state = MsiQueryFeatureStateA(prodcode, "feature");
2371     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2372 
2373     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
2374     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2375 
2376     state = MsiQueryFeatureStateA(prodcode, "feature");
2377     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2378 
2379     res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
2380     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2381 
2382     state = MsiQueryFeatureStateA(prodcode, "feature");
2383     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2384 
2385     RegDeleteValueA(compkey, prod_squashed);
2386     RegDeleteValueA(compkey2, prod_squashed);
2387     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2388     delete_key(compkey2, "", access & KEY_WOW64_64KEY);
2389     RegDeleteValueA(localkey, "feature");
2390     RegDeleteValueA(userkey, "feature");
2391     delete_key(userkey, "", access & KEY_WOW64_64KEY);
2392     RegCloseKey(compkey);
2393     RegCloseKey(compkey2);
2394     RegCloseKey(localkey);
2395     RegCloseKey(userkey);
2396 
2397     /* MSIINSTALLCONTEXT_MACHINE */
2398 
2399     lstrcpyA(keypath, "Software\\Classes\\Installer\\Features\\");
2400     lstrcatA(keypath, prod_squashed);
2401 
2402     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
2403     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2404 
2405     /* feature key exists */
2406     state = MsiQueryFeatureStateA(prodcode, "feature");
2407     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2408 
2409     res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 1);
2410     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2411 
2412     /* feature value exists */
2413     state = MsiQueryFeatureStateA(prodcode, "feature");
2414     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2415 
2416     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2417     lstrcatA(keypath, "S-1-5-18\\Products\\");
2418     lstrcatA(keypath, prod_squashed);
2419     lstrcatA(keypath, "\\Features");
2420 
2421     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
2422     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2423 
2424     /* userdata features key exists */
2425     state = MsiQueryFeatureStateA(prodcode, "feature");
2426     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2427 
2428     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
2429     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2430 
2431     state = MsiQueryFeatureStateA(prodcode, "feature");
2432     ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
2433 
2434     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
2435     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2436 
2437     state = MsiQueryFeatureStateA(prodcode, "feature");
2438     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2439 
2440     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
2441     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2442 
2443     state = MsiQueryFeatureStateA(prodcode, "feature");
2444     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2445 
2446     res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
2447     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2448 
2449     state = MsiQueryFeatureStateA(prodcode, "feature");
2450     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2451 
2452     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2453     lstrcatA(keypath, "S-1-5-18\\Components\\");
2454     lstrcatA(keypath, comp_squashed);
2455 
2456     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2457     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2458 
2459     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2460     lstrcatA(keypath, "S-1-5-18\\Components\\");
2461     lstrcatA(keypath, comp_squashed2);
2462 
2463     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
2464     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2465 
2466     state = MsiQueryFeatureStateA(prodcode, "feature");
2467     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2468 
2469     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
2470     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2471 
2472     state = MsiQueryFeatureStateA(prodcode, "feature");
2473     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2474 
2475     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
2476     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2477 
2478     state = MsiQueryFeatureStateA(prodcode, "feature");
2479     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2480 
2481     res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
2482     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2483 
2484     state = MsiQueryFeatureStateA(prodcode, "feature");
2485     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2486 
2487     RegDeleteValueA(compkey, prod_squashed);
2488     RegDeleteValueA(compkey2, prod_squashed);
2489     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2490     delete_key(compkey2, "", access & KEY_WOW64_64KEY);
2491     RegDeleteValueA(localkey, "feature");
2492     RegDeleteValueA(userkey, "feature");
2493     delete_key(userkey, "", access & KEY_WOW64_64KEY);
2494     RegCloseKey(compkey);
2495     RegCloseKey(compkey2);
2496     RegCloseKey(localkey);
2497     RegCloseKey(userkey);
2498     LocalFree(usersid);
2499 }
2500 
2501 static void test_MsiQueryComponentState(void)
2502 {
2503     HKEY compkey, prodkey;
2504     CHAR prodcode[MAX_PATH];
2505     CHAR prod_squashed[MAX_PATH];
2506     CHAR component[MAX_PATH];
2507     CHAR comp_base85[MAX_PATH];
2508     CHAR comp_squashed[MAX_PATH];
2509     CHAR keypath[MAX_PATH];
2510     INSTALLSTATE state;
2511     LPSTR usersid;
2512     LONG res;
2513     UINT r;
2514     REGSAM access = KEY_ALL_ACCESS;
2515     DWORD error;
2516 
2517     static const INSTALLSTATE MAGIC_ERROR = 0xdeadbeef;
2518 
2519     if (!pMsiQueryComponentStateA)
2520     {
2521         win_skip("MsiQueryComponentStateA not implemented\n");
2522         return;
2523     }
2524 
2525     create_test_guid(prodcode, prod_squashed);
2526     compose_base85_guid(component, comp_base85, comp_squashed);
2527     usersid = get_user_sid();
2528 
2529     if (is_wow64)
2530         access |= KEY_WOW64_64KEY;
2531 
2532     /* NULL szProductCode */
2533     state = MAGIC_ERROR;
2534     SetLastError(0xdeadbeef);
2535     r = pMsiQueryComponentStateA(NULL, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2536     error = GetLastError();
2537     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2538     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2539     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2540 
2541     /* empty szProductCode */
2542     state = MAGIC_ERROR;
2543     SetLastError(0xdeadbeef);
2544     r = pMsiQueryComponentStateA("", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2545     error = GetLastError();
2546     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2547     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2548     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2549 
2550     /* random szProductCode */
2551     state = MAGIC_ERROR;
2552     SetLastError(0xdeadbeef);
2553     r = pMsiQueryComponentStateA("random", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2554     error = GetLastError();
2555     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2556     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2557     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2558 
2559     /* GUID-length szProductCode */
2560     state = MAGIC_ERROR;
2561     SetLastError(0xdeadbeef);
2562     r = pMsiQueryComponentStateA("DJANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KDE", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2563     error = GetLastError();
2564     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2565     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2566     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2567 
2568     /* GUID-length with brackets */
2569     state = MAGIC_ERROR;
2570     SetLastError(0xdeadbeef);
2571     r = pMsiQueryComponentStateA("{JANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KD}", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2572     error = GetLastError();
2573     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2574     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2575     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2576 
2577     /* actual GUID */
2578     state = MAGIC_ERROR;
2579     SetLastError(0xdeadbeef);
2580     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2581     error = GetLastError();
2582     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2583     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2584     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2585 
2586     state = MAGIC_ERROR;
2587     SetLastError(0xdeadbeef);
2588     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2589     error = GetLastError();
2590     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2591     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2592     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2593 
2594     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
2595     lstrcatA(keypath, prod_squashed);
2596 
2597     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2598     if (res == ERROR_ACCESS_DENIED)
2599     {
2600         skip("Not enough rights to perform tests\n");
2601         LocalFree(usersid);
2602         return;
2603     }
2604     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2605 
2606     state = MAGIC_ERROR;
2607     SetLastError(0xdeadbeef);
2608     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2609     error = GetLastError();
2610     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2611     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2612     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2613 
2614     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2615     RegCloseKey(prodkey);
2616 
2617     /* create local system product key */
2618     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\");
2619     lstrcatA(keypath, prod_squashed);
2620     lstrcatA(keypath, "\\InstallProperties");
2621 
2622     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2623     if (res == ERROR_ACCESS_DENIED)
2624     {
2625         skip("Not enough rights to perform tests\n");
2626         LocalFree(usersid);
2627         return;
2628     }
2629     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2630 
2631     /* local system product key exists */
2632     state = MAGIC_ERROR;
2633     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2634     error = GetLastError();
2635     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2636     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2637     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2638 
2639     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2640     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2641 
2642     /* LocalPackage value exists */
2643     state = MAGIC_ERROR;
2644     SetLastError(0xdeadbeef);
2645     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2646     error = GetLastError();
2647     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2648     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2649     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2650 
2651     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\");
2652     lstrcatA(keypath, comp_squashed);
2653 
2654     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2655     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2656 
2657     /* component key exists */
2658     state = MAGIC_ERROR;
2659     SetLastError(0xdeadbeef);
2660     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2661     error = GetLastError();
2662     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2663     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2664     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2665 
2666     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
2667     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2668 
2669     /* component\product exists */
2670     state = MAGIC_ERROR;
2671     SetLastError(0xdeadbeef);
2672     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2673     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2674     error = GetLastError();
2675     ok(state == INSTALLSTATE_NOTUSED || state == INSTALLSTATE_LOCAL,
2676        "Expected INSTALLSTATE_NOTUSED or INSTALLSTATE_LOCAL, got %d\n", state);
2677     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2678 
2679     /* NULL component, product exists */
2680     state = MAGIC_ERROR;
2681     SetLastError(0xdeadbeef);
2682     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, NULL, &state);
2683     error = GetLastError();
2684     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2685     ok(state == MAGIC_ERROR, "Expected state not changed, got %d\n", state);
2686     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2687 
2688     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
2689     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2690 
2691     /* INSTALLSTATE_LOCAL */
2692     state = MAGIC_ERROR;
2693     SetLastError(0xdeadbeef);
2694     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2695     error = GetLastError();
2696     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2697     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2698     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2699 
2700     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01\\", 4);
2701     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2702 
2703     /* INSTALLSTATE_SOURCE */
2704     state = MAGIC_ERROR;
2705     SetLastError(0xdeadbeef);
2706     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2707     error = GetLastError();
2708     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2709     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2710     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2711 
2712     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
2713     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2714 
2715     /* bad INSTALLSTATE_SOURCE */
2716     state = MAGIC_ERROR;
2717     SetLastError(0xdeadbeef);
2718     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2719     error = GetLastError();
2720     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2721     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2722     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2723 
2724     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01a", 4);
2725     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2726 
2727     /* INSTALLSTATE_SOURCE */
2728     state = MAGIC_ERROR;
2729     SetLastError(0xdeadbeef);
2730     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2731     error = GetLastError();
2732     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2733     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2734     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2735 
2736     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01:", 4);
2737     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2738 
2739     /* registry component */
2740     state = MAGIC_ERROR;
2741     SetLastError(0xdeadbeef);
2742     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2743     error = GetLastError();
2744     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2745     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2746     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2747 
2748     RegDeleteValueA(prodkey, "LocalPackage");
2749     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2750     RegDeleteValueA(compkey, prod_squashed);
2751     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2752     RegCloseKey(prodkey);
2753     RegCloseKey(compkey);
2754 
2755     /* MSIINSTALLCONTEXT_USERUNMANAGED */
2756 
2757     state = MAGIC_ERROR;
2758     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2759     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2760     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2761 
2762     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2763     lstrcatA(keypath, prod_squashed);
2764 
2765     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
2766     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2767 
2768     state = MAGIC_ERROR;
2769     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2770     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2771     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2772 
2773     RegDeleteKeyA(prodkey, "");
2774     RegCloseKey(prodkey);
2775 
2776     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2777     lstrcatA(keypath, usersid);
2778     lstrcatA(keypath, "\\Products\\");
2779     lstrcatA(keypath, prod_squashed);
2780     lstrcatA(keypath, "\\InstallProperties");
2781 
2782     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2783     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2784 
2785     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2786     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2787 
2788     RegCloseKey(prodkey);
2789 
2790     state = MAGIC_ERROR;
2791     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2792     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2793     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2794 
2795     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2796     lstrcatA(keypath, usersid);
2797     lstrcatA(keypath, "\\Components\\");
2798     lstrcatA(keypath, comp_squashed);
2799 
2800     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2801     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2802 
2803     /* component key exists */
2804     state = MAGIC_ERROR;
2805     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2806     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2807     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2808 
2809     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
2810     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2811 
2812     /* component\product exists */
2813     state = MAGIC_ERROR;
2814     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2815     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2816     ok(state == INSTALLSTATE_NOTUSED || state == INSTALLSTATE_LOCAL,
2817        "Expected INSTALLSTATE_NOTUSED or INSTALLSTATE_LOCAL, got %d\n", state);
2818 
2819     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
2820     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2821 
2822     state = MAGIC_ERROR;
2823     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
2824     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2825     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2826 
2827     /* MSIINSTALLCONTEXT_USERMANAGED */
2828 
2829     state = MAGIC_ERROR;
2830     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2831     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2832     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2833 
2834     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
2835     lstrcatA(keypath, prod_squashed);
2836 
2837     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
2838     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2839 
2840     state = MAGIC_ERROR;
2841     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2842     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2843     ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2844 
2845     RegDeleteKeyA(prodkey, "");
2846     RegCloseKey(prodkey);
2847 
2848     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
2849     lstrcatA(keypath, usersid);
2850     lstrcatA(keypath, "\\Installer\\Products\\");
2851     lstrcatA(keypath, prod_squashed);
2852 
2853     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2854     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2855 
2856     state = MAGIC_ERROR;
2857     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2858     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2859     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2860 
2861     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2862     RegCloseKey(prodkey);
2863 
2864     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2865     lstrcatA(keypath, usersid);
2866     lstrcatA(keypath, "\\Products\\");
2867     lstrcatA(keypath, prod_squashed);
2868     lstrcatA(keypath, "\\InstallProperties");
2869 
2870     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2871     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2872 
2873     res = RegSetValueExA(prodkey, "ManagedLocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2874     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2875 
2876     state = MAGIC_ERROR;
2877     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
2878     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2879     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2880 
2881     RegDeleteValueA(prodkey, "LocalPackage");
2882     RegDeleteValueA(prodkey, "ManagedLocalPackage");
2883     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2884     RegDeleteValueA(compkey, prod_squashed);
2885     delete_key(compkey, "", access & KEY_WOW64_64KEY);
2886     RegCloseKey(prodkey);
2887     RegCloseKey(compkey);
2888     LocalFree(usersid);
2889 }
2890 
2891 static void test_MsiGetComponentPath(void)
2892 {
2893     HKEY compkey, prodkey, installprop;
2894     CHAR prodcode[MAX_PATH];
2895     CHAR prod_squashed[MAX_PATH];
2896     CHAR component[MAX_PATH];
2897     CHAR comp_base85[MAX_PATH];
2898     CHAR comp_squashed[MAX_PATH];
2899     CHAR keypath[MAX_PATH];
2900     CHAR path[MAX_PATH];
2901     INSTALLSTATE state;
2902     LPSTR usersid;
2903     DWORD size, val;
2904     REGSAM access = KEY_ALL_ACCESS;
2905     LONG res;
2906 
2907     create_test_guid(prodcode, prod_squashed);
2908     compose_base85_guid(component, comp_base85, comp_squashed);
2909     usersid = get_user_sid();
2910 
2911     if (is_wow64)
2912         access |= KEY_WOW64_64KEY;
2913 
2914     /* NULL szProduct */
2915     size = MAX_PATH;
2916     state = MsiGetComponentPathA(NULL, component, path, &size);
2917     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2918     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2919 
2920     /* NULL szComponent */
2921     size = MAX_PATH;
2922     state = MsiGetComponentPathA(prodcode, NULL, path, &size);
2923     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2924     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2925 
2926     size = MAX_PATH;
2927     state = MsiLocateComponentA(NULL, path, &size);
2928     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2929     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2930 
2931     /* NULL lpPathBuf */
2932     size = MAX_PATH;
2933     state = MsiGetComponentPathA(prodcode, component, NULL, &size);
2934     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2935     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2936 
2937     size = MAX_PATH;
2938     state = MsiLocateComponentA(component, NULL, &size);
2939     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2940     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2941 
2942     /* NULL pcchBuf */
2943     size = MAX_PATH;
2944     state = MsiGetComponentPathA(prodcode, component, path, NULL);
2945     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2946     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2947 
2948     size = MAX_PATH;
2949     state = MsiLocateComponentA(component, path, NULL);
2950     ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2951     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2952 
2953     /* all params valid */
2954     size = MAX_PATH;
2955     state = MsiGetComponentPathA(prodcode, component, path, &size);
2956     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2957     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2958 
2959     size = MAX_PATH;
2960     state = MsiLocateComponentA(component, path, &size);
2961     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2962     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2963 
2964     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
2965     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
2966     lstrcatA(keypath, comp_squashed);
2967 
2968     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2969     if (res == ERROR_ACCESS_DENIED)
2970     {
2971         skip("Not enough rights to perform tests\n");
2972         LocalFree(usersid);
2973         return;
2974     }
2975     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2976 
2977     /* local system component key exists */
2978     size = MAX_PATH;
2979     state = MsiGetComponentPathA(prodcode, component, path, &size);
2980     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2981     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2982 
2983     size = MAX_PATH;
2984     state = MsiLocateComponentA(component, path, &size);
2985     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2986     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
2987 
2988     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
2989     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2990 
2991     /* product value exists */
2992     path[0] = 0;
2993     size = MAX_PATH;
2994     state = MsiGetComponentPathA(prodcode, component, path, &size);
2995     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2996     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
2997     ok(size == 10, "Expected 10, got %d\n", size);
2998 
2999     path[0] = 0;
3000     size = MAX_PATH;
3001     state = MsiLocateComponentA(component, path, &size);
3002     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3003     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3004     ok(size == 10, "Expected 10, got %d\n", size);
3005 
3006     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3007     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
3008     lstrcatA(keypath, prod_squashed);
3009     lstrcatA(keypath, "\\InstallProperties");
3010 
3011     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &installprop, NULL);
3012     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3013 
3014     val = 1;
3015     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
3016     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3017 
3018     /* install properties key exists */
3019     path[0] = 0;
3020     size = MAX_PATH;
3021     state = MsiGetComponentPathA(prodcode, component, path, &size);
3022     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3023     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3024     ok(size == 10, "Expected 10, got %d\n", size);
3025 
3026     path[0] = 0;
3027     size = MAX_PATH;
3028     state = MsiLocateComponentA(component, path, &size);
3029     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3030     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3031     ok(size == 10, "Expected 10, got %d\n", size);
3032 
3033     create_file("C:\\imapath", "C:\\imapath", 11);
3034 
3035     /* file exists */
3036     path[0] = 'a';
3037     size = 0;
3038     state = MsiGetComponentPathA(prodcode, component, path, &size);
3039     ok(state == INSTALLSTATE_MOREDATA, "Expected INSTALLSTATE_MOREDATA, got %d\n", state);
3040     ok(path[0] == 'a', "got %s\n", path);
3041     ok(size == 10, "Expected 10, got %d\n", size);
3042 
3043     path[0] = 0;
3044     size = MAX_PATH;
3045     state = MsiGetComponentPathA(prodcode, component, path, &size);
3046     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3047     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3048     ok(size == 10, "Expected 10, got %d\n", size);
3049 
3050     size = 0;
3051     path[0] = 'a';
3052     state = MsiLocateComponentA(component, path, &size);
3053     ok(state == INSTALLSTATE_MOREDATA, "Expected INSTALLSTATE_MOREDATA, got %d\n", state);
3054     ok(path[0] == 'a', "got %s\n", path);
3055     ok(size == 10, "Expected 10, got %d\n", size);
3056 
3057     path[0] = 0;
3058     size = MAX_PATH;
3059     state = MsiLocateComponentA(component, path, &size);
3060     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3061     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3062     ok(size == 10, "Expected 10, got %d\n", size);
3063 
3064     RegDeleteValueA(compkey, prod_squashed);
3065     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3066     RegDeleteValueA(installprop, "WindowsInstaller");
3067     delete_key(installprop, "", access & KEY_WOW64_64KEY);
3068     RegCloseKey(compkey);
3069     RegCloseKey(installprop);
3070     DeleteFileA("C:\\imapath");
3071 
3072     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3073     lstrcatA(keypath, "Installer\\UserData\\");
3074     lstrcatA(keypath, usersid);
3075     lstrcatA(keypath, "\\Components\\");
3076     lstrcatA(keypath, comp_squashed);
3077 
3078     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3079     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3080 
3081     /* user managed component key exists */
3082     size = MAX_PATH;
3083     state = MsiGetComponentPathA(prodcode, component, path, &size);
3084     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3085     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3086 
3087     size = MAX_PATH;
3088     state = MsiLocateComponentA(component, path, &size);
3089     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3090     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3091 
3092     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3093     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3094 
3095     /* product value exists */
3096     path[0] = 0;
3097     size = MAX_PATH;
3098     state = MsiGetComponentPathA(prodcode, component, path, &size);
3099     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3100     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3101     ok(size == 10, "Expected 10, got %d\n", size);
3102 
3103     path[0] = 0;
3104     size = MAX_PATH;
3105     state = MsiLocateComponentA(component, path, &size);
3106     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3107     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3108     ok(size == 10, "Expected 10, got %d\n", size);
3109 
3110     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3111     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
3112     lstrcatA(keypath, prod_squashed);
3113     lstrcatA(keypath, "\\InstallProperties");
3114 
3115     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &installprop, NULL);
3116     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3117 
3118     val = 1;
3119     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
3120     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3121 
3122     /* install properties key exists */
3123     path[0] = 0;
3124     size = MAX_PATH;
3125     state = MsiGetComponentPathA(prodcode, component, path, &size);
3126     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3127     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3128     ok(size == 10, "Expected 10, got %d\n", size);
3129 
3130     path[0] = 0;
3131     size = MAX_PATH;
3132     state = MsiLocateComponentA(component, path, &size);
3133     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3134     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3135     ok(size == 10, "Expected 10, got %d\n", size);
3136 
3137     create_file("C:\\imapath", "C:\\imapath", 11);
3138 
3139     /* file exists */
3140     path[0] = 0;
3141     size = MAX_PATH;
3142     state = MsiGetComponentPathA(prodcode, component, path, &size);
3143     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3144     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3145     ok(size == 10, "Expected 10, got %d\n", size);
3146 
3147     path[0] = 0;
3148     size = MAX_PATH;
3149     state = MsiLocateComponentA(component, path, &size);
3150     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3151     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3152     ok(size == 10, "Expected 10, got %d\n", size);
3153 
3154     RegDeleteValueA(compkey, prod_squashed);
3155     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3156     RegDeleteValueA(installprop, "WindowsInstaller");
3157     delete_key(installprop, "", access & KEY_WOW64_64KEY);
3158     RegCloseKey(compkey);
3159     RegCloseKey(installprop);
3160     DeleteFileA("C:\\imapath");
3161 
3162     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3163     lstrcatA(keypath, "Installer\\Managed\\");
3164     lstrcatA(keypath, usersid);
3165     lstrcatA(keypath, "\\Installer\\Products\\");
3166     lstrcatA(keypath, prod_squashed);
3167 
3168     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3169     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3170 
3171     /* user managed product key exists */
3172     size = MAX_PATH;
3173     state = MsiGetComponentPathA(prodcode, component, path, &size);
3174     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3175     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3176 
3177     size = MAX_PATH;
3178     state = MsiLocateComponentA(component, path, &size);
3179     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3180     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3181 
3182     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3183     lstrcatA(keypath, "Installer\\UserData\\");
3184     lstrcatA(keypath, usersid);
3185     lstrcatA(keypath, "\\Components\\");
3186     lstrcatA(keypath, comp_squashed);
3187 
3188     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3189     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3190 
3191     /* user managed component key exists */
3192     size = MAX_PATH;
3193     state = MsiGetComponentPathA(prodcode, component, path, &size);
3194     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3195     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3196 
3197     size = MAX_PATH;
3198     state = MsiLocateComponentA(component, path, &size);
3199     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3200     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3201 
3202     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3203     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3204 
3205     /* product value exists */
3206     path[0] = 0;
3207     size = MAX_PATH;
3208     state = MsiGetComponentPathA(prodcode, component, path, &size);
3209     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3210     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3211     ok(size == 10, "Expected 10, got %d\n", size);
3212 
3213     path[0] = 0;
3214     size = MAX_PATH;
3215     state = MsiLocateComponentA(component, path, &size);
3216     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3217     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3218     ok(size == 10, "Expected 10, got %d\n", size);
3219 
3220     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3221     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
3222     lstrcatA(keypath, prod_squashed);
3223     lstrcatA(keypath, "\\InstallProperties");
3224 
3225     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &installprop, NULL);
3226     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3227 
3228     val = 1;
3229     res = RegSetValueExA(installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
3230     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3231 
3232     /* install properties key exists */
3233     path[0] = 0;
3234     size = MAX_PATH;
3235     state = MsiGetComponentPathA(prodcode, component, path, &size);
3236     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3237     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3238     ok(size == 10, "Expected 10, got %d\n", size);
3239 
3240     path[0] = 0;
3241     size = MAX_PATH;
3242     state = MsiLocateComponentA(component, path, &size);
3243     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3244     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3245     ok(size == 10, "Expected 10, got %d\n", size);
3246 
3247     create_file("C:\\imapath", "C:\\imapath", 11);
3248 
3249     /* file exists */
3250     path[0] = 0;
3251     size = MAX_PATH;
3252     state = MsiGetComponentPathA(prodcode, component, path, &size);
3253     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3254     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3255     ok(size == 10, "Expected 10, got %d\n", size);
3256 
3257     path[0] = 0;
3258     size = MAX_PATH;
3259     state = MsiLocateComponentA(component, path, &size);
3260     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3261     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3262     ok(size == 10, "Expected 10, got %d\n", size);
3263 
3264     RegDeleteValueA(compkey, prod_squashed);
3265     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3266     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3267     RegDeleteValueA(installprop, "WindowsInstaller");
3268     delete_key(installprop, "", access & KEY_WOW64_64KEY);
3269     RegCloseKey(prodkey);
3270     RegCloseKey(compkey);
3271     RegCloseKey(installprop);
3272     DeleteFileA("C:\\imapath");
3273 
3274     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
3275     lstrcatA(keypath, prod_squashed);
3276 
3277     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
3278     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3279 
3280     /* user unmanaged product key exists */
3281     size = MAX_PATH;
3282     state = MsiGetComponentPathA(prodcode, component, path, &size);
3283     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3284     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3285 
3286     size = MAX_PATH;
3287     state = MsiLocateComponentA(component, path, &size);
3288     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3289     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3290 
3291     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3292     lstrcatA(keypath, "Installer\\UserData\\");
3293     lstrcatA(keypath, usersid);
3294     lstrcatA(keypath, "\\Components\\");
3295     lstrcatA(keypath, comp_squashed);
3296 
3297     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3298     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3299 
3300     /* user unmanaged component key exists */
3301     size = MAX_PATH;
3302     state = MsiGetComponentPathA(prodcode, component, path, &size);
3303     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3304     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3305 
3306     size = MAX_PATH;
3307     state = MsiLocateComponentA(component, path, &size);
3308     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3309     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3310 
3311     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3312     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3313 
3314     /* product value exists */
3315     path[0] = 0;
3316     size = MAX_PATH;
3317     state = MsiGetComponentPathA(prodcode, component, path, &size);
3318     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3319     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3320     ok(size == 10, "Expected 10, got %d\n", size);
3321 
3322     path[0] = 0;
3323     size = MAX_PATH;
3324     state = MsiLocateComponentA(component, path, &size);
3325     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3326     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3327     ok(size == 10, "Expected 10, got %d\n", size);
3328 
3329     create_file("C:\\imapath", "C:\\imapath", 11);
3330 
3331     /* file exists */
3332     path[0] = 0;
3333     size = MAX_PATH;
3334     state = MsiGetComponentPathA(prodcode, component, path, &size);
3335     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3336     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3337     ok(size == 10, "Expected 10, got %d\n", size);
3338 
3339     path[0] = 0;
3340     size = MAX_PATH;
3341     state = MsiLocateComponentA(component, path, &size);
3342     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3343     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3344     ok(size == 10, "Expected 10, got %d\n", size);
3345 
3346     RegDeleteValueA(compkey, prod_squashed);
3347     RegDeleteKeyA(prodkey, "");
3348     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3349     RegCloseKey(prodkey);
3350     RegCloseKey(compkey);
3351     DeleteFileA("C:\\imapath");
3352 
3353     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
3354     lstrcatA(keypath, prod_squashed);
3355 
3356     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
3357     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3358 
3359     /* local classes product key exists */
3360     size = MAX_PATH;
3361     state = MsiGetComponentPathA(prodcode, component, path, &size);
3362     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3363     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3364 
3365     size = MAX_PATH;
3366     state = MsiLocateComponentA(component, path, &size);
3367     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3368     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3369 
3370     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3371     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
3372     lstrcatA(keypath, comp_squashed);
3373 
3374     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3375     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3376 
3377     /* local user component key exists */
3378     size = MAX_PATH;
3379     state = MsiGetComponentPathA(prodcode, component, path, &size);
3380     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3381     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3382 
3383     size = MAX_PATH;
3384     state = MsiLocateComponentA(component, path, &size);
3385     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3386     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
3387 
3388     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3389     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3390 
3391     /* product value exists */
3392     path[0] = 0;
3393     size = MAX_PATH;
3394     state = MsiGetComponentPathA(prodcode, component, path, &size);
3395     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3396     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3397     ok(size == 10, "Expected 10, got %d\n", size);
3398 
3399     path[0] = 0;
3400     size = MAX_PATH;
3401     state = MsiLocateComponentA(component, path, &size);
3402     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
3403     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3404     ok(size == 10, "Expected 10, got %d\n", size);
3405 
3406     create_file("C:\\imapath", "C:\\imapath", 11);
3407 
3408     /* file exists */
3409     path[0] = 0;
3410     size = MAX_PATH;
3411     state = MsiGetComponentPathA(prodcode, component, path, &size);
3412     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3413     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3414     ok(size == 10, "Expected 10, got %d\n", size);
3415 
3416     path[0] = 0;
3417     size = MAX_PATH;
3418     state = MsiLocateComponentA(component, path, &size);
3419     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3420     ok(!lstrcmpA(path, "C:\\imapath"), "Expected C:\\imapath, got %s\n", path);
3421     ok(size == 10, "Expected 10, got %d\n", size);
3422 
3423     RegDeleteValueA(compkey, prod_squashed);
3424     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
3425     delete_key(compkey, "", access & KEY_WOW64_64KEY);
3426     RegCloseKey(prodkey);
3427     RegCloseKey(compkey);
3428     DeleteFileA("C:\\imapath");
3429     LocalFree(usersid);
3430 }
3431 
3432 static void test_MsiGetComponentPathEx(void)
3433 {
3434     HKEY key_comp, key_installprop, key_prod;
3435     char prod[MAX_PATH], prod_squashed[MAX_PATH];
3436     char comp[MAX_PATH], comp_base85[MAX_PATH], comp_squashed[MAX_PATH];
3437     char path[MAX_PATH], path_key[MAX_PATH], *usersid;
3438     INSTALLSTATE state;
3439     DWORD size, val;
3440     REGSAM access = KEY_ALL_ACCESS;
3441     LONG res;
3442 
3443     if (!pMsiGetComponentPathExA)
3444     {
3445         win_skip( "MsiGetComponentPathExA not present\n" );
3446         return;
3447     }
3448 
3449     if (is_wow64) access |= KEY_WOW64_64KEY;
3450 
3451     create_test_guid( prod, prod_squashed );
3452     compose_base85_guid( comp, comp_base85, comp_squashed );
3453     usersid = get_user_sid();
3454 
3455     /* NULL product */
3456     size = MAX_PATH;
3457     state = pMsiGetComponentPathExA( NULL, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3458     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
3459     todo_wine ok( !size, "got %u\n", size );
3460 
3461     /* NULL component */
3462     size = MAX_PATH;
3463     state = pMsiGetComponentPathExA( prod, NULL, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3464     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
3465     todo_wine ok( !size, "got %u\n", size );
3466 
3467     /* non-NULL usersid, MSIINSTALLCONTEXT_MACHINE */
3468     size = MAX_PATH;
3469     state = pMsiGetComponentPathExA( prod, comp, usersid, MSIINSTALLCONTEXT_MACHINE, path, &size);
3470     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
3471     todo_wine ok( !size, "got %u\n", size );
3472 
3473     /* NULL buf */
3474     size = MAX_PATH;
3475     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, NULL, &size );
3476     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3477     todo_wine ok( size == MAX_PATH * 2, "got %u\n", size );
3478 
3479     /* NULL buflen */
3480     size = MAX_PATH;
3481     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, NULL );
3482     ok( state == INSTALLSTATE_INVALIDARG, "got %d\n", state );
3483     ok( size == MAX_PATH, "got %u\n", size );
3484 
3485     /* all params valid */
3486     size = MAX_PATH;
3487     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3488     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3489     todo_wine ok( !size, "got %u\n", size );
3490 
3491     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3492     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Components\\" );
3493     lstrcatA( path_key, comp_squashed );
3494 
3495     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3496     if (res == ERROR_ACCESS_DENIED)
3497     {
3498         skip( "insufficient rights\n" );
3499         LocalFree( usersid );
3500         return;
3501     }
3502     ok( res == ERROR_SUCCESS, "got %d\n", res );
3503 
3504     /* local system component key exists */
3505     size = MAX_PATH;
3506     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3507     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3508 
3509     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3510     ok( res == ERROR_SUCCESS, "got %d\n", res );
3511 
3512     /* product value exists */
3513     path[0] = 0;
3514     size = MAX_PATH;
3515     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3516     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3517     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3518     ok( size == 20, "got %u\n", size );
3519 
3520     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3521     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Products\\" );
3522     lstrcatA( path_key, prod_squashed );
3523     lstrcatA( path_key, "\\InstallProperties" );
3524 
3525     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_installprop, NULL );
3526     ok( res == ERROR_SUCCESS, "got %d\n", res );
3527 
3528     val = 1;
3529     res = RegSetValueExA( key_installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(val) );
3530     ok( res == ERROR_SUCCESS, "got %d\n", res );
3531 
3532     /* install properties key exists */
3533     path[0] = 0;
3534     size = MAX_PATH;
3535     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3536     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3537     ok( !lstrcmpA( path, "c:\\testcomponentpath"), "got %s\n", path );
3538     ok( size == 20, "got %u\n", size );
3539 
3540     create_file( "c:\\testcomponentpath", "c:\\testcomponentpath", 21 );
3541 
3542     /* file exists */
3543     path[0] = 0;
3544     size = 0;
3545     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3546     ok( state == INSTALLSTATE_MOREDATA, "got %d\n", state );
3547     ok( !path[0], "got %s\n", path );
3548     todo_wine ok( size == 40, "got %u\n", size );
3549 
3550     path[0] = 0;
3551     size = MAX_PATH;
3552     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3553     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3554     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3555     ok( size == 20, "got %d\n", size );
3556 
3557     RegDeleteValueA( key_comp, prod_squashed );
3558     delete_key( key_comp, "", access & KEY_WOW64_64KEY );
3559     RegDeleteValueA( key_installprop, "WindowsInstaller" );
3560     delete_key( key_installprop, "", access & KEY_WOW64_64KEY );
3561     RegCloseKey( key_comp );
3562     RegCloseKey( key_installprop );
3563     DeleteFileA( "c:\\testcomponentpath" );
3564 
3565     lstrcpyA( path_key, "Software\\Microsoft\\Installer\\Products\\" );
3566     lstrcatA( path_key, prod_squashed );
3567 
3568     res = RegCreateKeyA( HKEY_CURRENT_USER, path_key, &key_prod );
3569     ok( res == ERROR_SUCCESS, "got %d\n", res );
3570 
3571     /* user unmanaged product key exists */
3572     size = MAX_PATH;
3573     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3574     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3575     todo_wine ok(!size, "got %u\n", size);
3576 
3577     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3578     lstrcatA( path_key, "Installer\\UserData\\" );
3579     lstrcatA( path_key, usersid );
3580     lstrcatA( path_key, "\\Components\\" );
3581     lstrcatA( path_key, comp_squashed );
3582 
3583     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3584     ok( res == ERROR_SUCCESS, "got %d\n", res );
3585 
3586     /* user unmanaged component key exists */
3587     size = MAX_PATH;
3588     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3589     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3590     todo_wine ok(!size, "got %u\n", size);
3591 
3592     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3593     ok( res == ERROR_SUCCESS, "got %d\n", res );
3594 
3595     /* product value exists */
3596     path[0] = 0;
3597     size = MAX_PATH;
3598     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3599     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3600     ok( !lstrcmpA( path, "c:\\testcomponentpath"), "got %s\n", path );
3601     ok( size == 20, "got %u\n", size );
3602 
3603     create_file( "c:\\testcomponentpath", "c:\\testcomponentpath", 21 );
3604 
3605     /* file exists */
3606     path[0] = 0;
3607     size = MAX_PATH;
3608     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, path, &size );
3609     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3610     ok( !lstrcmpA( path, "c:\\testcomponentpath"), "got %s\n", path );
3611     ok( size == 20, "got %u\n", size );
3612 
3613     RegDeleteValueA( key_comp, prod_squashed );
3614     RegDeleteKeyA( key_prod, "" );
3615     delete_key( key_comp, "", access & KEY_WOW64_64KEY );
3616     RegCloseKey( key_prod );
3617     RegCloseKey( key_comp );
3618     DeleteFileA( "c:\\testcomponentpath" );
3619 
3620     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3621     lstrcatA( path_key, "Installer\\Managed\\" );
3622     lstrcatA( path_key, usersid );
3623     lstrcatA( path_key, "\\Installer\\Products\\" );
3624     lstrcatA( path_key, prod_squashed );
3625 
3626     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_prod, NULL );
3627     ok( res == ERROR_SUCCESS, "got %d\n", res );
3628 
3629     /* user managed product key exists */
3630     size = MAX_PATH;
3631     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3632     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3633 
3634     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3635     lstrcatA( path_key, "Installer\\UserData\\" );
3636     lstrcatA( path_key, usersid );
3637     lstrcatA( path_key, "\\Components\\" );
3638     lstrcatA( path_key, comp_squashed );
3639 
3640     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3641     ok( res == ERROR_SUCCESS, "got %d\n", res );
3642 
3643     /* user managed component key exists */
3644     size = MAX_PATH;
3645     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3646     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3647 
3648     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3649     ok( res == ERROR_SUCCESS, "got %d\n", res );
3650 
3651     /* product value exists */
3652     path[0] = 0;
3653     size = MAX_PATH;
3654     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3655     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3656     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3657     ok( size == 20, "got %u\n", size );
3658 
3659     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3660     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Products\\" );
3661     lstrcatA( path_key, prod_squashed );
3662     lstrcatA( path_key, "\\InstallProperties" );
3663 
3664     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_installprop, NULL );
3665     ok( res == ERROR_SUCCESS, "got %d\n", res );
3666 
3667     val = 1;
3668     res = RegSetValueExA( key_installprop, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&val, sizeof(val) );
3669     ok( res == ERROR_SUCCESS, "got %d\n", res );
3670 
3671     /* install properties key exists */
3672     path[0] = 0;
3673     size = MAX_PATH;
3674     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3675     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3676     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3677     ok( size == 20, "got %u\n", size );
3678 
3679     create_file( "c:\\testcomponentpath", "C:\\testcomponentpath", 21 );
3680 
3681     /* file exists */
3682     path[0] = 0;
3683     size = MAX_PATH;
3684     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_USERMANAGED, path, &size );
3685     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3686     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3687     ok( size == 20, "got %u\n", size );
3688 
3689     RegDeleteValueA( key_comp, prod_squashed );
3690     delete_key( key_prod, "", access & KEY_WOW64_64KEY );
3691     delete_key( key_comp, "", access & KEY_WOW64_64KEY );
3692     RegDeleteValueA( key_installprop, "WindowsInstaller" );
3693     delete_key( key_installprop, "", access & KEY_WOW64_64KEY );
3694     RegCloseKey( key_prod );
3695     RegCloseKey( key_comp );
3696     RegCloseKey( key_installprop );
3697     DeleteFileA( "c:\\testcomponentpath" );
3698     lstrcpyA( path_key, "Software\\Classes\\Installer\\Products\\" );
3699     lstrcatA( path_key, prod_squashed );
3700 
3701     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, path_key, 0, NULL, 0, access, NULL, &key_prod, NULL );
3702     ok( res == ERROR_SUCCESS, "got %d\n", res );
3703 
3704     /* local classes product key exists */
3705     size = MAX_PATH;
3706     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3707     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3708     todo_wine ok(!size, "got %u\n", size);
3709 
3710     lstrcpyA( path_key, "Software\\Microsoft\\Windows\\CurrentVersion\\" );
3711     lstrcatA( path_key, "Installer\\UserData\\S-1-5-18\\Components\\" );
3712     lstrcatA( path_key, comp_squashed );
3713 
3714     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE,  path_key, 0, NULL, 0, access, NULL, &key_comp, NULL );
3715     ok( res == ERROR_SUCCESS, "got %d\n", res );
3716 
3717     /* local user component key exists */
3718     size = MAX_PATH;
3719     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3720     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3721     todo_wine ok(!size, "got %u\n", size);
3722 
3723     res = RegSetValueExA( key_comp, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\testcomponentpath", 20 );
3724     ok( res == ERROR_SUCCESS, "got %d\n", res );
3725 
3726     /* product value exists */
3727     path[0] = 0;
3728     size = MAX_PATH;
3729     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3730     ok( state == INSTALLSTATE_ABSENT, "got %d\n", state );
3731     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3732     ok( size == 20, "got %u\n", size );
3733 
3734     create_file( "c:\\testcomponentpath", "c:\\testcomponentpath", 21 );
3735 
3736     /* file exists */
3737     path[0] = 0;
3738     size = MAX_PATH;
3739     state = pMsiGetComponentPathExA( prod, comp, NULL, MSIINSTALLCONTEXT_MACHINE, path, &size );
3740     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3741     ok( !lstrcmpA( path, "c:\\testcomponentpath" ), "got %s\n", path );
3742     ok( size == 20, "got %u\n", size );
3743 
3744     RegDeleteValueA( key_comp, prod_squashed );
3745     delete_key( key_prod, "", access & KEY_WOW64_64KEY );
3746     delete_key( key_comp, "", access & KEY_WOW64_64KEY );
3747     RegCloseKey( key_prod );
3748     RegCloseKey( key_comp );
3749     DeleteFileA( "c:\\testcomponentpath" );
3750     LocalFree( usersid );
3751 }
3752 
3753 static void test_MsiProvideComponent(void)
3754 {
3755     static const WCHAR sourcedirW[] =
3756         {'s','o','u','r','c','e','d','i','r',0};
3757     static const WCHAR productW[] =
3758         {'{','3','8','8','4','7','3','3','8','-','1','B','B','C','-','4','1','0','4','-',
3759          '8','1','A','C','-','2','F','A','A','C','7','E','C','D','D','C','D','}',0};
3760     static const WCHAR componentW[] =
3761         {'{','D','D','4','2','2','F','9','2','-','3','E','D','8','-','4','9','B','5','-',
3762          'A','0','B','7','-','F','2','6','6','F','9','8','3','5','7','D','F','}',0};
3763     INSTALLSTATE state;
3764     char buf[0x100];
3765     WCHAR bufW[0x100];
3766     DWORD len, len2;
3767     UINT r;
3768 
3769     if (is_process_limited())
3770     {
3771         skip("process is limited\n");
3772         return;
3773     }
3774 
3775     create_test_files();
3776     create_file("msitest\\sourcedir.txt", "msitest\\sourcedir.txt", 1000);
3777     create_database(msifile, sd_tables, sizeof(sd_tables) / sizeof(msi_table));
3778 
3779     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3780 
3781     buf[0] = 0;
3782     len = sizeof(buf);
3783     r = pMsiProvideComponentA("{90120000-0070-0000-0000-4000000FF1CE}",
3784                               "{17961602-C4E2-482E-800A-DF6E627549CF}",
3785                               "ProductFiles", INSTALLMODE_NODETECTION, buf, &len);
3786     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
3787 
3788     r = MsiInstallProductA(msifile, NULL);
3789     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3790 
3791     state = MsiQueryFeatureStateA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir");
3792     ok(state == INSTALLSTATE_LOCAL, "got %d\n", state);
3793 
3794     buf[0] = 0;
3795     len = sizeof(buf);
3796     r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir",
3797                               "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
3798                               INSTALLMODE_NODETECTION, buf, &len);
3799     ok(r == ERROR_SUCCESS, "got %u\n", r);
3800     ok(buf[0], "empty path\n");
3801     ok(len == lstrlenA(buf), "got %u\n", len);
3802 
3803     len2 = 0;
3804     r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir",
3805                               "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
3806                               INSTALLMODE_NODETECTION, NULL, &len2);
3807     ok(r == ERROR_SUCCESS, "got %u\n", r);
3808     ok(len2 == len, "got %u\n", len2);
3809 
3810     len2 = 0;
3811     r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir",
3812                               "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
3813                               INSTALLMODE_NODETECTION, buf, &len2);
3814     ok(r == ERROR_MORE_DATA, "got %u\n", r);
3815     ok(len2 == len, "got %u\n", len2);
3816 
3817     /* wide version */
3818 
3819     bufW[0] = 0;
3820     len = sizeof(buf);
3821     r = pMsiProvideComponentW(productW, sourcedirW, componentW,
3822                               INSTALLMODE_NODETECTION, bufW, &len);
3823     ok(r == ERROR_SUCCESS, "got %u\n", r);
3824     ok(bufW[0], "empty path\n");
3825     ok(len == lstrlenW(bufW), "got %u\n", len);
3826 
3827     len2 = 0;
3828     r = pMsiProvideComponentW(productW, sourcedirW, componentW,
3829                               INSTALLMODE_NODETECTION, NULL, &len2);
3830     ok(r == ERROR_SUCCESS, "got %u\n", r);
3831     ok(len2 == len, "got %u\n", len2);
3832 
3833     len2 = 0;
3834     r = pMsiProvideComponentW(productW, sourcedirW, componentW,
3835                               INSTALLMODE_NODETECTION, bufW, &len2);
3836     ok(r == ERROR_MORE_DATA, "got %u\n", r);
3837     ok(len2 == len, "got %u\n", len2);
3838 
3839     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3840     ok(r == ERROR_SUCCESS, "got %u\n", r);
3841 
3842     DeleteFileA("msitest\\sourcedir.txt");
3843     delete_test_files();
3844     DeleteFileA(msifile);
3845 }
3846 
3847 static void test_MsiProvideQualifiedComponentEx(void)
3848 {
3849     UINT r;
3850     INSTALLSTATE state;
3851     char comp[39], comp_squashed[33], comp2[39], comp2_base85[21], comp2_squashed[33];
3852     char prod[39], prod_base85[21], prod_squashed[33];
3853     char desc[MAX_PATH], buf[MAX_PATH], keypath[MAX_PATH], path[MAX_PATH];
3854     DWORD len = sizeof(buf);
3855     REGSAM access = KEY_ALL_ACCESS;
3856     HKEY hkey, hkey2, hkey3, hkey4, hkey5;
3857     LONG res;
3858 
3859     if (is_process_limited())
3860     {
3861         skip( "process is limited\n" );
3862         return;
3863     }
3864 
3865     create_test_guid( comp, comp_squashed );
3866     compose_base85_guid( comp2, comp2_base85, comp2_squashed );
3867     compose_base85_guid( prod, prod_base85, prod_squashed );
3868 
3869     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3870     ok( r == ERROR_UNKNOWN_COMPONENT, "got %u\n", r );
3871 
3872     lstrcpyA( keypath, "Software\\Classes\\Installer\\Components\\" );
3873     lstrcatA( keypath, comp_squashed );
3874 
3875     if (is_wow64) access |= KEY_WOW64_64KEY;
3876     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey, NULL );
3877     ok( res == ERROR_SUCCESS, "got %d\n", res );
3878 
3879     lstrcpyA( desc, prod_base85 );
3880     memcpy( desc + lstrlenA(desc), "feature<\0", sizeof("feature<\0") );
3881     res = RegSetValueExA( hkey, "qualifier", 0, REG_MULTI_SZ, (const BYTE *)desc,
3882                           lstrlenA(prod_base85) + sizeof("feature<\0") );
3883     ok( res == ERROR_SUCCESS, "got %d\n", res );
3884 
3885     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3886     ok( r == ERROR_UNKNOWN_PRODUCT, "got %u\n", r );
3887 
3888     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, NULL, 0, 0, buf, &len );
3889     ok( r == ERROR_UNKNOWN_PRODUCT, "got %u\n", r );
3890 
3891     state = MsiQueryProductStateA( prod );
3892     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3893 
3894     lstrcpyA( keypath, "Software\\Classes\\Installer\\Products\\" );
3895     lstrcatA( keypath, prod_squashed );
3896 
3897     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey2, NULL );
3898     ok( res == ERROR_SUCCESS, "got %d\n", res );
3899 
3900     state = MsiQueryProductStateA( prod );
3901     ok( state == INSTALLSTATE_ADVERTISED, "got %d\n", state );
3902 
3903     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3904     todo_wine ok( r == ERROR_UNKNOWN_FEATURE, "got %u\n", r );
3905 
3906     lstrcpyA( keypath, "Software\\Classes\\Installer\\Features\\" );
3907     lstrcatA( keypath, prod_squashed );
3908 
3909     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey3, NULL );
3910     ok( res == ERROR_SUCCESS, "got %d\n", res );
3911 
3912     state = MsiQueryFeatureStateA( prod, "feature" );
3913     ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
3914 
3915     res = RegSetValueExA( hkey3, "feature", 0, REG_SZ, (const BYTE *)"", 1 );
3916     ok( res == ERROR_SUCCESS, "got %d\n", res );
3917 
3918     state = MsiQueryFeatureStateA( prod, "feature" );
3919     ok( state == INSTALLSTATE_ADVERTISED, "got %d\n", state );
3920 
3921     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3922     ok( r == ERROR_FILE_NOT_FOUND, "got %u\n", r );
3923 
3924     len = sizeof(buf);
3925     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, NULL, 0, 0, buf, &len );
3926     ok( r == ERROR_FILE_NOT_FOUND, "got %u\n", r );
3927 
3928     lstrcpyA( keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\" );
3929     lstrcatA( keypath, prod_squashed );
3930     lstrcatA( keypath, "\\Features" );
3931 
3932     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey4, NULL );
3933     ok( res == ERROR_SUCCESS, "got %d\n", res );
3934 
3935     res = RegSetValueExA( hkey4, "feature", 0, REG_SZ, (const BYTE *)comp2_base85, sizeof(comp2_base85) );
3936     ok( res == ERROR_SUCCESS, "got %d\n", res );
3937 
3938     state = MsiQueryFeatureStateA( prod, "feature" );
3939     ok( state == INSTALLSTATE_ADVERTISED, "got %d\n", state );
3940 
3941     lstrcpyA( keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\" );
3942     lstrcatA( keypath, comp2_squashed );
3943 
3944     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey5, NULL );
3945     ok( res == ERROR_SUCCESS, "got %d\n", res );
3946 
3947     res = RegSetValueExA( hkey5, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\nosuchfile", sizeof("c:\\nosuchfile") );
3948     ok( res == ERROR_SUCCESS, "got %d\n", res );
3949 
3950     state = MsiQueryFeatureStateA( prod, "feature" );
3951     ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
3952 
3953     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3954     ok( r == ERROR_FILE_NOT_FOUND, "got %u\n", r );
3955 
3956     GetCurrentDirectoryA( MAX_PATH, path );
3957     lstrcatA( path, "\\msitest" );
3958     CreateDirectoryA( path, NULL );
3959     lstrcatA( path, "\\test.txt" );
3960     create_file( path, "test", 100 );
3961 
3962     res = RegSetValueExA( hkey5, prod_squashed, 0, REG_SZ, (const BYTE *)path, lstrlenA(path) + 1 );
3963     ok( res == ERROR_SUCCESS, "got %d\n", res );
3964 
3965     buf[0] = 0;
3966     len = sizeof(buf);
3967     r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
3968     ok( r == ERROR_SUCCESS, "got %u\n", r );
3969     ok( len == lstrlenA(path), "got %u\n", len );
3970     ok( !lstrcmpA( path, buf ), "got '%s'\n", buf );
3971 
3972     DeleteFileA( "msitest\\text.txt" );
3973     RemoveDirectoryA( "msitest" );
3974 
3975     delete_key( hkey5, "", access & KEY_WOW64_64KEY );
3976     RegCloseKey( hkey5 );
3977     delete_key( hkey4, "", access & KEY_WOW64_64KEY );
3978     RegCloseKey( hkey4 );
3979     delete_key( hkey3, "", access & KEY_WOW64_64KEY );
3980     RegCloseKey( hkey3 );
3981     delete_key( hkey2, "", access & KEY_WOW64_64KEY );
3982     RegCloseKey( hkey2 );
3983     delete_key( hkey, "", access & KEY_WOW64_64KEY );
3984     RegCloseKey( hkey );
3985 }
3986 
3987 static void test_MsiGetProductCode(void)
3988 {
3989     HKEY compkey, prodkey;
3990     CHAR prodcode[MAX_PATH];
3991     CHAR prod_squashed[MAX_PATH];
3992     CHAR prodcode2[MAX_PATH];
3993     CHAR prod2_squashed[MAX_PATH];
3994     CHAR component[MAX_PATH];
3995     CHAR comp_base85[MAX_PATH];
3996     CHAR comp_squashed[MAX_PATH];
3997     CHAR keypath[MAX_PATH];
3998     CHAR product[MAX_PATH];
3999     LPSTR usersid;
4000     LONG res;
4001     UINT r;
4002     REGSAM access = KEY_ALL_ACCESS;
4003 
4004     create_test_guid(prodcode, prod_squashed);
4005     create_test_guid(prodcode2, prod2_squashed);
4006     compose_base85_guid(component, comp_base85, comp_squashed);
4007     usersid = get_user_sid();
4008 
4009     if (is_wow64)
4010         access |= KEY_WOW64_64KEY;
4011 
4012     /* szComponent is NULL */
4013     lstrcpyA(product, "prod");
4014     r = MsiGetProductCodeA(NULL, product);
4015     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4016     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4017 
4018     /* szComponent is empty */
4019     lstrcpyA(product, "prod");
4020     r = MsiGetProductCodeA("", product);
4021     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4022     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4023 
4024     /* garbage szComponent */
4025     lstrcpyA(product, "prod");
4026     r = MsiGetProductCodeA("garbage", product);
4027     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4028     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4029 
4030     /* guid without brackets */
4031     lstrcpyA(product, "prod");
4032     r = MsiGetProductCodeA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", product);
4033     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4034     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4035 
4036     /* guid with brackets */
4037     lstrcpyA(product, "prod");
4038     r = MsiGetProductCodeA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", product);
4039     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
4040     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4041 
4042     /* same length as guid, but random */
4043     lstrcpyA(product, "prod");
4044     r = MsiGetProductCodeA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", product);
4045     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4046     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4047 
4048     /* all params correct, szComponent not published */
4049     lstrcpyA(product, "prod");
4050     r = MsiGetProductCodeA(component, product);
4051     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
4052     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4053 
4054     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4055     lstrcatA(keypath, "Installer\\UserData\\");
4056     lstrcatA(keypath, usersid);
4057     lstrcatA(keypath, "\\Components\\");
4058     lstrcatA(keypath, comp_squashed);
4059 
4060     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
4061     if (res == ERROR_ACCESS_DENIED)
4062     {
4063         skip("Not enough rights to perform tests\n");
4064         LocalFree(usersid);
4065         return;
4066     }
4067     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4068 
4069     /* user unmanaged component key exists */
4070     lstrcpyA(product, "prod");
4071     r = MsiGetProductCodeA(component, product);
4072     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
4073     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4074 
4075     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
4076     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4077 
4078     /* product value exists */
4079     lstrcpyA(product, "prod");
4080     r = MsiGetProductCodeA(component, product);
4081     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4082     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4083 
4084     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
4085     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4086 
4087     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4088     lstrcatA(keypath, "Installer\\Managed\\");
4089     lstrcatA(keypath, usersid);
4090     lstrcatA(keypath, "\\Installer\\Products\\");
4091     lstrcatA(keypath, prod_squashed);
4092 
4093     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4094     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4095 
4096     /* user managed product key of first product exists */
4097     lstrcpyA(product, "prod");
4098     r = MsiGetProductCodeA(component, product);
4099     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4100     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4101 
4102     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4103     RegCloseKey(prodkey);
4104 
4105     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
4106     lstrcatA(keypath, prod_squashed);
4107 
4108     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
4109     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4110 
4111     /* user unmanaged product key exists */
4112     lstrcpyA(product, "prod");
4113     r = MsiGetProductCodeA(component, product);
4114     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4115     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4116 
4117     RegDeleteKeyA(prodkey, "");
4118     RegCloseKey(prodkey);
4119 
4120     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
4121     lstrcatA(keypath, prod_squashed);
4122 
4123     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4124     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4125 
4126     /* local classes product key exists */
4127     lstrcpyA(product, "prod");
4128     r = MsiGetProductCodeA(component, product);
4129     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4130     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4131 
4132     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4133     RegCloseKey(prodkey);
4134 
4135     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4136     lstrcatA(keypath, "Installer\\Managed\\");
4137     lstrcatA(keypath, usersid);
4138     lstrcatA(keypath, "\\Installer\\Products\\");
4139     lstrcatA(keypath, prod2_squashed);
4140 
4141     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4142     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4143 
4144     /* user managed product key of second product exists */
4145     lstrcpyA(product, "prod");
4146     r = MsiGetProductCodeA(component, product);
4147     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4148     ok(!lstrcmpA(product, prodcode2), "Expected %s, got %s\n", prodcode2, product);
4149 
4150     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4151     RegCloseKey(prodkey);
4152     RegDeleteValueA(compkey, prod_squashed);
4153     RegDeleteValueA(compkey, prod2_squashed);
4154     delete_key(compkey, "", access & KEY_WOW64_64KEY);
4155     RegCloseKey(compkey);
4156 
4157     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4158     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
4159     lstrcatA(keypath, comp_squashed);
4160 
4161     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
4162     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4163 
4164     /* local user component key exists */
4165     lstrcpyA(product, "prod");
4166     r = MsiGetProductCodeA(component, product);
4167     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
4168     ok(!lstrcmpA(product, "prod"), "Expected product to be unchanged, got %s\n", product);
4169 
4170     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
4171     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4172 
4173     /* product value exists */
4174     lstrcpyA(product, "prod");
4175     r = MsiGetProductCodeA(component, product);
4176     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4177     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4178 
4179     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
4180     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4181 
4182     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4183     lstrcatA(keypath, "Installer\\Managed\\");
4184     lstrcatA(keypath, usersid);
4185     lstrcatA(keypath, "\\Installer\\Products\\");
4186     lstrcatA(keypath, prod_squashed);
4187 
4188     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4189     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4190 
4191     /* user managed product key of first product exists */
4192     lstrcpyA(product, "prod");
4193     r = MsiGetProductCodeA(component, product);
4194     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4195     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4196 
4197     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4198     RegCloseKey(prodkey);
4199 
4200     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
4201     lstrcatA(keypath, prod_squashed);
4202 
4203     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
4204     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4205 
4206     /* user unmanaged product key exists */
4207     lstrcpyA(product, "prod");
4208     r = MsiGetProductCodeA(component, product);
4209     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4210     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4211 
4212     RegDeleteKeyA(prodkey, "");
4213     RegCloseKey(prodkey);
4214 
4215     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
4216     lstrcatA(keypath, prod_squashed);
4217 
4218     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4219     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4220 
4221     /* local classes product key exists */
4222     lstrcpyA(product, "prod");
4223     r = MsiGetProductCodeA(component, product);
4224     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4225     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4226 
4227     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4228     RegCloseKey(prodkey);
4229 
4230     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4231     lstrcatA(keypath, "Installer\\Managed\\");
4232     lstrcatA(keypath, usersid);
4233     lstrcatA(keypath, "\\Installer\\Products\\");
4234     lstrcatA(keypath, prod2_squashed);
4235 
4236     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4237     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4238 
4239     /* user managed product key of second product exists */
4240     lstrcpyA(product, "prod");
4241     r = MsiGetProductCodeA(component, product);
4242     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4243     ok(!lstrcmpA(product, prodcode2), "Expected %s, got %s\n", prodcode2, product);
4244 
4245     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4246     RegCloseKey(prodkey);
4247     RegDeleteValueA(compkey, prod_squashed);
4248     RegDeleteValueA(compkey, prod2_squashed);
4249     delete_key(compkey, "", access & KEY_WOW64_64KEY);
4250     RegCloseKey(compkey);
4251     LocalFree(usersid);
4252 }
4253 
4254 static void test_MsiEnumClients(void)
4255 {
4256     HKEY compkey;
4257     CHAR prodcode[MAX_PATH];
4258     CHAR prod_squashed[MAX_PATH];
4259     CHAR prodcode2[MAX_PATH];
4260     CHAR prod2_squashed[MAX_PATH];
4261     CHAR component[MAX_PATH];
4262     CHAR comp_base85[MAX_PATH];
4263     CHAR comp_squashed[MAX_PATH];
4264     CHAR product[MAX_PATH];
4265     CHAR keypath[MAX_PATH];
4266     LPSTR usersid;
4267     LONG res;
4268     UINT r;
4269     REGSAM access = KEY_ALL_ACCESS;
4270 
4271     create_test_guid(prodcode, prod_squashed);
4272     create_test_guid(prodcode2, prod2_squashed);
4273     compose_base85_guid(component, comp_base85, comp_squashed);
4274     usersid = get_user_sid();
4275 
4276     if (is_wow64)
4277         access |= KEY_WOW64_64KEY;
4278 
4279     /* NULL szComponent */
4280     product[0] = '\0';
4281     r = MsiEnumClientsA(NULL, 0, product);
4282     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4283     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4284 
4285     /* empty szComponent */
4286     product[0] = '\0';
4287     r = MsiEnumClientsA("", 0, product);
4288     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4289     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4290 
4291     /* NULL lpProductBuf */
4292     r = MsiEnumClientsA(component, 0, NULL);
4293     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4294 
4295     /* all params correct, component missing */
4296     product[0] = '\0';
4297     r = MsiEnumClientsA(component, 0, product);
4298     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
4299     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4300 
4301     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4302     lstrcatA(keypath, "Installer\\UserData\\");
4303     lstrcatA(keypath, usersid);
4304     lstrcatA(keypath, "\\Components\\");
4305     lstrcatA(keypath, comp_squashed);
4306 
4307     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
4308     if (res == ERROR_ACCESS_DENIED)
4309     {
4310         skip("Not enough rights to perform tests\n");
4311         LocalFree(usersid);
4312         return;
4313     }
4314     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4315 
4316     /* user unmanaged component key exists */
4317     product[0] = '\0';
4318     r = MsiEnumClientsA(component, 0, product);
4319     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
4320     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4321 
4322     /* index > 0, no products exist */
4323     product[0] = '\0';
4324     r = MsiEnumClientsA(component, 1, product);
4325     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4326     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4327 
4328     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
4329     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4330 
4331     /* product value exists */
4332     r = MsiEnumClientsA(component, 0, product);
4333     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4334     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4335 
4336     /* try index 0 again */
4337     product[0] = '\0';
4338     r = MsiEnumClientsA(component, 0, product);
4339     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4340     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4341 
4342     /* try index 1, second product value does not exist */
4343     product[0] = '\0';
4344     r = MsiEnumClientsA(component, 1, product);
4345     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4346     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4347 
4348     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
4349     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4350 
4351     /* try index 1, second product value does exist */
4352     product[0] = '\0';
4353     r = MsiEnumClientsA(component, 1, product);
4354     todo_wine
4355     {
4356         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4357         ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4358     }
4359 
4360     /* start the enumeration over */
4361     product[0] = '\0';
4362     r = MsiEnumClientsA(component, 0, product);
4363     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4364     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
4365        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
4366 
4367     /* correctly query second product */
4368     product[0] = '\0';
4369     r = MsiEnumClientsA(component, 1, product);
4370     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4371     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
4372        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
4373 
4374     RegDeleteValueA(compkey, prod_squashed);
4375     RegDeleteValueA(compkey, prod2_squashed);
4376     delete_key(compkey, "", access & KEY_WOW64_64KEY);
4377     RegCloseKey(compkey);
4378 
4379     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
4380     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
4381     lstrcatA(keypath, comp_squashed);
4382 
4383     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
4384     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4385 
4386     /* user local component key exists */
4387     product[0] = '\0';
4388     r = MsiEnumClientsA(component, 0, product);
4389     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
4390     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4391 
4392     /* index > 0, no products exist */
4393     product[0] = '\0';
4394     r = MsiEnumClientsA(component, 1, product);
4395     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4396     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4397 
4398     res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
4399     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4400 
4401     /* product value exists */
4402     product[0] = '\0';
4403     r = MsiEnumClientsA(component, 0, product);
4404     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4405     ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
4406 
4407     /* try index 0 again */
4408     product[0] = '\0';
4409     r = MsiEnumClientsA(component, 0, product);
4410     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4411 
4412     /* try index 1, second product value does not exist */
4413     product[0] = '\0';
4414     r = MsiEnumClientsA(component, 1, product);
4415     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4416     ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4417 
4418     res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
4419     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4420 
4421     /* try index 1, second product value does exist */
4422     product[0] = '\0';
4423     r = MsiEnumClientsA(component, 1, product);
4424     todo_wine
4425     {
4426         ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4427         ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
4428     }
4429 
4430     /* start the enumeration over */
4431     product[0] = '\0';
4432     r = MsiEnumClientsA(component, 0, product);
4433     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4434     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
4435        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
4436 
4437     /* correctly query second product */
4438     product[0] = '\0';
4439     r = MsiEnumClientsA(component, 1, product);
4440     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4441     ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
4442        "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
4443 
4444     RegDeleteValueA(compkey, prod_squashed);
4445     RegDeleteValueA(compkey, prod2_squashed);
4446     delete_key(compkey, "", access & KEY_WOW64_64KEY);
4447     RegCloseKey(compkey);
4448     LocalFree(usersid);
4449 }
4450 
4451 static void get_version_info(LPSTR path, LPSTR *vercheck, LPDWORD verchecksz,
4452                              LPSTR *langcheck, LPDWORD langchecksz)
4453 {
4454     LPSTR version;
4455     VS_FIXEDFILEINFO *ffi;
4456     DWORD size = GetFileVersionInfoSizeA(path, NULL);
4457     USHORT *lang;
4458 
4459     version = HeapAlloc(GetProcessHeap(), 0, size);
4460     GetFileVersionInfoA(path, 0, size, version);
4461 
4462     VerQueryValueA(version, "\\", (LPVOID *)&ffi, &size);
4463     *vercheck = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
4464     sprintf(*vercheck, "%d.%d.%d.%d", HIWORD(ffi->dwFileVersionMS),
4465             LOWORD(ffi->dwFileVersionMS), HIWORD(ffi->dwFileVersionLS),
4466             LOWORD(ffi->dwFileVersionLS));
4467     *verchecksz = lstrlenA(*vercheck);
4468 
4469     VerQueryValueA(version, "\\VarFileInfo\\Translation", (void **)&lang, &size);
4470     *langcheck = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
4471     sprintf(*langcheck, "%d", *lang);
4472     *langchecksz = lstrlenA(*langcheck);
4473 
4474     HeapFree(GetProcessHeap(), 0, version);
4475 }
4476 
4477 static void test_MsiGetFileVersion(void)
4478 {
4479     UINT r;
4480     DWORD versz, langsz;
4481     char version[MAX_PATH];
4482     char lang[MAX_PATH];
4483     char path[MAX_PATH];
4484     LPSTR vercheck, langcheck;
4485     DWORD verchecksz, langchecksz;
4486 
4487     /* NULL szFilePath */
4488     r = MsiGetFileVersionA(NULL, NULL, NULL, NULL, NULL);
4489     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4490 
4491     versz = MAX_PATH;
4492     langsz = MAX_PATH;
4493     lstrcpyA(version, "version");
4494     lstrcpyA(lang, "lang");
4495     r = MsiGetFileVersionA(NULL, version, &versz, lang, &langsz);
4496     ok(r == ERROR_INVALID_PARAMETER,
4497        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4498     ok(!lstrcmpA(version, "version"),
4499        "Expected version to be unchanged, got %s\n", version);
4500     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4501     ok(!lstrcmpA(lang, "lang"),
4502        "Expected lang to be unchanged, got %s\n", lang);
4503     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4504 
4505     /* empty szFilePath */
4506     r = MsiGetFileVersionA("", NULL, NULL, NULL, NULL);
4507     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4508 
4509     versz = MAX_PATH;
4510     langsz = MAX_PATH;
4511     lstrcpyA(version, "version");
4512     lstrcpyA(lang, "lang");
4513     r = MsiGetFileVersionA("", version, &versz, lang, &langsz);
4514     ok(r == ERROR_FILE_NOT_FOUND,
4515        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4516     ok(!lstrcmpA(version, "version"),
4517        "Expected version to be unchanged, got %s\n", version);
4518     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4519     ok(!lstrcmpA(lang, "lang"),
4520        "Expected lang to be unchanged, got %s\n", lang);
4521     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4522 
4523     /* nonexistent szFilePath */
4524     versz = MAX_PATH;
4525     langsz = MAX_PATH;
4526     lstrcpyA(version, "version");
4527     lstrcpyA(lang, "lang");
4528     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
4529     ok(r == ERROR_FILE_NOT_FOUND,
4530        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4531     ok(!lstrcmpA(version, "version"),
4532        "Expected version to be unchanged, got %s\n", version);
4533     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4534     ok(!lstrcmpA(lang, "lang"),
4535        "Expected lang to be unchanged, got %s\n", lang);
4536     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4537 
4538     /* nonexistent szFilePath, valid lpVersionBuf, NULL pcchVersionBuf */
4539     versz = MAX_PATH;
4540     langsz = MAX_PATH;
4541     lstrcpyA(version, "version");
4542     lstrcpyA(lang, "lang");
4543     r = MsiGetFileVersionA("nonexistent", version, NULL, lang, &langsz);
4544     ok(r == ERROR_INVALID_PARAMETER,
4545        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4546     ok(!lstrcmpA(version, "version"),
4547        "Expected version to be unchanged, got %s\n", version);
4548     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4549     ok(!lstrcmpA(lang, "lang"),
4550        "Expected lang to be unchanged, got %s\n", lang);
4551     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4552 
4553     /* nonexistent szFilePath, valid lpLangBuf, NULL pcchLangBuf */
4554     versz = MAX_PATH;
4555     langsz = MAX_PATH;
4556     lstrcpyA(version, "version");
4557     lstrcpyA(lang, "lang");
4558     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, NULL);
4559     ok(r == ERROR_INVALID_PARAMETER,
4560        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4561     ok(!lstrcmpA(version, "version"),
4562        "Expected version to be unchanged, got %s\n", version);
4563     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4564     ok(!lstrcmpA(lang, "lang"),
4565        "Expected lang to be unchanged, got %s\n", lang);
4566     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4567 
4568     /* nonexistent szFilePath, valid lpVersionBuf, pcchVersionBuf is zero */
4569     versz = 0;
4570     langsz = MAX_PATH;
4571     lstrcpyA(version, "version");
4572     lstrcpyA(lang, "lang");
4573     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
4574     ok(r == ERROR_FILE_NOT_FOUND,
4575        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4576     ok(!lstrcmpA(version, "version"),
4577        "Expected version to be unchanged, got %s\n", version);
4578     ok(versz == 0, "Expected 0, got %d\n", versz);
4579     ok(!lstrcmpA(lang, "lang"),
4580        "Expected lang to be unchanged, got %s\n", lang);
4581     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4582 
4583     /* nonexistent szFilePath, valid lpLangBuf, pcchLangBuf is zero */
4584     versz = MAX_PATH;
4585     langsz = 0;
4586     lstrcpyA(version, "version");
4587     lstrcpyA(lang, "lang");
4588     r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz);
4589     ok(r == ERROR_FILE_NOT_FOUND,
4590        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4591     ok(!lstrcmpA(version, "version"),
4592        "Expected version to be unchanged, got %s\n", version);
4593     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4594     ok(!lstrcmpA(lang, "lang"),
4595        "Expected lang to be unchanged, got %s\n", lang);
4596     ok(langsz == 0, "Expected 0, got %d\n", langsz);
4597 
4598     /* nonexistent szFilePath, rest NULL */
4599     r = MsiGetFileVersionA("nonexistent", NULL, NULL, NULL, NULL);
4600     ok(r == ERROR_FILE_NOT_FOUND,
4601        "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4602 
4603     create_file("ver.txt", "ver.txt", 20);
4604 
4605     /* file exists, no version information */
4606     r = MsiGetFileVersionA("ver.txt", NULL, NULL, NULL, NULL);
4607     ok(r == ERROR_FILE_INVALID, "Expected ERROR_FILE_INVALID, got %d\n", r);
4608 
4609     versz = MAX_PATH;
4610     langsz = MAX_PATH;
4611     lstrcpyA(version, "version");
4612     lstrcpyA(lang, "lang");
4613     r = MsiGetFileVersionA("ver.txt", version, &versz, lang, &langsz);
4614     ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4615     ok(!lstrcmpA(version, "version"),
4616        "Expected version to be unchanged, got %s\n", version);
4617     ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4618     ok(!lstrcmpA(lang, "lang"),
4619        "Expected lang to be unchanged, got %s\n", lang);
4620     ok(r == ERROR_FILE_INVALID,
4621        "Expected ERROR_FILE_INVALID, got %d\n", r);
4622 
4623     DeleteFileA("ver.txt");
4624 
4625     /* relative path, has version information */
4626     versz = MAX_PATH;
4627     langsz = MAX_PATH;
4628     lstrcpyA(version, "version");
4629     lstrcpyA(lang, "lang");
4630     r = MsiGetFileVersionA("kernel32.dll", version, &versz, lang, &langsz);
4631     todo_wine
4632     {
4633         ok(r == ERROR_FILE_NOT_FOUND,
4634            "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
4635         ok(!lstrcmpA(version, "version"),
4636            "Expected version to be unchanged, got %s\n", version);
4637         ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz);
4638         ok(!lstrcmpA(lang, "lang"),
4639            "Expected lang to be unchanged, got %s\n", lang);
4640         ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz);
4641     }
4642 
4643     GetSystemDirectoryA(path, MAX_PATH);
4644     lstrcatA(path, "\\kernel32.dll");
4645 
4646     get_version_info(path, &vercheck, &verchecksz, &langcheck, &langchecksz);
4647 
4648     /* absolute path, has version information */
4649     versz = MAX_PATH;
4650     langsz = MAX_PATH;
4651     lstrcpyA(version, "version");
4652     lstrcpyA(lang, "lang");
4653     r = MsiGetFileVersionA(path, version, &versz, lang, &langsz);
4654     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4655     if (langchecksz && !langsz)
4656     {
4657         win_skip("broken MsiGetFileVersionA detected\n");
4658         HeapFree(GetProcessHeap(), 0, vercheck);
4659         HeapFree(GetProcessHeap(), 0, langcheck);
4660         return;
4661     }
4662     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4663     ok(strstr(lang, langcheck) != NULL, "Expected \"%s\" in \"%s\"\n", langcheck, lang);
4664     ok(!lstrcmpA(version, vercheck),
4665         "Expected %s, got %s\n", vercheck, version);
4666 
4667     /* only check version */
4668     versz = MAX_PATH;
4669     lstrcpyA(version, "version");
4670     r = MsiGetFileVersionA(path, version, &versz, NULL, NULL);
4671     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4672     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4673     ok(!lstrcmpA(version, vercheck),
4674        "Expected %s, got %s\n", vercheck, version);
4675 
4676     /* only check language */
4677     langsz = MAX_PATH;
4678     lstrcpyA(lang, "lang");
4679     r = MsiGetFileVersionA(path, NULL, NULL, lang, &langsz);
4680     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4681     ok(strstr(lang, langcheck) != NULL, "Expected \"%s\" in \"%s\"\n", langcheck, lang);
4682 
4683     /* check neither version nor language */
4684     r = MsiGetFileVersionA(path, NULL, NULL, NULL, NULL);
4685     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4686 
4687     /* get pcchVersionBuf */
4688     versz = MAX_PATH;
4689     r = MsiGetFileVersionA(path, NULL, &versz, NULL, NULL);
4690     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4691     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4692 
4693     /* get pcchLangBuf */
4694     langsz = MAX_PATH;
4695     r = MsiGetFileVersionA(path, NULL, NULL, NULL, &langsz);
4696     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4697     ok(langsz >= langchecksz, "Expected %d >= %d\n", langsz, langchecksz);
4698 
4699     /* pcchVersionBuf not big enough */
4700     versz = 5;
4701     lstrcpyA(version, "version");
4702     r = MsiGetFileVersionA(path, version, &versz, NULL, NULL);
4703     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4704     ok(!strncmp(version, vercheck, 4),
4705        "Expected first 4 characters of \"%s\", got \"%s\"\n", vercheck, version);
4706     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4707 
4708     /* pcchLangBuf not big enough */
4709     langsz = 4;
4710     lstrcpyA(lang, "lang");
4711     r = MsiGetFileVersionA(path, NULL, NULL, lang, &langsz);
4712     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4713     ok(lstrcmpA(lang, "lang"), "lang not set\n");
4714     ok(langsz >= langchecksz, "Expected %d >= %d\n", langsz, langchecksz);
4715 
4716     /* pcchVersionBuf big enough, pcchLangBuf not big enough */
4717     versz = MAX_PATH;
4718     langsz = 0;
4719     lstrcpyA(version, "version");
4720     r = MsiGetFileVersionA(path, version, &versz, NULL, &langsz);
4721     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4722     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4723     ok(!lstrcmpA(version, vercheck), "Expected \"%s\", got \"%s\"\n", vercheck, version);
4724     ok(langsz >= langchecksz && langsz < MAX_PATH, "Expected %d >= %d\n", langsz, langchecksz);
4725 
4726     /* pcchVersionBuf not big enough, pcchLangBuf big enough */
4727     versz = 5;
4728     langsz = MAX_PATH;
4729     lstrcpyA(lang, "lang");
4730     r = MsiGetFileVersionA(path, NULL, &versz, lang, &langsz);
4731     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4732     ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
4733     ok(langsz >= langchecksz && langsz < MAX_PATH, "Expected %d >= %d\n", langsz, langchecksz);
4734     ok(strstr(lang, langcheck) != NULL, "expected %s in %s\n", langcheck, lang);
4735 
4736     /* NULL pcchVersionBuf and pcchLangBuf */
4737     r = MsiGetFileVersionA(path, version, NULL, lang, NULL);
4738     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4739 
4740     /* All NULL except szFilePath */
4741     r = MsiGetFileVersionA(path, NULL, NULL, NULL, NULL);
4742     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4743 
4744     HeapFree(GetProcessHeap(), 0, vercheck);
4745     HeapFree(GetProcessHeap(), 0, langcheck);
4746 }
4747 
4748 static void test_MsiGetProductInfo(void)
4749 {
4750     UINT r;
4751     LONG res;
4752     HKEY propkey, source;
4753     HKEY prodkey, localkey;
4754     CHAR prodcode[MAX_PATH];
4755     CHAR prod_squashed[MAX_PATH];
4756     CHAR packcode[MAX_PATH];
4757     CHAR pack_squashed[MAX_PATH];
4758     CHAR buf[MAX_PATH];
4759     CHAR keypath[MAX_PATH];
4760     LPSTR usersid;
4761     DWORD sz, val = 42;
4762     REGSAM access = KEY_ALL_ACCESS;
4763 
4764     create_test_guid(prodcode, prod_squashed);
4765     create_test_guid(packcode, pack_squashed);
4766     usersid = get_user_sid();
4767 
4768     if (is_wow64)
4769         access |= KEY_WOW64_64KEY;
4770 
4771     /* NULL szProduct */
4772     sz = MAX_PATH;
4773     lstrcpyA(buf, "apple");
4774     r = MsiGetProductInfoA(NULL, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4775     ok(r == ERROR_INVALID_PARAMETER,
4776        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4777     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4778     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4779 
4780     /* empty szProduct */
4781     sz = MAX_PATH;
4782     lstrcpyA(buf, "apple");
4783     r = MsiGetProductInfoA("", INSTALLPROPERTY_HELPLINKA, buf, &sz);
4784     ok(r == ERROR_INVALID_PARAMETER,
4785        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4786     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4787     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4788 
4789     /* garbage szProduct */
4790     sz = MAX_PATH;
4791     lstrcpyA(buf, "apple");
4792     r = MsiGetProductInfoA("garbage", INSTALLPROPERTY_HELPLINKA, buf, &sz);
4793     ok(r == ERROR_INVALID_PARAMETER,
4794        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4795     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4796     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4797 
4798     /* guid without brackets */
4799     sz = MAX_PATH;
4800     lstrcpyA(buf, "apple");
4801     r = MsiGetProductInfoA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
4802                            INSTALLPROPERTY_HELPLINKA, buf, &sz);
4803     ok(r == ERROR_INVALID_PARAMETER,
4804        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4805     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4806     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4807 
4808     /* guid with brackets */
4809     sz = MAX_PATH;
4810     lstrcpyA(buf, "apple");
4811     r = MsiGetProductInfoA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
4812                            INSTALLPROPERTY_HELPLINKA, buf, &sz);
4813     ok(r == ERROR_UNKNOWN_PRODUCT,
4814        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4815     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4816     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4817 
4818     /* same length as guid, but random */
4819     sz = MAX_PATH;
4820     lstrcpyA(buf, "apple");
4821     r = MsiGetProductInfoA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
4822                            INSTALLPROPERTY_HELPLINKA, buf, &sz);
4823     ok(r == ERROR_INVALID_PARAMETER,
4824        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4825     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4826     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4827 
4828     /* not installed, NULL szAttribute */
4829     sz = MAX_PATH;
4830     lstrcpyA(buf, "apple");
4831     r = MsiGetProductInfoA(prodcode, NULL, buf, &sz);
4832     ok(r == ERROR_INVALID_PARAMETER,
4833        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4834     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4835     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4836 
4837     /* not installed, NULL lpValueBuf */
4838     sz = MAX_PATH;
4839     lstrcpyA(buf, "apple");
4840     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, &sz);
4841     ok(r == ERROR_UNKNOWN_PRODUCT,
4842        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4843     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4844     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4845 
4846     /* not installed, NULL pcchValueBuf */
4847     sz = MAX_PATH;
4848     lstrcpyA(buf, "apple");
4849     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, NULL);
4850     ok(r == ERROR_INVALID_PARAMETER,
4851        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
4852     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4853     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4854 
4855     /* created guid cannot possibly be an installed product code */
4856     sz = MAX_PATH;
4857     lstrcpyA(buf, "apple");
4858     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4859     ok(r == ERROR_UNKNOWN_PRODUCT,
4860        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4861     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4862     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4863 
4864     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
4865     lstrcatA(keypath, usersid);
4866     lstrcatA(keypath, "\\Installer\\Products\\");
4867     lstrcatA(keypath, prod_squashed);
4868 
4869     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4870     if (res == ERROR_ACCESS_DENIED)
4871     {
4872         skip("Not enough rights to perform tests\n");
4873         LocalFree(usersid);
4874         return;
4875     }
4876     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4877 
4878     /* managed product code exists */
4879     sz = MAX_PATH;
4880     lstrcpyA(buf, "apple");
4881     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4882     ok(r == ERROR_UNKNOWN_PROPERTY,
4883        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4884     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4885     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4886 
4887     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
4888     RegCloseKey(prodkey);
4889 
4890     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
4891     lstrcatA(keypath, usersid);
4892     lstrcatA(keypath, "\\Products\\");
4893     lstrcatA(keypath, prod_squashed);
4894 
4895     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
4896     if (res == ERROR_ACCESS_DENIED)
4897     {
4898         skip("Not enough rights to perform tests\n");
4899         LocalFree(usersid);
4900         return;
4901     }
4902     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4903 
4904     /* local user product code exists */
4905     sz = MAX_PATH;
4906     lstrcpyA(buf, "apple");
4907     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4908     ok(r == ERROR_UNKNOWN_PRODUCT,
4909        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4910     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4911     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4912 
4913     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
4914     lstrcatA(keypath, usersid);
4915     lstrcatA(keypath, "\\Installer\\Products\\");
4916     lstrcatA(keypath, prod_squashed);
4917 
4918     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
4919     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4920 
4921     /* both local and managed product code exist */
4922     sz = MAX_PATH;
4923     lstrcpyA(buf, "apple");
4924     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4925     ok(r == ERROR_UNKNOWN_PROPERTY,
4926        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4927     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
4928     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4929 
4930     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
4931     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4932 
4933     /* InstallProperties key exists */
4934     sz = MAX_PATH;
4935     lstrcpyA(buf, "apple");
4936     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4937     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4938     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
4939     ok(sz == 0, "Expected 0, got %d\n", sz);
4940 
4941     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
4942     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4943 
4944     /* HelpLink value exists */
4945     sz = MAX_PATH;
4946     lstrcpyA(buf, "apple");
4947     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4948     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4949     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
4950     ok(sz == 4, "Expected 4, got %d\n", sz);
4951 
4952     /* pcchBuf is NULL */
4953     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, NULL);
4954     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4955 
4956     /* lpValueBuf is NULL */
4957     sz = MAX_PATH;
4958     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, &sz);
4959     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4960     ok(sz == 4, "Expected 4, got %d\n", sz);
4961 
4962     /* lpValueBuf is NULL, pcchValueBuf is too small */
4963     sz = 2;
4964     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, NULL, &sz);
4965     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4966     ok(sz == 4, "Expected 4, got %d\n", sz);
4967 
4968     /* lpValueBuf is non-NULL, pcchValueBuf is too small */
4969     sz = 2;
4970     lstrcpyA(buf, "apple");
4971     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4972     ok(!lstrcmpA(buf, "apple"), "Expected buf to remain unchanged, got \"%s\"\n", buf);
4973     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4974     ok(sz == 4, "Expected 4, got %d\n", sz);
4975 
4976     /* lpValueBuf is non-NULL, pcchValueBuf is exactly 4 */
4977     sz = 4;
4978     lstrcpyA(buf, "apple");
4979     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
4980     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
4981     ok(!lstrcmpA(buf, "apple"),
4982        "Expected buf to remain unchanged, got \"%s\"\n", buf);
4983     ok(sz == 4, "Expected 4, got %d\n", sz);
4984 
4985     res = RegSetValueExA(propkey, "IMadeThis", 0, REG_SZ, (LPBYTE)"random", 7);
4986     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4987 
4988     /* random property not supported by MSI, value exists */
4989     sz = MAX_PATH;
4990     lstrcpyA(buf, "apple");
4991     r = MsiGetProductInfoA(prodcode, "IMadeThis", buf, &sz);
4992     ok(r == ERROR_UNKNOWN_PROPERTY,
4993        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
4994     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
4995     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
4996 
4997     RegDeleteValueA(propkey, "IMadeThis");
4998     RegDeleteValueA(propkey, "HelpLink");
4999     delete_key(propkey, "", access & KEY_WOW64_64KEY);
5000     delete_key(localkey, "", access & KEY_WOW64_64KEY);
5001     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
5002     RegCloseKey(propkey);
5003     RegCloseKey(localkey);
5004     RegCloseKey(prodkey);
5005 
5006     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
5007     lstrcatA(keypath, prod_squashed);
5008 
5009     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
5010     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5011 
5012     /* user product key exists */
5013     sz = MAX_PATH;
5014     lstrcpyA(buf, "apple");
5015     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5016     ok(r == ERROR_UNKNOWN_PROPERTY,
5017        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5018     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
5019     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5020 
5021     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
5022     lstrcatA(keypath, usersid);
5023     lstrcatA(keypath, "\\Products\\");
5024     lstrcatA(keypath, prod_squashed);
5025 
5026     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
5027     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5028 
5029     /* local user product key exists */
5030     sz = MAX_PATH;
5031     lstrcpyA(buf, "apple");
5032     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5033     ok(r == ERROR_UNKNOWN_PROPERTY,
5034        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5035     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
5036     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5037 
5038     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
5039     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5040 
5041     /* InstallProperties key exists */
5042     sz = MAX_PATH;
5043     lstrcpyA(buf, "apple");
5044     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5045     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5046     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5047     ok(sz == 0, "Expected 0, got %d\n", sz);
5048 
5049     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
5050     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5051 
5052     /* HelpLink value exists */
5053     sz = MAX_PATH;
5054     lstrcpyA(buf, "apple");
5055     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5056     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5057     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
5058     ok(sz == 4, "Expected 4, got %d\n", sz);
5059 
5060     RegDeleteValueA(propkey, "HelpLink");
5061     delete_key(propkey, "", access & KEY_WOW64_64KEY);
5062     delete_key(localkey, "", access & KEY_WOW64_64KEY);
5063     RegDeleteKeyA(prodkey, "");
5064     RegCloseKey(propkey);
5065     RegCloseKey(localkey);
5066     RegCloseKey(prodkey);
5067 
5068     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
5069     lstrcatA(keypath, prod_squashed);
5070 
5071     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
5072     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5073 
5074     /* classes product key exists */
5075     sz = MAX_PATH;
5076     lstrcpyA(buf, "apple");
5077     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5078     ok(r == ERROR_UNKNOWN_PROPERTY,
5079        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5080     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
5081     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5082 
5083     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
5084     lstrcatA(keypath, usersid);
5085     lstrcatA(keypath, "\\Products\\");
5086     lstrcatA(keypath, prod_squashed);
5087 
5088     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
5089     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5090 
5091     /* local user product key exists */
5092     sz = MAX_PATH;
5093     lstrcpyA(buf, "apple");
5094     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5095     ok(r == ERROR_UNKNOWN_PROPERTY,
5096        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5097     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
5098     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5099 
5100     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
5101     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5102 
5103     /* InstallProperties key exists */
5104     sz = MAX_PATH;
5105     lstrcpyA(buf, "apple");
5106     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5107     ok(r == ERROR_UNKNOWN_PROPERTY,
5108        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5109     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
5110     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5111 
5112     delete_key(propkey, "", access & KEY_WOW64_64KEY);
5113     delete_key(localkey, "", access & KEY_WOW64_64KEY);
5114     RegCloseKey(propkey);
5115     RegCloseKey(localkey);
5116 
5117     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
5118     lstrcatA(keypath, "S-1-5-18\\\\Products\\");
5119     lstrcatA(keypath, prod_squashed);
5120 
5121     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
5122     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5123 
5124     /* Local System product key exists */
5125     sz = MAX_PATH;
5126     lstrcpyA(buf, "apple");
5127     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5128     ok(r == ERROR_UNKNOWN_PROPERTY,
5129         "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
5130     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
5131     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5132 
5133     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
5134     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5135 
5136     /* InstallProperties key exists */
5137     sz = MAX_PATH;
5138     lstrcpyA(buf, "apple");
5139     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5140     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5141     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5142     ok(sz == 0, "Expected 0, got %d\n", sz);
5143 
5144     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
5145     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5146 
5147     /* HelpLink value exists */
5148     sz = MAX_PATH;
5149     lstrcpyA(buf, "apple");
5150     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5151     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5152     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
5153     ok(sz == 4, "Expected 4, got %d\n", sz);
5154 
5155     res = RegSetValueExA(propkey, "HelpLink", 0, REG_DWORD,
5156                          (const BYTE *)&val, sizeof(DWORD));
5157     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5158 
5159     /* HelpLink type is REG_DWORD */
5160     sz = MAX_PATH;
5161     lstrcpyA(buf, "apple");
5162     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINKA, buf, &sz);
5163     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5164     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5165     ok(sz == 2, "Expected 2, got %d\n", sz);
5166 
5167     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
5168     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5169 
5170     /* DisplayName value exists */
5171     sz = MAX_PATH;
5172     lstrcpyA(buf, "apple");
5173     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
5174     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5175     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
5176     ok(sz == 4, "Expected 4, got %d\n", sz);
5177 
5178     res = RegSetValueExA(propkey, "DisplayName", 0, REG_DWORD,
5179                          (const BYTE *)&val, sizeof(DWORD));
5180     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5181 
5182     /* DisplayName type is REG_DWORD */
5183     sz = MAX_PATH;
5184     lstrcpyA(buf, "apple");
5185     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
5186     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5187     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5188     ok(sz == 2, "Expected 2, got %d\n", sz);
5189 
5190     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"1.1.1", 6);
5191     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5192 
5193     /* DisplayVersion value exists */
5194     sz = MAX_PATH;
5195     lstrcpyA(buf, "apple");
5196     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
5197     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5198     ok(!lstrcmpA(buf, "1.1.1"), "Expected \"1.1.1\", got \"%s\"\n", buf);
5199     ok(sz == 5, "Expected 5, got %d\n", sz);
5200 
5201     res = RegSetValueExA(propkey, "DisplayVersion", 0,
5202                          REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
5203     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5204 
5205     /* DisplayVersion type is REG_DWORD */
5206     sz = MAX_PATH;
5207     lstrcpyA(buf, "apple");
5208     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
5209     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5210     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5211     ok(sz == 2, "Expected 2, got %d\n", sz);
5212 
5213     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"tele", 5);
5214     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5215 
5216     /* HelpTelephone value exists */
5217     sz = MAX_PATH;
5218     lstrcpyA(buf, "apple");
5219     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
5220     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5221     ok(!lstrcmpA(buf, "tele"), "Expected \"tele\", got \"%s\"\n", buf);
5222     ok(sz == 4, "Expected 4, got %d\n", sz);
5223 
5224     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_DWORD,
5225                          (const BYTE *)&val, sizeof(DWORD));
5226     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5227 
5228     /* HelpTelephone type is REG_DWORD */
5229     sz = MAX_PATH;
5230     lstrcpyA(buf, "apple");
5231     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
5232     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5233     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5234     ok(sz == 2, "Expected 2, got %d\n", sz);
5235 
5236     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
5237     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5238 
5239     /* InstallLocation value exists */
5240     sz = MAX_PATH;
5241     lstrcpyA(buf, "apple");
5242     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
5243     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5244     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
5245     ok(sz == 3, "Expected 3, got %d\n", sz);
5246 
5247     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_DWORD,
5248                          (const BYTE *)&val, sizeof(DWORD));
5249     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5250 
5251     /* InstallLocation type is REG_DWORD */
5252     sz = MAX_PATH;
5253     lstrcpyA(buf, "apple");
5254     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
5255     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5256     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5257     ok(sz == 2, "Expected 2, got %d\n", sz);
5258 
5259     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
5260     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5261 
5262     /* InstallSource value exists */
5263     sz = MAX_PATH;
5264     lstrcpyA(buf, "apple");
5265     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
5266     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5267     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
5268     ok(sz == 6, "Expected 6, got %d\n", sz);
5269 
5270     res = RegSetValueExA(propkey, "InstallSource", 0, REG_DWORD,
5271                          (const BYTE *)&val, sizeof(DWORD));
5272     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5273 
5274     /* InstallSource type is REG_DWORD */
5275     sz = MAX_PATH;
5276     lstrcpyA(buf, "apple");
5277     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
5278     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5279     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5280     ok(sz == 2, "Expected 2, got %d\n", sz);
5281 
5282     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
5283     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5284 
5285     /* InstallDate value exists */
5286     sz = MAX_PATH;
5287     lstrcpyA(buf, "apple");
5288     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
5289     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5290     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
5291     ok(sz == 4, "Expected 4, got %d\n", sz);
5292 
5293     res = RegSetValueExA(propkey, "InstallDate", 0, REG_DWORD,
5294                          (const BYTE *)&val, sizeof(DWORD));
5295     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5296 
5297     /* InstallDate type is REG_DWORD */
5298     sz = MAX_PATH;
5299     lstrcpyA(buf, "apple");
5300     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
5301     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5302     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5303     ok(sz == 2, "Expected 2, got %d\n", sz);
5304 
5305     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
5306     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5307 
5308     /* Publisher value exists */
5309     sz = MAX_PATH;
5310     lstrcpyA(buf, "apple");
5311     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PUBLISHERA, buf, &sz);
5312     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5313     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
5314     ok(sz == 3, "Expected 3, got %d\n", sz);
5315 
5316     res = RegSetValueExA(propkey, "Publisher", 0, REG_DWORD,
5317                          (const BYTE *)&val, sizeof(DWORD));
5318     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5319 
5320     /* Publisher type is REG_DWORD */
5321     sz = MAX_PATH;
5322     lstrcpyA(buf, "apple");
5323     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PUBLISHERA, buf, &sz);
5324     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5325     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5326     ok(sz == 2, "Expected 2, got %d\n", sz);
5327 
5328     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"pack", 5);
5329     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5330 
5331     /* LocalPackage value exists */
5332     sz = MAX_PATH;
5333     lstrcpyA(buf, "apple");
5334     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
5335     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5336     ok(!lstrcmpA(buf, "pack"), "Expected \"pack\", got \"%s\"\n", buf);
5337     ok(sz == 4, "Expected 4, got %d\n", sz);
5338 
5339     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_DWORD,
5340                          (const BYTE *)&val, sizeof(DWORD));
5341     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5342 
5343     /* LocalPackage type is REG_DWORD */
5344     sz = MAX_PATH;
5345     lstrcpyA(buf, "apple");
5346     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
5347     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5348     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5349     ok(sz == 2, "Expected 2, got %d\n", sz);
5350 
5351     res = RegSetValueExA(propkey, "UrlInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
5352     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5353 
5354     /* UrlInfoAbout value exists */
5355     sz = MAX_PATH;
5356     lstrcpyA(buf, "apple");
5357     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
5358     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5359     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
5360     ok(sz == 5, "Expected 5, got %d\n", sz);
5361 
5362     res = RegSetValueExA(propkey, "UrlInfoAbout", 0, REG_DWORD,
5363                          (const BYTE *)&val, sizeof(DWORD));
5364     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5365 
5366     /* UrlInfoAbout type is REG_DWORD */
5367     sz = MAX_PATH;
5368     lstrcpyA(buf, "apple");
5369     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
5370     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5371     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5372     ok(sz == 2, "Expected 2, got %d\n", sz);
5373 
5374     res = RegSetValueExA(propkey, "UrlUpdateInfo", 0, REG_SZ, (LPBYTE)"info", 5);
5375     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5376 
5377     /* UrlUpdateInfo value exists */
5378     sz = MAX_PATH;
5379     lstrcpyA(buf, "apple");
5380     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
5381     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5382     ok(!lstrcmpA(buf, "info"), "Expected \"info\", got \"%s\"\n", buf);
5383     ok(sz == 4, "Expected 4, got %d\n", sz);
5384 
5385     res = RegSetValueExA(propkey, "UrlUpdateInfo", 0, REG_DWORD,
5386                          (const BYTE *)&val, sizeof(DWORD));
5387     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5388 
5389     /* UrlUpdateInfo type is REG_DWORD */
5390     sz = MAX_PATH;
5391     lstrcpyA(buf, "apple");
5392     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
5393     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5394     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5395     ok(sz == 2, "Expected 2, got %d\n", sz);
5396 
5397     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"1", 2);
5398     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5399 
5400     /* VersionMinor value exists */
5401     sz = MAX_PATH;
5402     lstrcpyA(buf, "apple");
5403     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
5404     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5405     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
5406     ok(sz == 1, "Expected 1, got %d\n", sz);
5407 
5408     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_DWORD,
5409                          (const BYTE *)&val, sizeof(DWORD));
5410     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5411 
5412     /* VersionMinor type is REG_DWORD */
5413     sz = MAX_PATH;
5414     lstrcpyA(buf, "apple");
5415     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
5416     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5417     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5418     ok(sz == 2, "Expected 2, got %d\n", sz);
5419 
5420     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"1", 2);
5421     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5422 
5423     /* VersionMajor value exists */
5424     sz = MAX_PATH;
5425     lstrcpyA(buf, "apple");
5426     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
5427     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5428     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
5429     ok(sz == 1, "Expected 1, got %d\n", sz);
5430 
5431     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_DWORD,
5432                          (const BYTE *)&val, sizeof(DWORD));
5433     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5434 
5435     /* VersionMajor type is REG_DWORD */
5436     sz = MAX_PATH;
5437     lstrcpyA(buf, "apple");
5438     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
5439     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5440     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5441     ok(sz == 2, "Expected 2, got %d\n", sz);
5442 
5443     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
5444     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5445 
5446     /* ProductID value exists */
5447     sz = MAX_PATH;
5448     lstrcpyA(buf, "apple");
5449     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
5450     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5451     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
5452     ok(sz == 2, "Expected 2, got %d\n", sz);
5453 
5454     res = RegSetValueExA(propkey, "ProductID", 0, REG_DWORD,
5455                          (const BYTE *)&val, sizeof(DWORD));
5456     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5457 
5458     /* ProductID type is REG_DWORD */
5459     sz = MAX_PATH;
5460     lstrcpyA(buf, "apple");
5461     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
5462     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5463     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5464     ok(sz == 2, "Expected 2, got %d\n", sz);
5465 
5466     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
5467     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5468 
5469     /* RegCompany value exists */
5470     sz = MAX_PATH;
5471     lstrcpyA(buf, "apple");
5472     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
5473     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5474     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
5475     ok(sz == 4, "Expected 4, got %d\n", sz);
5476 
5477     res = RegSetValueExA(propkey, "RegCompany", 0, REG_DWORD,
5478                          (const BYTE *)&val, sizeof(DWORD));
5479     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5480 
5481     /* RegCompany type is REG_DWORD */
5482     sz = MAX_PATH;
5483     lstrcpyA(buf, "apple");
5484     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
5485     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5486     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5487     ok(sz == 2, "Expected 2, got %d\n", sz);
5488 
5489     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"own", 4);
5490     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5491 
5492     /* RegOwner value exists */
5493     sz = MAX_PATH;
5494     lstrcpyA(buf, "apple");
5495     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGOWNERA, buf, &sz);
5496     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5497     ok(!lstrcmpA(buf, "own"), "Expected \"own\", got \"%s\"\n", buf);
5498     ok(sz == 3, "Expected 3, got %d\n", sz);
5499 
5500     res = RegSetValueExA(propkey, "RegOwner", 0, REG_DWORD,
5501                          (const BYTE *)&val, sizeof(DWORD));
5502     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5503 
5504     /* RegOwner type is REG_DWORD */
5505     sz = MAX_PATH;
5506     lstrcpyA(buf, "apple");
5507     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_REGOWNERA, buf, &sz);
5508     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5509     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5510     ok(sz == 2, "Expected 2, got %d\n", sz);
5511 
5512     res = RegSetValueExA(propkey, "InstanceType", 0, REG_SZ, (LPBYTE)"type", 5);
5513     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5514 
5515     /* InstanceType value exists */
5516     sz = MAX_PATH;
5517     lstrcpyA(buf, "apple");
5518     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5519     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5520     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5521     ok(sz == 0, "Expected 0, got %d\n", sz);
5522 
5523     res = RegSetValueExA(propkey, "InstanceType", 0, REG_DWORD,
5524                          (const BYTE *)&val, sizeof(DWORD));
5525     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5526 
5527     /* InstanceType type is REG_DWORD */
5528     sz = MAX_PATH;
5529     lstrcpyA(buf, "apple");
5530     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5531     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5532     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5533     ok(sz == 0, "Expected 0, got %d\n", sz);
5534 
5535     res = RegSetValueExA(prodkey, "InstanceType", 0, REG_SZ, (LPBYTE)"type", 5);
5536     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5537 
5538     /* InstanceType value exists */
5539     sz = MAX_PATH;
5540     lstrcpyA(buf, "apple");
5541     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5542     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5543     ok(!lstrcmpA(buf, "type"), "Expected \"type\", got \"%s\"\n", buf);
5544     ok(sz == 4, "Expected 4, got %d\n", sz);
5545 
5546     res = RegSetValueExA(prodkey, "InstanceType", 0, REG_DWORD,
5547                          (const BYTE *)&val, sizeof(DWORD));
5548     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5549 
5550     /* InstanceType type is REG_DWORD */
5551     sz = MAX_PATH;
5552     lstrcpyA(buf, "apple");
5553     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_INSTANCETYPEA, buf, &sz);
5554     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5555     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5556     ok(sz == 2, "Expected 2, got %d\n", sz);
5557 
5558     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"tforms", 7);
5559     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5560 
5561     /* Transforms value exists */
5562     sz = MAX_PATH;
5563     lstrcpyA(buf, "apple");
5564     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5565     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5566     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5567     ok(sz == 0, "Expected 0, got %d\n", sz);
5568 
5569     res = RegSetValueExA(propkey, "Transforms", 0, REG_DWORD,
5570                          (const BYTE *)&val, sizeof(DWORD));
5571     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5572 
5573     /* Transforms type is REG_DWORD */
5574     sz = MAX_PATH;
5575     lstrcpyA(buf, "apple");
5576     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5577     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5578     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5579     ok(sz == 0, "Expected 0, got %d\n", sz);
5580 
5581     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"tforms", 7);
5582     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5583 
5584     /* Transforms value exists */
5585     sz = MAX_PATH;
5586     lstrcpyA(buf, "apple");
5587     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5588     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5589     ok(!lstrcmpA(buf, "tforms"), "Expected \"tforms\", got \"%s\"\n", buf);
5590     ok(sz == 6, "Expected 6, got %d\n", sz);
5591 
5592     res = RegSetValueExA(prodkey, "Transforms", 0, REG_DWORD,
5593                          (const BYTE *)&val, sizeof(DWORD));
5594     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5595 
5596     /* Transforms type is REG_DWORD */
5597     sz = MAX_PATH;
5598     lstrcpyA(buf, "apple");
5599     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
5600     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5601     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5602     ok(sz == 2, "Expected 2, got %d\n", sz);
5603 
5604     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
5605     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5606 
5607     /* Language value exists */
5608     sz = MAX_PATH;
5609     lstrcpyA(buf, "apple");
5610     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5611     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5612     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5613     ok(sz == 0, "Expected 0, got %d\n", sz);
5614 
5615     res = RegSetValueExA(propkey, "Language", 0, REG_DWORD,
5616                          (const BYTE *)&val, sizeof(DWORD));
5617     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5618 
5619     /* Language type is REG_DWORD */
5620     sz = MAX_PATH;
5621     lstrcpyA(buf, "apple");
5622     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5623     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5624     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5625     ok(sz == 0, "Expected 0, got %d\n", sz);
5626 
5627     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
5628     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5629 
5630     /* Language value exists */
5631     sz = MAX_PATH;
5632     lstrcpyA(buf, "apple");
5633     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5634     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5635     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
5636     ok(sz == 4, "Expected 4, got %d\n", sz);
5637 
5638     res = RegSetValueExA(prodkey, "Language", 0, REG_DWORD,
5639                          (const BYTE *)&val, sizeof(DWORD));
5640     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5641 
5642     /* Language type is REG_DWORD */
5643     sz = MAX_PATH;
5644     lstrcpyA(buf, "apple");
5645     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_LANGUAGEA, buf, &sz);
5646     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5647     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5648     ok(sz == 2, "Expected 2, got %d\n", sz);
5649 
5650     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
5651     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5652 
5653     /* ProductName value exists */
5654     sz = MAX_PATH;
5655     lstrcpyA(buf, "apple");
5656     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5657     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5658     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5659     ok(sz == 0, "Expected 0, got %d\n", sz);
5660 
5661     res = RegSetValueExA(propkey, "ProductName", 0, REG_DWORD,
5662                          (const BYTE *)&val, sizeof(DWORD));
5663     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5664 
5665     /* ProductName type is REG_DWORD */
5666     sz = MAX_PATH;
5667     lstrcpyA(buf, "apple");
5668     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5669     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5670     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5671     ok(sz == 0, "Expected 0, got %d\n", sz);
5672 
5673     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
5674     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5675 
5676     /* ProductName value exists */
5677     sz = MAX_PATH;
5678     lstrcpyA(buf, "apple");
5679     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5680     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5681     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
5682     ok(sz == 4, "Expected 4, got %d\n", sz);
5683 
5684     res = RegSetValueExA(prodkey, "ProductName", 0, REG_DWORD,
5685                          (const BYTE *)&val, sizeof(DWORD));
5686     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5687 
5688     /* ProductName type is REG_DWORD */
5689     sz = MAX_PATH;
5690     lstrcpyA(buf, "apple");
5691     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
5692     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5693     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5694     ok(sz == 2, "Expected 2, got %d\n", sz);
5695 
5696     res = RegSetValueExA(propkey, "Assignment", 0, REG_SZ, (LPBYTE)"at", 3);
5697     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5698 
5699     /* Assignment value exists */
5700     sz = MAX_PATH;
5701     lstrcpyA(buf, "apple");
5702     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5703     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5704     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5705     ok(sz == 0, "Expected 0, got %d\n", sz);
5706 
5707     res = RegSetValueExA(propkey, "Assignment", 0, REG_DWORD,
5708                          (const BYTE *)&val, sizeof(DWORD));
5709     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5710 
5711     /* Assignment type is REG_DWORD */
5712     sz = MAX_PATH;
5713     lstrcpyA(buf, "apple");
5714     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5715     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5716     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5717     ok(sz == 0, "Expected 0, got %d\n", sz);
5718 
5719     res = RegSetValueExA(prodkey, "Assignment", 0, REG_SZ, (LPBYTE)"at", 3);
5720     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5721 
5722     /* Assignment value exists */
5723     sz = MAX_PATH;
5724     lstrcpyA(buf, "apple");
5725     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5726     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5727     ok(!lstrcmpA(buf, "at"), "Expected \"at\", got \"%s\"\n", buf);
5728     ok(sz == 2, "Expected 2, got %d\n", sz);
5729 
5730     res = RegSetValueExA(prodkey, "Assignment", 0, REG_DWORD,
5731                          (const BYTE *)&val, sizeof(DWORD));
5732     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5733 
5734     /* Assignment type is REG_DWORD */
5735     sz = MAX_PATH;
5736     lstrcpyA(buf, "apple");
5737     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
5738     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5739     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5740     ok(sz == 2, "Expected 2, got %d\n", sz);
5741 
5742     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
5743     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5744 
5745     /* PackageCode value exists */
5746     sz = MAX_PATH;
5747     lstrcpyA(buf, "apple");
5748     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5749     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5750     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5751     ok(sz == 0, "Expected 0, got %d\n", sz);
5752 
5753     res = RegSetValueExA(propkey, "PackageCode", 0, REG_DWORD,
5754                          (const BYTE *)&val, sizeof(DWORD));
5755     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5756 
5757     /* PackageCode type is REG_DWORD */
5758     sz = MAX_PATH;
5759     lstrcpyA(buf, "apple");
5760     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5761     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5762     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5763     ok(sz == 0, "Expected 0, got %d\n", sz);
5764 
5765     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
5766     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5767 
5768     /* PackageCode value exists */
5769     sz = MAX_PATH;
5770     lstrcpyA(buf, "apple");
5771     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5772     ok(r == ERROR_BAD_CONFIGURATION,
5773        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
5774     ok(!lstrcmpA(buf, "code"), "Expected \"code\", got \"%s\"\n", buf);
5775     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
5776 
5777     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_DWORD,
5778                          (const BYTE *)&val, sizeof(DWORD));
5779     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5780 
5781     /* PackageCode type is REG_DWORD */
5782     sz = MAX_PATH;
5783     lstrcpyA(buf, "apple");
5784     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5785     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5786     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5787     ok(sz == 2, "Expected 2, got %d\n", sz);
5788 
5789     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)pack_squashed, 33);
5790     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5791 
5792     /* PackageCode value exists */
5793     sz = MAX_PATH;
5794     lstrcpyA(buf, "apple");
5795     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
5796     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5797     ok(!lstrcmpA(buf, packcode), "Expected \"%s\", got \"%s\"\n", packcode, buf);
5798     ok(sz == 38, "Expected 38, got %d\n", sz);
5799 
5800     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
5801     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5802 
5803     /* Version value exists */
5804     sz = MAX_PATH;
5805     lstrcpyA(buf, "apple");
5806     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5807     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5808     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5809     ok(sz == 0, "Expected 0, got %d\n", sz);
5810 
5811     res = RegSetValueExA(propkey, "Version", 0, REG_DWORD,
5812                          (const BYTE *)&val, sizeof(DWORD));
5813     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5814 
5815     /* Version type is REG_DWORD */
5816     sz = MAX_PATH;
5817     lstrcpyA(buf, "apple");
5818     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5819     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5820     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5821     ok(sz == 0, "Expected 0, got %d\n", sz);
5822 
5823     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
5824     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5825 
5826     /* Version value exists */
5827     sz = MAX_PATH;
5828     lstrcpyA(buf, "apple");
5829     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5830     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5831     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
5832     ok(sz == 3, "Expected 3, got %d\n", sz);
5833 
5834     res = RegSetValueExA(prodkey, "Version", 0, REG_DWORD,
5835                          (const BYTE *)&val, sizeof(DWORD));
5836     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5837 
5838     /* Version type is REG_DWORD */
5839     sz = MAX_PATH;
5840     lstrcpyA(buf, "apple");
5841     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_VERSIONA, buf, &sz);
5842     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5843     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5844     ok(sz == 2, "Expected 2, got %d\n", sz);
5845 
5846     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"ico", 4);
5847     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5848 
5849     /* ProductIcon value exists */
5850     sz = MAX_PATH;
5851     lstrcpyA(buf, "apple");
5852     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5853     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5854     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5855     ok(sz == 0, "Expected 0, got %d\n", sz);
5856 
5857     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_DWORD,
5858                          (const BYTE *)&val, sizeof(DWORD));
5859     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5860 
5861     /* ProductIcon type is REG_DWORD */
5862     sz = MAX_PATH;
5863     lstrcpyA(buf, "apple");
5864     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5865     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5866     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5867     ok(sz == 0, "Expected 0, got %d\n", sz);
5868 
5869     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"ico", 4);
5870     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5871 
5872     /* ProductIcon value exists */
5873     sz = MAX_PATH;
5874     lstrcpyA(buf, "apple");
5875     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5876     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5877     ok(!lstrcmpA(buf, "ico"), "Expected \"ico\", got \"%s\"\n", buf);
5878     ok(sz == 3, "Expected 3, got %d\n", sz);
5879 
5880     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_DWORD,
5881                          (const BYTE *)&val, sizeof(DWORD));
5882     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5883 
5884     /* ProductIcon type is REG_DWORD */
5885     sz = MAX_PATH;
5886     lstrcpyA(buf, "apple");
5887     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
5888     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5889     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5890     ok(sz == 2, "Expected 2, got %d\n", sz);
5891 
5892     /* SourceList key does not exist */
5893     sz = MAX_PATH;
5894     lstrcpyA(buf, "apple");
5895     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5896     ok(r == ERROR_UNKNOWN_PRODUCT,
5897        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5898     ok(!lstrcmpA(buf, "apple"),
5899        "Expected buf to be unchanged, got \"%s\"\n", buf);
5900     ok(sz == MAX_PATH, "Expected sz to be unchanged, got %d\n", sz);
5901 
5902     res = RegCreateKeyExA(prodkey, "SourceList", 0, NULL, 0, access, NULL, &source, NULL);
5903     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5904 
5905     /* SourceList key exists, but PackageName val does not exist */
5906     sz = MAX_PATH;
5907     lstrcpyA(buf, "apple");
5908     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5909     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5910     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5911     ok(sz == 0, "Expected 0, got %d\n", sz);
5912 
5913     res = RegSetValueExA(source, "PackageName", 0, REG_SZ, (LPBYTE)"packname", 9);
5914     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5915 
5916     /* PackageName val exists */
5917     sz = MAX_PATH;
5918     lstrcpyA(buf, "apple");
5919     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5920     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5921     ok(!lstrcmpA(buf, "packname"), "Expected \"packname\", got \"%s\"\n", buf);
5922     ok(sz == 8, "Expected 8, got %d\n", sz);
5923 
5924     res = RegSetValueExA(source, "PackageName", 0, REG_DWORD,
5925                          (const BYTE *)&val, sizeof(DWORD));
5926     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5927 
5928     /* PackageName type is REG_DWORD */
5929     sz = MAX_PATH;
5930     lstrcpyA(buf, "apple");
5931     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
5932     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5933     ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5934     ok(sz == 2, "Expected 2, got %d\n", sz);
5935 
5936     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
5937     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5938 
5939     /* Authorized value exists */
5940     sz = MAX_PATH;
5941     lstrcpyA(buf, "apple");
5942     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5943     if (r != ERROR_UNKNOWN_PROPERTY)
5944     {
5945         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5946         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5947         ok(sz == 0, "Expected 0, got %d\n", sz);
5948     }
5949 
5950     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_DWORD,
5951                          (const BYTE *)&val, sizeof(DWORD));
5952     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5953 
5954     /* AuthorizedLUAApp type is REG_DWORD */
5955     sz = MAX_PATH;
5956     lstrcpyA(buf, "apple");
5957     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5958     if (r != ERROR_UNKNOWN_PROPERTY)
5959     {
5960         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5961         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
5962         ok(sz == 0, "Expected 0, got %d\n", sz);
5963     }
5964 
5965     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
5966     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5967 
5968     /* Authorized value exists */
5969     sz = MAX_PATH;
5970     lstrcpyA(buf, "apple");
5971     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5972     if (r != ERROR_UNKNOWN_PROPERTY)
5973     {
5974         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5975         ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
5976         ok(sz == 4, "Expected 4, got %d\n", sz);
5977     }
5978 
5979     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_DWORD,
5980                          (const BYTE *)&val, sizeof(DWORD));
5981     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5982 
5983     /* AuthorizedLUAApp type is REG_DWORD */
5984     sz = MAX_PATH;
5985     lstrcpyA(buf, "apple");
5986     r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
5987     if (r != ERROR_UNKNOWN_PROPERTY)
5988     {
5989         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5990         ok(!lstrcmpA(buf, "42"), "Expected \"42\", got \"%s\"\n", buf);
5991         ok(sz == 2, "Expected 2, got %d\n", sz);
5992     }
5993 
5994     RegDeleteValueA(propkey, "HelpLink");
5995     RegDeleteValueA(propkey, "DisplayName");
5996     RegDeleteValueA(propkey, "DisplayVersion");
5997     RegDeleteValueA(propkey, "HelpTelephone");
5998     RegDeleteValueA(propkey, "InstallLocation");
5999     RegDeleteValueA(propkey, "InstallSource");
6000     RegDeleteValueA(propkey, "InstallDate");
6001     RegDeleteValueA(propkey, "Publisher");
6002     RegDeleteValueA(propkey, "LocalPackage");
6003     RegDeleteValueA(propkey, "UrlInfoAbout");
6004     RegDeleteValueA(propkey, "UrlUpdateInfo");
6005     RegDeleteValueA(propkey, "VersionMinor");
6006     RegDeleteValueA(propkey, "VersionMajor");
6007     RegDeleteValueA(propkey, "ProductID");
6008     RegDeleteValueA(propkey, "RegCompany");
6009     RegDeleteValueA(propkey, "RegOwner");
6010     RegDeleteValueA(propkey, "InstanceType");
6011     RegDeleteValueA(propkey, "Transforms");
6012     RegDeleteValueA(propkey, "Language");
6013     RegDeleteValueA(propkey, "ProductName");
6014     RegDeleteValueA(propkey, "Assignment");
6015     RegDeleteValueA(propkey, "PackageCode");
6016     RegDeleteValueA(propkey, "Version");
6017     RegDeleteValueA(propkey, "ProductIcon");
6018     RegDeleteValueA(propkey, "AuthorizedLUAApp");
6019     delete_key(propkey, "", access & KEY_WOW64_64KEY);
6020     delete_key(localkey, "", access & KEY_WOW64_64KEY);
6021     RegDeleteValueA(prodkey, "InstanceType");
6022     RegDeleteValueA(prodkey, "Transforms");
6023     RegDeleteValueA(prodkey, "Language");
6024     RegDeleteValueA(prodkey, "ProductName");
6025     RegDeleteValueA(prodkey, "Assignment");
6026     RegDeleteValueA(prodkey, "PackageCode");
6027     RegDeleteValueA(prodkey, "Version");
6028     RegDeleteValueA(prodkey, "ProductIcon");
6029     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
6030     RegDeleteValueA(source, "PackageName");
6031     delete_key(source, "", access & KEY_WOW64_64KEY);
6032     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
6033     RegCloseKey(propkey);
6034     RegCloseKey(localkey);
6035     RegCloseKey(source);
6036     RegCloseKey(prodkey);
6037     LocalFree(usersid);
6038 }
6039 
6040 static void test_MsiGetProductInfoEx(void)
6041 {
6042     UINT r;
6043     LONG res;
6044     HKEY propkey, userkey;
6045     HKEY prodkey, localkey;
6046     CHAR prodcode[MAX_PATH];
6047     CHAR prod_squashed[MAX_PATH];
6048     CHAR packcode[MAX_PATH];
6049     CHAR pack_squashed[MAX_PATH];
6050     CHAR buf[MAX_PATH];
6051     CHAR keypath[MAX_PATH];
6052     LPSTR usersid;
6053     DWORD sz;
6054     REGSAM access = KEY_ALL_ACCESS;
6055 
6056     if (!pMsiGetProductInfoExA)
6057     {
6058         win_skip("MsiGetProductInfoExA is not available\n");
6059         return;
6060     }
6061 
6062     create_test_guid(prodcode, prod_squashed);
6063     create_test_guid(packcode, pack_squashed);
6064     usersid = get_user_sid();
6065 
6066     if (is_wow64)
6067         access |= KEY_WOW64_64KEY;
6068 
6069     /* NULL szProductCode */
6070     sz = MAX_PATH;
6071     lstrcpyA(buf, "apple");
6072     r = pMsiGetProductInfoExA(NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
6073                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6074     ok(r == ERROR_INVALID_PARAMETER,
6075        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6076     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6077     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6078 
6079     /* empty szProductCode */
6080     sz = MAX_PATH;
6081     lstrcpyA(buf, "apple");
6082     r = pMsiGetProductInfoExA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
6083                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6084     ok(r == ERROR_INVALID_PARAMETER,
6085        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6086     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6087     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6088 
6089     /* garbage szProductCode */
6090     sz = MAX_PATH;
6091     lstrcpyA(buf, "apple");
6092     r = pMsiGetProductInfoExA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
6093                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6094     ok(r == ERROR_INVALID_PARAMETER,
6095        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6096     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6097     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6098 
6099     /* guid without brackets */
6100     sz = MAX_PATH;
6101     lstrcpyA(buf, "apple");
6102     r = pMsiGetProductInfoExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", usersid,
6103                               MSIINSTALLCONTEXT_USERUNMANAGED,
6104                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6105     ok(r == ERROR_INVALID_PARAMETER,
6106        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6107     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6108     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6109 
6110     /* guid with brackets */
6111     sz = MAX_PATH;
6112     lstrcpyA(buf, "apple");
6113     r = pMsiGetProductInfoExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", usersid,
6114                               MSIINSTALLCONTEXT_USERUNMANAGED,
6115                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6116     ok(r == ERROR_UNKNOWN_PRODUCT,
6117        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6118     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6119     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6120 
6121     /* szValue is non-NULL while pcchValue is NULL */
6122     lstrcpyA(buf, "apple");
6123     r = pMsiGetProductInfoExA(prodcode, usersid,
6124                               MSIINSTALLCONTEXT_USERUNMANAGED,
6125                               INSTALLPROPERTY_PRODUCTSTATEA, buf, NULL);
6126     ok(r == ERROR_INVALID_PARAMETER,
6127        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6128     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6129 
6130     /* dwContext is out of range */
6131     sz = MAX_PATH;
6132     lstrcpyA(buf, "apple");
6133     r = pMsiGetProductInfoExA(prodcode, usersid, 42,
6134                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6135     ok(r == ERROR_INVALID_PARAMETER,
6136        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6137     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6138     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6139 
6140     /* szProperty is NULL */
6141     sz = MAX_PATH;
6142     lstrcpyA(buf, "apple");
6143     r = pMsiGetProductInfoExA(prodcode, usersid,
6144                               MSIINSTALLCONTEXT_USERUNMANAGED,
6145                               NULL, buf, &sz);
6146     ok(r == ERROR_INVALID_PARAMETER,
6147        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6148     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6149     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6150 
6151     /* szProperty is empty */
6152     sz = MAX_PATH;
6153     lstrcpyA(buf, "apple");
6154     r = pMsiGetProductInfoExA(prodcode, usersid,
6155                               MSIINSTALLCONTEXT_USERUNMANAGED,
6156                               "", buf, &sz);
6157     ok(r == ERROR_INVALID_PARAMETER,
6158        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6159     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6160     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6161 
6162     /* szProperty is not a valid property */
6163     sz = MAX_PATH;
6164     lstrcpyA(buf, "apple");
6165     r = pMsiGetProductInfoExA(prodcode, usersid,
6166                               MSIINSTALLCONTEXT_USERUNMANAGED,
6167                               "notvalid", buf, &sz);
6168     ok(r == ERROR_UNKNOWN_PRODUCT,
6169        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6170     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6171     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6172 
6173     /* same length as guid, but random */
6174     sz = MAX_PATH;
6175     lstrcpyA(buf, "apple");
6176     r = pMsiGetProductInfoExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", usersid,
6177                               MSIINSTALLCONTEXT_USERUNMANAGED,
6178                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6179     ok(r == ERROR_INVALID_PARAMETER,
6180        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6181     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6182     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6183 
6184     /* MSIINSTALLCONTEXT_USERUNMANAGED */
6185 
6186     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
6187     lstrcatA(keypath, usersid);
6188     lstrcatA(keypath, "\\Products\\");
6189     lstrcatA(keypath, prod_squashed);
6190 
6191     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
6192     if (res == ERROR_ACCESS_DENIED)
6193     {
6194         skip("Not enough rights to perform tests\n");
6195         LocalFree(usersid);
6196         return;
6197     }
6198     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6199 
6200     /* local user product key exists */
6201     sz = MAX_PATH;
6202     lstrcpyA(buf, "apple");
6203     r = pMsiGetProductInfoExA(prodcode, usersid,
6204                               MSIINSTALLCONTEXT_USERUNMANAGED,
6205                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6206     ok(r == ERROR_UNKNOWN_PRODUCT,
6207        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6208     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6209     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6210 
6211     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
6212     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6213 
6214     /* InstallProperties key exists */
6215     sz = MAX_PATH;
6216     lstrcpyA(buf, "apple");
6217     r = pMsiGetProductInfoExA(prodcode, usersid,
6218                               MSIINSTALLCONTEXT_USERUNMANAGED,
6219                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6220     ok(r == ERROR_UNKNOWN_PRODUCT,
6221        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6222     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6223     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6224 
6225     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6226     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6227 
6228     /* LocalPackage value exists */
6229     sz = MAX_PATH;
6230     lstrcpyA(buf, "apple");
6231     r = pMsiGetProductInfoExA(prodcode, usersid,
6232                               MSIINSTALLCONTEXT_USERUNMANAGED,
6233                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6234     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6235     ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
6236     ok(sz == 1, "Expected 1, got %d\n", sz);
6237 
6238     RegDeleteValueA(propkey, "LocalPackage");
6239 
6240     /* LocalPackage value must exist */
6241     sz = MAX_PATH;
6242     lstrcpyA(buf, "apple");
6243     r = pMsiGetProductInfoExA(prodcode, usersid,
6244                               MSIINSTALLCONTEXT_USERUNMANAGED,
6245                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
6246     ok(r == ERROR_UNKNOWN_PRODUCT,
6247        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6248     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6249     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6250 
6251     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6252     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6253 
6254     /* LocalPackage exists, but HelpLink does not exist */
6255     sz = MAX_PATH;
6256     lstrcpyA(buf, "apple");
6257     r = pMsiGetProductInfoExA(prodcode, usersid,
6258                               MSIINSTALLCONTEXT_USERUNMANAGED,
6259                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
6260     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6261     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
6262     ok(sz == 0, "Expected 0, got %d\n", sz);
6263 
6264     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
6265     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6266 
6267     /* HelpLink value exists */
6268     sz = MAX_PATH;
6269     lstrcpyA(buf, "apple");
6270     r = pMsiGetProductInfoExA(prodcode, usersid,
6271                               MSIINSTALLCONTEXT_USERUNMANAGED,
6272                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
6273     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6274     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
6275     ok(sz == 4, "Expected 4, got %d\n", sz);
6276 
6277     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
6278     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6279 
6280     /* HelpTelephone value exists */
6281     sz = MAX_PATH;
6282     lstrcpyA(buf, "apple");
6283     r = pMsiGetProductInfoExA(prodcode, usersid,
6284                               MSIINSTALLCONTEXT_USERUNMANAGED,
6285                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
6286     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6287     ok(!lstrcmpA(buf, "phone"), "Expected \"phone\", got \"%s\"\n", buf);
6288     ok(sz == 5, "Expected 5, got %d\n", sz);
6289 
6290     /* szValue and pcchValue are NULL */
6291     r = pMsiGetProductInfoExA(prodcode, usersid,
6292                               MSIINSTALLCONTEXT_USERUNMANAGED,
6293                               INSTALLPROPERTY_HELPTELEPHONEA, NULL, NULL);
6294     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6295 
6296     /* pcchValue is exactly 5 */
6297     sz = 5;
6298     lstrcpyA(buf, "apple");
6299     r = pMsiGetProductInfoExA(prodcode, usersid,
6300                               MSIINSTALLCONTEXT_USERUNMANAGED,
6301                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
6302     ok(r == ERROR_MORE_DATA,
6303        "Expected ERROR_MORE_DATA, got %d\n", r);
6304     ok(sz == 10, "Expected 10, got %d\n", sz);
6305 
6306     /* szValue is NULL, pcchValue is exactly 5 */
6307     sz = 5;
6308     r = pMsiGetProductInfoExA(prodcode, usersid,
6309                               MSIINSTALLCONTEXT_USERUNMANAGED,
6310                               INSTALLPROPERTY_HELPTELEPHONEA, NULL, &sz);
6311     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6312     ok(sz == 10, "Expected 10, got %d\n", sz);
6313 
6314     /* szValue is NULL, pcchValue is MAX_PATH */
6315     sz = MAX_PATH;
6316     r = pMsiGetProductInfoExA(prodcode, usersid,
6317                               MSIINSTALLCONTEXT_USERUNMANAGED,
6318                               INSTALLPROPERTY_HELPTELEPHONEA, NULL, &sz);
6319     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6320     ok(sz == 10, "Expected 10, got %d\n", sz);
6321 
6322     /* pcchValue is exactly 0 */
6323     sz = 0;
6324     lstrcpyA(buf, "apple");
6325     r = pMsiGetProductInfoExA(prodcode, usersid,
6326                               MSIINSTALLCONTEXT_USERUNMANAGED,
6327                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
6328     ok(r == ERROR_MORE_DATA,
6329        "Expected ERROR_MORE_DATA, got %d\n", r);
6330     ok(!lstrcmpA(buf, "apple"), "Expected \"apple\", got \"%s\"\n", buf);
6331     ok(sz == 10, "Expected 10, got %d\n", sz);
6332 
6333     res = RegSetValueExA(propkey, "notvalid", 0, REG_SZ, (LPBYTE)"invalid", 8);
6334     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6335 
6336     /* szProperty is not a valid property */
6337     sz = MAX_PATH;
6338     lstrcpyA(buf, "apple");
6339     r = pMsiGetProductInfoExA(prodcode, usersid,
6340                               MSIINSTALLCONTEXT_USERUNMANAGED,
6341                               "notvalid", buf, &sz);
6342     ok(r == ERROR_UNKNOWN_PROPERTY,
6343        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6344     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6345     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6346 
6347     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
6348     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6349 
6350     /* InstallDate value exists */
6351     sz = MAX_PATH;
6352     lstrcpyA(buf, "apple");
6353     r = pMsiGetProductInfoExA(prodcode, usersid,
6354                               MSIINSTALLCONTEXT_USERUNMANAGED,
6355                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
6356     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6357     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
6358     ok(sz == 4, "Expected 4, got %d\n", sz);
6359 
6360     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
6361     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6362 
6363     /* DisplayName value exists */
6364     sz = MAX_PATH;
6365     lstrcpyA(buf, "apple");
6366     r = pMsiGetProductInfoExA(prodcode, usersid,
6367                               MSIINSTALLCONTEXT_USERUNMANAGED,
6368                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
6369     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6370     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
6371     ok(sz == 4, "Expected 4, got %d\n", sz);
6372 
6373     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
6374     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6375 
6376     /* InstallLocation value exists */
6377     sz = MAX_PATH;
6378     lstrcpyA(buf, "apple");
6379     r = pMsiGetProductInfoExA(prodcode, usersid,
6380                               MSIINSTALLCONTEXT_USERUNMANAGED,
6381                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
6382     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6383     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
6384     ok(sz == 3, "Expected 3, got %d\n", sz);
6385 
6386     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
6387     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6388 
6389     /* InstallSource value exists */
6390     sz = MAX_PATH;
6391     lstrcpyA(buf, "apple");
6392     r = pMsiGetProductInfoExA(prodcode, usersid,
6393                               MSIINSTALLCONTEXT_USERUNMANAGED,
6394                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
6395     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6396     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
6397     ok(sz == 6, "Expected 6, got %d\n", sz);
6398 
6399     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6400     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6401 
6402     /* LocalPackage value exists */
6403     sz = MAX_PATH;
6404     lstrcpyA(buf, "apple");
6405     r = pMsiGetProductInfoExA(prodcode, usersid,
6406                               MSIINSTALLCONTEXT_USERUNMANAGED,
6407                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
6408     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6409     ok(!lstrcmpA(buf, "local"), "Expected \"local\", got \"%s\"\n", buf);
6410     ok(sz == 5, "Expected 5, got %d\n", sz);
6411 
6412     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
6413     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6414 
6415     /* Publisher value exists */
6416     sz = MAX_PATH;
6417     lstrcpyA(buf, "apple");
6418     r = pMsiGetProductInfoExA(prodcode, usersid,
6419                               MSIINSTALLCONTEXT_USERUNMANAGED,
6420                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
6421     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6422     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
6423     ok(sz == 3, "Expected 3, got %d\n", sz);
6424 
6425     res = RegSetValueExA(propkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
6426     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6427 
6428     /* URLInfoAbout value exists */
6429     sz = MAX_PATH;
6430     lstrcpyA(buf, "apple");
6431     r = pMsiGetProductInfoExA(prodcode, usersid,
6432                               MSIINSTALLCONTEXT_USERUNMANAGED,
6433                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
6434     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6435     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
6436     ok(sz == 5, "Expected 5, got %d\n", sz);
6437 
6438     res = RegSetValueExA(propkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
6439     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6440 
6441     /* URLUpdateInfo value exists */
6442     sz = MAX_PATH;
6443     lstrcpyA(buf, "apple");
6444     r = pMsiGetProductInfoExA(prodcode, usersid,
6445                               MSIINSTALLCONTEXT_USERUNMANAGED,
6446                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
6447     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6448     ok(!lstrcmpA(buf, "update"), "Expected \"update\", got \"%s\"\n", buf);
6449     ok(sz == 6, "Expected 6, got %d\n", sz);
6450 
6451     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
6452     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6453 
6454     /* VersionMinor value exists */
6455     sz = MAX_PATH;
6456     lstrcpyA(buf, "apple");
6457     r = pMsiGetProductInfoExA(prodcode, usersid,
6458                               MSIINSTALLCONTEXT_USERUNMANAGED,
6459                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
6460     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6461     ok(!lstrcmpA(buf, "2"), "Expected \"2\", got \"%s\"\n", buf);
6462     ok(sz == 1, "Expected 1, got %d\n", sz);
6463 
6464     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
6465     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6466 
6467     /* VersionMajor value exists */
6468     sz = MAX_PATH;
6469     lstrcpyA(buf, "apple");
6470     r = pMsiGetProductInfoExA(prodcode, usersid,
6471                               MSIINSTALLCONTEXT_USERUNMANAGED,
6472                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
6473     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6474     ok(!lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
6475     ok(sz == 1, "Expected 1, got %d\n", sz);
6476 
6477     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
6478     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6479 
6480     /* DisplayVersion value exists */
6481     sz = MAX_PATH;
6482     lstrcpyA(buf, "apple");
6483     r = pMsiGetProductInfoExA(prodcode, usersid,
6484                               MSIINSTALLCONTEXT_USERUNMANAGED,
6485                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
6486     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6487     ok(!lstrcmpA(buf, "3.2.1"), "Expected \"3.2.1\", got \"%s\"\n", buf);
6488     ok(sz == 5, "Expected 5, got %d\n", sz);
6489 
6490     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
6491     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6492 
6493     /* ProductID value exists */
6494     sz = MAX_PATH;
6495     lstrcpyA(buf, "apple");
6496     r = pMsiGetProductInfoExA(prodcode, usersid,
6497                               MSIINSTALLCONTEXT_USERUNMANAGED,
6498                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
6499     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6500     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
6501     ok(sz == 2, "Expected 2, got %d\n", sz);
6502 
6503     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
6504     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6505 
6506     /* RegCompany value exists */
6507     sz = MAX_PATH;
6508     lstrcpyA(buf, "apple");
6509     r = pMsiGetProductInfoExA(prodcode, usersid,
6510                               MSIINSTALLCONTEXT_USERUNMANAGED,
6511                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
6512     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6513     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
6514     ok(sz == 4, "Expected 4, got %d\n", sz);
6515 
6516     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
6517     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6518 
6519     /* RegOwner value exists */
6520     sz = MAX_PATH;
6521     lstrcpyA(buf, "apple");
6522     r = pMsiGetProductInfoExA(prodcode, usersid,
6523                               MSIINSTALLCONTEXT_USERUNMANAGED,
6524                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
6525     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6526     ok(!lstrcmpA(buf, "owner"), "Expected \"owner\", got \"%s\"\n", buf);
6527     ok(sz == 5, "Expected 5, got %d\n", sz);
6528 
6529     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
6530     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6531 
6532     /* Transforms value exists */
6533     sz = MAX_PATH;
6534     lstrcpyA(buf, "apple");
6535     r = pMsiGetProductInfoExA(prodcode, usersid,
6536                               MSIINSTALLCONTEXT_USERUNMANAGED,
6537                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
6538     ok(r == ERROR_UNKNOWN_PRODUCT,
6539        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6540     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6541     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6542 
6543     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
6544     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6545 
6546     /* Language value exists */
6547     sz = MAX_PATH;
6548     lstrcpyA(buf, "apple");
6549     r = pMsiGetProductInfoExA(prodcode, usersid,
6550                               MSIINSTALLCONTEXT_USERUNMANAGED,
6551                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
6552     ok(r == ERROR_UNKNOWN_PRODUCT,
6553        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6554     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6555     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6556 
6557     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
6558     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6559 
6560     /* ProductName value exists */
6561     sz = MAX_PATH;
6562     lstrcpyA(buf, "apple");
6563     r = pMsiGetProductInfoExA(prodcode, usersid,
6564                               MSIINSTALLCONTEXT_USERUNMANAGED,
6565                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
6566     ok(r == ERROR_UNKNOWN_PRODUCT,
6567        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6568     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6569     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6570 
6571     res = RegSetValueExA(propkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
6572     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6573 
6574     /* FIXME */
6575 
6576     /* AssignmentType value exists */
6577     sz = MAX_PATH;
6578     lstrcpyA(buf, "apple");
6579     r = pMsiGetProductInfoExA(prodcode, usersid,
6580                               MSIINSTALLCONTEXT_USERUNMANAGED,
6581                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
6582     ok(r == ERROR_UNKNOWN_PRODUCT,
6583        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6584     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6585     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6586 
6587     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
6588     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6589 
6590     /* PackageCode value exists */
6591     sz = MAX_PATH;
6592     lstrcpyA(buf, "apple");
6593     r = pMsiGetProductInfoExA(prodcode, usersid,
6594                               MSIINSTALLCONTEXT_USERUNMANAGED,
6595                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
6596     ok(r == ERROR_UNKNOWN_PRODUCT,
6597        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6598     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6599     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6600 
6601     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
6602     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6603 
6604     /* Version value exists */
6605     sz = MAX_PATH;
6606     lstrcpyA(buf, "apple");
6607     r = pMsiGetProductInfoExA(prodcode, usersid,
6608                               MSIINSTALLCONTEXT_USERUNMANAGED,
6609                               INSTALLPROPERTY_VERSIONA, buf, &sz);
6610     ok(r == ERROR_UNKNOWN_PRODUCT,
6611        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6612     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6613     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6614 
6615     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
6616     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6617 
6618     /* ProductIcon value exists */
6619     sz = MAX_PATH;
6620     lstrcpyA(buf, "apple");
6621     r = pMsiGetProductInfoExA(prodcode, usersid,
6622                               MSIINSTALLCONTEXT_USERUNMANAGED,
6623                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
6624     ok(r == ERROR_UNKNOWN_PRODUCT,
6625        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6626     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6627     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6628 
6629     res = RegSetValueExA(propkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
6630     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6631 
6632     /* PackageName value exists */
6633     sz = MAX_PATH;
6634     lstrcpyA(buf, "apple");
6635     r = pMsiGetProductInfoExA(prodcode, usersid,
6636                               MSIINSTALLCONTEXT_USERUNMANAGED,
6637                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
6638     ok(r == ERROR_UNKNOWN_PRODUCT,
6639        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6640     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6641     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6642 
6643     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
6644     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6645 
6646     /* AuthorizedLUAApp value exists */
6647     sz = MAX_PATH;
6648     lstrcpyA(buf, "apple");
6649     r = pMsiGetProductInfoExA(prodcode, usersid,
6650                               MSIINSTALLCONTEXT_USERUNMANAGED,
6651                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
6652     ok(r == ERROR_UNKNOWN_PRODUCT,
6653        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6654     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6655     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6656 
6657     RegDeleteValueA(propkey, "AuthorizedLUAApp");
6658     RegDeleteValueA(propkey, "PackageName");
6659     RegDeleteValueA(propkey, "ProductIcon");
6660     RegDeleteValueA(propkey, "Version");
6661     RegDeleteValueA(propkey, "PackageCode");
6662     RegDeleteValueA(propkey, "AssignmentType");
6663     RegDeleteValueA(propkey, "ProductName");
6664     RegDeleteValueA(propkey, "Language");
6665     RegDeleteValueA(propkey, "Transforms");
6666     RegDeleteValueA(propkey, "RegOwner");
6667     RegDeleteValueA(propkey, "RegCompany");
6668     RegDeleteValueA(propkey, "ProductID");
6669     RegDeleteValueA(propkey, "DisplayVersion");
6670     RegDeleteValueA(propkey, "VersionMajor");
6671     RegDeleteValueA(propkey, "VersionMinor");
6672     RegDeleteValueA(propkey, "URLUpdateInfo");
6673     RegDeleteValueA(propkey, "URLInfoAbout");
6674     RegDeleteValueA(propkey, "Publisher");
6675     RegDeleteValueA(propkey, "LocalPackage");
6676     RegDeleteValueA(propkey, "InstallSource");
6677     RegDeleteValueA(propkey, "InstallLocation");
6678     RegDeleteValueA(propkey, "DisplayName");
6679     RegDeleteValueA(propkey, "InstallDate");
6680     RegDeleteValueA(propkey, "HelpTelephone");
6681     RegDeleteValueA(propkey, "HelpLink");
6682     RegDeleteValueA(propkey, "LocalPackage");
6683     RegDeleteKeyA(propkey, "");
6684     RegCloseKey(propkey);
6685     RegDeleteKeyA(localkey, "");
6686     RegCloseKey(localkey);
6687 
6688     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
6689     lstrcatA(keypath, usersid);
6690     lstrcatA(keypath, "\\Installer\\Products\\");
6691     lstrcatA(keypath, prod_squashed);
6692 
6693     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
6694     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6695 
6696     /* user product key exists */
6697     sz = MAX_PATH;
6698     lstrcpyA(buf, "apple");
6699     r = pMsiGetProductInfoExA(prodcode, usersid,
6700                               MSIINSTALLCONTEXT_USERUNMANAGED,
6701                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6702     ok(r == ERROR_UNKNOWN_PRODUCT,
6703        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6704     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6705     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6706 
6707     RegDeleteKeyA(userkey, "");
6708     RegCloseKey(userkey);
6709 
6710     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
6711     lstrcatA(keypath, prod_squashed);
6712 
6713     res = RegCreateKeyExA(HKEY_CURRENT_USER, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
6714     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6715 
6716     sz = MAX_PATH;
6717     lstrcpyA(buf, "apple");
6718     r = pMsiGetProductInfoExA(prodcode, usersid,
6719                               MSIINSTALLCONTEXT_USERUNMANAGED,
6720                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
6721     ok(r == ERROR_SUCCESS || broken(r == ERROR_UNKNOWN_PRODUCT), "Expected ERROR_SUCCESS, got %d\n", r);
6722     if (r == ERROR_UNKNOWN_PRODUCT)
6723     {
6724         win_skip("skipping remaining tests for MsiGetProductInfoEx\n");
6725         delete_key(prodkey, "", access);
6726         RegCloseKey(prodkey);
6727         return;
6728     }
6729     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
6730     ok(sz == 1, "Expected 1, got %d\n", sz);
6731 
6732     res = RegSetValueExA(prodkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
6733     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6734 
6735     /* HelpLink value exists */
6736     sz = MAX_PATH;
6737     lstrcpyA(buf, "apple");
6738     r = pMsiGetProductInfoExA(prodcode, usersid,
6739                               MSIINSTALLCONTEXT_USERUNMANAGED,
6740                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
6741     ok(r == ERROR_UNKNOWN_PROPERTY,
6742        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6743     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6744     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6745 
6746     res = RegSetValueExA(prodkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
6747     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6748 
6749     /* HelpTelephone value exists */
6750     sz = MAX_PATH;
6751     lstrcpyA(buf, "apple");
6752     r = pMsiGetProductInfoExA(prodcode, usersid,
6753                               MSIINSTALLCONTEXT_USERUNMANAGED,
6754                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
6755     ok(r == ERROR_UNKNOWN_PROPERTY,
6756        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6757     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6758     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6759 
6760     res = RegSetValueExA(prodkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
6761     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6762 
6763     /* InstallDate value exists */
6764     sz = MAX_PATH;
6765     lstrcpyA(buf, "apple");
6766     r = pMsiGetProductInfoExA(prodcode, usersid,
6767                               MSIINSTALLCONTEXT_USERUNMANAGED,
6768                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
6769     ok(r == ERROR_UNKNOWN_PROPERTY,
6770        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6771     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6772     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6773 
6774     res = RegSetValueExA(prodkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
6775     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6776 
6777     /* DisplayName value exists */
6778     sz = MAX_PATH;
6779     lstrcpyA(buf, "apple");
6780     r = pMsiGetProductInfoExA(prodcode, usersid,
6781                               MSIINSTALLCONTEXT_USERUNMANAGED,
6782                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
6783     ok(r == ERROR_UNKNOWN_PROPERTY,
6784        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6785     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6786     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6787 
6788     res = RegSetValueExA(prodkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
6789     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6790 
6791     /* InstallLocation value exists */
6792     sz = MAX_PATH;
6793     lstrcpyA(buf, "apple");
6794     r = pMsiGetProductInfoExA(prodcode, usersid,
6795                               MSIINSTALLCONTEXT_USERUNMANAGED,
6796                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
6797     ok(r == ERROR_UNKNOWN_PROPERTY,
6798        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6799     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6800     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6801 
6802     res = RegSetValueExA(prodkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
6803     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6804 
6805     /* InstallSource value exists */
6806     sz = MAX_PATH;
6807     lstrcpyA(buf, "apple");
6808     r = pMsiGetProductInfoExA(prodcode, usersid,
6809                               MSIINSTALLCONTEXT_USERUNMANAGED,
6810                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
6811     ok(r == ERROR_UNKNOWN_PROPERTY,
6812        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6813     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6814     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6815 
6816     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
6817     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6818 
6819     /* LocalPackage value exists */
6820     sz = MAX_PATH;
6821     lstrcpyA(buf, "apple");
6822     r = pMsiGetProductInfoExA(prodcode, usersid,
6823                               MSIINSTALLCONTEXT_USERUNMANAGED,
6824                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
6825     ok(r == ERROR_UNKNOWN_PROPERTY,
6826        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6827     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6828     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6829 
6830     res = RegSetValueExA(prodkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
6831     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6832 
6833     /* Publisher value exists */
6834     sz = MAX_PATH;
6835     lstrcpyA(buf, "apple");
6836     r = pMsiGetProductInfoExA(prodcode, usersid,
6837                               MSIINSTALLCONTEXT_USERUNMANAGED,
6838                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
6839     ok(r == ERROR_UNKNOWN_PROPERTY,
6840        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6841     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6842     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6843 
6844     res = RegSetValueExA(prodkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
6845     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6846 
6847     /* URLInfoAbout value exists */
6848     sz = MAX_PATH;
6849     lstrcpyA(buf, "apple");
6850     r = pMsiGetProductInfoExA(prodcode, usersid,
6851                               MSIINSTALLCONTEXT_USERUNMANAGED,
6852                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
6853     ok(r == ERROR_UNKNOWN_PROPERTY,
6854        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6855     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6856     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6857 
6858     res = RegSetValueExA(prodkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
6859     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6860 
6861     /* URLUpdateInfo value exists */
6862     sz = MAX_PATH;
6863     lstrcpyA(buf, "apple");
6864     r = pMsiGetProductInfoExA(prodcode, usersid,
6865                               MSIINSTALLCONTEXT_USERUNMANAGED,
6866                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
6867     ok(r == ERROR_UNKNOWN_PROPERTY,
6868        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6869     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6870     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6871 
6872     res = RegSetValueExA(prodkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
6873     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6874 
6875     /* VersionMinor value exists */
6876     sz = MAX_PATH;
6877     lstrcpyA(buf, "apple");
6878     r = pMsiGetProductInfoExA(prodcode, usersid,
6879                               MSIINSTALLCONTEXT_USERUNMANAGED,
6880                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
6881     ok(r == ERROR_UNKNOWN_PROPERTY,
6882        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6883     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6884     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6885 
6886     res = RegSetValueExA(prodkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
6887     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6888 
6889     /* VersionMajor value exists */
6890     sz = MAX_PATH;
6891     lstrcpyA(buf, "apple");
6892     r = pMsiGetProductInfoExA(prodcode, usersid,
6893                               MSIINSTALLCONTEXT_USERUNMANAGED,
6894                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
6895     ok(r == ERROR_UNKNOWN_PROPERTY,
6896        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6897     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6898     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6899 
6900     res = RegSetValueExA(prodkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
6901     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6902 
6903     /* DisplayVersion value exists */
6904     sz = MAX_PATH;
6905     lstrcpyA(buf, "apple");
6906     r = pMsiGetProductInfoExA(prodcode, usersid,
6907                               MSIINSTALLCONTEXT_USERUNMANAGED,
6908                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
6909     ok(r == ERROR_UNKNOWN_PROPERTY,
6910        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6911     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6912     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6913 
6914     res = RegSetValueExA(prodkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
6915     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6916 
6917     /* ProductID value exists */
6918     sz = MAX_PATH;
6919     lstrcpyA(buf, "apple");
6920     r = pMsiGetProductInfoExA(prodcode, usersid,
6921                               MSIINSTALLCONTEXT_USERUNMANAGED,
6922                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
6923     ok(r == ERROR_UNKNOWN_PROPERTY,
6924        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6925     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6926     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6927 
6928     res = RegSetValueExA(prodkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
6929     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6930 
6931     /* RegCompany value exists */
6932     sz = MAX_PATH;
6933     lstrcpyA(buf, "apple");
6934     r = pMsiGetProductInfoExA(prodcode, usersid,
6935                               MSIINSTALLCONTEXT_USERUNMANAGED,
6936                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
6937     ok(r == ERROR_UNKNOWN_PROPERTY,
6938        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6939     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6940     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6941 
6942     res = RegSetValueExA(prodkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
6943     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6944 
6945     /* RegOwner value exists */
6946     sz = MAX_PATH;
6947     lstrcpyA(buf, "apple");
6948     r = pMsiGetProductInfoExA(prodcode, usersid,
6949                               MSIINSTALLCONTEXT_USERUNMANAGED,
6950                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
6951     ok(r == ERROR_UNKNOWN_PROPERTY,
6952        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
6953     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
6954     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
6955 
6956     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
6957     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6958 
6959     /* Transforms value exists */
6960     sz = MAX_PATH;
6961     lstrcpyA(buf, "apple");
6962     r = pMsiGetProductInfoExA(prodcode, usersid,
6963                               MSIINSTALLCONTEXT_USERUNMANAGED,
6964                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
6965     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6966     ok(!lstrcmpA(buf, "trans"), "Expected \"trans\", got \"%s\"\n", buf);
6967     ok(sz == 5, "Expected 5, got %d\n", sz);
6968 
6969     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
6970     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6971 
6972     /* Language value exists */
6973     sz = MAX_PATH;
6974     lstrcpyA(buf, "apple");
6975     r = pMsiGetProductInfoExA(prodcode, usersid,
6976                               MSIINSTALLCONTEXT_USERUNMANAGED,
6977                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
6978     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6979     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
6980     ok(sz == 4, "Expected 4, got %d\n", sz);
6981 
6982     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
6983     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6984 
6985     /* ProductName value exists */
6986     sz = MAX_PATH;
6987     lstrcpyA(buf, "apple");
6988     r = pMsiGetProductInfoExA(prodcode, usersid,
6989                               MSIINSTALLCONTEXT_USERUNMANAGED,
6990                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
6991     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6992     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
6993     ok(sz == 4, "Expected 4, got %d\n", sz);
6994 
6995     res = RegSetValueExA(prodkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
6996     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6997 
6998     /* FIXME */
6999 
7000     /* AssignmentType value exists */
7001     sz = MAX_PATH;
7002     lstrcpyA(buf, "apple");
7003     r = pMsiGetProductInfoExA(prodcode, usersid,
7004                               MSIINSTALLCONTEXT_USERUNMANAGED,
7005                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
7006     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7007     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7008     ok(sz == 0, "Expected 0, got %d\n", sz);
7009 
7010     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
7011     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7012 
7013     /* FIXME */
7014 
7015     /* PackageCode value exists */
7016     sz = MAX_PATH;
7017     lstrcpyA(buf, "apple");
7018     r = pMsiGetProductInfoExA(prodcode, usersid,
7019                               MSIINSTALLCONTEXT_USERUNMANAGED,
7020                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
7021     todo_wine
7022     {
7023         ok(r == ERROR_BAD_CONFIGURATION,
7024            "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
7025         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7026         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7027     }
7028 
7029     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
7030     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7031 
7032     /* Version value exists */
7033     sz = MAX_PATH;
7034     lstrcpyA(buf, "apple");
7035     r = pMsiGetProductInfoExA(prodcode, usersid,
7036                               MSIINSTALLCONTEXT_USERUNMANAGED,
7037                               INSTALLPROPERTY_VERSIONA, buf, &sz);
7038     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7039     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
7040     ok(sz == 3, "Expected 3, got %d\n", sz);
7041 
7042     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
7043     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7044 
7045     /* ProductIcon value exists */
7046     sz = MAX_PATH;
7047     lstrcpyA(buf, "apple");
7048     r = pMsiGetProductInfoExA(prodcode, usersid,
7049                               MSIINSTALLCONTEXT_USERUNMANAGED,
7050                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
7051     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7052     ok(!lstrcmpA(buf, "icon"), "Expected \"icon\", got \"%s\"\n", buf);
7053     ok(sz == 4, "Expected 4, got %d\n", sz);
7054 
7055     res = RegSetValueExA(prodkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
7056     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7057 
7058     /* PackageName value exists */
7059     sz = MAX_PATH;
7060     lstrcpyA(buf, "apple");
7061     r = pMsiGetProductInfoExA(prodcode, usersid,
7062                               MSIINSTALLCONTEXT_USERUNMANAGED,
7063                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
7064     todo_wine
7065     {
7066         ok(r == ERROR_UNKNOWN_PRODUCT,
7067            "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7068         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7069         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7070     }
7071 
7072     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
7073     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7074 
7075     /* AuthorizedLUAApp value exists */
7076     sz = MAX_PATH;
7077     lstrcpyA(buf, "apple");
7078     r = pMsiGetProductInfoExA(prodcode, usersid,
7079                               MSIINSTALLCONTEXT_USERUNMANAGED,
7080                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
7081     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7082     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
7083     ok(sz == 4, "Expected 4, got %d\n", sz);
7084 
7085     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
7086     RegDeleteValueA(prodkey, "PackageName");
7087     RegDeleteValueA(prodkey, "ProductIcon");
7088     RegDeleteValueA(prodkey, "Version");
7089     RegDeleteValueA(prodkey, "PackageCode");
7090     RegDeleteValueA(prodkey, "AssignmentType");
7091     RegDeleteValueA(prodkey, "ProductName");
7092     RegDeleteValueA(prodkey, "Language");
7093     RegDeleteValueA(prodkey, "Transforms");
7094     RegDeleteValueA(prodkey, "RegOwner");
7095     RegDeleteValueA(prodkey, "RegCompany");
7096     RegDeleteValueA(prodkey, "ProductID");
7097     RegDeleteValueA(prodkey, "DisplayVersion");
7098     RegDeleteValueA(prodkey, "VersionMajor");
7099     RegDeleteValueA(prodkey, "VersionMinor");
7100     RegDeleteValueA(prodkey, "URLUpdateInfo");
7101     RegDeleteValueA(prodkey, "URLInfoAbout");
7102     RegDeleteValueA(prodkey, "Publisher");
7103     RegDeleteValueA(prodkey, "LocalPackage");
7104     RegDeleteValueA(prodkey, "InstallSource");
7105     RegDeleteValueA(prodkey, "InstallLocation");
7106     RegDeleteValueA(prodkey, "DisplayName");
7107     RegDeleteValueA(prodkey, "InstallDate");
7108     RegDeleteValueA(prodkey, "HelpTelephone");
7109     RegDeleteValueA(prodkey, "HelpLink");
7110     RegDeleteValueA(prodkey, "LocalPackage");
7111     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
7112     RegCloseKey(prodkey);
7113 
7114     /* MSIINSTALLCONTEXT_USERMANAGED */
7115 
7116     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
7117     lstrcatA(keypath, usersid);
7118     lstrcatA(keypath, "\\Products\\");
7119     lstrcatA(keypath, prod_squashed);
7120 
7121     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
7122     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7123 
7124     /* local user product key exists */
7125     sz = MAX_PATH;
7126     lstrcpyA(buf, "apple");
7127     r = pMsiGetProductInfoExA(prodcode, usersid,
7128                               MSIINSTALLCONTEXT_USERMANAGED,
7129                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7130     ok(r == ERROR_UNKNOWN_PRODUCT,
7131        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7132     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7133     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7134 
7135     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
7136     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7137 
7138     /* InstallProperties key exists */
7139     sz = MAX_PATH;
7140     lstrcpyA(buf, "apple");
7141     r = pMsiGetProductInfoExA(prodcode, usersid,
7142                               MSIINSTALLCONTEXT_USERMANAGED,
7143                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7144     ok(r == ERROR_UNKNOWN_PRODUCT,
7145        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7146     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7147     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7148 
7149     res = RegSetValueExA(propkey, "ManagedLocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
7150     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7151 
7152     /* ManagedLocalPackage value exists */
7153     sz = MAX_PATH;
7154     lstrcpyA(buf, "apple");
7155     r = pMsiGetProductInfoExA(prodcode, usersid,
7156                               MSIINSTALLCONTEXT_USERMANAGED,
7157                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7158     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7159     ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
7160     ok(sz == 1, "Expected 1, got %d\n", sz);
7161 
7162     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
7163     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7164 
7165     /* HelpLink value exists */
7166     sz = MAX_PATH;
7167     lstrcpyA(buf, "apple");
7168     r = pMsiGetProductInfoExA(prodcode, usersid,
7169                               MSIINSTALLCONTEXT_USERMANAGED,
7170                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
7171     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7172     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
7173     ok(sz == 4, "Expected 4, got %d\n", sz);
7174 
7175     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
7176     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7177 
7178     /* HelpTelephone value exists */
7179     sz = MAX_PATH;
7180     lstrcpyA(buf, "apple");
7181     r = pMsiGetProductInfoExA(prodcode, usersid,
7182                               MSIINSTALLCONTEXT_USERMANAGED,
7183                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
7184     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7185     ok(!lstrcmpA(buf, "phone"), "Expected \"phone\", got \"%s\"\n", buf);
7186     ok(sz == 5, "Expected 5, got %d\n", sz);
7187 
7188     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
7189     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7190 
7191     /* InstallDate value exists */
7192     sz = MAX_PATH;
7193     lstrcpyA(buf, "apple");
7194     r = pMsiGetProductInfoExA(prodcode, usersid,
7195                               MSIINSTALLCONTEXT_USERMANAGED,
7196                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
7197     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7198     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
7199     ok(sz == 4, "Expected 4, got %d\n", sz);
7200 
7201     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
7202     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7203 
7204     /* DisplayName value exists */
7205     sz = MAX_PATH;
7206     lstrcpyA(buf, "apple");
7207     r = pMsiGetProductInfoExA(prodcode, usersid,
7208                               MSIINSTALLCONTEXT_USERMANAGED,
7209                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
7210     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7211     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
7212     ok(sz == 4, "Expected 4, got %d\n", sz);
7213 
7214     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
7215     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7216 
7217     /* InstallLocation value exists */
7218     sz = MAX_PATH;
7219     lstrcpyA(buf, "apple");
7220     r = pMsiGetProductInfoExA(prodcode, usersid,
7221                               MSIINSTALLCONTEXT_USERMANAGED,
7222                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
7223     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7224     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
7225     ok(sz == 3, "Expected 3, got %d\n", sz);
7226 
7227     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
7228     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7229 
7230     /* InstallSource value exists */
7231     sz = MAX_PATH;
7232     lstrcpyA(buf, "apple");
7233     r = pMsiGetProductInfoExA(prodcode, usersid,
7234                               MSIINSTALLCONTEXT_USERMANAGED,
7235                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
7236     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7237     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
7238     ok(sz == 6, "Expected 6, got %d\n", sz);
7239 
7240     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
7241     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7242 
7243     /* LocalPackage value exists */
7244     sz = MAX_PATH;
7245     lstrcpyA(buf, "apple");
7246     r = pMsiGetProductInfoExA(prodcode, usersid,
7247                               MSIINSTALLCONTEXT_USERMANAGED,
7248                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
7249     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7250     ok(!lstrcmpA(buf, "local"), "Expected \"local\", got \"%s\"\n", buf);
7251     ok(sz == 5, "Expected 5, got %d\n", sz);
7252 
7253     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
7254     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7255 
7256     /* Publisher value exists */
7257     sz = MAX_PATH;
7258     lstrcpyA(buf, "apple");
7259     r = pMsiGetProductInfoExA(prodcode, usersid,
7260                               MSIINSTALLCONTEXT_USERMANAGED,
7261                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
7262     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7263     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
7264     ok(sz == 3, "Expected 3, got %d\n", sz);
7265 
7266     res = RegSetValueExA(propkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
7267     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7268 
7269     /* URLInfoAbout value exists */
7270     sz = MAX_PATH;
7271     lstrcpyA(buf, "apple");
7272     r = pMsiGetProductInfoExA(prodcode, usersid,
7273                               MSIINSTALLCONTEXT_USERMANAGED,
7274                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
7275     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7276     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
7277     ok(sz == 5, "Expected 5, got %d\n", sz);
7278 
7279     res = RegSetValueExA(propkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
7280     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7281 
7282     /* URLUpdateInfo value exists */
7283     sz = MAX_PATH;
7284     lstrcpyA(buf, "apple");
7285     r = pMsiGetProductInfoExA(prodcode, usersid,
7286                               MSIINSTALLCONTEXT_USERMANAGED,
7287                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
7288     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7289     ok(!lstrcmpA(buf, "update"), "Expected \"update\", got \"%s\"\n", buf);
7290     ok(sz == 6, "Expected 6, got %d\n", sz);
7291 
7292     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
7293     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7294 
7295     /* VersionMinor value exists */
7296     sz = MAX_PATH;
7297     lstrcpyA(buf, "apple");
7298     r = pMsiGetProductInfoExA(prodcode, usersid,
7299                               MSIINSTALLCONTEXT_USERMANAGED,
7300                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
7301     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7302     ok(!lstrcmpA(buf, "2"), "Expected \"2\", got \"%s\"\n", buf);
7303     ok(sz == 1, "Expected 1, got %d\n", sz);
7304 
7305     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
7306     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7307 
7308     /* VersionMajor value exists */
7309     sz = MAX_PATH;
7310     lstrcpyA(buf, "apple");
7311     r = pMsiGetProductInfoExA(prodcode, usersid,
7312                               MSIINSTALLCONTEXT_USERMANAGED,
7313                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
7314     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7315     ok(!lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
7316     ok(sz == 1, "Expected 1, got %d\n", sz);
7317 
7318     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
7319     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7320 
7321     /* DisplayVersion value exists */
7322     sz = MAX_PATH;
7323     lstrcpyA(buf, "apple");
7324     r = pMsiGetProductInfoExA(prodcode, usersid,
7325                               MSIINSTALLCONTEXT_USERMANAGED,
7326                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
7327     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7328     ok(!lstrcmpA(buf, "3.2.1"), "Expected \"3.2.1\", got \"%s\"\n", buf);
7329     ok(sz == 5, "Expected 5, got %d\n", sz);
7330 
7331     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
7332     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7333 
7334     /* ProductID value exists */
7335     sz = MAX_PATH;
7336     lstrcpyA(buf, "apple");
7337     r = pMsiGetProductInfoExA(prodcode, usersid,
7338                               MSIINSTALLCONTEXT_USERMANAGED,
7339                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
7340     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7341     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
7342     ok(sz == 2, "Expected 2, got %d\n", sz);
7343 
7344     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
7345     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7346 
7347     /* RegCompany value exists */
7348     sz = MAX_PATH;
7349     lstrcpyA(buf, "apple");
7350     r = pMsiGetProductInfoExA(prodcode, usersid,
7351                               MSIINSTALLCONTEXT_USERMANAGED,
7352                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
7353     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7354     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
7355     ok(sz == 4, "Expected 4, got %d\n", sz);
7356 
7357     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
7358     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7359 
7360     /* RegOwner value exists */
7361     sz = MAX_PATH;
7362     lstrcpyA(buf, "apple");
7363     r = pMsiGetProductInfoExA(prodcode, usersid,
7364                               MSIINSTALLCONTEXT_USERMANAGED,
7365                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
7366     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7367     ok(!lstrcmpA(buf, "owner"), "Expected \"owner\", got \"%s\"\n", buf);
7368     ok(sz == 5, "Expected 5, got %d\n", sz);
7369 
7370     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
7371     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7372 
7373     /* Transforms value exists */
7374     sz = MAX_PATH;
7375     lstrcpyA(buf, "apple");
7376     r = pMsiGetProductInfoExA(prodcode, usersid,
7377                               MSIINSTALLCONTEXT_USERMANAGED,
7378                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
7379     ok(r == ERROR_UNKNOWN_PRODUCT,
7380        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7381     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7382     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7383 
7384     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
7385     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7386 
7387     /* Language value exists */
7388     sz = MAX_PATH;
7389     lstrcpyA(buf, "apple");
7390     r = pMsiGetProductInfoExA(prodcode, usersid,
7391                               MSIINSTALLCONTEXT_USERMANAGED,
7392                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
7393     ok(r == ERROR_UNKNOWN_PRODUCT,
7394        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7395     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7396     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7397 
7398     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
7399     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7400 
7401     /* ProductName value exists */
7402     sz = MAX_PATH;
7403     lstrcpyA(buf, "apple");
7404     r = pMsiGetProductInfoExA(prodcode, usersid,
7405                               MSIINSTALLCONTEXT_USERMANAGED,
7406                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
7407     ok(r == ERROR_UNKNOWN_PRODUCT,
7408        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7409     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7410     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7411 
7412     res = RegSetValueExA(propkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
7413     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7414 
7415     /* FIXME */
7416 
7417     /* AssignmentType value exists */
7418     sz = MAX_PATH;
7419     lstrcpyA(buf, "apple");
7420     r = pMsiGetProductInfoExA(prodcode, usersid,
7421                               MSIINSTALLCONTEXT_USERMANAGED,
7422                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
7423     ok(r == ERROR_UNKNOWN_PRODUCT,
7424        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7425     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7426     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7427 
7428     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
7429     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7430 
7431     /* PackageCode value exists */
7432     sz = MAX_PATH;
7433     lstrcpyA(buf, "apple");
7434     r = pMsiGetProductInfoExA(prodcode, usersid,
7435                               MSIINSTALLCONTEXT_USERMANAGED,
7436                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
7437     ok(r == ERROR_UNKNOWN_PRODUCT,
7438        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7439     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7440     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7441 
7442     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
7443     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7444 
7445     /* Version value exists */
7446     sz = MAX_PATH;
7447     lstrcpyA(buf, "apple");
7448     r = pMsiGetProductInfoExA(prodcode, usersid,
7449                               MSIINSTALLCONTEXT_USERMANAGED,
7450                               INSTALLPROPERTY_VERSIONA, buf, &sz);
7451     ok(r == ERROR_UNKNOWN_PRODUCT,
7452        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7453     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7454     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7455 
7456     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
7457     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7458 
7459     /* ProductIcon value exists */
7460     sz = MAX_PATH;
7461     lstrcpyA(buf, "apple");
7462     r = pMsiGetProductInfoExA(prodcode, usersid,
7463                               MSIINSTALLCONTEXT_USERMANAGED,
7464                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
7465     ok(r == ERROR_UNKNOWN_PRODUCT,
7466        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7467     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7468     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7469 
7470     res = RegSetValueExA(propkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
7471     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7472 
7473     /* PackageName value exists */
7474     sz = MAX_PATH;
7475     lstrcpyA(buf, "apple");
7476     r = pMsiGetProductInfoExA(prodcode, usersid,
7477                               MSIINSTALLCONTEXT_USERMANAGED,
7478                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
7479     ok(r == ERROR_UNKNOWN_PRODUCT,
7480        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7481     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7482     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7483 
7484     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
7485     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7486 
7487     /* AuthorizedLUAApp value exists */
7488     sz = MAX_PATH;
7489     lstrcpyA(buf, "apple");
7490     r = pMsiGetProductInfoExA(prodcode, usersid,
7491                               MSIINSTALLCONTEXT_USERMANAGED,
7492                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
7493     ok(r == ERROR_UNKNOWN_PRODUCT,
7494        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7495     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7496     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7497 
7498     RegDeleteValueA(propkey, "AuthorizedLUAApp");
7499     RegDeleteValueA(propkey, "PackageName");
7500     RegDeleteValueA(propkey, "ProductIcon");
7501     RegDeleteValueA(propkey, "Version");
7502     RegDeleteValueA(propkey, "PackageCode");
7503     RegDeleteValueA(propkey, "AssignmentType");
7504     RegDeleteValueA(propkey, "ProductName");
7505     RegDeleteValueA(propkey, "Language");
7506     RegDeleteValueA(propkey, "Transforms");
7507     RegDeleteValueA(propkey, "RegOwner");
7508     RegDeleteValueA(propkey, "RegCompany");
7509     RegDeleteValueA(propkey, "ProductID");
7510     RegDeleteValueA(propkey, "DisplayVersion");
7511     RegDeleteValueA(propkey, "VersionMajor");
7512     RegDeleteValueA(propkey, "VersionMinor");
7513     RegDeleteValueA(propkey, "URLUpdateInfo");
7514     RegDeleteValueA(propkey, "URLInfoAbout");
7515     RegDeleteValueA(propkey, "Publisher");
7516     RegDeleteValueA(propkey, "LocalPackage");
7517     RegDeleteValueA(propkey, "InstallSource");
7518     RegDeleteValueA(propkey, "InstallLocation");
7519     RegDeleteValueA(propkey, "DisplayName");
7520     RegDeleteValueA(propkey, "InstallDate");
7521     RegDeleteValueA(propkey, "HelpTelephone");
7522     RegDeleteValueA(propkey, "HelpLink");
7523     RegDeleteValueA(propkey, "ManagedLocalPackage");
7524     delete_key(propkey, "", access & KEY_WOW64_64KEY);
7525     RegCloseKey(propkey);
7526     delete_key(localkey, "", access & KEY_WOW64_64KEY);
7527     RegCloseKey(localkey);
7528 
7529     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
7530     lstrcatA(keypath, usersid);
7531     lstrcatA(keypath, "\\Installer\\Products\\");
7532     lstrcatA(keypath, prod_squashed);
7533 
7534     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
7535     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7536 
7537     /* user product key exists */
7538     sz = MAX_PATH;
7539     lstrcpyA(buf, "apple");
7540     r = pMsiGetProductInfoExA(prodcode, usersid,
7541                               MSIINSTALLCONTEXT_USERMANAGED,
7542                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7543     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7544     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
7545     ok(sz == 1, "Expected 1, got %d\n", sz);
7546 
7547     delete_key(userkey, "", access & KEY_WOW64_64KEY);
7548     RegCloseKey(userkey);
7549 
7550     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
7551     lstrcatA(keypath, prod_squashed);
7552 
7553     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
7554     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7555 
7556     /* current user product key exists */
7557     sz = MAX_PATH;
7558     lstrcpyA(buf, "apple");
7559     r = pMsiGetProductInfoExA(prodcode, usersid,
7560                               MSIINSTALLCONTEXT_USERMANAGED,
7561                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7562     ok(r == ERROR_UNKNOWN_PRODUCT,
7563        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7564     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7565     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7566 
7567     res = RegSetValueExA(prodkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
7568     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7569 
7570     /* HelpLink value exists, user product key does not exist */
7571     sz = MAX_PATH;
7572     lstrcpyA(buf, "apple");
7573     r = pMsiGetProductInfoExA(prodcode, usersid,
7574                               MSIINSTALLCONTEXT_USERMANAGED,
7575                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
7576     ok(r == ERROR_UNKNOWN_PRODUCT,
7577        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7578     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7579     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7580 
7581     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
7582     lstrcatA(keypath, usersid);
7583     lstrcatA(keypath, "\\Installer\\Products\\");
7584     lstrcatA(keypath, prod_squashed);
7585 
7586     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
7587     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7588 
7589     res = RegSetValueExA(userkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
7590     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7591 
7592     /* HelpLink value exists, user product key does exist */
7593     sz = MAX_PATH;
7594     lstrcpyA(buf, "apple");
7595     r = pMsiGetProductInfoExA(prodcode, usersid,
7596                               MSIINSTALLCONTEXT_USERMANAGED,
7597                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
7598     ok(r == ERROR_UNKNOWN_PROPERTY,
7599        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7600     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7601     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7602 
7603     res = RegSetValueExA(userkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
7604     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7605 
7606     /* HelpTelephone value exists */
7607     sz = MAX_PATH;
7608     lstrcpyA(buf, "apple");
7609     r = pMsiGetProductInfoExA(prodcode, usersid,
7610                               MSIINSTALLCONTEXT_USERMANAGED,
7611                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
7612     ok(r == ERROR_UNKNOWN_PROPERTY,
7613        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7614     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7615     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7616 
7617     res = RegSetValueExA(userkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
7618     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7619 
7620     /* InstallDate value exists */
7621     sz = MAX_PATH;
7622     lstrcpyA(buf, "apple");
7623     r = pMsiGetProductInfoExA(prodcode, usersid,
7624                               MSIINSTALLCONTEXT_USERMANAGED,
7625                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
7626     ok(r == ERROR_UNKNOWN_PROPERTY,
7627        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7628     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7629     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7630 
7631     res = RegSetValueExA(userkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
7632     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7633 
7634     /* DisplayName value exists */
7635     sz = MAX_PATH;
7636     lstrcpyA(buf, "apple");
7637     r = pMsiGetProductInfoExA(prodcode, usersid,
7638                               MSIINSTALLCONTEXT_USERMANAGED,
7639                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
7640     ok(r == ERROR_UNKNOWN_PROPERTY,
7641        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7642     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7643     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7644 
7645     res = RegSetValueExA(userkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
7646     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7647 
7648     /* InstallLocation value exists */
7649     sz = MAX_PATH;
7650     lstrcpyA(buf, "apple");
7651     r = pMsiGetProductInfoExA(prodcode, usersid,
7652                               MSIINSTALLCONTEXT_USERMANAGED,
7653                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
7654     ok(r == ERROR_UNKNOWN_PROPERTY,
7655        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7656     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7657     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7658 
7659     res = RegSetValueExA(userkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
7660     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7661 
7662     /* InstallSource value exists */
7663     sz = MAX_PATH;
7664     lstrcpyA(buf, "apple");
7665     r = pMsiGetProductInfoExA(prodcode, usersid,
7666                               MSIINSTALLCONTEXT_USERMANAGED,
7667                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
7668     ok(r == ERROR_UNKNOWN_PROPERTY,
7669        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7670     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7671     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7672 
7673     res = RegSetValueExA(userkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
7674     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7675 
7676     /* LocalPackage value exists */
7677     sz = MAX_PATH;
7678     lstrcpyA(buf, "apple");
7679     r = pMsiGetProductInfoExA(prodcode, usersid,
7680                               MSIINSTALLCONTEXT_USERMANAGED,
7681                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
7682     ok(r == ERROR_UNKNOWN_PROPERTY,
7683        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7684     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7685     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7686 
7687     res = RegSetValueExA(userkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
7688     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7689 
7690     /* Publisher value exists */
7691     sz = MAX_PATH;
7692     lstrcpyA(buf, "apple");
7693     r = pMsiGetProductInfoExA(prodcode, usersid,
7694                               MSIINSTALLCONTEXT_USERMANAGED,
7695                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
7696     ok(r == ERROR_UNKNOWN_PROPERTY,
7697        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7698     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7699     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7700 
7701     res = RegSetValueExA(userkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
7702     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7703 
7704     /* URLInfoAbout value exists */
7705     sz = MAX_PATH;
7706     lstrcpyA(buf, "apple");
7707     r = pMsiGetProductInfoExA(prodcode, usersid,
7708                               MSIINSTALLCONTEXT_USERMANAGED,
7709                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
7710     ok(r == ERROR_UNKNOWN_PROPERTY,
7711        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7712     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7713     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7714 
7715     res = RegSetValueExA(userkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
7716     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7717 
7718     /* URLUpdateInfo value exists */
7719     sz = MAX_PATH;
7720     lstrcpyA(buf, "apple");
7721     r = pMsiGetProductInfoExA(prodcode, usersid,
7722                               MSIINSTALLCONTEXT_USERMANAGED,
7723                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
7724     ok(r == ERROR_UNKNOWN_PROPERTY,
7725        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7726     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7727     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7728 
7729     res = RegSetValueExA(userkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
7730     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7731 
7732     /* VersionMinor value exists */
7733     sz = MAX_PATH;
7734     lstrcpyA(buf, "apple");
7735     r = pMsiGetProductInfoExA(prodcode, usersid,
7736                               MSIINSTALLCONTEXT_USERMANAGED,
7737                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
7738     ok(r == ERROR_UNKNOWN_PROPERTY,
7739        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7740     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7741     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7742 
7743     res = RegSetValueExA(userkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
7744     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7745 
7746     /* VersionMajor value exists */
7747     sz = MAX_PATH;
7748     lstrcpyA(buf, "apple");
7749     r = pMsiGetProductInfoExA(prodcode, usersid,
7750                               MSIINSTALLCONTEXT_USERMANAGED,
7751                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
7752     ok(r == ERROR_UNKNOWN_PROPERTY,
7753        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7754     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7755     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7756 
7757     res = RegSetValueExA(userkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
7758     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7759 
7760     /* DisplayVersion value exists */
7761     sz = MAX_PATH;
7762     lstrcpyA(buf, "apple");
7763     r = pMsiGetProductInfoExA(prodcode, usersid,
7764                               MSIINSTALLCONTEXT_USERMANAGED,
7765                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
7766     ok(r == ERROR_UNKNOWN_PROPERTY,
7767        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7768     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7769     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7770 
7771     res = RegSetValueExA(userkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
7772     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7773 
7774     /* ProductID value exists */
7775     sz = MAX_PATH;
7776     lstrcpyA(buf, "apple");
7777     r = pMsiGetProductInfoExA(prodcode, usersid,
7778                               MSIINSTALLCONTEXT_USERMANAGED,
7779                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
7780     ok(r == ERROR_UNKNOWN_PROPERTY,
7781        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7782     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7783     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7784 
7785     res = RegSetValueExA(userkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
7786     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7787 
7788     /* RegCompany value exists */
7789     sz = MAX_PATH;
7790     lstrcpyA(buf, "apple");
7791     r = pMsiGetProductInfoExA(prodcode, usersid,
7792                               MSIINSTALLCONTEXT_USERMANAGED,
7793                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
7794     ok(r == ERROR_UNKNOWN_PROPERTY,
7795        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7796     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7797     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7798 
7799     res = RegSetValueExA(userkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
7800     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7801 
7802     /* RegOwner value exists */
7803     sz = MAX_PATH;
7804     lstrcpyA(buf, "apple");
7805     r = pMsiGetProductInfoExA(prodcode, usersid,
7806                               MSIINSTALLCONTEXT_USERMANAGED,
7807                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
7808     ok(r == ERROR_UNKNOWN_PROPERTY,
7809        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
7810     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7811     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7812 
7813     res = RegSetValueExA(userkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
7814     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7815 
7816     /* Transforms value exists */
7817     sz = MAX_PATH;
7818     lstrcpyA(buf, "apple");
7819     r = pMsiGetProductInfoExA(prodcode, usersid,
7820                               MSIINSTALLCONTEXT_USERMANAGED,
7821                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
7822     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7823     ok(!lstrcmpA(buf, "trans"), "Expected \"trans\", got \"%s\"\n", buf);
7824     ok(sz == 5, "Expected 5, got %d\n", sz);
7825 
7826     res = RegSetValueExA(userkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
7827     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7828 
7829     /* Language value exists */
7830     sz = MAX_PATH;
7831     lstrcpyA(buf, "apple");
7832     r = pMsiGetProductInfoExA(prodcode, usersid,
7833                               MSIINSTALLCONTEXT_USERMANAGED,
7834                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
7835     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7836     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
7837     ok(sz == 4, "Expected 4, got %d\n", sz);
7838 
7839     res = RegSetValueExA(userkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
7840     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7841 
7842     /* ProductName value exists */
7843     sz = MAX_PATH;
7844     lstrcpyA(buf, "apple");
7845     r = pMsiGetProductInfoExA(prodcode, usersid,
7846                               MSIINSTALLCONTEXT_USERMANAGED,
7847                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
7848     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7849     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
7850     ok(sz == 4, "Expected 4, got %d\n", sz);
7851 
7852     res = RegSetValueExA(userkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
7853     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7854 
7855     /* FIXME */
7856 
7857     /* AssignmentType value exists */
7858     sz = MAX_PATH;
7859     lstrcpyA(buf, "apple");
7860     r = pMsiGetProductInfoExA(prodcode, usersid,
7861                               MSIINSTALLCONTEXT_USERMANAGED,
7862                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
7863     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7864     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7865     ok(sz == 0, "Expected 0, got %d\n", sz);
7866 
7867     res = RegSetValueExA(userkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
7868     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7869 
7870     /* FIXME */
7871 
7872     /* PackageCode value exists */
7873     sz = MAX_PATH;
7874     lstrcpyA(buf, "apple");
7875     r = pMsiGetProductInfoExA(prodcode, usersid,
7876                               MSIINSTALLCONTEXT_USERMANAGED,
7877                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
7878     todo_wine
7879     {
7880         ok(r == ERROR_BAD_CONFIGURATION,
7881            "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
7882         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7883         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7884     }
7885 
7886     res = RegSetValueExA(userkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
7887     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7888 
7889     /* Version value exists */
7890     sz = MAX_PATH;
7891     lstrcpyA(buf, "apple");
7892     r = pMsiGetProductInfoExA(prodcode, usersid,
7893                               MSIINSTALLCONTEXT_USERMANAGED,
7894                               INSTALLPROPERTY_VERSIONA, buf, &sz);
7895     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7896     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
7897     ok(sz == 3, "Expected 3, got %d\n", sz);
7898 
7899     res = RegSetValueExA(userkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
7900     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7901 
7902     /* ProductIcon value exists */
7903     sz = MAX_PATH;
7904     lstrcpyA(buf, "apple");
7905     r = pMsiGetProductInfoExA(prodcode, usersid,
7906                               MSIINSTALLCONTEXT_USERMANAGED,
7907                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
7908     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7909     ok(!lstrcmpA(buf, "icon"), "Expected \"icon\", got \"%s\"\n", buf);
7910     ok(sz == 4, "Expected 4, got %d\n", sz);
7911 
7912     res = RegSetValueExA(userkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
7913     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7914 
7915     /* PackageName value exists */
7916     sz = MAX_PATH;
7917     lstrcpyA(buf, "apple");
7918     r = pMsiGetProductInfoExA(prodcode, usersid,
7919                               MSIINSTALLCONTEXT_USERMANAGED,
7920                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
7921     todo_wine
7922     {
7923         ok(r == ERROR_UNKNOWN_PRODUCT,
7924            "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7925         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7926         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7927     }
7928 
7929     res = RegSetValueExA(userkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
7930     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7931 
7932     /* AuthorizedLUAApp value exists */
7933     sz = MAX_PATH;
7934     lstrcpyA(buf, "apple");
7935     r = pMsiGetProductInfoExA(prodcode, usersid,
7936                               MSIINSTALLCONTEXT_USERMANAGED,
7937                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
7938     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7939     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
7940     ok(sz == 4, "Expected 4, got %d\n", sz);
7941 
7942     RegDeleteValueA(userkey, "AuthorizedLUAApp");
7943     RegDeleteValueA(userkey, "PackageName");
7944     RegDeleteValueA(userkey, "ProductIcon");
7945     RegDeleteValueA(userkey, "Version");
7946     RegDeleteValueA(userkey, "PackageCode");
7947     RegDeleteValueA(userkey, "AssignmentType");
7948     RegDeleteValueA(userkey, "ProductName");
7949     RegDeleteValueA(userkey, "Language");
7950     RegDeleteValueA(userkey, "Transforms");
7951     RegDeleteValueA(userkey, "RegOwner");
7952     RegDeleteValueA(userkey, "RegCompany");
7953     RegDeleteValueA(userkey, "ProductID");
7954     RegDeleteValueA(userkey, "DisplayVersion");
7955     RegDeleteValueA(userkey, "VersionMajor");
7956     RegDeleteValueA(userkey, "VersionMinor");
7957     RegDeleteValueA(userkey, "URLUpdateInfo");
7958     RegDeleteValueA(userkey, "URLInfoAbout");
7959     RegDeleteValueA(userkey, "Publisher");
7960     RegDeleteValueA(userkey, "LocalPackage");
7961     RegDeleteValueA(userkey, "InstallSource");
7962     RegDeleteValueA(userkey, "InstallLocation");
7963     RegDeleteValueA(userkey, "DisplayName");
7964     RegDeleteValueA(userkey, "InstallDate");
7965     RegDeleteValueA(userkey, "HelpTelephone");
7966     RegDeleteValueA(userkey, "HelpLink");
7967     delete_key(userkey, "", access & KEY_WOW64_64KEY);
7968     RegCloseKey(userkey);
7969     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
7970     RegCloseKey(prodkey);
7971 
7972     /* MSIINSTALLCONTEXT_MACHINE */
7973 
7974     /* szUserSid is non-NULL */
7975     sz = MAX_PATH;
7976     lstrcpyA(buf, "apple");
7977     r = pMsiGetProductInfoExA(prodcode, usersid,
7978                               MSIINSTALLCONTEXT_MACHINE,
7979                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7980     ok(r == ERROR_INVALID_PARAMETER,
7981        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
7982     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7983     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
7984 
7985     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\");
7986     lstrcatA(keypath, prod_squashed);
7987 
7988     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
7989     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
7990 
7991     /* local system product key exists */
7992     sz = MAX_PATH;
7993     lstrcpyA(buf, "apple");
7994     r = pMsiGetProductInfoExA(prodcode, NULL,
7995                               MSIINSTALLCONTEXT_MACHINE,
7996                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
7997     ok(r == ERROR_UNKNOWN_PRODUCT,
7998        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
7999     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8000     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8001 
8002     res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &propkey, NULL);
8003     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8004 
8005     /* InstallProperties key exists */
8006     sz = MAX_PATH;
8007     lstrcpyA(buf, "apple");
8008     r = pMsiGetProductInfoExA(prodcode, NULL,
8009                               MSIINSTALLCONTEXT_MACHINE,
8010                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
8011     ok(r == ERROR_UNKNOWN_PRODUCT,
8012        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8013     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8014     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8015 
8016     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
8017     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8018 
8019     /* LocalPackage value exists */
8020     sz = MAX_PATH;
8021     lstrcpyA(buf, "apple");
8022     r = pMsiGetProductInfoExA(prodcode, NULL,
8023                               MSIINSTALLCONTEXT_MACHINE,
8024                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
8025     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8026     ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
8027     ok(sz == 1, "Expected 1, got %d\n", sz);
8028 
8029     res = RegSetValueExA(propkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
8030     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8031 
8032     /* HelpLink value exists */
8033     sz = MAX_PATH;
8034     lstrcpyA(buf, "apple");
8035     r = pMsiGetProductInfoExA(prodcode, NULL,
8036                               MSIINSTALLCONTEXT_MACHINE,
8037                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
8038     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8039     ok(!lstrcmpA(buf, "link"), "Expected \"link\", got \"%s\"\n", buf);
8040     ok(sz == 4, "Expected 4, got %d\n", sz);
8041 
8042     res = RegSetValueExA(propkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
8043     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8044 
8045     /* HelpTelephone value exists */
8046     sz = MAX_PATH;
8047     lstrcpyA(buf, "apple");
8048     r = pMsiGetProductInfoExA(prodcode, NULL,
8049                               MSIINSTALLCONTEXT_MACHINE,
8050                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
8051     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8052     ok(!lstrcmpA(buf, "phone"), "Expected \"phone\", got \"%s\"\n", buf);
8053     ok(sz == 5, "Expected 5, got %d\n", sz);
8054 
8055     res = RegSetValueExA(propkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
8056     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8057 
8058     /* InstallDate value exists */
8059     sz = MAX_PATH;
8060     lstrcpyA(buf, "apple");
8061     r = pMsiGetProductInfoExA(prodcode, NULL,
8062                               MSIINSTALLCONTEXT_MACHINE,
8063                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
8064     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8065     ok(!lstrcmpA(buf, "date"), "Expected \"date\", got \"%s\"\n", buf);
8066     ok(sz == 4, "Expected 4, got %d\n", sz);
8067 
8068     res = RegSetValueExA(propkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
8069     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8070 
8071     /* DisplayName value exists */
8072     sz = MAX_PATH;
8073     lstrcpyA(buf, "apple");
8074     r = pMsiGetProductInfoExA(prodcode, NULL,
8075                               MSIINSTALLCONTEXT_MACHINE,
8076                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
8077     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8078     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
8079     ok(sz == 4, "Expected 4, got %d\n", sz);
8080 
8081     res = RegSetValueExA(propkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
8082     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8083 
8084     /* InstallLocation value exists */
8085     sz = MAX_PATH;
8086     lstrcpyA(buf, "apple");
8087     r = pMsiGetProductInfoExA(prodcode, NULL,
8088                               MSIINSTALLCONTEXT_MACHINE,
8089                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
8090     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8091     ok(!lstrcmpA(buf, "loc"), "Expected \"loc\", got \"%s\"\n", buf);
8092     ok(sz == 3, "Expected 3, got %d\n", sz);
8093 
8094     res = RegSetValueExA(propkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
8095     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8096 
8097     /* InstallSource value exists */
8098     sz = MAX_PATH;
8099     lstrcpyA(buf, "apple");
8100     r = pMsiGetProductInfoExA(prodcode, NULL,
8101                               MSIINSTALLCONTEXT_MACHINE,
8102                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
8103     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8104     ok(!lstrcmpA(buf, "source"), "Expected \"source\", got \"%s\"\n", buf);
8105     ok(sz == 6, "Expected 6, got %d\n", sz);
8106 
8107     res = RegSetValueExA(propkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
8108     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8109 
8110     /* LocalPackage value exists */
8111     sz = MAX_PATH;
8112     lstrcpyA(buf, "apple");
8113     r = pMsiGetProductInfoExA(prodcode, NULL,
8114                               MSIINSTALLCONTEXT_MACHINE,
8115                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
8116     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8117     ok(!lstrcmpA(buf, "local"), "Expected \"local\", got \"%s\"\n", buf);
8118     ok(sz == 5, "Expected 5, got %d\n", sz);
8119 
8120     res = RegSetValueExA(propkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
8121     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8122 
8123     /* Publisher value exists */
8124     sz = MAX_PATH;
8125     lstrcpyA(buf, "apple");
8126     r = pMsiGetProductInfoExA(prodcode, NULL,
8127                               MSIINSTALLCONTEXT_MACHINE,
8128                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
8129     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8130     ok(!lstrcmpA(buf, "pub"), "Expected \"pub\", got \"%s\"\n", buf);
8131     ok(sz == 3, "Expected 3, got %d\n", sz);
8132 
8133     res = RegSetValueExA(propkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
8134     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8135 
8136     /* URLInfoAbout value exists */
8137     sz = MAX_PATH;
8138     lstrcpyA(buf, "apple");
8139     r = pMsiGetProductInfoExA(prodcode, NULL,
8140                               MSIINSTALLCONTEXT_MACHINE,
8141                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
8142     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8143     ok(!lstrcmpA(buf, "about"), "Expected \"about\", got \"%s\"\n", buf);
8144     ok(sz == 5, "Expected 5, got %d\n", sz);
8145 
8146     res = RegSetValueExA(propkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
8147     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8148 
8149     /* URLUpdateInfo value exists */
8150     sz = MAX_PATH;
8151     lstrcpyA(buf, "apple");
8152     r = pMsiGetProductInfoExA(prodcode, NULL,
8153                               MSIINSTALLCONTEXT_MACHINE,
8154                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
8155     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8156     ok(!lstrcmpA(buf, "update"), "Expected \"update\", got \"%s\"\n", buf);
8157     ok(sz == 6, "Expected 6, got %d\n", sz);
8158 
8159     res = RegSetValueExA(propkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
8160     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8161 
8162     /* VersionMinor value exists */
8163     sz = MAX_PATH;
8164     lstrcpyA(buf, "apple");
8165     r = pMsiGetProductInfoExA(prodcode, NULL,
8166                               MSIINSTALLCONTEXT_MACHINE,
8167                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
8168     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8169     ok(!lstrcmpA(buf, "2"), "Expected \"2\", got \"%s\"\n", buf);
8170     ok(sz == 1, "Expected 1, got %d\n", sz);
8171 
8172     res = RegSetValueExA(propkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
8173     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8174 
8175     /* VersionMajor value exists */
8176     sz = MAX_PATH;
8177     lstrcpyA(buf, "apple");
8178     r = pMsiGetProductInfoExA(prodcode, NULL,
8179                               MSIINSTALLCONTEXT_MACHINE,
8180                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
8181     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8182     ok(!lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
8183     ok(sz == 1, "Expected 1, got %d\n", sz);
8184 
8185     res = RegSetValueExA(propkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
8186     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8187 
8188     /* DisplayVersion value exists */
8189     sz = MAX_PATH;
8190     lstrcpyA(buf, "apple");
8191     r = pMsiGetProductInfoExA(prodcode, NULL,
8192                               MSIINSTALLCONTEXT_MACHINE,
8193                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
8194     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8195     ok(!lstrcmpA(buf, "3.2.1"), "Expected \"3.2.1\", got \"%s\"\n", buf);
8196     ok(sz == 5, "Expected 5, got %d\n", sz);
8197 
8198     res = RegSetValueExA(propkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
8199     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8200 
8201     /* ProductID value exists */
8202     sz = MAX_PATH;
8203     lstrcpyA(buf, "apple");
8204     r = pMsiGetProductInfoExA(prodcode, NULL,
8205                               MSIINSTALLCONTEXT_MACHINE,
8206                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
8207     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8208     ok(!lstrcmpA(buf, "id"), "Expected \"id\", got \"%s\"\n", buf);
8209     ok(sz == 2, "Expected 2, got %d\n", sz);
8210 
8211     res = RegSetValueExA(propkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
8212     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8213 
8214     /* RegCompany value exists */
8215     sz = MAX_PATH;
8216     lstrcpyA(buf, "apple");
8217     r = pMsiGetProductInfoExA(prodcode, NULL,
8218                               MSIINSTALLCONTEXT_MACHINE,
8219                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
8220     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8221     ok(!lstrcmpA(buf, "comp"), "Expected \"comp\", got \"%s\"\n", buf);
8222     ok(sz == 4, "Expected 4, got %d\n", sz);
8223 
8224     res = RegSetValueExA(propkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
8225     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8226 
8227     /* RegOwner value exists */
8228     sz = MAX_PATH;
8229     lstrcpyA(buf, "apple");
8230     r = pMsiGetProductInfoExA(prodcode, NULL,
8231                               MSIINSTALLCONTEXT_MACHINE,
8232                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
8233     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8234     ok(!lstrcmpA(buf, "owner"), "Expected \"owner\", got \"%s\"\n", buf);
8235     ok(sz == 5, "Expected 5, got %d\n", sz);
8236 
8237     res = RegSetValueExA(propkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
8238     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8239 
8240     /* Transforms value exists */
8241     sz = MAX_PATH;
8242     lstrcpyA(buf, "apple");
8243     r = pMsiGetProductInfoExA(prodcode, NULL,
8244                               MSIINSTALLCONTEXT_MACHINE,
8245                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
8246     ok(r == ERROR_UNKNOWN_PRODUCT,
8247        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8248     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8249     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8250 
8251     res = RegSetValueExA(propkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
8252     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8253 
8254     /* Language value exists */
8255     sz = MAX_PATH;
8256     lstrcpyA(buf, "apple");
8257     r = pMsiGetProductInfoExA(prodcode, NULL,
8258                               MSIINSTALLCONTEXT_MACHINE,
8259                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
8260     ok(r == ERROR_UNKNOWN_PRODUCT,
8261        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8262     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8263     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8264 
8265     res = RegSetValueExA(propkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
8266     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8267 
8268     /* ProductName value exists */
8269     sz = MAX_PATH;
8270     lstrcpyA(buf, "apple");
8271     r = pMsiGetProductInfoExA(prodcode, NULL,
8272                               MSIINSTALLCONTEXT_MACHINE,
8273                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
8274     ok(r == ERROR_UNKNOWN_PRODUCT,
8275        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8276     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8277     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8278 
8279     res = RegSetValueExA(propkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
8280     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8281 
8282     /* FIXME */
8283 
8284     /* AssignmentType value exists */
8285     sz = MAX_PATH;
8286     lstrcpyA(buf, "apple");
8287     r = pMsiGetProductInfoExA(prodcode, NULL,
8288                               MSIINSTALLCONTEXT_MACHINE,
8289                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
8290     ok(r == ERROR_UNKNOWN_PRODUCT,
8291        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8292     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8293     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8294 
8295     res = RegSetValueExA(propkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
8296     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8297 
8298     /* PackageCode value exists */
8299     sz = MAX_PATH;
8300     lstrcpyA(buf, "apple");
8301     r = pMsiGetProductInfoExA(prodcode, NULL,
8302                               MSIINSTALLCONTEXT_MACHINE,
8303                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
8304     ok(r == ERROR_UNKNOWN_PRODUCT,
8305        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8306     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8307     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8308 
8309     res = RegSetValueExA(propkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
8310     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8311 
8312     /* Version value exists */
8313     sz = MAX_PATH;
8314     lstrcpyA(buf, "apple");
8315     r = pMsiGetProductInfoExA(prodcode, NULL,
8316                               MSIINSTALLCONTEXT_MACHINE,
8317                               INSTALLPROPERTY_VERSIONA, buf, &sz);
8318     ok(r == ERROR_UNKNOWN_PRODUCT,
8319        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8320     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8321     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8322 
8323     res = RegSetValueExA(propkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
8324     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8325 
8326     /* ProductIcon value exists */
8327     sz = MAX_PATH;
8328     lstrcpyA(buf, "apple");
8329     r = pMsiGetProductInfoExA(prodcode, NULL,
8330                               MSIINSTALLCONTEXT_MACHINE,
8331                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
8332     ok(r == ERROR_UNKNOWN_PRODUCT,
8333        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8334     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8335     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8336 
8337     res = RegSetValueExA(propkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
8338     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8339 
8340     /* PackageName value exists */
8341     sz = MAX_PATH;
8342     lstrcpyA(buf, "apple");
8343     r = pMsiGetProductInfoExA(prodcode, NULL,
8344                               MSIINSTALLCONTEXT_MACHINE,
8345                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
8346     ok(r == ERROR_UNKNOWN_PRODUCT,
8347        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8348     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8349     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8350 
8351     res = RegSetValueExA(propkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
8352     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8353 
8354     /* AuthorizedLUAApp value exists */
8355     sz = MAX_PATH;
8356     lstrcpyA(buf, "apple");
8357     r = pMsiGetProductInfoExA(prodcode, NULL,
8358                               MSIINSTALLCONTEXT_MACHINE,
8359                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
8360     ok(r == ERROR_UNKNOWN_PRODUCT,
8361        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8362     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8363     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8364 
8365     RegDeleteValueA(propkey, "AuthorizedLUAApp");
8366     RegDeleteValueA(propkey, "PackageName");
8367     RegDeleteValueA(propkey, "ProductIcon");
8368     RegDeleteValueA(propkey, "Version");
8369     RegDeleteValueA(propkey, "PackageCode");
8370     RegDeleteValueA(propkey, "AssignmentType");
8371     RegDeleteValueA(propkey, "ProductName");
8372     RegDeleteValueA(propkey, "Language");
8373     RegDeleteValueA(propkey, "Transforms");
8374     RegDeleteValueA(propkey, "RegOwner");
8375     RegDeleteValueA(propkey, "RegCompany");
8376     RegDeleteValueA(propkey, "ProductID");
8377     RegDeleteValueA(propkey, "DisplayVersion");
8378     RegDeleteValueA(propkey, "VersionMajor");
8379     RegDeleteValueA(propkey, "VersionMinor");
8380     RegDeleteValueA(propkey, "URLUpdateInfo");
8381     RegDeleteValueA(propkey, "URLInfoAbout");
8382     RegDeleteValueA(propkey, "Publisher");
8383     RegDeleteValueA(propkey, "LocalPackage");
8384     RegDeleteValueA(propkey, "InstallSource");
8385     RegDeleteValueA(propkey, "InstallLocation");
8386     RegDeleteValueA(propkey, "DisplayName");
8387     RegDeleteValueA(propkey, "InstallDate");
8388     RegDeleteValueA(propkey, "HelpTelephone");
8389     RegDeleteValueA(propkey, "HelpLink");
8390     RegDeleteValueA(propkey, "LocalPackage");
8391     delete_key(propkey, "", access & KEY_WOW64_64KEY);
8392     RegCloseKey(propkey);
8393     delete_key(localkey, "", access & KEY_WOW64_64KEY);
8394     RegCloseKey(localkey);
8395 
8396     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
8397     lstrcatA(keypath, prod_squashed);
8398 
8399     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8400     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8401 
8402     /* local classes product key exists */
8403     sz = MAX_PATH;
8404     lstrcpyA(buf, "apple");
8405     r = pMsiGetProductInfoExA(prodcode, NULL,
8406                               MSIINSTALLCONTEXT_MACHINE,
8407                               INSTALLPROPERTY_PRODUCTSTATEA, buf, &sz);
8408     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8409     ok(!lstrcmpA(buf, "1"), "Expected \"1\", got \"%s\"\n", buf);
8410     ok(sz == 1, "Expected 1, got %d\n", sz);
8411 
8412     res = RegSetValueExA(prodkey, "HelpLink", 0, REG_SZ, (LPBYTE)"link", 5);
8413     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8414 
8415     /* HelpLink value exists */
8416     sz = MAX_PATH;
8417     lstrcpyA(buf, "apple");
8418     r = pMsiGetProductInfoExA(prodcode, NULL,
8419                               MSIINSTALLCONTEXT_MACHINE,
8420                               INSTALLPROPERTY_HELPLINKA, buf, &sz);
8421     ok(r == ERROR_UNKNOWN_PROPERTY,
8422        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8423     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8424     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8425 
8426     res = RegSetValueExA(prodkey, "HelpTelephone", 0, REG_SZ, (LPBYTE)"phone", 6);
8427     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8428 
8429     /* HelpTelephone value exists */
8430     sz = MAX_PATH;
8431     lstrcpyA(buf, "apple");
8432     r = pMsiGetProductInfoExA(prodcode, NULL,
8433                               MSIINSTALLCONTEXT_MACHINE,
8434                               INSTALLPROPERTY_HELPTELEPHONEA, buf, &sz);
8435     ok(r == ERROR_UNKNOWN_PROPERTY,
8436        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8437     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8438     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8439 
8440     res = RegSetValueExA(prodkey, "InstallDate", 0, REG_SZ, (LPBYTE)"date", 5);
8441     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8442 
8443     /* InstallDate value exists */
8444     sz = MAX_PATH;
8445     lstrcpyA(buf, "apple");
8446     r = pMsiGetProductInfoExA(prodcode, NULL,
8447                               MSIINSTALLCONTEXT_MACHINE,
8448                               INSTALLPROPERTY_INSTALLDATEA, buf, &sz);
8449     ok(r == ERROR_UNKNOWN_PROPERTY,
8450        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8451     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8452     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8453 
8454     res = RegSetValueExA(prodkey, "DisplayName", 0, REG_SZ, (LPBYTE)"name", 5);
8455     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8456 
8457     /* DisplayName value exists */
8458     sz = MAX_PATH;
8459     lstrcpyA(buf, "apple");
8460     r = pMsiGetProductInfoExA(prodcode, NULL,
8461                               MSIINSTALLCONTEXT_MACHINE,
8462                               INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA, buf, &sz);
8463     ok(r == ERROR_UNKNOWN_PROPERTY,
8464        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8465     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8466     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8467 
8468     res = RegSetValueExA(prodkey, "InstallLocation", 0, REG_SZ, (LPBYTE)"loc", 4);
8469     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8470 
8471     /* InstallLocation value exists */
8472     sz = MAX_PATH;
8473     lstrcpyA(buf, "apple");
8474     r = pMsiGetProductInfoExA(prodcode, NULL,
8475                               MSIINSTALLCONTEXT_MACHINE,
8476                               INSTALLPROPERTY_INSTALLLOCATIONA, buf, &sz);
8477     ok(r == ERROR_UNKNOWN_PROPERTY,
8478        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8479     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8480     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8481 
8482     res = RegSetValueExA(prodkey, "InstallSource", 0, REG_SZ, (LPBYTE)"source", 7);
8483     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8484 
8485     /* InstallSource value exists */
8486     sz = MAX_PATH;
8487     lstrcpyA(buf, "apple");
8488     r = pMsiGetProductInfoExA(prodcode, NULL,
8489                               MSIINSTALLCONTEXT_MACHINE,
8490                               INSTALLPROPERTY_INSTALLSOURCEA, buf, &sz);
8491     ok(r == ERROR_UNKNOWN_PROPERTY,
8492        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8493     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8494     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8495 
8496     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (LPBYTE)"local", 6);
8497     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8498 
8499     /* LocalPackage value exists */
8500     sz = MAX_PATH;
8501     lstrcpyA(buf, "apple");
8502     r = pMsiGetProductInfoExA(prodcode, NULL,
8503                               MSIINSTALLCONTEXT_MACHINE,
8504                               INSTALLPROPERTY_LOCALPACKAGEA, buf, &sz);
8505     ok(r == ERROR_UNKNOWN_PROPERTY,
8506        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8507     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8508     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8509 
8510     res = RegSetValueExA(prodkey, "Publisher", 0, REG_SZ, (LPBYTE)"pub", 4);
8511     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8512 
8513     /* Publisher value exists */
8514     sz = MAX_PATH;
8515     lstrcpyA(buf, "apple");
8516     r = pMsiGetProductInfoExA(prodcode, NULL,
8517                               MSIINSTALLCONTEXT_MACHINE,
8518                               INSTALLPROPERTY_PUBLISHERA, buf, &sz);
8519     ok(r == ERROR_UNKNOWN_PROPERTY,
8520        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8521     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8522     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8523 
8524     res = RegSetValueExA(prodkey, "URLInfoAbout", 0, REG_SZ, (LPBYTE)"about", 6);
8525     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8526 
8527     /* URLInfoAbout value exists */
8528     sz = MAX_PATH;
8529     lstrcpyA(buf, "apple");
8530     r = pMsiGetProductInfoExA(prodcode, NULL,
8531                               MSIINSTALLCONTEXT_MACHINE,
8532                               INSTALLPROPERTY_URLINFOABOUTA, buf, &sz);
8533     ok(r == ERROR_UNKNOWN_PROPERTY,
8534        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8535     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8536     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8537 
8538     res = RegSetValueExA(prodkey, "URLUpdateInfo", 0, REG_SZ, (LPBYTE)"update", 7);
8539     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8540 
8541     /* URLUpdateInfo value exists */
8542     sz = MAX_PATH;
8543     lstrcpyA(buf, "apple");
8544     r = pMsiGetProductInfoExA(prodcode, NULL,
8545                               MSIINSTALLCONTEXT_MACHINE,
8546                               INSTALLPROPERTY_URLUPDATEINFOA, buf, &sz);
8547     ok(r == ERROR_UNKNOWN_PROPERTY,
8548        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8549     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8550     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8551 
8552     res = RegSetValueExA(prodkey, "VersionMinor", 0, REG_SZ, (LPBYTE)"2", 2);
8553     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8554 
8555     /* VersionMinor value exists */
8556     sz = MAX_PATH;
8557     lstrcpyA(buf, "apple");
8558     r = pMsiGetProductInfoExA(prodcode, NULL,
8559                               MSIINSTALLCONTEXT_MACHINE,
8560                               INSTALLPROPERTY_VERSIONMINORA, buf, &sz);
8561     ok(r == ERROR_UNKNOWN_PROPERTY,
8562        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8563     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8564     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8565 
8566     res = RegSetValueExA(prodkey, "VersionMajor", 0, REG_SZ, (LPBYTE)"3", 2);
8567     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8568 
8569     /* VersionMajor value exists */
8570     sz = MAX_PATH;
8571     lstrcpyA(buf, "apple");
8572     r = pMsiGetProductInfoExA(prodcode, NULL,
8573                               MSIINSTALLCONTEXT_MACHINE,
8574                               INSTALLPROPERTY_VERSIONMAJORA, buf, &sz);
8575     ok(r == ERROR_UNKNOWN_PROPERTY,
8576        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8577     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8578     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8579 
8580     res = RegSetValueExA(prodkey, "DisplayVersion", 0, REG_SZ, (LPBYTE)"3.2.1", 6);
8581     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8582 
8583     /* DisplayVersion value exists */
8584     sz = MAX_PATH;
8585     lstrcpyA(buf, "apple");
8586     r = pMsiGetProductInfoExA(prodcode, NULL,
8587                               MSIINSTALLCONTEXT_MACHINE,
8588                               INSTALLPROPERTY_VERSIONSTRINGA, buf, &sz);
8589     ok(r == ERROR_UNKNOWN_PROPERTY,
8590        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8591     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8592     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8593 
8594     res = RegSetValueExA(prodkey, "ProductID", 0, REG_SZ, (LPBYTE)"id", 3);
8595     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8596 
8597     /* ProductID value exists */
8598     sz = MAX_PATH;
8599     lstrcpyA(buf, "apple");
8600     r = pMsiGetProductInfoExA(prodcode, NULL,
8601                               MSIINSTALLCONTEXT_MACHINE,
8602                               INSTALLPROPERTY_PRODUCTIDA, buf, &sz);
8603     ok(r == ERROR_UNKNOWN_PROPERTY,
8604        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8605     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8606     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8607 
8608     res = RegSetValueExA(prodkey, "RegCompany", 0, REG_SZ, (LPBYTE)"comp", 5);
8609     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8610 
8611     /* RegCompany value exists */
8612     sz = MAX_PATH;
8613     lstrcpyA(buf, "apple");
8614     r = pMsiGetProductInfoExA(prodcode, NULL,
8615                               MSIINSTALLCONTEXT_MACHINE,
8616                               INSTALLPROPERTY_REGCOMPANYA, buf, &sz);
8617     ok(r == ERROR_UNKNOWN_PROPERTY,
8618        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8619     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8620     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8621 
8622     res = RegSetValueExA(prodkey, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
8623     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8624 
8625     /* RegOwner value exists */
8626     sz = MAX_PATH;
8627     lstrcpyA(buf, "apple");
8628     r = pMsiGetProductInfoExA(prodcode, NULL,
8629                               MSIINSTALLCONTEXT_MACHINE,
8630                               INSTALLPROPERTY_REGOWNERA, buf, &sz);
8631     ok(r == ERROR_UNKNOWN_PROPERTY,
8632        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
8633     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8634     ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8635 
8636     res = RegSetValueExA(prodkey, "Transforms", 0, REG_SZ, (LPBYTE)"trans", 6);
8637     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8638 
8639     /* Transforms value exists */
8640     sz = MAX_PATH;
8641     lstrcpyA(buf, "apple");
8642     r = pMsiGetProductInfoExA(prodcode, NULL,
8643                               MSIINSTALLCONTEXT_MACHINE,
8644                               INSTALLPROPERTY_TRANSFORMSA, buf, &sz);
8645     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8646     ok(!lstrcmpA(buf, "trans"), "Expected \"trans\", got \"%s\"\n", buf);
8647     ok(sz == 5, "Expected 5, got %d\n", sz);
8648 
8649     res = RegSetValueExA(prodkey, "Language", 0, REG_SZ, (LPBYTE)"lang", 5);
8650     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8651 
8652     /* Language value exists */
8653     sz = MAX_PATH;
8654     lstrcpyA(buf, "apple");
8655     r = pMsiGetProductInfoExA(prodcode, NULL,
8656                               MSIINSTALLCONTEXT_MACHINE,
8657                               INSTALLPROPERTY_LANGUAGEA, buf, &sz);
8658     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8659     ok(!lstrcmpA(buf, "lang"), "Expected \"lang\", got \"%s\"\n", buf);
8660     ok(sz == 4, "Expected 4, got %d\n", sz);
8661 
8662     res = RegSetValueExA(prodkey, "ProductName", 0, REG_SZ, (LPBYTE)"name", 5);
8663     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8664 
8665     /* ProductName value exists */
8666     sz = MAX_PATH;
8667     lstrcpyA(buf, "apple");
8668     r = pMsiGetProductInfoExA(prodcode, NULL,
8669                               MSIINSTALLCONTEXT_MACHINE,
8670                               INSTALLPROPERTY_PRODUCTNAMEA, buf, &sz);
8671     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8672     ok(!lstrcmpA(buf, "name"), "Expected \"name\", got \"%s\"\n", buf);
8673     ok(sz == 4, "Expected 4, got %d\n", sz);
8674 
8675     res = RegSetValueExA(prodkey, "AssignmentType", 0, REG_SZ, (LPBYTE)"type", 5);
8676     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8677 
8678     /* FIXME */
8679 
8680     /* AssignmentType value exists */
8681     sz = MAX_PATH;
8682     lstrcpyA(buf, "apple");
8683     r = pMsiGetProductInfoExA(prodcode, NULL,
8684                               MSIINSTALLCONTEXT_MACHINE,
8685                               INSTALLPROPERTY_ASSIGNMENTTYPEA, buf, &sz);
8686     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8687     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
8688     ok(sz == 0, "Expected 0, got %d\n", sz);
8689 
8690     res = RegSetValueExA(prodkey, "PackageCode", 0, REG_SZ, (LPBYTE)"code", 5);
8691     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8692 
8693     /* FIXME */
8694 
8695     /* PackageCode value exists */
8696     sz = MAX_PATH;
8697     lstrcpyA(buf, "apple");
8698     r = pMsiGetProductInfoExA(prodcode, NULL,
8699                               MSIINSTALLCONTEXT_MACHINE,
8700                               INSTALLPROPERTY_PACKAGECODEA, buf, &sz);
8701     todo_wine
8702     {
8703         ok(r == ERROR_BAD_CONFIGURATION,
8704            "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
8705         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8706         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8707     }
8708 
8709     res = RegSetValueExA(prodkey, "Version", 0, REG_SZ, (LPBYTE)"ver", 4);
8710     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8711 
8712     /* Version value exists */
8713     sz = MAX_PATH;
8714     lstrcpyA(buf, "apple");
8715     r = pMsiGetProductInfoExA(prodcode, NULL,
8716                               MSIINSTALLCONTEXT_MACHINE,
8717                               INSTALLPROPERTY_VERSIONA, buf, &sz);
8718     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8719     ok(!lstrcmpA(buf, "ver"), "Expected \"ver\", got \"%s\"\n", buf);
8720     ok(sz == 3, "Expected 3, got %d\n", sz);
8721 
8722     res = RegSetValueExA(prodkey, "ProductIcon", 0, REG_SZ, (LPBYTE)"icon", 5);
8723     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8724 
8725     /* ProductIcon value exists */
8726     sz = MAX_PATH;
8727     lstrcpyA(buf, "apple");
8728     r = pMsiGetProductInfoExA(prodcode, NULL,
8729                               MSIINSTALLCONTEXT_MACHINE,
8730                               INSTALLPROPERTY_PRODUCTICONA, buf, &sz);
8731     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8732     ok(!lstrcmpA(buf, "icon"), "Expected \"icon\", got \"%s\"\n", buf);
8733     ok(sz == 4, "Expected 4, got %d\n", sz);
8734 
8735     res = RegSetValueExA(prodkey, "PackageName", 0, REG_SZ, (LPBYTE)"name", 5);
8736     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8737 
8738     /* PackageName value exists */
8739     sz = MAX_PATH;
8740     lstrcpyA(buf, "apple");
8741     r = pMsiGetProductInfoExA(prodcode, NULL,
8742                               MSIINSTALLCONTEXT_MACHINE,
8743                               INSTALLPROPERTY_PACKAGENAMEA, buf, &sz);
8744     todo_wine
8745     {
8746         ok(r == ERROR_UNKNOWN_PRODUCT,
8747            "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
8748         ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
8749         ok(sz == MAX_PATH, "Expected MAX_PATH, got %d\n", sz);
8750     }
8751 
8752     res = RegSetValueExA(prodkey, "AuthorizedLUAApp", 0, REG_SZ, (LPBYTE)"auth", 5);
8753     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8754 
8755     /* AuthorizedLUAApp value exists */
8756     sz = MAX_PATH;
8757     lstrcpyA(buf, "apple");
8758     r = pMsiGetProductInfoExA(prodcode, NULL,
8759                               MSIINSTALLCONTEXT_MACHINE,
8760                               INSTALLPROPERTY_AUTHORIZED_LUA_APPA, buf, &sz);
8761     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8762     ok(!lstrcmpA(buf, "auth"), "Expected \"auth\", got \"%s\"\n", buf);
8763     ok(sz == 4, "Expected 4, got %d\n", sz);
8764 
8765     RegDeleteValueA(prodkey, "AuthorizedLUAApp");
8766     RegDeleteValueA(prodkey, "PackageName");
8767     RegDeleteValueA(prodkey, "ProductIcon");
8768     RegDeleteValueA(prodkey, "Version");
8769     RegDeleteValueA(prodkey, "PackageCode");
8770     RegDeleteValueA(prodkey, "AssignmentType");
8771     RegDeleteValueA(prodkey, "ProductName");
8772     RegDeleteValueA(prodkey, "Language");
8773     RegDeleteValueA(prodkey, "Transforms");
8774     RegDeleteValueA(prodkey, "RegOwner");
8775     RegDeleteValueA(prodkey, "RegCompany");
8776     RegDeleteValueA(prodkey, "ProductID");
8777     RegDeleteValueA(prodkey, "DisplayVersion");
8778     RegDeleteValueA(prodkey, "VersionMajor");
8779     RegDeleteValueA(prodkey, "VersionMinor");
8780     RegDeleteValueA(prodkey, "URLUpdateInfo");
8781     RegDeleteValueA(prodkey, "URLInfoAbout");
8782     RegDeleteValueA(prodkey, "Publisher");
8783     RegDeleteValueA(prodkey, "LocalPackage");
8784     RegDeleteValueA(prodkey, "InstallSource");
8785     RegDeleteValueA(prodkey, "InstallLocation");
8786     RegDeleteValueA(prodkey, "DisplayName");
8787     RegDeleteValueA(prodkey, "InstallDate");
8788     RegDeleteValueA(prodkey, "HelpTelephone");
8789     RegDeleteValueA(prodkey, "HelpLink");
8790     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
8791     RegCloseKey(prodkey);
8792     LocalFree(usersid);
8793 }
8794 
8795 #define INIT_USERINFO() \
8796     lstrcpyA(user, "apple"); \
8797     lstrcpyA(org, "orange"); \
8798     lstrcpyA(serial, "banana"); \
8799     usersz = orgsz = serialsz = MAX_PATH;
8800 
8801 static void test_MsiGetUserInfo(void)
8802 {
8803     USERINFOSTATE state;
8804     CHAR user[MAX_PATH];
8805     CHAR org[MAX_PATH];
8806     CHAR serial[MAX_PATH];
8807     DWORD usersz, orgsz, serialsz;
8808     CHAR keypath[MAX_PATH * 2];
8809     CHAR prodcode[MAX_PATH];
8810     CHAR prod_squashed[MAX_PATH];
8811     HKEY prodkey, userprod, props;
8812     LPSTR usersid;
8813     LONG res;
8814     REGSAM access = KEY_ALL_ACCESS;
8815 
8816     create_test_guid(prodcode, prod_squashed);
8817     usersid = get_user_sid();
8818 
8819     if (is_wow64)
8820         access |= KEY_WOW64_64KEY;
8821 
8822     /* NULL szProduct */
8823     INIT_USERINFO();
8824     state = MsiGetUserInfoA(NULL, user, &usersz, org, &orgsz, serial, &serialsz);
8825     ok(state == USERINFOSTATE_INVALIDARG,
8826        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8827     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8828     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8829     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8830     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8831     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8832     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8833 
8834     /* empty szProductCode */
8835     INIT_USERINFO();
8836     state = MsiGetUserInfoA("", user, &usersz, org, &orgsz, serial, &serialsz);
8837     ok(state == USERINFOSTATE_INVALIDARG,
8838        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8839     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8840     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8841     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8842     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8843     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8844     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8845 
8846     /* garbage szProductCode */
8847     INIT_USERINFO();
8848     state = MsiGetUserInfoA("garbage", user, &usersz, org, &orgsz, serial, &serialsz);
8849     ok(state == USERINFOSTATE_INVALIDARG,
8850        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8851     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8852     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8853     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8854     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8855     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8856     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8857 
8858     /* guid without brackets */
8859     INIT_USERINFO();
8860     state = MsiGetUserInfoA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
8861                             user, &usersz, org, &orgsz, serial, &serialsz);
8862     ok(state == USERINFOSTATE_INVALIDARG,
8863        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8864     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8865     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8866     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8867     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8868     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8869     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8870 
8871     /* guid with brackets */
8872     INIT_USERINFO();
8873     state = MsiGetUserInfoA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
8874                             user, &usersz, org, &orgsz, serial, &serialsz);
8875     ok(state == USERINFOSTATE_UNKNOWN,
8876        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8877     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8878     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8879     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8880     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8881     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8882     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8883 
8884     /* NULL lpUserNameBuf */
8885     INIT_USERINFO();
8886     state = MsiGetUserInfoA(prodcode, NULL, &usersz, org, &orgsz, serial, &serialsz);
8887     ok(state == USERINFOSTATE_UNKNOWN,
8888        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8889     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8890     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8891     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8892     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8893     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8894 
8895     /* NULL pcchUserNameBuf */
8896     INIT_USERINFO();
8897     state = MsiGetUserInfoA(prodcode, user, NULL, org, &orgsz, serial, &serialsz);
8898     ok(state == USERINFOSTATE_INVALIDARG,
8899        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8900     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8901     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8902     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8903     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8904     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8905 
8906     /* both lpUserNameBuf and pcchUserNameBuf NULL */
8907     INIT_USERINFO();
8908     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
8909     ok(state == USERINFOSTATE_UNKNOWN,
8910        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8911     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8912     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8913     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8914     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8915 
8916     /* NULL lpOrgNameBuf */
8917     INIT_USERINFO();
8918     state = MsiGetUserInfoA(prodcode, user, &usersz, NULL, &orgsz, serial, &serialsz);
8919     ok(state == USERINFOSTATE_UNKNOWN,
8920        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8921     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8922     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8923     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8924     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8925     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8926 
8927     /* NULL pcchOrgNameBuf */
8928     INIT_USERINFO();
8929     state = MsiGetUserInfoA(prodcode, user, &usersz, org, NULL, serial, &serialsz);
8930     ok(state == USERINFOSTATE_INVALIDARG,
8931        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8932     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8933     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8934     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8935     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8936     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8937 
8938     /* both lpOrgNameBuf and pcchOrgNameBuf NULL */
8939     INIT_USERINFO();
8940     state = MsiGetUserInfoA(prodcode, user, &usersz, NULL, NULL, serial, &serialsz);
8941     ok(state == USERINFOSTATE_UNKNOWN,
8942        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8943     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8944     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8945     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8946     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8947 
8948     /* NULL lpSerialBuf */
8949     INIT_USERINFO();
8950     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, NULL, &serialsz);
8951     ok(state == USERINFOSTATE_UNKNOWN,
8952        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8953     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8954     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8955     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8956     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8957     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
8958 
8959     /* NULL pcchSerialBuf */
8960     INIT_USERINFO();
8961     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, NULL);
8962     ok(state == USERINFOSTATE_INVALIDARG,
8963        "Expected USERINFOSTATE_INVALIDARG, got %d\n", state);
8964     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8965     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8966     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
8967     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8968     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8969 
8970     /* both lpSerialBuf and pcchSerialBuf NULL */
8971     INIT_USERINFO();
8972     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, NULL, NULL);
8973     ok(state == USERINFOSTATE_UNKNOWN,
8974        "Expected USERINFOSTATE_UNKNOWN, got %d\n", state);
8975     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
8976     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
8977     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
8978     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
8979 
8980     /* MSIINSTALLCONTEXT_USERMANAGED */
8981 
8982     /* create local system product key */
8983     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
8984     lstrcatA(keypath, usersid);
8985     lstrcatA(keypath, "\\Installer\\Products\\");
8986     lstrcatA(keypath, prod_squashed);
8987 
8988     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8989     if (res == ERROR_ACCESS_DENIED)
8990     {
8991         skip("Not enough rights to perform tests\n");
8992         LocalFree(usersid);
8993         return;
8994     }
8995     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8996 
8997     /* managed product key exists */
8998     INIT_USERINFO();
8999     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9000     ok(state == USERINFOSTATE_ABSENT,
9001        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9002     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9003     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
9004     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9005     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
9006     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
9007     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
9008 
9009     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9010     lstrcatA(keypath, "Installer\\UserData\\");
9011     lstrcatA(keypath, usersid);
9012     lstrcatA(keypath, "\\Products\\");
9013     lstrcatA(keypath, prod_squashed);
9014 
9015     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL);
9016     if (res == ERROR_ACCESS_DENIED)
9017     {
9018         skip("Not enough rights to perform tests\n");
9019         LocalFree(usersid);
9020         return;
9021     }
9022     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9023 
9024     res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9025     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9026 
9027     /* InstallProperties key exists */
9028     INIT_USERINFO();
9029     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9030     ok(state == USERINFOSTATE_ABSENT,
9031        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9032     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9033     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
9034     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9035     ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", usersz);
9036     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
9037     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
9038 
9039     /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */
9040     INIT_USERINFO();
9041     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
9042     ok(state == USERINFOSTATE_ABSENT,
9043        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9044     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
9045     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9046     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
9047     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9048 
9049     /* RegOwner, RegCompany don't exist, out params are NULL */
9050     INIT_USERINFO();
9051     state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz);
9052     ok(state == USERINFOSTATE_ABSENT,
9053        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9054     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9055     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9056 
9057     res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
9058     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9059 
9060     /* RegOwner value exists */
9061     INIT_USERINFO();
9062     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9063     ok(state == USERINFOSTATE_ABSENT,
9064        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9065     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9066     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
9067     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9068     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9069     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
9070     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9071 
9072     res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8);
9073     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9074 
9075     /* RegCompany value exists */
9076     INIT_USERINFO();
9077     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9078     ok(state == USERINFOSTATE_ABSENT,
9079        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9080     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9081     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9082     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9083     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9084     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
9085     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9086 
9087     res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3);
9088     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9089 
9090     /* ProductID value exists */
9091     INIT_USERINFO();
9092     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9093     ok(state == USERINFOSTATE_PRESENT,
9094        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
9095     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9096     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9097     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
9098     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9099     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
9100     ok(serialsz == 2, "Expected 2, got %d\n", serialsz);
9101 
9102     /* pcchUserNameBuf is too small */
9103     INIT_USERINFO();
9104     usersz = 0;
9105     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9106     ok(state == USERINFOSTATE_MOREDATA,
9107        "Expected USERINFOSTATE_MOREDATA, got %d\n", state);
9108     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9109     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
9110     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9111     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9112     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
9113     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
9114 
9115     /* pcchUserNameBuf has no room for NULL terminator */
9116     INIT_USERINFO();
9117     usersz = 5;
9118     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9119     ok(state == USERINFOSTATE_MOREDATA,
9120        "Expected USERINFOSTATE_MOREDATA, got %d\n", state);
9121     todo_wine
9122     {
9123         ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9124     }
9125     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
9126     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9127     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9128     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
9129     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
9130 
9131     /* pcchUserNameBuf is too small, lpUserNameBuf is NULL */
9132     INIT_USERINFO();
9133     usersz = 0;
9134     state = MsiGetUserInfoA(prodcode, NULL, &usersz, org, &orgsz, serial, &serialsz);
9135     ok(state == USERINFOSTATE_PRESENT,
9136        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
9137     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9138     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9139     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
9140     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9141     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
9142     ok(serialsz == 2, "Expected 2, got %d\n", serialsz);
9143 
9144     RegDeleteValueA(props, "ProductID");
9145     RegDeleteValueA(props, "RegCompany");
9146     RegDeleteValueA(props, "RegOwner");
9147     delete_key(props, "", access & KEY_WOW64_64KEY);
9148     RegCloseKey(props);
9149     delete_key(userprod, "", access & KEY_WOW64_64KEY);
9150     RegCloseKey(userprod);
9151     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
9152     RegCloseKey(prodkey);
9153 
9154     /* MSIINSTALLCONTEXT_USERUNMANAGED */
9155 
9156     /* create local system product key */
9157     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
9158     lstrcatA(keypath, prod_squashed);
9159 
9160     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
9161     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9162 
9163     /* product key exists */
9164     INIT_USERINFO();
9165     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9166     ok(state == USERINFOSTATE_ABSENT,
9167        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9168     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9169     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
9170     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9171     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
9172     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
9173     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
9174 
9175     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9176     lstrcatA(keypath, "Installer\\UserData\\");
9177     lstrcatA(keypath, usersid);
9178     lstrcatA(keypath, "\\Products\\");
9179     lstrcatA(keypath, prod_squashed);
9180 
9181     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL);
9182     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9183 
9184     res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9185     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9186 
9187     /* InstallProperties key exists */
9188     INIT_USERINFO();
9189     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9190     ok(state == USERINFOSTATE_ABSENT,
9191        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9192     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9193     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
9194     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9195     ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", usersz);
9196     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
9197     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
9198 
9199     /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */
9200     INIT_USERINFO();
9201     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
9202     ok(state == USERINFOSTATE_ABSENT,
9203        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9204     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
9205     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9206     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
9207     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9208 
9209     /* RegOwner, RegCompany don't exist, out params are NULL */
9210     INIT_USERINFO();
9211     state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz);
9212     ok(state == USERINFOSTATE_ABSENT,
9213        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9214     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9215     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9216 
9217     res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
9218     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9219 
9220     /* RegOwner value exists */
9221     INIT_USERINFO();
9222     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9223     ok(state == USERINFOSTATE_ABSENT,
9224        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9225     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9226     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
9227     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9228     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9229     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
9230     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9231 
9232     res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8);
9233     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9234 
9235     /* RegCompany value exists */
9236     INIT_USERINFO();
9237     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9238     ok(state == USERINFOSTATE_ABSENT,
9239        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9240     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9241     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9242     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9243     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9244     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
9245     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9246 
9247     res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3);
9248     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9249 
9250     /* ProductID value exists */
9251     INIT_USERINFO();
9252     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9253     ok(state == USERINFOSTATE_PRESENT,
9254        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
9255     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9256     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9257     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
9258     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9259     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
9260     ok(serialsz == 2, "Expected 2, got %d\n", serialsz);
9261 
9262     RegDeleteValueA(props, "ProductID");
9263     RegDeleteValueA(props, "RegCompany");
9264     RegDeleteValueA(props, "RegOwner");
9265     delete_key(props, "", access & KEY_WOW64_64KEY);
9266     RegCloseKey(props);
9267     delete_key(userprod, "", access & KEY_WOW64_64KEY);
9268     RegCloseKey(userprod);
9269     RegDeleteKeyA(prodkey, "");
9270     RegCloseKey(prodkey);
9271 
9272     /* MSIINSTALLCONTEXT_MACHINE */
9273 
9274     /* create local system product key */
9275     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
9276     lstrcatA(keypath, prod_squashed);
9277 
9278     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
9279     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9280 
9281     /* product key exists */
9282     INIT_USERINFO();
9283     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9284     ok(state == USERINFOSTATE_ABSENT,
9285        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9286     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9287     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
9288     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9289     ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz);
9290     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
9291     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
9292 
9293     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9294     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18");
9295     lstrcatA(keypath, "\\Products\\");
9296     lstrcatA(keypath, prod_squashed);
9297 
9298     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL);
9299     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9300 
9301     res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9302     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9303 
9304     /* InstallProperties key exists */
9305     INIT_USERINFO();
9306     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9307     ok(state == USERINFOSTATE_ABSENT,
9308        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9309     ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user);
9310     ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org);
9311     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9312     ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", usersz);
9313     ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz);
9314     ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz);
9315 
9316     /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */
9317     INIT_USERINFO();
9318     state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz);
9319     ok(state == USERINFOSTATE_ABSENT,
9320        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9321     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
9322     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9323     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
9324     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9325 
9326     /* RegOwner, RegCompany don't exist, out params are NULL */
9327     INIT_USERINFO();
9328     state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz);
9329     ok(state == USERINFOSTATE_ABSENT,
9330        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9331     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9332     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9333 
9334     res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6);
9335     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9336 
9337     /* RegOwner value exists */
9338     INIT_USERINFO();
9339     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9340     ok(state == USERINFOSTATE_ABSENT,
9341        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9342     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9343     ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org);
9344     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9345     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9346     ok(orgsz == 0, "Expected 0, got %d\n", orgsz);
9347     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9348 
9349     res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8);
9350     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9351 
9352     /* RegCompany value exists */
9353     INIT_USERINFO();
9354     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9355     ok(state == USERINFOSTATE_ABSENT,
9356        "Expected USERINFOSTATE_ABSENT, got %d\n", state);
9357     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9358     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9359     ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial);
9360     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9361     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
9362     ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz);
9363 
9364     res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3);
9365     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9366 
9367     /* ProductID value exists */
9368     INIT_USERINFO();
9369     state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz);
9370     ok(state == USERINFOSTATE_PRESENT,
9371        "Expected USERINFOSTATE_PRESENT, got %d\n", state);
9372     ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user);
9373     ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org);
9374     ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial);
9375     ok(usersz == 5, "Expected 5, got %d\n", usersz);
9376     ok(orgsz == 7, "Expected 7, got %d\n", orgsz);
9377     ok(serialsz == 2, "Expected 2, got %d\n", serialsz);
9378 
9379     RegDeleteValueA(props, "ProductID");
9380     RegDeleteValueA(props, "RegCompany");
9381     RegDeleteValueA(props, "RegOwner");
9382     delete_key(props, "", access & KEY_WOW64_64KEY);
9383     RegCloseKey(props);
9384     delete_key(userprod, "", access & KEY_WOW64_64KEY);
9385     RegCloseKey(userprod);
9386     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
9387     RegCloseKey(prodkey);
9388     LocalFree(usersid);
9389 }
9390 
9391 static void test_MsiOpenProduct(void)
9392 {
9393     MSIHANDLE hprod, hdb;
9394     CHAR val[MAX_PATH];
9395     CHAR path[MAX_PATH];
9396     CHAR keypath[MAX_PATH*2];
9397     CHAR prodcode[MAX_PATH];
9398     CHAR prod_squashed[MAX_PATH];
9399     HKEY prodkey, userkey, props;
9400     LPSTR usersid;
9401     DWORD size;
9402     LONG res;
9403     UINT r;
9404     REGSAM access = KEY_ALL_ACCESS;
9405 
9406     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
9407 
9408     GetCurrentDirectoryA(MAX_PATH, path);
9409     lstrcatA(path, "\\");
9410 
9411     create_test_guid(prodcode, prod_squashed);
9412     usersid = get_user_sid();
9413 
9414     if (is_wow64)
9415         access |= KEY_WOW64_64KEY;
9416 
9417     hdb = create_package_db(prodcode);
9418     MsiCloseHandle(hdb);
9419 
9420     /* NULL szProduct */
9421     hprod = 0xdeadbeef;
9422     r = MsiOpenProductA(NULL, &hprod);
9423     ok(r == ERROR_INVALID_PARAMETER,
9424        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9425     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9426 
9427     /* empty szProduct */
9428     hprod = 0xdeadbeef;
9429     r = MsiOpenProductA("", &hprod);
9430     ok(r == ERROR_INVALID_PARAMETER,
9431        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9432     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9433 
9434     /* garbage szProduct */
9435     hprod = 0xdeadbeef;
9436     r = MsiOpenProductA("garbage", &hprod);
9437     ok(r == ERROR_INVALID_PARAMETER,
9438        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9439     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9440 
9441     /* guid without brackets */
9442     hprod = 0xdeadbeef;
9443     r = MsiOpenProductA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", &hprod);
9444     ok(r == ERROR_INVALID_PARAMETER,
9445        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9446     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9447 
9448     /* guid with brackets */
9449     hprod = 0xdeadbeef;
9450     r = MsiOpenProductA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", &hprod);
9451     ok(r == ERROR_UNKNOWN_PRODUCT,
9452        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9453     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9454 
9455     /* same length as guid, but random */
9456     hprod = 0xdeadbeef;
9457     r = MsiOpenProductA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", &hprod);
9458     ok(r == ERROR_INVALID_PARAMETER,
9459        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9460     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9461 
9462     /* hProduct is NULL */
9463     hprod = 0xdeadbeef;
9464     r = MsiOpenProductA(prodcode, NULL);
9465     ok(r == ERROR_INVALID_PARAMETER,
9466        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9467     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9468 
9469     /* MSIINSTALLCONTEXT_USERMANAGED */
9470 
9471     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9472     lstrcatA(keypath, "Installer\\Managed\\");
9473     lstrcatA(keypath, usersid);
9474     lstrcatA(keypath, "\\Installer\\Products\\");
9475     lstrcatA(keypath, prod_squashed);
9476 
9477     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
9478     if (res == ERROR_ACCESS_DENIED)
9479     {
9480         skip("Not enough rights to perform tests\n");
9481         LocalFree(usersid);
9482         return;
9483     }
9484     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9485 
9486     /* managed product key exists */
9487     hprod = 0xdeadbeef;
9488     r = MsiOpenProductA(prodcode, &hprod);
9489     ok(r == ERROR_UNKNOWN_PRODUCT,
9490        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9491     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9492 
9493     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9494     lstrcatA(keypath, "Installer\\UserData\\");
9495     lstrcatA(keypath, usersid);
9496     lstrcatA(keypath, "\\Products\\");
9497     lstrcatA(keypath, prod_squashed);
9498 
9499     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
9500     if (res == ERROR_ACCESS_DENIED)
9501     {
9502         skip("Not enough rights to perform tests\n");
9503         LocalFree(usersid);
9504         return;
9505     }
9506     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9507 
9508     /* user product key exists */
9509     hprod = 0xdeadbeef;
9510     r = MsiOpenProductA(prodcode, &hprod);
9511     ok(r == ERROR_UNKNOWN_PRODUCT,
9512        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9513     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9514 
9515     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9516     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9517 
9518     /* InstallProperties key exists */
9519     hprod = 0xdeadbeef;
9520     r = MsiOpenProductA(prodcode, &hprod);
9521     ok(r == ERROR_UNKNOWN_PRODUCT,
9522        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9523     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9524 
9525     lstrcpyA(val, path);
9526     lstrcatA(val, "\\winetest.msi");
9527     res = RegSetValueExA(props, "ManagedLocalPackage", 0, REG_SZ,
9528                          (const BYTE *)val, lstrlenA(val) + 1);
9529     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9530 
9531     /* ManagedLocalPackage value exists */
9532     hprod = 0xdeadbeef;
9533     r = MsiOpenProductA(prodcode, &hprod);
9534     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9535     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
9536 
9537     size = MAX_PATH;
9538     r = MsiGetPropertyA(hprod, "ProductCode", val, &size);
9539     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9540     ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val);
9541     ok(size == lstrlenA(prodcode), "Expected %d, got %d\n", lstrlenA(prodcode), size);
9542 
9543     MsiCloseHandle(hprod);
9544 
9545     RegDeleteValueA(props, "ManagedLocalPackage");
9546     delete_key(props, "", access & KEY_WOW64_64KEY);
9547     RegCloseKey(props);
9548     delete_key(userkey, "", access & KEY_WOW64_64KEY);
9549     RegCloseKey(userkey);
9550     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
9551     RegCloseKey(prodkey);
9552 
9553     /* MSIINSTALLCONTEXT_USERUNMANAGED */
9554 
9555     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
9556     lstrcatA(keypath, prod_squashed);
9557 
9558     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
9559     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9560 
9561     /* unmanaged product key exists */
9562     hprod = 0xdeadbeef;
9563     r = MsiOpenProductA(prodcode, &hprod);
9564     ok(r == ERROR_UNKNOWN_PRODUCT,
9565        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9566     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9567 
9568     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9569     lstrcatA(keypath, "Installer\\UserData\\");
9570     lstrcatA(keypath, usersid);
9571     lstrcatA(keypath, "\\Products\\");
9572     lstrcatA(keypath, prod_squashed);
9573 
9574     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
9575     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9576 
9577     /* user product key exists */
9578     hprod = 0xdeadbeef;
9579     r = MsiOpenProductA(prodcode, &hprod);
9580     ok(r == ERROR_UNKNOWN_PRODUCT,
9581        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9582     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9583 
9584     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9585     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9586 
9587     /* InstallProperties key exists */
9588     hprod = 0xdeadbeef;
9589     r = MsiOpenProductA(prodcode, &hprod);
9590     ok(r == ERROR_UNKNOWN_PRODUCT,
9591        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9592     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9593 
9594     lstrcpyA(val, path);
9595     lstrcatA(val, "\\winetest.msi");
9596     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
9597                          (const BYTE *)val, lstrlenA(val) + 1);
9598     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9599 
9600     /* LocalPackage value exists */
9601     hprod = 0xdeadbeef;
9602     r = MsiOpenProductA(prodcode, &hprod);
9603     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9604     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
9605 
9606     size = MAX_PATH;
9607     r = MsiGetPropertyA(hprod, "ProductCode", val, &size);
9608     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9609     ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val);
9610     ok(size == lstrlenA(prodcode), "Expected %d, got %d\n", lstrlenA(prodcode), size);
9611 
9612     MsiCloseHandle(hprod);
9613 
9614     RegDeleteValueA(props, "LocalPackage");
9615     delete_key(props, "", access & KEY_WOW64_64KEY);
9616     RegCloseKey(props);
9617     delete_key(userkey, "", access & KEY_WOW64_64KEY);
9618     RegCloseKey(userkey);
9619     RegDeleteKeyA(prodkey, "");
9620     RegCloseKey(prodkey);
9621 
9622     /* MSIINSTALLCONTEXT_MACHINE */
9623 
9624     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
9625     lstrcatA(keypath, prod_squashed);
9626 
9627     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
9628     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9629 
9630     /* managed product key exists */
9631     hprod = 0xdeadbeef;
9632     r = MsiOpenProductA(prodcode, &hprod);
9633     ok(r == ERROR_UNKNOWN_PRODUCT,
9634        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9635     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9636 
9637     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9638     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
9639     lstrcatA(keypath, prod_squashed);
9640 
9641     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
9642     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9643 
9644     /* user product key exists */
9645     hprod = 0xdeadbeef;
9646     r = MsiOpenProductA(prodcode, &hprod);
9647     ok(r == ERROR_UNKNOWN_PRODUCT,
9648        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9649     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9650 
9651     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
9652     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9653 
9654     /* InstallProperties key exists */
9655     hprod = 0xdeadbeef;
9656     r = MsiOpenProductA(prodcode, &hprod);
9657     ok(r == ERROR_UNKNOWN_PRODUCT,
9658        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9659     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9660 
9661     lstrcpyA(val, path);
9662     lstrcatA(val, "\\winetest.msi");
9663     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
9664                          (const BYTE *)val, lstrlenA(val) + 1);
9665     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9666 
9667     /* LocalPackage value exists */
9668     hprod = 0xdeadbeef;
9669     r = MsiOpenProductA(prodcode, &hprod);
9670     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9671     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
9672 
9673     size = MAX_PATH;
9674     r = MsiGetPropertyA(hprod, "ProductCode", val, &size);
9675     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9676     ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val);
9677     ok(size == lstrlenA(prodcode), "Expected %d, got %d\n", lstrlenA(prodcode), size);
9678 
9679     MsiCloseHandle(hprod);
9680 
9681     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
9682                          (const BYTE *)"winetest.msi", 13);
9683     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9684 
9685     lstrcpyA(val, path);
9686     lstrcatA(val, "\\winetest.msi");
9687     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
9688                          (const BYTE *)val, lstrlenA(val) + 1);
9689     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9690 
9691     DeleteFileA(msifile);
9692 
9693     /* local package does not exist */
9694     hprod = 0xdeadbeef;
9695     r = MsiOpenProductA(prodcode, &hprod);
9696     ok(r == ERROR_UNKNOWN_PRODUCT,
9697        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
9698     ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n");
9699 
9700     RegDeleteValueA(props, "LocalPackage");
9701     delete_key(props, "", access & KEY_WOW64_64KEY);
9702     RegCloseKey(props);
9703     delete_key(userkey, "", access & KEY_WOW64_64KEY);
9704     RegCloseKey(userkey);
9705     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
9706     RegCloseKey(prodkey);
9707 
9708     DeleteFileA(msifile);
9709     LocalFree(usersid);
9710 }
9711 
9712 static void test_MsiEnumPatchesEx_usermanaged(LPCSTR usersid, LPCSTR expectedsid)
9713 {
9714     MSIINSTALLCONTEXT context;
9715     CHAR keypath[MAX_PATH], patch[MAX_PATH];
9716     CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
9717     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
9718     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
9719     HKEY prodkey, patches, udprod, udpatch, hpatch;
9720     DWORD size, data;
9721     LONG res;
9722     UINT r;
9723     REGSAM access = KEY_ALL_ACCESS;
9724 
9725     create_test_guid(prodcode, prod_squashed);
9726     create_test_guid(patch, patch_squashed);
9727 
9728     if (is_wow64)
9729         access |= KEY_WOW64_64KEY;
9730 
9731     /* MSIPATCHSTATE_APPLIED */
9732 
9733     lstrcpyA(patchcode, "apple");
9734     lstrcpyA(targetprod, "banana");
9735     context = 0xdeadbeef;
9736     lstrcpyA(targetsid, "kiwi");
9737     size = MAX_PATH;
9738     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9739                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9740                            &context, targetsid, &size);
9741     if (r == ERROR_ACCESS_DENIED)
9742     {
9743         skip("Not enough rights to perform tests\n");
9744         return;
9745     }
9746     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9747     ok(!lstrcmpA(patchcode, "apple"),
9748        "Expected patchcode to be unchanged, got %s\n", patchcode);
9749     ok(!lstrcmpA(targetprod, "banana"),
9750        "Expected targetprod to be unchanged, got %s\n", targetprod);
9751     ok(context == 0xdeadbeef,
9752        "Expected context to be unchanged, got %d\n", context);
9753     ok(!lstrcmpA(targetsid, "kiwi"),
9754        "Expected targetsid to be unchanged, got %s\n", targetsid);
9755     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9756 
9757     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
9758     lstrcatA(keypath, expectedsid);
9759     lstrcatA(keypath, "\\Installer\\Products\\");
9760     lstrcatA(keypath, prod_squashed);
9761 
9762     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
9763     if (res == ERROR_ACCESS_DENIED)
9764     {
9765         skip("Not enough rights to perform tests\n");
9766         return;
9767     }
9768     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9769 
9770     /* managed product key exists */
9771     lstrcpyA(patchcode, "apple");
9772     lstrcpyA(targetprod, "banana");
9773     context = 0xdeadbeef;
9774     lstrcpyA(targetsid, "kiwi");
9775     size = MAX_PATH;
9776     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9777                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9778                            &context, targetsid, &size);
9779     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9780     ok(!lstrcmpA(patchcode, "apple"),
9781        "Expected patchcode to be unchanged, got %s\n", patchcode);
9782     ok(!lstrcmpA(targetprod, "banana"),
9783        "Expected targetprod to be unchanged, got %s\n", targetprod);
9784     ok(context == 0xdeadbeef,
9785        "Expected context to be unchanged, got %d\n", context);
9786     ok(!lstrcmpA(targetsid, "kiwi"),
9787        "Expected targetsid to be unchanged, got %s\n", targetsid);
9788     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9789 
9790     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
9791     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9792 
9793     /* patches key exists */
9794     lstrcpyA(patchcode, "apple");
9795     lstrcpyA(targetprod, "banana");
9796     context = 0xdeadbeef;
9797     lstrcpyA(targetsid, "kiwi");
9798     size = MAX_PATH;
9799     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9800                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9801                            &context, targetsid, &size);
9802     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9803     ok(!lstrcmpA(patchcode, "apple"),
9804        "Expected patchcode to be unchanged, got %s\n", patchcode);
9805     ok(!lstrcmpA(targetprod, "banana"),
9806        "Expected targetprod to be unchanged, got %s\n", targetprod);
9807     ok(context == 0xdeadbeef,
9808        "Expected context to be unchanged, got %d\n", context);
9809     ok(!lstrcmpA(targetsid, "kiwi"),
9810        "Expected targetsid to be unchanged, got %s\n", targetsid);
9811     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9812 
9813     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
9814                          (const BYTE *)patch_squashed,
9815                          lstrlenA(patch_squashed) + 1);
9816     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9817 
9818     /* Patches value exists, is not REG_MULTI_SZ */
9819     lstrcpyA(patchcode, "apple");
9820     lstrcpyA(targetprod, "banana");
9821     context = 0xdeadbeef;
9822     lstrcpyA(targetsid, "kiwi");
9823     size = MAX_PATH;
9824     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9825                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9826                            &context, targetsid, &size);
9827     ok(r == ERROR_BAD_CONFIGURATION,
9828        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9829     ok(!lstrcmpA(patchcode, "apple"),
9830        "Expected patchcode to be unchanged, got %s\n", patchcode);
9831     ok(!lstrcmpA(targetprod, "banana"),
9832        "Expected targetprod to be unchanged, got %s\n", targetprod);
9833     ok(context == 0xdeadbeef,
9834        "Expected context to be unchanged, got %d\n", context);
9835     ok(!lstrcmpA(targetsid, "kiwi"),
9836        "Expected targetsid to be unchanged, got %s\n", targetsid);
9837     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9838 
9839     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
9840                          (const BYTE *)"a\0b\0c\0\0", 7);
9841     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9842 
9843     /* Patches value exists, is not a squashed guid */
9844     lstrcpyA(patchcode, "apple");
9845     lstrcpyA(targetprod, "banana");
9846     context = 0xdeadbeef;
9847     lstrcpyA(targetsid, "kiwi");
9848     size = MAX_PATH;
9849     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9850                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9851                            &context, targetsid, &size);
9852     ok(r == ERROR_BAD_CONFIGURATION,
9853        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9854     ok(!lstrcmpA(patchcode, "apple"),
9855        "Expected patchcode to be unchanged, got %s\n", patchcode);
9856     ok(!lstrcmpA(targetprod, "banana"),
9857        "Expected targetprod to be unchanged, got %s\n", targetprod);
9858     ok(context == 0xdeadbeef,
9859        "Expected context to be unchanged, got %d\n", context);
9860     ok(!lstrcmpA(targetsid, "kiwi"),
9861        "Expected targetsid to be unchanged, got %s\n", targetsid);
9862     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9863 
9864     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
9865     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
9866                          (const BYTE *)patch_squashed,
9867                          lstrlenA(patch_squashed) + 2);
9868     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9869 
9870     /* Patches value exists */
9871     lstrcpyA(patchcode, "apple");
9872     lstrcpyA(targetprod, "banana");
9873     context = 0xdeadbeef;
9874     lstrcpyA(targetsid, "kiwi");
9875     size = MAX_PATH;
9876     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9877                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9878                            &context, targetsid, &size);
9879     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9880     ok(!lstrcmpA(patchcode, "apple"),
9881        "Expected patchcode to be unchanged, got %s\n", patchcode);
9882     ok(!lstrcmpA(targetprod, "banana"),
9883        "Expected targetprod to be unchanged, got %s\n", targetprod);
9884     ok(context == 0xdeadbeef,
9885        "Expected context to be unchanged, got %d\n", context);
9886     ok(!lstrcmpA(targetsid, "kiwi"),
9887        "Expected targetsid to be unchanged, got %s\n", targetsid);
9888     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9889 
9890     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
9891                          (const BYTE *)"whatever", 9);
9892     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9893 
9894     /* patch squashed value exists */
9895     lstrcpyA(patchcode, "apple");
9896     lstrcpyA(targetprod, "banana");
9897     context = 0xdeadbeef;
9898     lstrcpyA(targetsid, "kiwi");
9899     size = MAX_PATH;
9900     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9901                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9902                            &context, targetsid, &size);
9903     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9904     ok(!lstrcmpA(patchcode, patch),
9905        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9906     ok(!lstrcmpA(targetprod, prodcode),
9907        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9908     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9909        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9910     ok(!lstrcmpA(targetsid, expectedsid),
9911        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9912     ok(size == lstrlenA(expectedsid),
9913        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9914 
9915     /* increase the index */
9916     lstrcpyA(patchcode, "apple");
9917     lstrcpyA(targetprod, "banana");
9918     context = 0xdeadbeef;
9919     lstrcpyA(targetsid, "kiwi");
9920     size = MAX_PATH;
9921     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9922                            MSIPATCHSTATE_APPLIED, 1, patchcode, targetprod,
9923                            &context, targetsid, &size);
9924     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9925     ok(!lstrcmpA(patchcode, "apple"),
9926        "Expected patchcode to be unchanged, got %s\n", patchcode);
9927     ok(!lstrcmpA(targetprod, "banana"),
9928        "Expected targetprod to be unchanged, got %s\n", targetprod);
9929     ok(context == 0xdeadbeef,
9930        "Expected context to be unchanged, got %d\n", context);
9931     ok(!lstrcmpA(targetsid, "kiwi"),
9932        "Expected targetsid to be unchanged, got %s\n", targetsid);
9933     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9934 
9935     /* increase again */
9936     lstrcpyA(patchcode, "apple");
9937     lstrcpyA(targetprod, "banana");
9938     context = 0xdeadbeef;
9939     lstrcpyA(targetsid, "kiwi");
9940     size = MAX_PATH;
9941     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9942                            MSIPATCHSTATE_APPLIED, 2, patchcode, targetprod,
9943                            &context, targetsid, &size);
9944     ok(r == ERROR_INVALID_PARAMETER,
9945        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9946     ok(!lstrcmpA(patchcode, "apple"),
9947        "Expected patchcode to be unchanged, got %s\n", patchcode);
9948     ok(!lstrcmpA(targetprod, "banana"),
9949        "Expected targetprod to be unchanged, got %s\n", targetprod);
9950     ok(context == 0xdeadbeef,
9951        "Expected context to be unchanged, got %d\n", context);
9952     ok(!lstrcmpA(targetsid, "kiwi"),
9953        "Expected targetsid to be unchanged, got %s\n", targetsid);
9954     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
9955 
9956     /* szPatchCode is NULL */
9957     lstrcpyA(targetprod, "banana");
9958     context = 0xdeadbeef;
9959     lstrcpyA(targetsid, "kiwi");
9960     size = MAX_PATH;
9961     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9962                            MSIPATCHSTATE_APPLIED, 0, NULL, targetprod,
9963                            &context, targetsid, &size);
9964     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9965     ok(!lstrcmpA(targetprod, prodcode),
9966        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9967     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9968        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9969     ok(!lstrcmpA(targetsid, expectedsid),
9970        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9971     ok(size == lstrlenA(expectedsid),
9972        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9973 
9974     /* szTargetProductCode is NULL */
9975     lstrcpyA(patchcode, "apple");
9976     context = 0xdeadbeef;
9977     lstrcpyA(targetsid, "kiwi");
9978     size = MAX_PATH;
9979     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9980                            MSIPATCHSTATE_APPLIED, 0, patchcode, NULL,
9981                            &context, targetsid, &size);
9982     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9983     ok(!lstrcmpA(patchcode, patch),
9984        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9985     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
9986        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
9987     ok(!lstrcmpA(targetsid, expectedsid),
9988        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
9989     ok(size == lstrlenA(expectedsid),
9990        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
9991 
9992     /* pdwTargetProductContext is NULL */
9993     lstrcpyA(patchcode, "apple");
9994     lstrcpyA(targetprod, "banana");
9995     lstrcpyA(targetsid, "kiwi");
9996     size = MAX_PATH;
9997     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
9998                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
9999                            NULL, targetsid, &size);
10000     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10001     ok(!lstrcmpA(patchcode, patch),
10002        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10003     ok(!lstrcmpA(targetprod, prodcode),
10004        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10005     ok(!lstrcmpA(targetsid, expectedsid),
10006        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10007     ok(size == lstrlenA(expectedsid),
10008        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10009 
10010     /* szTargetUserSid is NULL */
10011     lstrcpyA(patchcode, "apple");
10012     lstrcpyA(targetprod, "banana");
10013     context = 0xdeadbeef;
10014     size = MAX_PATH;
10015     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10016                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10017                            &context, NULL, &size);
10018     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10019     ok(!lstrcmpA(patchcode, patch),
10020        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10021     ok(!lstrcmpA(targetprod, prodcode),
10022        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10023     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
10024        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
10025     ok(size == lstrlenA(expectedsid) * sizeof(WCHAR),
10026        "Expected %d*sizeof(WCHAR), got %d\n", lstrlenA(expectedsid), size);
10027 
10028     /* pcchTargetUserSid is exactly the length of szTargetUserSid */
10029     lstrcpyA(patchcode, "apple");
10030     lstrcpyA(targetprod, "banana");
10031     context = 0xdeadbeef;
10032     lstrcpyA(targetsid, "kiwi");
10033     size = lstrlenA(expectedsid);
10034     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10035                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10036                            &context, targetsid, &size);
10037     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
10038     ok(!lstrcmpA(patchcode, patch),
10039        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10040     ok(!lstrcmpA(targetprod, prodcode),
10041        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10042     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
10043        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
10044     ok(!strncmp(targetsid, expectedsid, lstrlenA(expectedsid) - 1),
10045        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10046     ok(size == lstrlenA(expectedsid) * sizeof(WCHAR),
10047        "Expected %d*sizeof(WCHAR), got %d\n", lstrlenA(expectedsid), size);
10048 
10049     /* pcchTargetUserSid has enough room for NULL terminator */
10050     lstrcpyA(patchcode, "apple");
10051     lstrcpyA(targetprod, "banana");
10052     context = 0xdeadbeef;
10053     lstrcpyA(targetsid, "kiwi");
10054     size = lstrlenA(expectedsid) + 1;
10055     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10056                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10057                            &context, targetsid, &size);
10058     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10059     ok(!lstrcmpA(patchcode, patch),
10060        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10061     ok(!lstrcmpA(targetprod, prodcode),
10062        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10063     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
10064        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
10065     ok(!lstrcmpA(targetsid, expectedsid),
10066        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10067     ok(size == lstrlenA(expectedsid),
10068        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10069 
10070     /* both szTargetuserSid and pcchTargetUserSid are NULL */
10071     lstrcpyA(patchcode, "apple");
10072     lstrcpyA(targetprod, "banana");
10073     context = 0xdeadbeef;
10074     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10075                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10076                            &context, NULL, NULL);
10077     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10078     ok(!lstrcmpA(patchcode, patch),
10079        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10080     ok(!lstrcmpA(targetprod, prodcode),
10081        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10082     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
10083        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
10084 
10085     /* MSIPATCHSTATE_SUPERSEDED */
10086 
10087     lstrcpyA(patchcode, "apple");
10088     lstrcpyA(targetprod, "banana");
10089     context = 0xdeadbeef;
10090     lstrcpyA(targetsid, "kiwi");
10091     size = MAX_PATH;
10092     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10093                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10094                            &context, targetsid, &size);
10095     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10096     ok(!lstrcmpA(patchcode, "apple"),
10097        "Expected patchcode to be unchanged, got %s\n", patchcode);
10098     ok(!lstrcmpA(targetprod, "banana"),
10099        "Expected targetprod to be unchanged, got %s\n", targetprod);
10100     ok(context == 0xdeadbeef,
10101        "Expected context to be unchanged, got %d\n", context);
10102     ok(!lstrcmpA(targetsid, "kiwi"),
10103        "Expected targetsid to be unchanged, got %s\n", targetsid);
10104     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10105 
10106     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
10107     lstrcatA(keypath, expectedsid);
10108     lstrcatA(keypath, "\\Products\\");
10109     lstrcatA(keypath, prod_squashed);
10110 
10111     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
10112     if (res == ERROR_ACCESS_DENIED)
10113     {
10114         skip("Not enough rights to perform tests\n");
10115         return;
10116     }
10117     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10118 
10119     /* UserData product key exists */
10120     lstrcpyA(patchcode, "apple");
10121     lstrcpyA(targetprod, "banana");
10122     context = 0xdeadbeef;
10123     lstrcpyA(targetsid, "kiwi");
10124     size = MAX_PATH;
10125     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10126                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10127                            &context, targetsid, &size);
10128     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10129     ok(!lstrcmpA(patchcode, "apple"),
10130        "Expected patchcode to be unchanged, got %s\n", patchcode);
10131     ok(!lstrcmpA(targetprod, "banana"),
10132        "Expected targetprod to be unchanged, got %s\n", targetprod);
10133     ok(context == 0xdeadbeef,
10134        "Expected context to be unchanged, got %d\n", context);
10135     ok(!lstrcmpA(targetsid, "kiwi"),
10136        "Expected targetsid to be unchanged, got %s\n", targetsid);
10137     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10138 
10139     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
10140     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10141 
10142     /* UserData patches key exists */
10143     lstrcpyA(patchcode, "apple");
10144     lstrcpyA(targetprod, "banana");
10145     context = 0xdeadbeef;
10146     lstrcpyA(targetsid, "kiwi");
10147     size = MAX_PATH;
10148     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10149                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10150                            &context, targetsid, &size);
10151     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10152     ok(!lstrcmpA(patchcode, "apple"),
10153        "Expected patchcode to be unchanged, got %s\n", patchcode);
10154     ok(!lstrcmpA(targetprod, "banana"),
10155        "Expected targetprod to be unchanged, got %s\n", targetprod);
10156     ok(context == 0xdeadbeef,
10157        "Expected context to be unchanged, got %d\n", context);
10158     ok(!lstrcmpA(targetsid, "kiwi"),
10159        "Expected targetsid to be unchanged, got %s\n", targetsid);
10160     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10161 
10162     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
10163     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10164 
10165     /* specific UserData patch key exists */
10166     lstrcpyA(patchcode, "apple");
10167     lstrcpyA(targetprod, "banana");
10168     context = 0xdeadbeef;
10169     lstrcpyA(targetsid, "kiwi");
10170     size = MAX_PATH;
10171     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10172                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10173                            &context, targetsid, &size);
10174     ok(r == ERROR_BAD_CONFIGURATION,
10175        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10176     ok(!lstrcmpA(patchcode, "apple"),
10177        "Expected patchcode to be unchanged, got %s\n", patchcode);
10178     ok(!lstrcmpA(targetprod, "banana"),
10179        "Expected targetprod to be unchanged, got %s\n", targetprod);
10180     ok(context == 0xdeadbeef,
10181        "Expected context to be unchanged, got %d\n", context);
10182     ok(!lstrcmpA(targetsid, "kiwi"),
10183        "Expected targetsid to be unchanged, got %s\n", targetsid);
10184     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10185 
10186     data = MSIPATCHSTATE_SUPERSEDED;
10187     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10188                          (const BYTE *)&data, sizeof(DWORD));
10189     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10190 
10191     /* State value exists */
10192     lstrcpyA(patchcode, "apple");
10193     lstrcpyA(targetprod, "banana");
10194     context = 0xdeadbeef;
10195     lstrcpyA(targetsid, "kiwi");
10196     size = MAX_PATH;
10197     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10198                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10199                            &context, targetsid, &size);
10200     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10201     ok(!lstrcmpA(patchcode, patch),
10202        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10203     ok(!lstrcmpA(targetprod, prodcode),
10204        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10205     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
10206        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
10207     ok(!lstrcmpA(targetsid, expectedsid),
10208        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10209     ok(size == lstrlenA(expectedsid),
10210        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10211 
10212     /* MSIPATCHSTATE_OBSOLETED */
10213 
10214     lstrcpyA(patchcode, "apple");
10215     lstrcpyA(targetprod, "banana");
10216     context = 0xdeadbeef;
10217     lstrcpyA(targetsid, "kiwi");
10218     size = MAX_PATH;
10219     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10220                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
10221                            &context, targetsid, &size);
10222     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10223     ok(!lstrcmpA(patchcode, "apple"),
10224        "Expected patchcode to be unchanged, got %s\n", patchcode);
10225     ok(!lstrcmpA(targetprod, "banana"),
10226        "Expected targetprod to be unchanged, got %s\n", targetprod);
10227     ok(context == 0xdeadbeef,
10228        "Expected context to be unchanged, got %d\n", context);
10229     ok(!lstrcmpA(targetsid, "kiwi"),
10230        "Expected targetsid to be unchanged, got %s\n", targetsid);
10231     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10232 
10233     data = MSIPATCHSTATE_OBSOLETED;
10234     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10235                          (const BYTE *)&data, sizeof(DWORD));
10236     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10237 
10238     /* State value is obsoleted */
10239     lstrcpyA(patchcode, "apple");
10240     lstrcpyA(targetprod, "banana");
10241     context = 0xdeadbeef;
10242     lstrcpyA(targetsid, "kiwi");
10243     size = MAX_PATH;
10244     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10245                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
10246                            &context, targetsid, &size);
10247     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10248     ok(!lstrcmpA(patchcode, patch),
10249        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10250     ok(!lstrcmpA(targetprod, prodcode),
10251        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10252     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
10253        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
10254     ok(!lstrcmpA(targetsid, expectedsid),
10255        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10256     ok(size == lstrlenA(expectedsid),
10257        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10258 
10259     /* MSIPATCHSTATE_REGISTERED */
10260     /* FIXME */
10261 
10262     /* MSIPATCHSTATE_ALL */
10263 
10264     /* 1st */
10265     lstrcpyA(patchcode, "apple");
10266     lstrcpyA(targetprod, "banana");
10267     context = 0xdeadbeef;
10268     lstrcpyA(targetsid, "kiwi");
10269     size = MAX_PATH;
10270     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10271                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
10272                            &context, targetsid, &size);
10273     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10274     ok(!lstrcmpA(patchcode, patch),
10275        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10276     ok(!lstrcmpA(targetprod, prodcode),
10277        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10278     ok(context == MSIINSTALLCONTEXT_USERMANAGED,
10279        "Expected MSIINSTALLCONTEXT_USERMANAGED, got %d\n", context);
10280     ok(!lstrcmpA(targetsid, expectedsid),
10281        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10282     ok(size == lstrlenA(expectedsid),
10283        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10284 
10285     /* same patch in multiple places, only one is enumerated */
10286     lstrcpyA(patchcode, "apple");
10287     lstrcpyA(targetprod, "banana");
10288     context = 0xdeadbeef;
10289     lstrcpyA(targetsid, "kiwi");
10290     size = MAX_PATH;
10291     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERMANAGED,
10292                            MSIPATCHSTATE_ALL, 1, patchcode, targetprod,
10293                            &context, targetsid, &size);
10294     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10295     ok(!lstrcmpA(patchcode, "apple"),
10296        "Expected patchcode to be unchanged, got %s\n", patchcode);
10297     ok(!lstrcmpA(targetprod, "banana"),
10298        "Expected targetprod to be unchanged, got %s\n", targetprod);
10299     ok(context == 0xdeadbeef,
10300        "Expected context to be unchanged, got %d\n", context);
10301     ok(!lstrcmpA(targetsid, "kiwi"),
10302        "Expected targetsid to be unchanged, got %s\n", targetsid);
10303     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10304 
10305     RegDeleteValueA(hpatch, "State");
10306     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
10307     RegCloseKey(hpatch);
10308     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
10309     RegCloseKey(udpatch);
10310     delete_key(udprod, "", access & KEY_WOW64_64KEY);
10311     RegCloseKey(udprod);
10312     RegDeleteValueA(patches, "Patches");
10313     delete_key(patches, "", access & KEY_WOW64_64KEY);
10314     RegCloseKey(patches);
10315     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
10316     RegCloseKey(prodkey);
10317 }
10318 
10319 static void test_MsiEnumPatchesEx_userunmanaged(LPCSTR usersid, LPCSTR expectedsid)
10320 {
10321     MSIINSTALLCONTEXT context;
10322     CHAR keypath[MAX_PATH], patch[MAX_PATH];
10323     CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
10324     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
10325     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
10326     HKEY prodkey, patches, udprod, udpatch;
10327     HKEY userkey, hpatch;
10328     DWORD size, data;
10329     LONG res;
10330     UINT r;
10331     REGSAM access = KEY_ALL_ACCESS;
10332 
10333     create_test_guid(prodcode, prod_squashed);
10334     create_test_guid(patch, patch_squashed);
10335 
10336     if (is_wow64)
10337         access |= KEY_WOW64_64KEY;
10338 
10339     /* MSIPATCHSTATE_APPLIED */
10340 
10341     lstrcpyA(patchcode, "apple");
10342     lstrcpyA(targetprod, "banana");
10343     context = 0xdeadbeef;
10344     lstrcpyA(targetsid, "kiwi");
10345     size = MAX_PATH;
10346     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10347                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10348                            &context, targetsid, &size);
10349     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10350     ok(!lstrcmpA(patchcode, "apple"),
10351        "Expected patchcode to be unchanged, got %s\n", patchcode);
10352     ok(!lstrcmpA(targetprod, "banana"),
10353        "Expected targetprod to be unchanged, got %s\n", targetprod);
10354     ok(context == 0xdeadbeef,
10355        "Expected context to be unchanged, got %d\n", context);
10356     ok(!lstrcmpA(targetsid, "kiwi"),
10357        "Expected targetsid to be unchanged, got %s\n", targetsid);
10358     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10359 
10360     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
10361     lstrcatA(keypath, prod_squashed);
10362 
10363     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
10364     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10365 
10366     /* current user product key exists */
10367     lstrcpyA(patchcode, "apple");
10368     lstrcpyA(targetprod, "banana");
10369     context = 0xdeadbeef;
10370     lstrcpyA(targetsid, "kiwi");
10371     size = MAX_PATH;
10372     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10373                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10374                            &context, targetsid, &size);
10375     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10376     ok(!lstrcmpA(patchcode, "apple"),
10377        "Expected patchcode to be unchanged, got %s\n", patchcode);
10378     ok(!lstrcmpA(targetprod, "banana"),
10379        "Expected targetprod to be unchanged, got %s\n", targetprod);
10380     ok(context == 0xdeadbeef,
10381        "Expected context to be unchanged, got %d\n", context);
10382     ok(!lstrcmpA(targetsid, "kiwi"),
10383        "Expected targetsid to be unchanged, got %s\n", targetsid);
10384     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10385 
10386     res = RegCreateKeyA(prodkey, "Patches", &patches);
10387     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10388 
10389     /* Patches key exists */
10390     lstrcpyA(patchcode, "apple");
10391     lstrcpyA(targetprod, "banana");
10392     context = 0xdeadbeef;
10393     lstrcpyA(targetsid, "kiwi");
10394     size = MAX_PATH;
10395     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10396                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10397                            &context, targetsid, &size);
10398     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10399     ok(!lstrcmpA(patchcode, "apple"),
10400        "Expected patchcode to be unchanged, got %s\n", patchcode);
10401     ok(!lstrcmpA(targetprod, "banana"),
10402        "Expected targetprod to be unchanged, got %s\n", targetprod);
10403     ok(context == 0xdeadbeef,
10404        "Expected context to be unchanged, got %d\n", context);
10405     ok(!lstrcmpA(targetsid, "kiwi"),
10406        "Expected targetsid to be unchanged, got %s\n", targetsid);
10407     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10408 
10409     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
10410                          (const BYTE *)patch_squashed,
10411                          lstrlenA(patch_squashed) + 1);
10412     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10413 
10414     /* Patches value exists, is not REG_MULTI_SZ */
10415     lstrcpyA(patchcode, "apple");
10416     lstrcpyA(targetprod, "banana");
10417     context = 0xdeadbeef;
10418     lstrcpyA(targetsid, "kiwi");
10419     size = MAX_PATH;
10420     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10421                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10422                            &context, targetsid, &size);
10423     ok(r == ERROR_BAD_CONFIGURATION,
10424        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10425     ok(!lstrcmpA(patchcode, "apple"),
10426        "Expected patchcode to be unchanged, got %s\n", patchcode);
10427     ok(!lstrcmpA(targetprod, "banana"),
10428        "Expected targetprod to be unchanged, got %s\n", targetprod);
10429     ok(context == 0xdeadbeef,
10430        "Expected context to be unchanged, got %d\n", context);
10431     ok(!lstrcmpA(targetsid, "kiwi"),
10432        "Expected targetsid to be unchanged, got %s\n", targetsid);
10433     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10434 
10435     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10436                          (const BYTE *)"a\0b\0c\0\0", 7);
10437     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10438 
10439     /* Patches value exists, is not a squashed guid */
10440     lstrcpyA(patchcode, "apple");
10441     lstrcpyA(targetprod, "banana");
10442     context = 0xdeadbeef;
10443     lstrcpyA(targetsid, "kiwi");
10444     size = MAX_PATH;
10445     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10446                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10447                            &context, targetsid, &size);
10448     ok(r == ERROR_BAD_CONFIGURATION,
10449        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10450     ok(!lstrcmpA(patchcode, "apple"),
10451        "Expected patchcode to be unchanged, got %s\n", patchcode);
10452     ok(!lstrcmpA(targetprod, "banana"),
10453        "Expected targetprod to be unchanged, got %s\n", targetprod);
10454     ok(context == 0xdeadbeef,
10455        "Expected context to be unchanged, got %d\n", context);
10456     ok(!lstrcmpA(targetsid, "kiwi"),
10457        "Expected targetsid to be unchanged, got %s\n", targetsid);
10458     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10459 
10460     patch_squashed[lstrlenA(patch_squashed) + 1] = 0;
10461     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10462                          (const BYTE *)patch_squashed,
10463                          lstrlenA(patch_squashed) + 2);
10464     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10465 
10466     /* Patches value exists */
10467     lstrcpyA(patchcode, "apple");
10468     lstrcpyA(targetprod, "banana");
10469     context = 0xdeadbeef;
10470     lstrcpyA(targetsid, "kiwi");
10471     size = MAX_PATH;
10472     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10473                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10474                            &context, targetsid, &size);
10475     ok(r == ERROR_NO_MORE_ITEMS ||
10476        broken(r == ERROR_BAD_CONFIGURATION), /* Windows Installer 3.0 */
10477        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10478     ok(!lstrcmpA(patchcode, "apple"),
10479        "Expected patchcode to be unchanged, got %s\n", patchcode);
10480     ok(!lstrcmpA(targetprod, "banana"),
10481        "Expected targetprod to be unchanged, got %s\n", targetprod);
10482     ok(context == 0xdeadbeef,
10483        "Expected context to be unchanged, got %d\n", context);
10484     ok(!lstrcmpA(targetsid, "kiwi"),
10485        "Expected targetsid to be unchanged, got %s\n", targetsid);
10486     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10487 
10488     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
10489                          (const BYTE *)"whatever", 9);
10490     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10491 
10492     /* patch code value exists */
10493     lstrcpyA(patchcode, "apple");
10494     lstrcpyA(targetprod, "banana");
10495     context = 0xdeadbeef;
10496     lstrcpyA(targetsid, "kiwi");
10497     size = MAX_PATH;
10498     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10499                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10500                            &context, targetsid, &size);
10501     ok(r == ERROR_NO_MORE_ITEMS ||
10502        broken(r == ERROR_BAD_CONFIGURATION), /* Windows Installer 3.0 */
10503        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10504     ok(!lstrcmpA(patchcode, "apple"),
10505        "Expected patchcode to be unchanged, got %s\n", patchcode);
10506     ok(!lstrcmpA(targetprod, "banana"),
10507        "Expected targetprod to be unchanged, got %s\n", targetprod);
10508     ok(context == 0xdeadbeef,
10509        "Expected context to be unchanged, got %d\n", context);
10510     ok(!lstrcmpA(targetsid, "kiwi"),
10511        "Expected targetsid to be unchanged, got %s\n", targetsid);
10512     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10513 
10514     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
10515     lstrcatA(keypath, expectedsid);
10516     lstrcatA(keypath, "\\Patches\\");
10517     lstrcatA(keypath, patch_squashed);
10518 
10519     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
10520     if (res == ERROR_ACCESS_DENIED)
10521     {
10522         skip("Not enough rights to perform tests\n");
10523         goto error;
10524     }
10525     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10526 
10527     /* userdata patch key exists */
10528     lstrcpyA(patchcode, "apple");
10529     lstrcpyA(targetprod, "banana");
10530     context = 0xdeadbeef;
10531     lstrcpyA(targetsid, "kiwi");
10532     size = MAX_PATH;
10533     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10534                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10535                            &context, targetsid, &size);
10536     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10537     ok(!lstrcmpA(patchcode, patch),
10538        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10539     ok(!lstrcmpA(targetprod, prodcode),
10540        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10541     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
10542        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
10543     ok(!lstrcmpA(targetsid, expectedsid),
10544        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10545     ok(size == lstrlenA(expectedsid),
10546        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10547 
10548     /* MSIPATCHSTATE_SUPERSEDED */
10549 
10550     lstrcpyA(patchcode, "apple");
10551     lstrcpyA(targetprod, "banana");
10552     context = 0xdeadbeef;
10553     lstrcpyA(targetsid, "kiwi");
10554     size = MAX_PATH;
10555     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10556                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10557                            &context, targetsid, &size);
10558     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10559     ok(!lstrcmpA(patchcode, "apple"),
10560        "Expected patchcode to be unchanged, got %s\n", patchcode);
10561     ok(!lstrcmpA(targetprod, "banana"),
10562        "Expected targetprod to be unchanged, got %s\n", targetprod);
10563     ok(context == 0xdeadbeef,
10564        "Expected context to be unchanged, got %d\n", context);
10565     ok(!lstrcmpA(targetsid, "kiwi"),
10566        "Expected targetsid to be unchanged, got %s\n", targetsid);
10567     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10568 
10569     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
10570     lstrcatA(keypath, expectedsid);
10571     lstrcatA(keypath, "\\Products\\");
10572     lstrcatA(keypath, prod_squashed);
10573 
10574     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
10575     if (res == ERROR_ACCESS_DENIED)
10576     {
10577         skip("Not enough rights to perform tests\n");
10578         goto error;
10579     }
10580     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10581 
10582     /* UserData product key exists */
10583     lstrcpyA(patchcode, "apple");
10584     lstrcpyA(targetprod, "banana");
10585     context = 0xdeadbeef;
10586     lstrcpyA(targetsid, "kiwi");
10587     size = MAX_PATH;
10588     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10589                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10590                            &context, targetsid, &size);
10591     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10592     ok(!lstrcmpA(patchcode, "apple"),
10593        "Expected patchcode to be unchanged, got %s\n", patchcode);
10594     ok(!lstrcmpA(targetprod, "banana"),
10595        "Expected targetprod to be unchanged, got %s\n", targetprod);
10596     ok(context == 0xdeadbeef,
10597        "Expected context to be unchanged, got %d\n", context);
10598     ok(!lstrcmpA(targetsid, "kiwi"),
10599        "Expected targetsid to be unchanged, got %s\n", targetsid);
10600     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10601 
10602     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
10603     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10604 
10605     /* UserData patches key exists */
10606     lstrcpyA(patchcode, "apple");
10607     lstrcpyA(targetprod, "banana");
10608     context = 0xdeadbeef;
10609     lstrcpyA(targetsid, "kiwi");
10610     size = MAX_PATH;
10611     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10612                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10613                            &context, targetsid, &size);
10614     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10615     ok(!lstrcmpA(patchcode, "apple"),
10616        "Expected patchcode to be unchanged, got %s\n", patchcode);
10617     ok(!lstrcmpA(targetprod, "banana"),
10618        "Expected targetprod to be unchanged, got %s\n", targetprod);
10619     ok(context == 0xdeadbeef,
10620        "Expected context to be unchanged, got %d\n", context);
10621     ok(!lstrcmpA(targetsid, "kiwi"),
10622        "Expected targetsid to be unchanged, got %s\n", targetsid);
10623     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10624 
10625     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
10626     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10627 
10628     /* specific UserData patch key exists */
10629     lstrcpyA(patchcode, "apple");
10630     lstrcpyA(targetprod, "banana");
10631     context = 0xdeadbeef;
10632     lstrcpyA(targetsid, "kiwi");
10633     size = MAX_PATH;
10634     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10635                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10636                            &context, targetsid, &size);
10637     ok(r == ERROR_BAD_CONFIGURATION,
10638        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10639     ok(!lstrcmpA(patchcode, "apple"),
10640        "Expected patchcode to be unchanged, got %s\n", patchcode);
10641     ok(!lstrcmpA(targetprod, "banana"),
10642        "Expected targetprod to be unchanged, got %s\n", targetprod);
10643     ok(context == 0xdeadbeef,
10644        "Expected context to be unchanged, got %d\n", context);
10645     ok(!lstrcmpA(targetsid, "kiwi"),
10646        "Expected targetsid to be unchanged, got %s\n", targetsid);
10647     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10648 
10649     data = MSIPATCHSTATE_SUPERSEDED;
10650     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10651                          (const BYTE *)&data, sizeof(DWORD));
10652     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10653 
10654     /* State value exists */
10655     lstrcpyA(patchcode, "apple");
10656     lstrcpyA(targetprod, "banana");
10657     context = 0xdeadbeef;
10658     lstrcpyA(targetsid, "kiwi");
10659     size = MAX_PATH;
10660     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10661                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
10662                            &context, targetsid, &size);
10663     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10664     ok(!lstrcmpA(patchcode, patch),
10665        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10666     ok(!lstrcmpA(targetprod, prodcode),
10667        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10668     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
10669        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
10670     ok(!lstrcmpA(targetsid, expectedsid),
10671        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10672     ok(size == lstrlenA(expectedsid),
10673        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10674 
10675     /* MSIPATCHSTATE_OBSOLETED */
10676 
10677     lstrcpyA(patchcode, "apple");
10678     lstrcpyA(targetprod, "banana");
10679     context = 0xdeadbeef;
10680     lstrcpyA(targetsid, "kiwi");
10681     size = MAX_PATH;
10682     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10683                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
10684                            &context, targetsid, &size);
10685     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10686     ok(!lstrcmpA(patchcode, "apple"),
10687        "Expected patchcode to be unchanged, got %s\n", patchcode);
10688     ok(!lstrcmpA(targetprod, "banana"),
10689        "Expected targetprod to be unchanged, got %s\n", targetprod);
10690     ok(context == 0xdeadbeef,
10691        "Expected context to be unchanged, got %d\n", context);
10692     ok(!lstrcmpA(targetsid, "kiwi"),
10693        "Expected targetsid to be unchanged, got %s\n", targetsid);
10694     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10695 
10696     data = MSIPATCHSTATE_OBSOLETED;
10697     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10698                          (const BYTE *)&data, sizeof(DWORD));
10699     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10700 
10701     /* State value is obsoleted */
10702     lstrcpyA(patchcode, "apple");
10703     lstrcpyA(targetprod, "banana");
10704     context = 0xdeadbeef;
10705     lstrcpyA(targetsid, "kiwi");
10706     size = MAX_PATH;
10707     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10708                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
10709                            &context, targetsid, &size);
10710     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10711     ok(!lstrcmpA(patchcode, patch),
10712        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10713     ok(!lstrcmpA(targetprod, prodcode),
10714        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10715     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
10716        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
10717     ok(!lstrcmpA(targetsid, expectedsid),
10718        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10719     ok(size == lstrlenA(expectedsid),
10720        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10721 
10722     /* MSIPATCHSTATE_REGISTERED */
10723     /* FIXME */
10724 
10725     /* MSIPATCHSTATE_ALL */
10726 
10727     /* 1st */
10728     lstrcpyA(patchcode, "apple");
10729     lstrcpyA(targetprod, "banana");
10730     context = 0xdeadbeef;
10731     lstrcpyA(targetsid, "kiwi");
10732     size = MAX_PATH;
10733     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10734                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
10735                            &context, targetsid, &size);
10736     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10737     ok(!lstrcmpA(patchcode, patch),
10738        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10739     ok(!lstrcmpA(targetprod, prodcode),
10740        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10741     ok(context == MSIINSTALLCONTEXT_USERUNMANAGED,
10742        "Expected MSIINSTALLCONTEXT_USERUNMANAGED, got %d\n", context);
10743     ok(!lstrcmpA(targetsid, expectedsid),
10744        "Expected \"%s\", got \"%s\"\n", expectedsid, targetsid);
10745     ok(size == lstrlenA(expectedsid),
10746        "Expected %d, got %d\n", lstrlenA(expectedsid), size);
10747 
10748     /* same patch in multiple places, only one is enumerated */
10749     lstrcpyA(patchcode, "apple");
10750     lstrcpyA(targetprod, "banana");
10751     context = 0xdeadbeef;
10752     lstrcpyA(targetsid, "kiwi");
10753     size = MAX_PATH;
10754     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10755                            MSIPATCHSTATE_ALL, 1, patchcode, targetprod,
10756                            &context, targetsid, &size);
10757     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10758     ok(!lstrcmpA(patchcode, "apple"),
10759        "Expected patchcode to be unchanged, got %s\n", patchcode);
10760     ok(!lstrcmpA(targetprod, "banana"),
10761        "Expected targetprod to be unchanged, got %s\n", targetprod);
10762     ok(context == 0xdeadbeef,
10763        "Expected context to be unchanged, got %d\n", context);
10764     ok(!lstrcmpA(targetsid, "kiwi"),
10765        "Expected targetsid to be unchanged, got %s\n", targetsid);
10766     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10767 
10768     RegDeleteValueA(hpatch, "State");
10769     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
10770     RegCloseKey(hpatch);
10771     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
10772     RegCloseKey(udpatch);
10773     delete_key(udprod, "", access & KEY_WOW64_64KEY);
10774     RegCloseKey(udprod);
10775     delete_key(userkey, "", access & KEY_WOW64_64KEY);
10776     RegCloseKey(userkey);
10777     RegDeleteValueA(patches, patch_squashed);
10778     RegDeleteValueA(patches, "Patches");
10779 
10780 error:
10781     RegDeleteKeyA(patches, "");
10782     RegCloseKey(patches);
10783     RegDeleteKeyA(prodkey, "");
10784     RegCloseKey(prodkey);
10785 }
10786 
10787 static void test_MsiEnumPatchesEx_machine(void)
10788 {
10789     CHAR keypath[MAX_PATH], patch[MAX_PATH];
10790     CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
10791     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
10792     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
10793     HKEY prodkey, patches, udprod, udpatch;
10794     HKEY hpatch;
10795     MSIINSTALLCONTEXT context;
10796     DWORD size, data;
10797     LONG res;
10798     UINT r;
10799     REGSAM access = KEY_ALL_ACCESS;
10800 
10801     create_test_guid(prodcode, prod_squashed);
10802     create_test_guid(patch, patch_squashed);
10803 
10804     if (is_wow64)
10805         access |= KEY_WOW64_64KEY;
10806 
10807     /* MSIPATCHSTATE_APPLIED */
10808 
10809     lstrcpyA(patchcode, "apple");
10810     lstrcpyA(targetprod, "banana");
10811     context = 0xdeadbeef;
10812     lstrcpyA(targetsid, "kiwi");
10813     size = MAX_PATH;
10814     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10815                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10816                            &context, targetsid, &size);
10817     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10818     ok(!lstrcmpA(patchcode, "apple"),
10819        "Expected patchcode to be unchanged, got %s\n", patchcode);
10820     ok(!lstrcmpA(targetprod, "banana"),
10821        "Expected targetprod to be unchanged, got %s\n", targetprod);
10822     ok(context == 0xdeadbeef,
10823        "Expected context to be unchanged, got %d\n", context);
10824     ok(!lstrcmpA(targetsid, "kiwi"),
10825        "Expected targetsid to be unchanged, got %s\n", targetsid);
10826     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10827 
10828     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
10829     lstrcatA(keypath, prod_squashed);
10830 
10831     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
10832     if (res == ERROR_ACCESS_DENIED)
10833     {
10834         skip("Not enough rights to perform tests\n");
10835         return;
10836     }
10837     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10838 
10839     /* local product key exists */
10840     lstrcpyA(patchcode, "apple");
10841     lstrcpyA(targetprod, "banana");
10842     context = 0xdeadbeef;
10843     lstrcpyA(targetsid, "kiwi");
10844     size = MAX_PATH;
10845     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10846                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10847                            &context, targetsid, &size);
10848     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10849     ok(!lstrcmpA(patchcode, "apple"),
10850        "Expected patchcode to be unchanged, got %s\n", patchcode);
10851     ok(!lstrcmpA(targetprod, "banana"),
10852        "Expected targetprod to be unchanged, got %s\n", targetprod);
10853     ok(context == 0xdeadbeef,
10854        "Expected context to be unchanged, got %d\n", context);
10855     ok(!lstrcmpA(targetsid, "kiwi"),
10856        "Expected targetsid to be unchanged, got %s\n", targetsid);
10857     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10858 
10859     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
10860     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10861 
10862     /* Patches key exists */
10863     lstrcpyA(patchcode, "apple");
10864     lstrcpyA(targetprod, "banana");
10865     context = 0xdeadbeef;
10866     lstrcpyA(targetsid, "kiwi");
10867     size = MAX_PATH;
10868     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10869                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10870                            &context, targetsid, &size);
10871     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10872     ok(!lstrcmpA(patchcode, "apple"),
10873        "Expected patchcode to be unchanged, got %s\n", patchcode);
10874     ok(!lstrcmpA(targetprod, "banana"),
10875        "Expected targetprod to be unchanged, got %s\n", targetprod);
10876     ok(context == 0xdeadbeef,
10877        "Expected context to be unchanged, got %d\n", context);
10878     ok(!lstrcmpA(targetsid, "kiwi"),
10879        "Expected targetsid to be unchanged, got %s\n", targetsid);
10880     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10881 
10882     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
10883                          (const BYTE *)patch_squashed,
10884                          lstrlenA(patch_squashed) + 1);
10885     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10886 
10887     /* Patches value exists, is not REG_MULTI_SZ */
10888     lstrcpyA(patchcode, "apple");
10889     lstrcpyA(targetprod, "banana");
10890     context = 0xdeadbeef;
10891     lstrcpyA(targetsid, "kiwi");
10892     size = MAX_PATH;
10893     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10894                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10895                            &context, targetsid, &size);
10896     ok(r == ERROR_BAD_CONFIGURATION,
10897        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10898     ok(!lstrcmpA(patchcode, "apple"),
10899        "Expected patchcode to be unchanged, got %s\n", patchcode);
10900     ok(!lstrcmpA(targetprod, "banana"),
10901        "Expected targetprod to be unchanged, got %s\n", targetprod);
10902     ok(context == 0xdeadbeef,
10903        "Expected context to be unchanged, got %d\n", context);
10904     ok(!lstrcmpA(targetsid, "kiwi"),
10905        "Expected targetsid to be unchanged, got %s\n", targetsid);
10906     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10907 
10908     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10909                          (const BYTE *)"a\0b\0c\0\0", 7);
10910     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10911 
10912     /* Patches value exists, is not a squashed guid */
10913     lstrcpyA(patchcode, "apple");
10914     lstrcpyA(targetprod, "banana");
10915     context = 0xdeadbeef;
10916     lstrcpyA(targetsid, "kiwi");
10917     size = MAX_PATH;
10918     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10919                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10920                            &context, targetsid, &size);
10921     ok(r == ERROR_BAD_CONFIGURATION,
10922        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10923     ok(!lstrcmpA(patchcode, "apple"),
10924        "Expected patchcode to be unchanged, got %s\n", patchcode);
10925     ok(!lstrcmpA(targetprod, "banana"),
10926        "Expected targetprod to be unchanged, got %s\n", targetprod);
10927     ok(context == 0xdeadbeef,
10928        "Expected context to be unchanged, got %d\n", context);
10929     ok(!lstrcmpA(targetsid, "kiwi"),
10930        "Expected targetsid to be unchanged, got %s\n", targetsid);
10931     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10932 
10933     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
10934     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
10935                          (const BYTE *)patch_squashed,
10936                          lstrlenA(patch_squashed) + 2);
10937     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10938 
10939     /* Patches value exists */
10940     lstrcpyA(patchcode, "apple");
10941     lstrcpyA(targetprod, "banana");
10942     context = 0xdeadbeef;
10943     lstrcpyA(targetsid, "kiwi");
10944     size = MAX_PATH;
10945     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10946                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10947                            &context, targetsid, &size);
10948     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10949     ok(!lstrcmpA(patchcode, "apple"),
10950        "Expected patchcode to be unchanged, got %s\n", patchcode);
10951     ok(!lstrcmpA(targetprod, "banana"),
10952        "Expected targetprod to be unchanged, got %s\n", targetprod);
10953     ok(context == 0xdeadbeef,
10954        "Expected context to be unchanged, got %d\n", context);
10955     ok(!lstrcmpA(targetsid, "kiwi"),
10956        "Expected targetsid to be unchanged, got %s\n", targetsid);
10957     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
10958 
10959     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
10960                          (const BYTE *)"whatever", 9);
10961     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10962 
10963     /* patch code value exists */
10964     lstrcpyA(patchcode, "apple");
10965     lstrcpyA(targetprod, "banana");
10966     context = 0xdeadbeef;
10967     lstrcpyA(targetsid, "kiwi");
10968     size = MAX_PATH;
10969     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
10970                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
10971                            &context, targetsid, &size);
10972     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10973     ok(!lstrcmpA(patchcode, patch),
10974        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10975     ok(!lstrcmpA(targetprod, prodcode),
10976        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10977     ok(context == MSIINSTALLCONTEXT_MACHINE,
10978        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10979     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
10980     ok(size == 0, "Expected 0, got %d\n", size);
10981 
10982     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
10983     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
10984     lstrcatA(keypath, prod_squashed);
10985 
10986     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
10987     if (res == ERROR_ACCESS_DENIED)
10988     {
10989         skip("Not enough rights to perform tests\n");
10990         goto done;
10991     }
10992     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
10993 
10994     /* local UserData product key exists */
10995     lstrcpyA(patchcode, "apple");
10996     lstrcpyA(targetprod, "banana");
10997     context = 0xdeadbeef;
10998     lstrcpyA(targetsid, "kiwi");
10999     size = MAX_PATH;
11000     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11001                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
11002                            &context, targetsid, &size);
11003     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11004     ok(!lstrcmpA(patchcode, patch),
11005        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
11006     ok(!lstrcmpA(targetprod, prodcode),
11007        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
11008     ok(context == MSIINSTALLCONTEXT_MACHINE,
11009        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
11010     ok(!lstrcmpA(targetsid, ""),
11011        "Expected \"\", got \"%s\"\n", targetsid);
11012     ok(size == 0, "Expected 0, got %d\n", size);
11013 
11014     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
11015     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11016 
11017     /* local UserData Patches key exists */
11018     lstrcpyA(patchcode, "apple");
11019     lstrcpyA(targetprod, "banana");
11020     context = 0xdeadbeef;
11021     lstrcpyA(targetsid, "kiwi");
11022     size = MAX_PATH;
11023     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11024                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
11025                            &context, targetsid, &size);
11026     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11027     ok(!lstrcmpA(patchcode, patch),
11028        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
11029     ok(!lstrcmpA(targetprod, prodcode),
11030        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
11031     ok(context == MSIINSTALLCONTEXT_MACHINE,
11032        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
11033     ok(!lstrcmpA(targetsid, ""),
11034        "Expected \"\", got \"%s\"\n", targetsid);
11035     ok(size == 0, "Expected 0, got %d\n", size);
11036 
11037     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
11038     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11039 
11040     /* local UserData Product patch key exists */
11041     lstrcpyA(patchcode, "apple");
11042     lstrcpyA(targetprod, "banana");
11043     context = 0xdeadbeef;
11044     lstrcpyA(targetsid, "kiwi");
11045     size = MAX_PATH;
11046     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11047                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
11048                            &context, targetsid, &size);
11049     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11050     ok(!lstrcmpA(patchcode, "apple"),
11051        "Expected patchcode to be unchanged, got %s\n", patchcode);
11052     ok(!lstrcmpA(targetprod, "banana"),
11053        "Expected targetprod to be unchanged, got %s\n", targetprod);
11054     ok(context == 0xdeadbeef,
11055        "Expected context to be unchanged, got %d\n", context);
11056     ok(!lstrcmpA(targetsid, "kiwi"),
11057        "Expected targetsid to be unchanged, got %s\n", targetsid);
11058     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11059 
11060     data = MSIPATCHSTATE_APPLIED;
11061     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
11062                          (const BYTE *)&data, sizeof(DWORD));
11063     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11064 
11065     /* State value exists */
11066     lstrcpyA(patchcode, "apple");
11067     lstrcpyA(targetprod, "banana");
11068     context = 0xdeadbeef;
11069     lstrcpyA(targetsid, "kiwi");
11070     size = MAX_PATH;
11071     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11072                            MSIPATCHSTATE_APPLIED, 0, patchcode, targetprod,
11073                            &context, targetsid, &size);
11074     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11075     ok(!lstrcmpA(patchcode, patch),
11076        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
11077     ok(!lstrcmpA(targetprod, prodcode),
11078        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
11079     ok(context == MSIINSTALLCONTEXT_MACHINE,
11080        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
11081     ok(!lstrcmpA(targetsid, ""),
11082        "Expected \"\", got \"%s\"\n", targetsid);
11083     ok(size == 0, "Expected 0, got %d\n", size);
11084 
11085     /* MSIPATCHSTATE_SUPERSEDED */
11086 
11087     lstrcpyA(patchcode, "apple");
11088     lstrcpyA(targetprod, "banana");
11089     context = 0xdeadbeef;
11090     lstrcpyA(targetsid, "kiwi");
11091     size = MAX_PATH;
11092     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11093                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
11094                            &context, targetsid, &size);
11095     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11096     ok(!lstrcmpA(patchcode, "apple"),
11097        "Expected patchcode to be unchanged, got %s\n", patchcode);
11098     ok(!lstrcmpA(targetprod, "banana"),
11099        "Expected targetprod to be unchanged, got %s\n", targetprod);
11100     ok(context == 0xdeadbeef,
11101        "Expected context to be unchanged, got %d\n", context);
11102     ok(!lstrcmpA(targetsid, "kiwi"),
11103        "Expected targetsid to be unchanged, got %s\n", targetsid);
11104     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11105 
11106     data = MSIPATCHSTATE_SUPERSEDED;
11107     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
11108                          (const BYTE *)&data, sizeof(DWORD));
11109     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11110 
11111     /* State value is MSIPATCHSTATE_SUPERSEDED */
11112     lstrcpyA(patchcode, "apple");
11113     lstrcpyA(targetprod, "banana");
11114     context = 0xdeadbeef;
11115     lstrcpyA(targetsid, "kiwi");
11116     size = MAX_PATH;
11117     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11118                            MSIPATCHSTATE_SUPERSEDED, 0, patchcode, targetprod,
11119                            &context, targetsid, &size);
11120     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11121     ok(!lstrcmpA(patchcode, patch),
11122        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
11123     ok(!lstrcmpA(targetprod, prodcode),
11124        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
11125     ok(context == MSIINSTALLCONTEXT_MACHINE,
11126        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
11127     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
11128     ok(size == 0, "Expected 0, got %d\n", size);
11129 
11130     /* MSIPATCHSTATE_OBSOLETED */
11131 
11132     lstrcpyA(patchcode, "apple");
11133     lstrcpyA(targetprod, "banana");
11134     context = 0xdeadbeef;
11135     lstrcpyA(targetsid, "kiwi");
11136     size = MAX_PATH;
11137     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11138                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
11139                            &context, targetsid, &size);
11140     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11141     ok(!lstrcmpA(patchcode, "apple"),
11142        "Expected patchcode to be unchanged, got %s\n", patchcode);
11143     ok(!lstrcmpA(targetprod, "banana"),
11144        "Expected targetprod to be unchanged, got %s\n", targetprod);
11145     ok(context == 0xdeadbeef,
11146        "Expected context to be unchanged, got %d\n", context);
11147     ok(!lstrcmpA(targetsid, "kiwi"),
11148        "Expected targetsid to be unchanged, got %s\n", targetsid);
11149     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11150 
11151     data = MSIPATCHSTATE_OBSOLETED;
11152     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
11153                          (const BYTE *)&data, sizeof(DWORD));
11154     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11155 
11156     /* State value is obsoleted */
11157     lstrcpyA(patchcode, "apple");
11158     lstrcpyA(targetprod, "banana");
11159     context = 0xdeadbeef;
11160     lstrcpyA(targetsid, "kiwi");
11161     size = MAX_PATH;
11162     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11163                            MSIPATCHSTATE_OBSOLETED, 0, patchcode, targetprod,
11164                            &context, targetsid, &size);
11165     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11166     ok(!lstrcmpA(patchcode, patch),
11167        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
11168     ok(!lstrcmpA(targetprod, prodcode),
11169        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
11170     ok(context == MSIINSTALLCONTEXT_MACHINE,
11171        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
11172     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
11173     ok(size == 0, "Expected 0, got %d\n", size);
11174 
11175     /* MSIPATCHSTATE_REGISTERED */
11176     /* FIXME */
11177 
11178     /* MSIPATCHSTATE_ALL */
11179 
11180     /* 1st */
11181     lstrcpyA(patchcode, "apple");
11182     lstrcpyA(targetprod, "banana");
11183     context = 0xdeadbeef;
11184     lstrcpyA(targetsid, "kiwi");
11185     size = MAX_PATH;
11186     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11187                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
11188                            &context, targetsid, &size);
11189     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11190     ok(!lstrcmpA(patchcode, patch),
11191        "Expected \"%s\", got \"%s\"\n", patch, patchcode);
11192     ok(!lstrcmpA(targetprod, prodcode),
11193        "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
11194     ok(context == MSIINSTALLCONTEXT_MACHINE,
11195        "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
11196     ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
11197     ok(size == 0, "Expected 0, got %d\n", size);
11198 
11199     /* same patch in multiple places, only one is enumerated */
11200     lstrcpyA(patchcode, "apple");
11201     lstrcpyA(targetprod, "banana");
11202     context = 0xdeadbeef;
11203     lstrcpyA(targetsid, "kiwi");
11204     size = MAX_PATH;
11205     r = pMsiEnumPatchesExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE,
11206                            MSIPATCHSTATE_ALL, 1, patchcode, targetprod,
11207                            &context, targetsid, &size);
11208     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11209     ok(!lstrcmpA(patchcode, "apple"),
11210        "Expected patchcode to be unchanged, got %s\n", patchcode);
11211     ok(!lstrcmpA(targetprod, "banana"),
11212        "Expected targetprod to be unchanged, got %s\n", targetprod);
11213     ok(context == 0xdeadbeef,
11214        "Expected context to be unchanged, got %d\n", context);
11215     ok(!lstrcmpA(targetsid, "kiwi"),
11216        "Expected targetsid to be unchanged, got %s\n", targetsid);
11217     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11218 
11219     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
11220     RegDeleteValueA(hpatch, "State");
11221     RegCloseKey(hpatch);
11222     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
11223     RegCloseKey(udpatch);
11224     delete_key(udprod, "", access & KEY_WOW64_64KEY);
11225     RegCloseKey(udprod);
11226 
11227 done:
11228     RegDeleteValueA(patches, patch_squashed);
11229     RegDeleteValueA(patches, "Patches");
11230     delete_key(patches, "", access & KEY_WOW64_64KEY);
11231     RegCloseKey(patches);
11232     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
11233     RegCloseKey(prodkey);
11234 }
11235 
11236 static void test_MsiEnumPatchesEx(void)
11237 {
11238     CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
11239     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
11240     CHAR patchcode[MAX_PATH];
11241     MSIINSTALLCONTEXT context;
11242     LPSTR usersid;
11243     DWORD size;
11244     UINT r;
11245 
11246     if (!pMsiEnumPatchesExA)
11247     {
11248         win_skip("MsiEnumPatchesExA not implemented\n");
11249         return;
11250     }
11251 
11252     create_test_guid(prodcode, prod_squashed);
11253     usersid = get_user_sid();
11254 
11255     /* empty szProductCode */
11256     lstrcpyA(patchcode, "apple");
11257     lstrcpyA(targetprod, "banana");
11258     context = 0xdeadbeef;
11259     lstrcpyA(targetsid, "kiwi");
11260     size = MAX_PATH;
11261     r = pMsiEnumPatchesExA("", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
11262                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod, &context,
11263                            targetsid, &size);
11264     ok(r == ERROR_INVALID_PARAMETER,
11265        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11266     ok(!lstrcmpA(patchcode, "apple"),
11267        "Expected patchcode to be unchanged, got %s\n", patchcode);
11268     ok(!lstrcmpA(targetprod, "banana"),
11269        "Expected targetprod to be unchanged, got %s\n", targetprod);
11270     ok(context == 0xdeadbeef,
11271        "Expected context to be unchanged, got %d\n", context);
11272     ok(!lstrcmpA(targetsid, "kiwi"),
11273        "Expected targetsid to be unchanged, got %s\n", targetsid);
11274     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11275 
11276     /* garbage szProductCode */
11277     lstrcpyA(patchcode, "apple");
11278     lstrcpyA(targetprod, "banana");
11279     context = 0xdeadbeef;
11280     lstrcpyA(targetsid, "kiwi");
11281     size = MAX_PATH;
11282     r = pMsiEnumPatchesExA("garbage", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
11283                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod, &context,
11284                            targetsid, &size);
11285     ok(r == ERROR_INVALID_PARAMETER,
11286        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11287     ok(!lstrcmpA(patchcode, "apple"),
11288        "Expected patchcode to be unchanged, got %s\n", patchcode);
11289     ok(!lstrcmpA(targetprod, "banana"),
11290        "Expected targetprod to be unchanged, got %s\n", targetprod);
11291     ok(context == 0xdeadbeef,
11292        "Expected context to be unchanged, got %d\n", context);
11293     ok(!lstrcmpA(targetsid, "kiwi"),
11294        "Expected targetsid to be unchanged, got %s\n", targetsid);
11295     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11296 
11297     /* guid without brackets */
11298     lstrcpyA(patchcode, "apple");
11299     lstrcpyA(targetprod, "banana");
11300     context = 0xdeadbeef;
11301     lstrcpyA(targetsid, "kiwi");
11302     size = MAX_PATH;
11303     r = pMsiEnumPatchesExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", usersid,
11304                            MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
11305                            0, patchcode, targetprod, &context,
11306                            targetsid, &size);
11307     ok(r == ERROR_INVALID_PARAMETER,
11308        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11309     ok(!lstrcmpA(patchcode, "apple"),
11310        "Expected patchcode to be unchanged, got %s\n", patchcode);
11311     ok(!lstrcmpA(targetprod, "banana"),
11312        "Expected targetprod to be unchanged, got %s\n", targetprod);
11313     ok(context == 0xdeadbeef,
11314        "Expected context to be unchanged, got %d\n", context);
11315     ok(!lstrcmpA(targetsid, "kiwi"),
11316        "Expected targetsid to be unchanged, got %s\n", targetsid);
11317     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11318 
11319     /* guid with brackets */
11320     lstrcpyA(patchcode, "apple");
11321     lstrcpyA(targetprod, "banana");
11322     context = 0xdeadbeef;
11323     lstrcpyA(targetsid, "kiwi");
11324     size = MAX_PATH;
11325     r = pMsiEnumPatchesExA("{6700E8CF-95AB-4D9C-BC2C-15840DDA7A5D}", usersid,
11326                            MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
11327                            0, patchcode, targetprod, &context,
11328                            targetsid, &size);
11329     ok(r == ERROR_NO_MORE_ITEMS,
11330        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11331     ok(!lstrcmpA(patchcode, "apple"),
11332        "Expected patchcode to be unchanged, got %s\n", patchcode);
11333     ok(!lstrcmpA(targetprod, "banana"),
11334        "Expected targetprod to be unchanged, got %s\n", targetprod);
11335     ok(context == 0xdeadbeef,
11336        "Expected context to be unchanged, got %d\n", context);
11337     ok(!lstrcmpA(targetsid, "kiwi"),
11338        "Expected targetsid to be unchanged, got %s\n", targetsid);
11339     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11340 
11341     /* szUserSid is S-1-5-18 */
11342     lstrcpyA(patchcode, "apple");
11343     lstrcpyA(targetprod, "banana");
11344     context = 0xdeadbeef;
11345     lstrcpyA(targetsid, "kiwi");
11346     size = MAX_PATH;
11347     r = pMsiEnumPatchesExA(prodcode, "S-1-5-18",
11348                            MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_ALL,
11349                            0, patchcode, targetprod, &context,
11350                            targetsid, &size);
11351     ok(r == ERROR_INVALID_PARAMETER,
11352        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11353     ok(!lstrcmpA(patchcode, "apple"),
11354        "Expected patchcode to be unchanged, got %s\n", patchcode);
11355     ok(!lstrcmpA(targetprod, "banana"),
11356        "Expected targetprod to be unchanged, got %s\n", targetprod);
11357     ok(context == 0xdeadbeef,
11358        "Expected context to be unchanged, got %d\n", context);
11359     ok(!lstrcmpA(targetsid, "kiwi"),
11360        "Expected targetsid to be unchanged, got %s\n", targetsid);
11361     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11362 
11363     /* dwContext is MSIINSTALLCONTEXT_MACHINE, but szUserSid is non-NULL */
11364     lstrcpyA(patchcode, "apple");
11365     lstrcpyA(targetprod, "banana");
11366     context = 0xdeadbeef;
11367     lstrcpyA(targetsid, "kiwi");
11368     size = MAX_PATH;
11369     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_MACHINE,
11370                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
11371                            &context, targetsid, &size);
11372     ok(r == ERROR_INVALID_PARAMETER,
11373        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11374     ok(!lstrcmpA(patchcode, "apple"),
11375        "Expected patchcode to be unchanged, got %s\n", patchcode);
11376     ok(!lstrcmpA(targetprod, "banana"),
11377        "Expected targetprod to be unchanged, got %s\n", targetprod);
11378     ok(context == 0xdeadbeef,
11379        "Expected context to be unchanged, got %d\n", context);
11380     ok(!lstrcmpA(targetsid, "kiwi"),
11381        "Expected targetsid to be unchanged, got %s\n", targetsid);
11382     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11383 
11384     /* dwContext is out of bounds */
11385     lstrcpyA(patchcode, "apple");
11386     lstrcpyA(targetprod, "banana");
11387     context = 0xdeadbeef;
11388     lstrcpyA(targetsid, "kiwi");
11389     size = MAX_PATH;
11390     r = pMsiEnumPatchesExA(prodcode, usersid, 0,
11391                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
11392                            &context, targetsid, &size);
11393     ok(r == ERROR_INVALID_PARAMETER,
11394        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11395     ok(!lstrcmpA(patchcode, "apple"),
11396        "Expected patchcode to be unchanged, got %s\n", patchcode);
11397     ok(!lstrcmpA(targetprod, "banana"),
11398        "Expected targetprod to be unchanged, got %s\n", targetprod);
11399     ok(context == 0xdeadbeef,
11400        "Expected context to be unchanged, got %d\n", context);
11401     ok(!lstrcmpA(targetsid, "kiwi"),
11402        "Expected targetsid to be unchanged, got %s\n", targetsid);
11403     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11404 
11405     /* dwContext is out of bounds */
11406     lstrcpyA(patchcode, "apple");
11407     lstrcpyA(targetprod, "banana");
11408     context = 0xdeadbeef;
11409     lstrcpyA(targetsid, "kiwi");
11410     size = MAX_PATH;
11411     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_ALL + 1,
11412                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
11413                            &context, targetsid, &size);
11414     ok(r == ERROR_INVALID_PARAMETER,
11415        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11416     ok(!lstrcmpA(patchcode, "apple"),
11417        "Expected patchcode to be unchanged, got %s\n", patchcode);
11418     ok(!lstrcmpA(targetprod, "banana"),
11419        "Expected targetprod to be unchanged, got %s\n", targetprod);
11420     ok(context == 0xdeadbeef,
11421        "Expected context to be unchanged, got %d\n", context);
11422     ok(!lstrcmpA(targetsid, "kiwi"),
11423        "Expected targetsid to be unchanged, got %s\n", targetsid);
11424     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11425 
11426     /* dwFilter is out of bounds */
11427     lstrcpyA(patchcode, "apple");
11428     lstrcpyA(targetprod, "banana");
11429     context = 0xdeadbeef;
11430     lstrcpyA(targetsid, "kiwi");
11431     size = MAX_PATH;
11432     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
11433                            MSIPATCHSTATE_INVALID, 0, patchcode, targetprod,
11434                            &context, targetsid, &size);
11435     ok(r == ERROR_INVALID_PARAMETER,
11436        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11437     ok(!lstrcmpA(patchcode, "apple"),
11438        "Expected patchcode to be unchanged, got %s\n", patchcode);
11439     ok(!lstrcmpA(targetprod, "banana"),
11440        "Expected targetprod to be unchanged, got %s\n", targetprod);
11441     ok(context == 0xdeadbeef,
11442        "Expected context to be unchanged, got %d\n", context);
11443     ok(!lstrcmpA(targetsid, "kiwi"),
11444        "Expected targetsid to be unchanged, got %s\n", targetsid);
11445     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11446 
11447     /* dwFilter is out of bounds */
11448     lstrcpyA(patchcode, "apple");
11449     lstrcpyA(targetprod, "banana");
11450     context = 0xdeadbeef;
11451     lstrcpyA(targetsid, "kiwi");
11452     size = MAX_PATH;
11453     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
11454                            MSIPATCHSTATE_ALL + 1, 0, patchcode, targetprod,
11455                            &context, targetsid, &size);
11456     ok(r == ERROR_INVALID_PARAMETER,
11457        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11458     ok(!lstrcmpA(patchcode, "apple"),
11459        "Expected patchcode to be unchanged, got %s\n", patchcode);
11460     ok(!lstrcmpA(targetprod, "banana"),
11461        "Expected targetprod to be unchanged, got %s\n", targetprod);
11462     ok(context == 0xdeadbeef,
11463        "Expected context to be unchanged, got %d\n", context);
11464     ok(!lstrcmpA(targetsid, "kiwi"),
11465        "Expected targetsid to be unchanged, got %s\n", targetsid);
11466     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11467 
11468     /* pcchTargetUserSid is NULL while szTargetUserSid is non-NULL */
11469     lstrcpyA(patchcode, "apple");
11470     lstrcpyA(targetprod, "banana");
11471     context = 0xdeadbeef;
11472     lstrcpyA(targetsid, "kiwi");
11473     r = pMsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
11474                            MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
11475                            &context, targetsid, NULL);
11476     ok(r == ERROR_INVALID_PARAMETER,
11477        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11478     ok(!lstrcmpA(patchcode, "apple"),
11479        "Expected patchcode to be unchanged, got %s\n", patchcode);
11480     ok(!lstrcmpA(targetprod, "banana"),
11481        "Expected targetprod to be unchanged, got %s\n", targetprod);
11482     ok(context == 0xdeadbeef,
11483        "Expected context to be unchanged, got %d\n", context);
11484     ok(!lstrcmpA(targetsid, "kiwi"),
11485        "Expected targetsid to be unchanged, got %s\n", targetsid);
11486 
11487     test_MsiEnumPatchesEx_usermanaged(usersid, usersid);
11488     test_MsiEnumPatchesEx_usermanaged(NULL, usersid);
11489     test_MsiEnumPatchesEx_usermanaged("S-1-2-34", "S-1-2-34");
11490     test_MsiEnumPatchesEx_userunmanaged(usersid, usersid);
11491     test_MsiEnumPatchesEx_userunmanaged(NULL, usersid);
11492     /* FIXME: Successfully test userunmanaged with a different user */
11493     test_MsiEnumPatchesEx_machine();
11494     LocalFree(usersid);
11495 }
11496 
11497 static void test_MsiEnumPatches(void)
11498 {
11499     CHAR keypath[MAX_PATH], patch[MAX_PATH];
11500     CHAR patchcode[MAX_PATH], patch_squashed[MAX_PATH];
11501     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
11502     CHAR transforms[MAX_PATH];
11503     WCHAR patchW[MAX_PATH], prodcodeW[MAX_PATH], transformsW[MAX_PATH];
11504     HKEY prodkey, patches, udprod;
11505     HKEY userkey, hpatch, udpatch;
11506     DWORD size, data;
11507     LPSTR usersid;
11508     LONG res;
11509     UINT r;
11510     REGSAM access = KEY_ALL_ACCESS;
11511 
11512     create_test_guid(prodcode, prod_squashed);
11513     create_test_guid(patchcode, patch_squashed);
11514     usersid = get_user_sid();
11515 
11516     if (is_wow64)
11517         access |= KEY_WOW64_64KEY;
11518 
11519     /* NULL szProduct */
11520     size = MAX_PATH;
11521     lstrcpyA(patch, "apple");
11522     lstrcpyA(transforms, "banana");
11523     r = MsiEnumPatchesA(NULL, 0, patch, transforms, &size);
11524     ok(r == ERROR_INVALID_PARAMETER,
11525        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11526     ok(!lstrcmpA(patch, "apple"),
11527        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11528     ok(!lstrcmpA(transforms, "banana"),
11529        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11530     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11531 
11532     /* empty szProduct */
11533     size = MAX_PATH;
11534     lstrcpyA(patch, "apple");
11535     lstrcpyA(transforms, "banana");
11536     r = MsiEnumPatchesA("", 0, patch, transforms, &size);
11537     ok(r == ERROR_INVALID_PARAMETER,
11538        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11539     ok(!lstrcmpA(patch, "apple"),
11540        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11541     ok(!lstrcmpA(transforms, "banana"),
11542        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11543     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11544 
11545     /* garbage szProduct */
11546     size = MAX_PATH;
11547     lstrcpyA(patch, "apple");
11548     lstrcpyA(transforms, "banana");
11549     r = MsiEnumPatchesA("garbage", 0, patch, transforms, &size);
11550     ok(r == ERROR_INVALID_PARAMETER,
11551        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11552     ok(!lstrcmpA(patch, "apple"),
11553        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11554     ok(!lstrcmpA(transforms, "banana"),
11555        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11556     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11557 
11558     /* guid without brackets */
11559     size = MAX_PATH;
11560     lstrcpyA(patch, "apple");
11561     lstrcpyA(transforms, "banana");
11562     r = MsiEnumPatchesA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", 0, patch,
11563                         transforms, &size);
11564     ok(r == ERROR_INVALID_PARAMETER,
11565        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11566     ok(!lstrcmpA(patch, "apple"),
11567        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11568     ok(!lstrcmpA(transforms, "banana"),
11569        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11570     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11571 
11572     /* guid with brackets */
11573     size = MAX_PATH;
11574     lstrcpyA(patch, "apple");
11575     lstrcpyA(transforms, "banana");
11576     r = MsiEnumPatchesA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", 0, patch,
11577                         transforms, &size);
11578     ok(r == ERROR_UNKNOWN_PRODUCT,
11579        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11580     ok(!lstrcmpA(patch, "apple"),
11581        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11582     ok(!lstrcmpA(transforms, "banana"),
11583        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11584     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11585 
11586     /* same length as guid, but random */
11587     size = MAX_PATH;
11588     lstrcpyA(patch, "apple");
11589     lstrcpyA(transforms, "banana");
11590     r = MsiEnumPatchesA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", 0, patch,
11591                         transforms, &size);
11592     ok(r == ERROR_INVALID_PARAMETER,
11593        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11594     ok(!lstrcmpA(patch, "apple"),
11595        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11596     ok(!lstrcmpA(transforms, "banana"),
11597        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11598     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11599 
11600     /* MSIINSTALLCONTEXT_USERMANAGED */
11601 
11602     size = MAX_PATH;
11603     lstrcpyA(patch, "apple");
11604     lstrcpyA(transforms, "banana");
11605     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11606     ok(r == ERROR_UNKNOWN_PRODUCT,
11607        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11608     ok(!lstrcmpA(patch, "apple"),
11609        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11610     ok(!lstrcmpA(transforms, "banana"),
11611        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11612     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11613 
11614     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
11615     lstrcatA(keypath, usersid);
11616     lstrcatA(keypath, "\\Installer\\Products\\");
11617     lstrcatA(keypath, prod_squashed);
11618 
11619     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
11620     if (res == ERROR_ACCESS_DENIED)
11621     {
11622         skip("Not enough rights to perform tests\n");
11623         LocalFree(usersid);
11624         return;
11625     }
11626     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11627 
11628     /* managed product key exists */
11629     size = MAX_PATH;
11630     lstrcpyA(patch, "apple");
11631     lstrcpyA(transforms, "banana");
11632     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11633     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11634     ok(!lstrcmpA(patch, "apple"),
11635        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11636     ok(!lstrcmpA(transforms, "banana"),
11637        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11638     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11639 
11640     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
11641     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11642 
11643     /* patches key exists */
11644     size = MAX_PATH;
11645     lstrcpyA(patch, "apple");
11646     lstrcpyA(transforms, "banana");
11647     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11648     ok(r == ERROR_NO_MORE_ITEMS ||
11649        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11650        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11651     ok(!lstrcmpA(patch, "apple"),
11652        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11653     ok(!lstrcmpA(transforms, "banana"),
11654        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11655     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11656 
11657     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
11658                          (const BYTE *)patch_squashed,
11659                          lstrlenA(patch_squashed) + 1);
11660     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11661 
11662     /* Patches value exists, is not REG_MULTI_SZ */
11663     size = MAX_PATH;
11664     lstrcpyA(patch, "apple");
11665     lstrcpyA(transforms, "banana");
11666     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11667     ok(r == ERROR_BAD_CONFIGURATION ||
11668        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
11669        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11670     ok(!lstrcmpA(patch, "apple"),
11671        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11672     ok(!lstrcmpA(transforms, "banana"),
11673        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11674     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11675 
11676     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11677                          (const BYTE *)"a\0b\0c\0\0", 7);
11678     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11679 
11680     /* Patches value exists, is not a squashed guid */
11681     size = MAX_PATH;
11682     lstrcpyA(patch, "apple");
11683     lstrcpyA(transforms, "banana");
11684     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11685     ok(r == ERROR_BAD_CONFIGURATION,
11686        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11687     ok(!lstrcmpA(patch, "apple"),
11688        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11689     ok(!lstrcmpA(transforms, "banana"),
11690        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11691     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11692 
11693     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
11694     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11695                          (const BYTE *)patch_squashed,
11696                          lstrlenA(patch_squashed) + 2);
11697     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11698 
11699     /* Patches value exists */
11700     size = MAX_PATH;
11701     lstrcpyA(patch, "apple");
11702     lstrcpyA(transforms, "banana");
11703     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11704     ok(r == ERROR_NO_MORE_ITEMS ||
11705        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11706        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11707     ok(!lstrcmpA(patch, "apple") ||
11708        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
11709        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11710     ok(!lstrcmpA(transforms, "banana"),
11711        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11712     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11713 
11714     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
11715                          (const BYTE *)"whatever", 9);
11716     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11717 
11718     /* patch squashed value exists */
11719     size = MAX_PATH;
11720     lstrcpyA(patch, "apple");
11721     lstrcpyA(transforms, "banana");
11722     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11723     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11724     ok(!lstrcmpA(patch, patchcode),
11725        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11726     ok(!lstrcmpA(transforms, "whatever"),
11727        "Expected \"whatever\", got \"%s\"\n", transforms);
11728     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
11729 
11730     /* lpPatchBuf is NULL */
11731     size = MAX_PATH;
11732     lstrcpyA(transforms, "banana");
11733     r = MsiEnumPatchesA(prodcode, 0, NULL, transforms, &size);
11734     ok(r == ERROR_INVALID_PARAMETER,
11735        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11736     ok(!lstrcmpA(transforms, "banana"),
11737        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11738     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11739 
11740     /* lpTransformsBuf is NULL, pcchTransformsBuf is not */
11741     size = MAX_PATH;
11742     lstrcpyA(patch, "apple");
11743     r = MsiEnumPatchesA(prodcode, 0, patch, NULL, &size);
11744     ok(r == ERROR_INVALID_PARAMETER,
11745        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11746     ok(!lstrcmpA(patch, "apple"),
11747        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11748     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11749 
11750     /* pcchTransformsBuf is NULL, lpTransformsBuf is not */
11751     lstrcpyA(patch, "apple");
11752     lstrcpyA(transforms, "banana");
11753     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, NULL);
11754     ok(r == ERROR_INVALID_PARAMETER,
11755        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
11756     ok(!lstrcmpA(patch, "apple"),
11757        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11758     ok(!lstrcmpA(transforms, "banana"),
11759        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11760 
11761     /* pcchTransformsBuf is too small */
11762     size = 6;
11763     lstrcpyA(patch, "apple");
11764     lstrcpyA(transforms, "banana");
11765     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11766     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
11767     ok(!lstrcmpA(patch, patchcode),
11768        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11769     ok(!lstrcmpA(transforms, "whate") ||
11770        broken(!lstrcmpA(transforms, "banana")), /* Windows Installer < 3.0 */
11771        "Expected \"whate\", got \"%s\"\n", transforms);
11772     ok(size == 8 || size == 16, "Expected 8 or 16, got %d\n", size);
11773 
11774     /* increase the index */
11775     size = MAX_PATH;
11776     lstrcpyA(patch, "apple");
11777     lstrcpyA(transforms, "banana");
11778     r = MsiEnumPatchesA(prodcode, 1, patch, transforms, &size);
11779     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11780     ok(!lstrcmpA(patch, "apple"),
11781        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11782     ok(!lstrcmpA(transforms, "banana"),
11783        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11784     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11785 
11786     /* increase again */
11787     size = MAX_PATH;
11788     lstrcpyA(patch, "apple");
11789     lstrcpyA(transforms, "banana");
11790     r = MsiEnumPatchesA(prodcode, 2, patch, transforms, &size);
11791     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11792     ok(!lstrcmpA(patch, "apple"),
11793        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11794     ok(!lstrcmpA(transforms, "banana"),
11795        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11796     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11797 
11798     RegDeleteValueA(patches, "Patches");
11799     delete_key(patches, "", access & KEY_WOW64_64KEY);
11800     RegCloseKey(patches);
11801     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
11802     RegCloseKey(prodkey);
11803 
11804     /* MSIINSTALLCONTEXT_USERUNMANAGED */
11805 
11806     size = MAX_PATH;
11807     lstrcpyA(patch, "apple");
11808     lstrcpyA(transforms, "banana");
11809     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11810     ok(r == ERROR_UNKNOWN_PRODUCT,
11811        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11812     ok(!lstrcmpA(patch, "apple"),
11813        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11814     ok(!lstrcmpA(transforms, "banana"),
11815        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11816     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11817 
11818     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
11819     lstrcatA(keypath, prod_squashed);
11820 
11821     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
11822     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11823 
11824     /* current user product key exists */
11825     size = MAX_PATH;
11826     lstrcpyA(patch, "apple");
11827     lstrcpyA(transforms, "banana");
11828     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11829     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11830     ok(!lstrcmpA(patch, "apple"),
11831        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11832     ok(!lstrcmpA(transforms, "banana"),
11833        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11834     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11835 
11836     res = RegCreateKeyA(prodkey, "Patches", &patches);
11837     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11838 
11839     /* Patches key exists */
11840     size = MAX_PATH;
11841     lstrcpyA(patch, "apple");
11842     lstrcpyA(transforms, "banana");
11843     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11844     ok(r == ERROR_NO_MORE_ITEMS ||
11845        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11846        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11847     ok(!lstrcmpA(patch, "apple"),
11848        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11849     ok(!lstrcmpA(transforms, "banana"),
11850        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11851     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11852 
11853     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
11854                          (const BYTE *)patch_squashed,
11855                          lstrlenA(patch_squashed) + 1);
11856     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11857 
11858     /* Patches value exists, is not REG_MULTI_SZ */
11859     size = MAX_PATH;
11860     lstrcpyA(patch, "apple");
11861     lstrcpyA(transforms, "banana");
11862     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11863     ok(r == ERROR_BAD_CONFIGURATION ||
11864        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
11865        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11866     ok(!lstrcmpA(patch, "apple"),
11867        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11868     ok(!lstrcmpA(transforms, "banana"),
11869        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11870     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11871 
11872     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11873                          (const BYTE *)"a\0b\0c\0\0", 7);
11874     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11875 
11876     /* Patches value exists, is not a squashed guid */
11877     size = MAX_PATH;
11878     lstrcpyA(patch, "apple");
11879     lstrcpyA(transforms, "banana");
11880     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11881     ok(r == ERROR_BAD_CONFIGURATION,
11882        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
11883     ok(!lstrcmpA(patch, "apple"),
11884        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11885     ok(!lstrcmpA(transforms, "banana"),
11886        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11887     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11888 
11889     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
11890     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
11891                          (const BYTE *)patch_squashed,
11892                          lstrlenA(patch_squashed) + 2);
11893     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11894 
11895     /* Patches value exists */
11896     size = MAX_PATH;
11897     lstrcpyA(patch, "apple");
11898     lstrcpyA(transforms, "banana");
11899     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11900     ok(r == ERROR_NO_MORE_ITEMS ||
11901        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
11902        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11903     ok(!lstrcmpA(patch, "apple") ||
11904        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
11905        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11906     ok(!lstrcmpA(transforms, "banana"),
11907        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11908     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11909 
11910     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
11911                          (const BYTE *)"whatever", 9);
11912     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11913 
11914     /* patch code value exists */
11915     size = MAX_PATH;
11916     lstrcpyA(patch, "apple");
11917     lstrcpyA(transforms, "banana");
11918     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11919     ok(r == ERROR_NO_MORE_ITEMS ||
11920        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
11921        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11922     ok(!lstrcmpA(patch, "apple") ||
11923        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
11924        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11925     ok(!lstrcmpA(transforms, "banana") ||
11926        broken(!lstrcmpA(transforms, "whatever")), /* Windows Installer < 3.0 */
11927        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11928     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11929 
11930     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
11931     lstrcatA(keypath, usersid);
11932     lstrcatA(keypath, "\\Patches\\");
11933     lstrcatA(keypath, patch_squashed);
11934 
11935     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
11936     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11937 
11938     /* userdata patch key exists */
11939     size = MAX_PATH;
11940     lstrcpyA(patch, "apple");
11941     lstrcpyA(transforms, "banana");
11942     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11943     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
11944     ok(!lstrcmpA(patch, patchcode),
11945        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
11946     ok(!lstrcmpA(transforms, "whatever"),
11947        "Expected \"whatever\", got \"%s\"\n", transforms);
11948     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
11949 
11950     delete_key(userkey, "", access & KEY_WOW64_64KEY);
11951     RegCloseKey(userkey);
11952     RegDeleteValueA(patches, patch_squashed);
11953     RegDeleteValueA(patches, "Patches");
11954     RegDeleteKeyA(patches, "");
11955     RegCloseKey(patches);
11956     RegDeleteKeyA(prodkey, "");
11957     RegCloseKey(prodkey);
11958 
11959     /* MSIINSTALLCONTEXT_MACHINE */
11960 
11961     size = MAX_PATH;
11962     lstrcpyA(patch, "apple");
11963     lstrcpyA(transforms, "banana");
11964     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11965     ok(r == ERROR_UNKNOWN_PRODUCT,
11966        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
11967     ok(!lstrcmpA(patch, "apple"),
11968        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11969     ok(!lstrcmpA(transforms, "banana"),
11970        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11971     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11972 
11973     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
11974     lstrcatA(keypath, prod_squashed);
11975 
11976     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
11977     if (res == ERROR_ACCESS_DENIED)
11978     {
11979         skip("Not enough rights to perform tests\n");
11980         LocalFree(usersid);
11981         return;
11982     }
11983     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11984 
11985     /* local product key exists */
11986     size = MAX_PATH;
11987     lstrcpyA(patch, "apple");
11988     lstrcpyA(transforms, "banana");
11989     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
11990     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
11991     ok(!lstrcmpA(patch, "apple"),
11992        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
11993     ok(!lstrcmpA(transforms, "banana"),
11994        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
11995     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
11996 
11997     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
11998     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
11999 
12000     /* Patches key exists */
12001     size = MAX_PATH;
12002     lstrcpyA(patch, "apple");
12003     lstrcpyA(transforms, "banana");
12004     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12005     ok(r == ERROR_NO_MORE_ITEMS ||
12006        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
12007        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
12008     ok(!lstrcmpA(patch, "apple"),
12009        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
12010     ok(!lstrcmpA(transforms, "banana"),
12011        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
12012     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12013 
12014     res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
12015                          (const BYTE *)patch_squashed,
12016                          lstrlenA(patch_squashed) + 1);
12017     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12018 
12019     /* Patches value exists, is not REG_MULTI_SZ */
12020     size = MAX_PATH;
12021     lstrcpyA(patch, "apple");
12022     lstrcpyA(transforms, "banana");
12023     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12024     ok(r == ERROR_BAD_CONFIGURATION ||
12025        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
12026        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
12027     ok(!lstrcmpA(patch, "apple"),
12028        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
12029     ok(!lstrcmpA(transforms, "banana"),
12030        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
12031     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12032 
12033     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
12034                          (const BYTE *)"a\0b\0c\0\0", 7);
12035     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12036 
12037     /* Patches value exists, is not a squashed guid */
12038     size = MAX_PATH;
12039     lstrcpyA(patch, "apple");
12040     lstrcpyA(transforms, "banana");
12041     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12042     ok(r == ERROR_BAD_CONFIGURATION,
12043        "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
12044     ok(!lstrcmpA(patch, "apple"),
12045        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
12046     ok(!lstrcmpA(transforms, "banana"),
12047        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
12048     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12049 
12050     patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
12051     res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
12052                          (const BYTE *)patch_squashed,
12053                          lstrlenA(patch_squashed) + 2);
12054     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12055 
12056     /* Patches value exists */
12057     size = MAX_PATH;
12058     lstrcpyA(patch, "apple");
12059     lstrcpyA(transforms, "banana");
12060     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12061     ok(r == ERROR_NO_MORE_ITEMS ||
12062        broken(r == ERROR_FILE_NOT_FOUND), /* Windows Installer < 3.0 */
12063        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
12064     ok(!lstrcmpA(patch, "apple") ||
12065        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
12066        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
12067     ok(!lstrcmpA(transforms, "banana"),
12068        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
12069     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12070 
12071     res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
12072                          (const BYTE *)"whatever", 9);
12073     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12074 
12075     /* patch code value exists */
12076     size = MAX_PATH;
12077     lstrcpyA(patch, "apple");
12078     lstrcpyA(transforms, "banana");
12079     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12080     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12081     ok(!lstrcmpA(patch, patchcode),
12082        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
12083     ok(!lstrcmpA(transforms, "whatever"),
12084        "Expected \"whatever\", got \"%s\"\n", transforms);
12085     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
12086 
12087     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
12088     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
12089     lstrcatA(keypath, prod_squashed);
12090 
12091     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
12092     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12093 
12094     /* local UserData product key exists */
12095     size = MAX_PATH;
12096     lstrcpyA(patch, "apple");
12097     lstrcpyA(transforms, "banana");
12098     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12099     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12100     ok(!lstrcmpA(patch, patchcode),
12101        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
12102     ok(!lstrcmpA(transforms, "whatever"),
12103        "Expected \"whatever\", got \"%s\"\n", transforms);
12104     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
12105 
12106     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
12107     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12108 
12109     /* local UserData Patches key exists */
12110     size = MAX_PATH;
12111     lstrcpyA(patch, "apple");
12112     lstrcpyA(transforms, "banana");
12113     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12114     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12115     ok(!lstrcmpA(patch, patchcode),
12116        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
12117     ok(!lstrcmpA(transforms, "whatever"),
12118        "Expected \"whatever\", got \"%s\"\n", transforms);
12119     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
12120 
12121     res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
12122     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12123 
12124     /* local UserData Product patch key exists */
12125     size = MAX_PATH;
12126     lstrcpyA(patch, "apple");
12127     lstrcpyA(transforms, "banana");
12128     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12129     ok(r == ERROR_NO_MORE_ITEMS ||
12130        broken(r == ERROR_SUCCESS), /* Windows Installer < 3.0 */
12131        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
12132     ok(!lstrcmpA(patch, "apple") ||
12133        broken(!lstrcmpA(patch, patchcode)), /* Windows Installer < 3.0 */
12134        "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
12135     ok(!lstrcmpA(transforms, "banana") ||
12136        broken(!lstrcmpA(transforms, "whatever")), /* Windows Installer < 3.0 */
12137        "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
12138     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12139 
12140     data = MSIPATCHSTATE_APPLIED;
12141     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
12142                          (const BYTE *)&data, sizeof(DWORD));
12143     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12144 
12145     /* State value exists */
12146     size = MAX_PATH;
12147     lstrcpyA(patch, "apple");
12148     lstrcpyA(transforms, "banana");
12149     r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
12150     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12151     ok(!lstrcmpA(patch, patchcode),
12152        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
12153     ok(!lstrcmpA(transforms, "whatever"),
12154        "Expected \"whatever\", got \"%s\"\n", transforms);
12155     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
12156 
12157     /* now duplicate some of the tests for the W version */
12158 
12159     /* pcchTransformsBuf is too small */
12160     size = 6;
12161     MultiByteToWideChar( CP_ACP, 0, prodcode, -1, prodcodeW, MAX_PATH );
12162     MultiByteToWideChar( CP_ACP, 0, "apple", -1, patchW, MAX_PATH );
12163     MultiByteToWideChar( CP_ACP, 0, "banana", -1, transformsW, MAX_PATH );
12164     r = MsiEnumPatchesW(prodcodeW, 0, patchW, transformsW, &size);
12165     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
12166     WideCharToMultiByte( CP_ACP, 0, patchW, -1, patch, MAX_PATH, NULL, NULL );
12167     WideCharToMultiByte( CP_ACP, 0, transformsW, -1, transforms, MAX_PATH, NULL, NULL );
12168     ok(!lstrcmpA(patch, patchcode),
12169        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
12170     ok(!lstrcmpA(transforms, "whate") ||
12171        broken(!lstrcmpA(transforms, "banana")), /* Windows Installer < 3.0 */
12172        "Expected \"whate\", got \"%s\"\n", transforms);
12173     ok(size == 8, "Expected 8, got %d\n", size);
12174 
12175     /* patch code value exists */
12176     size = MAX_PATH;
12177     MultiByteToWideChar( CP_ACP, 0, "apple", -1, patchW, MAX_PATH );
12178     MultiByteToWideChar( CP_ACP, 0, "banana", -1, transformsW, MAX_PATH );
12179     r = MsiEnumPatchesW(prodcodeW, 0, patchW, transformsW, &size);
12180     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12181     WideCharToMultiByte( CP_ACP, 0, patchW, -1, patch, MAX_PATH, NULL, NULL );
12182     WideCharToMultiByte( CP_ACP, 0, transformsW, -1, transforms, MAX_PATH, NULL, NULL );
12183     ok(!lstrcmpA(patch, patchcode),
12184        "Expected \"%s\", got \"%s\"\n", patchcode, patch);
12185     ok(!lstrcmpA(transforms, "whatever"),
12186        "Expected \"whatever\", got \"%s\"\n", transforms);
12187     ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %d\n", size);
12188 
12189     RegDeleteValueA(patches, patch_squashed);
12190     RegDeleteValueA(patches, "Patches");
12191     delete_key(patches, "", access & KEY_WOW64_64KEY);
12192     RegCloseKey(patches);
12193     RegDeleteValueA(hpatch, "State");
12194     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
12195     RegCloseKey(hpatch);
12196     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
12197     RegCloseKey(udpatch);
12198     delete_key(udprod, "", access & KEY_WOW64_64KEY);
12199     RegCloseKey(udprod);
12200     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
12201     RegCloseKey(prodkey);
12202     LocalFree(usersid);
12203 }
12204 
12205 static void test_MsiGetPatchInfoEx(void)
12206 {
12207     CHAR keypath[MAX_PATH], val[MAX_PATH];
12208     CHAR patchcode[MAX_PATH], patch_squashed[MAX_PATH];
12209     CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
12210     HKEY prodkey, patches, udprod, props;
12211     HKEY hpatch, udpatch, prodpatches;
12212     LPSTR usersid;
12213     DWORD size;
12214     LONG res;
12215     UINT r;
12216     REGSAM access = KEY_ALL_ACCESS;
12217 
12218     if (!pMsiGetPatchInfoExA)
12219     {
12220         win_skip("MsiGetPatchInfoEx not implemented\n");
12221         return;
12222     }
12223 
12224     create_test_guid(prodcode, prod_squashed);
12225     create_test_guid(patchcode, patch_squashed);
12226     usersid = get_user_sid();
12227 
12228     if (is_wow64)
12229         access |= KEY_WOW64_64KEY;
12230 
12231     /* NULL szPatchCode */
12232     lstrcpyA(val, "apple");
12233     size = MAX_PATH;
12234     r = pMsiGetPatchInfoExA(NULL, prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED,
12235                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12236     ok(r == ERROR_INVALID_PARAMETER,
12237        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12238     ok(!lstrcmpA(val, "apple"),
12239        "Expected val to be unchanged, got \"%s\"\n", val);
12240     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12241 
12242     /* empty szPatchCode */
12243     size = MAX_PATH;
12244     lstrcpyA(val, "apple");
12245     r = pMsiGetPatchInfoExA("", prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED,
12246                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12247     ok(r == ERROR_INVALID_PARAMETER,
12248        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12249     ok(!lstrcmpA(val, "apple"),
12250        "Expected val to be unchanged, got \"%s\"\n", val);
12251     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12252 
12253     /* garbage szPatchCode */
12254     size = MAX_PATH;
12255     lstrcpyA(val, "apple");
12256     r = pMsiGetPatchInfoExA("garbage", prodcode, NULL,
12257                             MSIINSTALLCONTEXT_USERMANAGED,
12258                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12259     ok(r == ERROR_INVALID_PARAMETER,
12260        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12261     ok(!lstrcmpA(val, "apple"),
12262        "Expected val to be unchanged, got \"%s\"\n", val);
12263     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12264 
12265     /* guid without brackets */
12266     size = MAX_PATH;
12267     lstrcpyA(val, "apple");
12268     r = pMsiGetPatchInfoExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", prodcode,
12269                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
12270                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12271     ok(r == ERROR_INVALID_PARAMETER,
12272        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12273     ok(!lstrcmpA(val, "apple"),
12274        "Expected val to be unchanged, got \"%s\"\n", val);
12275     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12276 
12277     /* guid with brackets */
12278     size = MAX_PATH;
12279     lstrcpyA(val, "apple");
12280     r = pMsiGetPatchInfoExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", prodcode,
12281                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
12282                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12283     ok(r == ERROR_UNKNOWN_PRODUCT,
12284        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12285     ok(!lstrcmpA(val, "apple"),
12286        "Expected val to be unchanged, got \"%s\"\n", val);
12287     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12288 
12289     /* same length as guid, but random */
12290     size = MAX_PATH;
12291     lstrcpyA(val, "apple");
12292     r = pMsiGetPatchInfoExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", prodcode,
12293                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
12294                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12295     ok(r == ERROR_INVALID_PARAMETER,
12296        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12297     ok(!lstrcmpA(val, "apple"),
12298        "Expected val to be unchanged, got \"%s\"\n", val);
12299     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12300 
12301     /* NULL szProductCode */
12302     lstrcpyA(val, "apple");
12303     size = MAX_PATH;
12304     r = pMsiGetPatchInfoExA(patchcode, NULL, NULL, MSIINSTALLCONTEXT_USERMANAGED,
12305                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12306     ok(r == ERROR_INVALID_PARAMETER,
12307        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12308     ok(!lstrcmpA(val, "apple"),
12309        "Expected val to be unchanged, got \"%s\"\n", val);
12310     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12311 
12312     /* empty szProductCode */
12313     size = MAX_PATH;
12314     lstrcpyA(val, "apple");
12315     r = pMsiGetPatchInfoExA(patchcode, "", NULL, MSIINSTALLCONTEXT_USERMANAGED,
12316                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12317     ok(r == ERROR_INVALID_PARAMETER,
12318        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12319     ok(!lstrcmpA(val, "apple"),
12320        "Expected val to be unchanged, got \"%s\"\n", val);
12321     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12322 
12323     /* garbage szProductCode */
12324     size = MAX_PATH;
12325     lstrcpyA(val, "apple");
12326     r = pMsiGetPatchInfoExA(patchcode, "garbage", NULL,
12327                             MSIINSTALLCONTEXT_USERMANAGED,
12328                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12329     ok(r == ERROR_INVALID_PARAMETER,
12330        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12331     ok(!lstrcmpA(val, "apple"),
12332        "Expected val to be unchanged, got \"%s\"\n", val);
12333     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12334 
12335     /* guid without brackets */
12336     size = MAX_PATH;
12337     lstrcpyA(val, "apple");
12338     r = pMsiGetPatchInfoExA(patchcode, "6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
12339                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
12340                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12341     ok(r == ERROR_INVALID_PARAMETER,
12342        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12343     ok(!lstrcmpA(val, "apple"),
12344        "Expected val to be unchanged, got \"%s\"\n", val);
12345     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12346 
12347     /* guid with brackets */
12348     size = MAX_PATH;
12349     lstrcpyA(val, "apple");
12350     r = pMsiGetPatchInfoExA(patchcode, "{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
12351                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
12352                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12353     ok(r == ERROR_UNKNOWN_PRODUCT,
12354        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12355     ok(!lstrcmpA(val, "apple"),
12356        "Expected val to be unchanged, got \"%s\"\n", val);
12357     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12358 
12359     /* same length as guid, but random */
12360     size = MAX_PATH;
12361     lstrcpyA(val, "apple");
12362     r = pMsiGetPatchInfoExA(patchcode, "A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
12363                             NULL, MSIINSTALLCONTEXT_USERMANAGED,
12364                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12365     ok(r == ERROR_INVALID_PARAMETER,
12366        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12367     ok(!lstrcmpA(val, "apple"),
12368        "Expected val to be unchanged, got \"%s\"\n", val);
12369     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12370 
12371     /* szUserSid cannot be S-1-5-18 for MSIINSTALLCONTEXT_USERMANAGED */
12372     size = MAX_PATH;
12373     lstrcpyA(val, "apple");
12374     r = pMsiGetPatchInfoExA(patchcode, prodcode, "S-1-5-18",
12375                             MSIINSTALLCONTEXT_USERMANAGED,
12376                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12377     ok(r == ERROR_INVALID_PARAMETER,
12378        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12379     ok(!lstrcmpA(val, "apple"),
12380        "Expected val to be unchanged, got \"%s\"\n", val);
12381     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12382 
12383     /* szUserSid cannot be S-1-5-18 for MSIINSTALLCONTEXT_USERUNMANAGED */
12384     size = MAX_PATH;
12385     lstrcpyA(val, "apple");
12386     r = pMsiGetPatchInfoExA(patchcode, prodcode, "S-1-5-18",
12387                             MSIINSTALLCONTEXT_USERUNMANAGED,
12388                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12389     ok(r == ERROR_INVALID_PARAMETER,
12390        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12391     ok(!lstrcmpA(val, "apple"),
12392        "Expected val to be unchanged, got \"%s\"\n", val);
12393     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12394 
12395     /* szUserSid cannot be S-1-5-18 for MSIINSTALLCONTEXT_MACHINE */
12396     size = MAX_PATH;
12397     lstrcpyA(val, "apple");
12398     r = pMsiGetPatchInfoExA(patchcode, prodcode, "S-1-5-18",
12399                             MSIINSTALLCONTEXT_MACHINE,
12400                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12401     ok(r == ERROR_INVALID_PARAMETER,
12402        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12403     ok(!lstrcmpA(val, "apple"),
12404        "Expected val to be unchanged, got \"%s\"\n", val);
12405     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12406 
12407     /* szUserSid must be NULL for MSIINSTALLCONTEXT_MACHINE */
12408     size = MAX_PATH;
12409     lstrcpyA(val, "apple");
12410     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12411                             MSIINSTALLCONTEXT_MACHINE,
12412                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12413     ok(r == ERROR_INVALID_PARAMETER,
12414        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12415     ok(!lstrcmpA(val, "apple"),
12416        "Expected val to be unchanged, got \"%s\"\n", val);
12417     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12418 
12419     /* dwContext is out of range */
12420     size = MAX_PATH;
12421     lstrcpyA(val, "apple");
12422     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12423                             MSIINSTALLCONTEXT_NONE,
12424                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12425     ok(r == ERROR_INVALID_PARAMETER,
12426        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12427     ok(!lstrcmpA(val, "apple"),
12428        "Expected val to be unchanged, got \"%s\"\n", val);
12429     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12430 
12431     /* dwContext is out of range */
12432     size = MAX_PATH;
12433     lstrcpyA(val, "apple");
12434     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12435                             MSIINSTALLCONTEXT_ALL,
12436                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12437     ok(r == ERROR_INVALID_PARAMETER,
12438        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12439     ok(!lstrcmpA(val, "apple"),
12440        "Expected val to be unchanged, got \"%s\"\n", val);
12441     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12442 
12443     /* dwContext is invalid */
12444     size = MAX_PATH;
12445     lstrcpyA(val, "apple");
12446     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid, 3,
12447                            INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12448     ok(r == ERROR_INVALID_PARAMETER,
12449        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12450     ok(!lstrcmpA(val, "apple"),
12451        "Expected val to be unchanged, got \"%s\"\n", val);
12452     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12453 
12454     /* MSIINSTALLCONTEXT_USERMANAGED */
12455 
12456     size = MAX_PATH;
12457     lstrcpyA(val, "apple");
12458     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12459                             MSIINSTALLCONTEXT_USERMANAGED,
12460                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12461     ok(r == ERROR_UNKNOWN_PRODUCT,
12462        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12463     ok(!lstrcmpA(val, "apple"),
12464        "Expected val to be unchanged, got \"%s\"\n", val);
12465     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12466 
12467     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
12468     lstrcatA(keypath, usersid);
12469     lstrcatA(keypath, "\\Products\\");
12470     lstrcatA(keypath, prod_squashed);
12471 
12472     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
12473     if (res == ERROR_ACCESS_DENIED)
12474     {
12475         skip("Not enough rights to perform tests\n");
12476         LocalFree(usersid);
12477         return;
12478     }
12479     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12480 
12481     /* local UserData product key exists */
12482     size = MAX_PATH;
12483     lstrcpyA(val, "apple");
12484     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12485                             MSIINSTALLCONTEXT_USERMANAGED,
12486                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12487     ok(r == ERROR_UNKNOWN_PRODUCT,
12488        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12489     ok(!lstrcmpA(val, "apple"),
12490        "Expected val to be unchanged, got \"%s\"\n", val);
12491     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12492 
12493     res = RegCreateKeyExA(udprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
12494     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12495 
12496     /* InstallProperties key exists */
12497     size = MAX_PATH;
12498     lstrcpyA(val, "apple");
12499     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12500                             MSIINSTALLCONTEXT_USERMANAGED,
12501                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12502     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12503     ok(!lstrcmpA(val, "apple"),
12504        "Expected val to be unchanged, got \"%s\"\n", val);
12505     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12506 
12507     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
12508     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12509 
12510     /* Patches key exists */
12511     size = MAX_PATH;
12512     lstrcpyA(val, "apple");
12513     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12514                             MSIINSTALLCONTEXT_USERMANAGED,
12515                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12516     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCHA, got %d\n", r);
12517     ok(!lstrcmpA(val, "apple"),
12518        "Expected val to be unchanged, got \"%s\"\n", val);
12519     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12520 
12521     res = RegCreateKeyExA(patches, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
12522     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12523 
12524     /* Patches key exists */
12525     size = MAX_PATH;
12526     lstrcpyA(val, "apple");
12527     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12528                             MSIINSTALLCONTEXT_USERMANAGED,
12529                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12530     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12531     ok(!lstrcmpA(val, "apple"),
12532        "Expected val to be unchanged, got \"%s\"\n", val);
12533     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12534 
12535     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
12536     lstrcatA(keypath, usersid);
12537     lstrcatA(keypath, "\\Installer\\Products\\");
12538     lstrcatA(keypath, prod_squashed);
12539 
12540     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
12541     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12542 
12543     /* managed product key exists */
12544     size = MAX_PATH;
12545     lstrcpyA(val, "apple");
12546     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12547                             MSIINSTALLCONTEXT_USERMANAGED,
12548                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12549     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12550     ok(!lstrcmpA(val, "apple"),
12551        "Expected val to be unchanged, got \"%s\"\n", val);
12552     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12553 
12554     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &prodpatches, NULL);
12555     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12556 
12557     /* Patches key exists */
12558     size = MAX_PATH;
12559     lstrcpyA(val, "apple");
12560     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12561                             MSIINSTALLCONTEXT_USERMANAGED,
12562                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12563     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12564     ok(!lstrcmpA(val, "apple"),
12565        "Expected val to be unchanged, got \"%s\"\n", val);
12566     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12567 
12568     res = RegSetValueExA(prodpatches, patch_squashed, 0, REG_SZ,
12569                          (const BYTE *)"transforms", 11);
12570     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12571 
12572     /* specific patch value exists */
12573     size = MAX_PATH;
12574     lstrcpyA(val, "apple");
12575     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12576                             MSIINSTALLCONTEXT_USERMANAGED,
12577                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12578     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12579     ok(!lstrcmpA(val, "apple"),
12580        "Expected val to be unchanged, got \"%s\"\n", val);
12581     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12582 
12583     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
12584     lstrcatA(keypath, usersid);
12585     lstrcatA(keypath, "\\Patches\\");
12586     lstrcatA(keypath, patch_squashed);
12587 
12588     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udpatch, NULL);
12589     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12590 
12591     /* UserData Patches key exists */
12592     size = MAX_PATH;
12593     lstrcpyA(val, "apple");
12594     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12595                             MSIINSTALLCONTEXT_USERMANAGED,
12596                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12597     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12598     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
12599     ok(size == 0, "Expected 0, got %d\n", size);
12600 
12601     res = RegSetValueExA(udpatch, "ManagedLocalPackage", 0, REG_SZ,
12602                          (const BYTE *)"pack", 5);
12603     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12604 
12605     /* ManagedLocalPatch value exists */
12606     size = MAX_PATH;
12607     lstrcpyA(val, "apple");
12608     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12609                             MSIINSTALLCONTEXT_USERMANAGED,
12610                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12611     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12612     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12613     ok(size == 4, "Expected 4, got %d\n", size);
12614 
12615     size = MAX_PATH;
12616     lstrcpyA(val, "apple");
12617     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12618                             MSIINSTALLCONTEXT_USERMANAGED,
12619                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12620     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12621     ok(!lstrcmpA(val, "transforms"), "Expected \"transforms\", got \"%s\"\n", val);
12622     ok(size == 10, "Expected 10, got %d\n", size);
12623 
12624     res = RegSetValueExA(hpatch, "Installed", 0, REG_SZ,
12625                          (const BYTE *)"mydate", 7);
12626     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12627 
12628     /* Installed value exists */
12629     size = MAX_PATH;
12630     lstrcpyA(val, "apple");
12631     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12632                             MSIINSTALLCONTEXT_USERMANAGED,
12633                             INSTALLPROPERTY_INSTALLDATEA, val, &size);
12634     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12635     ok(!lstrcmpA(val, "mydate"), "Expected \"mydate\", got \"%s\"\n", val);
12636     ok(size == 6, "Expected 6, got %d\n", size);
12637 
12638     res = RegSetValueExA(hpatch, "Uninstallable", 0, REG_SZ,
12639                          (const BYTE *)"yes", 4);
12640     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12641 
12642     /* Uninstallable value exists */
12643     size = MAX_PATH;
12644     lstrcpyA(val, "apple");
12645     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12646                             MSIINSTALLCONTEXT_USERMANAGED,
12647                             INSTALLPROPERTY_UNINSTALLABLEA, val, &size);
12648     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12649     ok(!lstrcmpA(val, "yes"), "Expected \"yes\", got \"%s\"\n", val);
12650     ok(size == 3, "Expected 3, got %d\n", size);
12651 
12652     res = RegSetValueExA(hpatch, "State", 0, REG_SZ,
12653                          (const BYTE *)"good", 5);
12654     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12655 
12656     /* State value exists */
12657     size = MAX_PATH;
12658     lstrcpyA(val, "apple");
12659     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12660                             MSIINSTALLCONTEXT_USERMANAGED,
12661                             INSTALLPROPERTY_PATCHSTATEA, val, &size);
12662     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12663     ok(!lstrcmpA(val, "good"), "Expected \"good\", got \"%s\"\n", val);
12664     ok(size == 4, "Expected 4, got %d\n", size);
12665 
12666     size = 1;
12667     res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
12668                          (const BYTE *)&size, sizeof(DWORD));
12669     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12670 
12671     /* State value exists */
12672     size = MAX_PATH;
12673     lstrcpyA(val, "apple");
12674     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12675                             MSIINSTALLCONTEXT_USERMANAGED,
12676                             INSTALLPROPERTY_PATCHSTATEA, val, &size);
12677     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12678     ok(!lstrcmpA(val, "1"), "Expected \"1\", got \"%s\"\n", val);
12679     ok(size == 1, "Expected 1, got %d\n", size);
12680 
12681     size = 1;
12682     res = RegSetValueExA(hpatch, "Uninstallable", 0, REG_DWORD,
12683                          (const BYTE *)&size, sizeof(DWORD));
12684     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12685 
12686     /* Uninstallable value exists */
12687     size = MAX_PATH;
12688     lstrcpyA(val, "apple");
12689     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12690                             MSIINSTALLCONTEXT_USERMANAGED,
12691                             INSTALLPROPERTY_UNINSTALLABLEA, val, &size);
12692     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12693     ok(!lstrcmpA(val, "1"), "Expected \"1\", got \"%s\"\n", val);
12694     ok(size == 1, "Expected 1, got %d\n", size);
12695 
12696     res = RegSetValueExA(hpatch, "DisplayName", 0, REG_SZ,
12697                          (const BYTE *)"display", 8);
12698     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12699 
12700     /* DisplayName value exists */
12701     size = MAX_PATH;
12702     lstrcpyA(val, "apple");
12703     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12704                             MSIINSTALLCONTEXT_USERMANAGED,
12705                             INSTALLPROPERTY_DISPLAYNAMEA, val, &size);
12706     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12707     ok(!lstrcmpA(val, "display"), "Expected \"display\", got \"%s\"\n", val);
12708     ok(size == 7, "Expected 7, got %d\n", size);
12709 
12710     res = RegSetValueExA(hpatch, "MoreInfoURL", 0, REG_SZ,
12711                          (const BYTE *)"moreinfo", 9);
12712     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12713 
12714     /* MoreInfoURL value exists */
12715     size = MAX_PATH;
12716     lstrcpyA(val, "apple");
12717     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12718                             MSIINSTALLCONTEXT_USERMANAGED,
12719                             INSTALLPROPERTY_MOREINFOURLA, val, &size);
12720     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12721     ok(!lstrcmpA(val, "moreinfo"), "Expected \"moreinfo\", got \"%s\"\n", val);
12722     ok(size == 8, "Expected 8, got %d\n", size);
12723 
12724     /* szProperty is invalid */
12725     size = MAX_PATH;
12726     lstrcpyA(val, "apple");
12727     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12728                             MSIINSTALLCONTEXT_USERMANAGED,
12729                             "IDontExist", val, &size);
12730     ok(r == ERROR_UNKNOWN_PROPERTY,
12731        "Expected ERROR_UNKNOWN_PROPERTY, got %d\n", r);
12732     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
12733     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
12734 
12735     /* lpValue is NULL, while pcchValue is non-NULL */
12736     size = MAX_PATH;
12737     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12738                             MSIINSTALLCONTEXT_USERMANAGED,
12739                             INSTALLPROPERTY_MOREINFOURLA, NULL, &size);
12740     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12741     ok(size == 16, "Expected 16, got %d\n", size);
12742 
12743     /* pcchValue is NULL, while lpValue is non-NULL */
12744     lstrcpyA(val, "apple");
12745     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12746                             MSIINSTALLCONTEXT_USERMANAGED,
12747                             INSTALLPROPERTY_MOREINFOURLA, val, NULL);
12748     ok(r == ERROR_INVALID_PARAMETER,
12749        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12750     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
12751 
12752     /* both lpValue and pcchValue are NULL */
12753     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12754                             MSIINSTALLCONTEXT_USERMANAGED,
12755                             INSTALLPROPERTY_MOREINFOURLA, NULL, NULL);
12756     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12757 
12758     /* pcchValue doesn't have enough room for NULL terminator */
12759     size = 8;
12760     lstrcpyA(val, "apple");
12761     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12762                             MSIINSTALLCONTEXT_USERMANAGED,
12763                             INSTALLPROPERTY_MOREINFOURLA, val, &size);
12764     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
12765     ok(!lstrcmpA(val, "moreinf"),
12766        "Expected \"moreinf\", got \"%s\"\n", val);
12767     ok(size == 16, "Expected 16, got %d\n", size);
12768 
12769     /* pcchValue has exactly enough room for NULL terminator */
12770     size = 9;
12771     lstrcpyA(val, "apple");
12772     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12773                             MSIINSTALLCONTEXT_USERMANAGED,
12774                             INSTALLPROPERTY_MOREINFOURLA, val, &size);
12775     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12776     ok(!lstrcmpA(val, "moreinfo"),
12777        "Expected \"moreinfo\", got \"%s\"\n", val);
12778     ok(size == 8, "Expected 8, got %d\n", size);
12779 
12780     /* pcchValue is too small, lpValue is NULL */
12781     size = 0;
12782     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12783                             MSIINSTALLCONTEXT_USERMANAGED,
12784                             INSTALLPROPERTY_MOREINFOURLA, NULL, &size);
12785     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12786     ok(size == 16, "Expected 16, got %d\n", size);
12787 
12788     RegDeleteValueA(prodpatches, patch_squashed);
12789     delete_key(prodpatches, "", access & KEY_WOW64_64KEY);
12790     RegCloseKey(prodpatches);
12791     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
12792     RegCloseKey(prodkey);
12793 
12794     /* UserData is sufficient for all properties
12795      * except INSTALLPROPERTY_TRANSFORMS
12796      */
12797     size = MAX_PATH;
12798     lstrcpyA(val, "apple");
12799     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12800                             MSIINSTALLCONTEXT_USERMANAGED,
12801                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12802     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12803     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12804     ok(size == 4, "Expected 4, got %d\n", size);
12805 
12806     /* UserData is sufficient for all properties
12807      * except INSTALLPROPERTY_TRANSFORMS
12808      */
12809     size = MAX_PATH;
12810     lstrcpyA(val, "apple");
12811     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12812                             MSIINSTALLCONTEXT_USERMANAGED,
12813                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12814     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12815     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
12816     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
12817 
12818     RegDeleteValueA(hpatch, "MoreInfoURL");
12819     RegDeleteValueA(hpatch, "Display");
12820     RegDeleteValueA(hpatch, "State");
12821     RegDeleteValueA(hpatch, "Uninstallable");
12822     RegDeleteValueA(hpatch, "Installed");
12823     RegDeleteValueA(udpatch, "ManagedLocalPackage");
12824     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
12825     RegCloseKey(udpatch);
12826     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
12827     RegCloseKey(hpatch);
12828     delete_key(patches, "", access & KEY_WOW64_64KEY);
12829     RegCloseKey(patches);
12830     delete_key(props, "", access & KEY_WOW64_64KEY);
12831     RegCloseKey(props);
12832     delete_key(udprod, "", access & KEY_WOW64_64KEY);
12833     RegCloseKey(udprod);
12834 
12835     /* MSIINSTALLCONTEXT_USERUNMANAGED */
12836 
12837     size = MAX_PATH;
12838     lstrcpyA(val, "apple");
12839     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12840                             MSIINSTALLCONTEXT_USERUNMANAGED,
12841                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12842     ok(r == ERROR_UNKNOWN_PRODUCT,
12843        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12844     ok(!lstrcmpA(val, "apple"),
12845        "Expected val to be unchanged, got \"%s\"\n", val);
12846     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12847 
12848     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
12849     lstrcatA(keypath, usersid);
12850     lstrcatA(keypath, "\\Products\\");
12851     lstrcatA(keypath, prod_squashed);
12852 
12853     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
12854     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12855 
12856     /* local UserData product key exists */
12857     size = MAX_PATH;
12858     lstrcpyA(val, "apple");
12859     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12860                             MSIINSTALLCONTEXT_USERUNMANAGED,
12861                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12862     ok(r == ERROR_UNKNOWN_PRODUCT,
12863        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12864     ok(!lstrcmpA(val, "apple"),
12865        "Expected val to be unchanged, got \"%s\"\n", val);
12866     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12867 
12868     res = RegCreateKeyExA(udprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
12869     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12870 
12871     /* InstallProperties key exists */
12872     size = MAX_PATH;
12873     lstrcpyA(val, "apple");
12874     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12875                             MSIINSTALLCONTEXT_USERUNMANAGED,
12876                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12877     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12878     ok(!lstrcmpA(val, "apple"),
12879        "Expected val to be unchanged, got \"%s\"\n", val);
12880     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12881 
12882     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
12883     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12884 
12885     /* Patches key exists */
12886     size = MAX_PATH;
12887     lstrcpyA(val, "apple");
12888     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12889                             MSIINSTALLCONTEXT_USERUNMANAGED,
12890                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12891     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12892     ok(!lstrcmpA(val, "apple"),
12893        "Expected val to be unchanged, got \"%s\"\n", val);
12894     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12895 
12896     res = RegCreateKeyExA(patches, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
12897     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12898 
12899     /* Patches key exists */
12900     size = MAX_PATH;
12901     lstrcpyA(val, "apple");
12902     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12903                             MSIINSTALLCONTEXT_USERUNMANAGED,
12904                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12905     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12906     ok(!lstrcmpA(val, "apple"),
12907        "Expected val to be unchanged, got \"%s\"\n", val);
12908     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12909 
12910     lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
12911     lstrcatA(keypath, prod_squashed);
12912 
12913     res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
12914     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12915 
12916     /* current user product key exists */
12917     size = MAX_PATH;
12918     lstrcpyA(val, "apple");
12919     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12920                             MSIINSTALLCONTEXT_USERUNMANAGED,
12921                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12922     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12923     ok(!lstrcmpA(val, "apple"),
12924        "Expected val to be unchanged, got \"%s\"\n", val);
12925     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12926 
12927     res = RegCreateKeyA(prodkey, "Patches", &prodpatches);
12928     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12929 
12930     /* Patches key exists */
12931     size = MAX_PATH;
12932     lstrcpyA(val, "apple");
12933     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12934                             MSIINSTALLCONTEXT_USERUNMANAGED,
12935                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12936     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12937     ok(!lstrcmpA(val, "apple"),
12938        "Expected val to be unchanged, got \"%s\"\n", val);
12939     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12940 
12941     res = RegSetValueExA(prodpatches, patch_squashed, 0, REG_SZ,
12942                          (const BYTE *)"transforms", 11);
12943     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12944 
12945     /* specific patch value exists */
12946     size = MAX_PATH;
12947     lstrcpyA(val, "apple");
12948     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12949                             MSIINSTALLCONTEXT_USERUNMANAGED,
12950                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12951     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
12952     ok(!lstrcmpA(val, "apple"),
12953        "Expected val to be unchanged, got \"%s\"\n", val);
12954     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
12955 
12956     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
12957     lstrcatA(keypath, usersid);
12958     lstrcatA(keypath, "\\Patches\\");
12959     lstrcatA(keypath, patch_squashed);
12960 
12961     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udpatch, NULL);
12962     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12963 
12964     /* UserData Patches key exists */
12965     size = MAX_PATH;
12966     lstrcpyA(val, "apple");
12967     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12968                             MSIINSTALLCONTEXT_USERUNMANAGED,
12969                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12970     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12971     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
12972     ok(size == 0, "Expected 0, got %d\n", size);
12973 
12974     res = RegSetValueExA(udpatch, "LocalPackage", 0, REG_SZ,
12975                          (const BYTE *)"pack", 5);
12976     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
12977 
12978     /* LocalPatch value exists */
12979     size = MAX_PATH;
12980     lstrcpyA(val, "apple");
12981     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12982                             MSIINSTALLCONTEXT_USERUNMANAGED,
12983                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
12984     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12985     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
12986     ok(size == 4, "Expected 4, got %d\n", size);
12987 
12988     size = MAX_PATH;
12989     lstrcpyA(val, "apple");
12990     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
12991                             MSIINSTALLCONTEXT_USERUNMANAGED,
12992                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
12993     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12994     ok(!lstrcmpA(val, "transforms"), "Expected \"transforms\", got \"%s\"\n", val);
12995     ok(size == 10, "Expected 10, got %d\n", size);
12996 
12997     RegDeleteValueA(prodpatches, patch_squashed);
12998     delete_key(prodpatches, "", access & KEY_WOW64_64KEY);
12999     RegCloseKey(prodpatches);
13000     RegDeleteKeyA(prodkey, "");
13001     RegCloseKey(prodkey);
13002 
13003     /* UserData is sufficient for all properties
13004      * except INSTALLPROPERTY_TRANSFORMS
13005      */
13006     size = MAX_PATH;
13007     lstrcpyA(val, "apple");
13008     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
13009                             MSIINSTALLCONTEXT_USERUNMANAGED,
13010                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13011     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13012     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
13013     ok(size == 4, "Expected 4, got %d\n", size);
13014 
13015     /* UserData is sufficient for all properties
13016      * except INSTALLPROPERTY_TRANSFORMS
13017      */
13018     size = MAX_PATH;
13019     lstrcpyA(val, "apple");
13020     r = pMsiGetPatchInfoExA(patchcode, prodcode, usersid,
13021                             MSIINSTALLCONTEXT_USERUNMANAGED,
13022                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
13023     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
13024     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
13025     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
13026 
13027     RegDeleteValueA(udpatch, "LocalPackage");
13028     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
13029     RegCloseKey(udpatch);
13030     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
13031     RegCloseKey(hpatch);
13032     delete_key(patches, "", access & KEY_WOW64_64KEY);
13033     RegCloseKey(patches);
13034     delete_key(props, "", access & KEY_WOW64_64KEY);
13035     RegCloseKey(props);
13036     delete_key(udprod, "", access & KEY_WOW64_64KEY);
13037     RegCloseKey(udprod);
13038 
13039     /* MSIINSTALLCONTEXT_MACHINE */
13040 
13041     size = MAX_PATH;
13042     lstrcpyA(val, "apple");
13043     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13044                             MSIINSTALLCONTEXT_MACHINE,
13045                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13046     ok(r == ERROR_UNKNOWN_PRODUCT,
13047        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
13048     ok(!lstrcmpA(val, "apple"),
13049        "Expected val to be unchanged, got \"%s\"\n", val);
13050     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
13051 
13052     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
13053     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Products\\");
13054     lstrcatA(keypath, prod_squashed);
13055 
13056     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
13057     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13058 
13059     /* local UserData product key exists */
13060     size = MAX_PATH;
13061     lstrcpyA(val, "apple");
13062     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13063                             MSIINSTALLCONTEXT_MACHINE,
13064                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13065     ok(r == ERROR_UNKNOWN_PRODUCT,
13066        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
13067     ok(!lstrcmpA(val, "apple"),
13068        "Expected val to be unchanged, got \"%s\"\n", val);
13069     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
13070 
13071     res = RegCreateKeyExA(udprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
13072     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13073 
13074     /* InstallProperties key exists */
13075     size = MAX_PATH;
13076     lstrcpyA(val, "apple");
13077     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13078                             MSIINSTALLCONTEXT_MACHINE,
13079                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13080     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
13081     ok(!lstrcmpA(val, "apple"),
13082        "Expected val to be unchanged, got \"%s\"\n", val);
13083     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
13084 
13085     res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
13086     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13087 
13088     /* Patches key exists */
13089     size = MAX_PATH;
13090     lstrcpyA(val, "apple");
13091     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13092                             MSIINSTALLCONTEXT_MACHINE,
13093                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13094     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
13095     ok(!lstrcmpA(val, "apple"),
13096        "Expected val to be unchanged, got \"%s\"\n", val);
13097     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
13098 
13099     res = RegCreateKeyExA(patches, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
13100     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13101 
13102     /* Patches key exists */
13103     size = MAX_PATH;
13104     lstrcpyA(val, "apple");
13105     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13106                             MSIINSTALLCONTEXT_MACHINE,
13107                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13108     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
13109     ok(!lstrcmpA(val, "apple"),
13110        "Expected val to be unchanged, got \"%s\"\n", val);
13111     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
13112 
13113     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
13114     lstrcatA(keypath, prod_squashed);
13115 
13116     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
13117     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13118 
13119     /* local product key exists */
13120     size = MAX_PATH;
13121     lstrcpyA(val, "apple");
13122     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13123                             MSIINSTALLCONTEXT_MACHINE,
13124                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13125     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
13126     ok(!lstrcmpA(val, "apple"),
13127        "Expected val to be unchanged, got \"%s\"\n", val);
13128     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
13129 
13130     res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &prodpatches, NULL);
13131     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13132 
13133     /* Patches key exists */
13134     size = MAX_PATH;
13135     lstrcpyA(val, "apple");
13136     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13137                             MSIINSTALLCONTEXT_MACHINE,
13138                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13139     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
13140     ok(!lstrcmpA(val, "apple"),
13141        "Expected val to be unchanged, got \"%s\"\n", val);
13142     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
13143 
13144     res = RegSetValueExA(prodpatches, patch_squashed, 0, REG_SZ,
13145                          (const BYTE *)"transforms", 11);
13146     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13147 
13148     /* specific patch value exists */
13149     size = MAX_PATH;
13150     lstrcpyA(val, "apple");
13151     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13152                             MSIINSTALLCONTEXT_MACHINE,
13153                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13154     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
13155     ok(!lstrcmpA(val, "apple"),
13156        "Expected val to be unchanged, got \"%s\"\n", val);
13157     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
13158 
13159     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
13160     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Patches\\");
13161     lstrcatA(keypath, patch_squashed);
13162 
13163     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udpatch, NULL);
13164     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13165 
13166     /* UserData Patches key exists */
13167     size = MAX_PATH;
13168     lstrcpyA(val, "apple");
13169     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13170                             MSIINSTALLCONTEXT_MACHINE,
13171                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13172     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13173     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
13174     ok(size == 0, "Expected 0, got %d\n", size);
13175 
13176     res = RegSetValueExA(udpatch, "LocalPackage", 0, REG_SZ,
13177                          (const BYTE *)"pack", 5);
13178     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13179 
13180     /* LocalPatch value exists */
13181     size = MAX_PATH;
13182     lstrcpyA(val, "apple");
13183     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13184                             MSIINSTALLCONTEXT_MACHINE,
13185                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13186     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13187     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
13188     ok(size == 4, "Expected 4, got %d\n", size);
13189 
13190     size = MAX_PATH;
13191     lstrcpyA(val, "apple");
13192     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13193                             MSIINSTALLCONTEXT_MACHINE,
13194                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
13195     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13196     ok(!lstrcmpA(val, "transforms"), "Expected \"transforms\", got \"%s\"\n", val);
13197     ok(size == 10, "Expected 10, got %d\n", size);
13198 
13199     RegDeleteValueA(prodpatches, patch_squashed);
13200     delete_key(prodpatches, "", access & KEY_WOW64_64KEY);
13201     RegCloseKey(prodpatches);
13202     delete_key(prodkey, "", access & KEY_WOW64_64KEY);
13203     RegCloseKey(prodkey);
13204 
13205     /* UserData is sufficient for all properties
13206      * except INSTALLPROPERTY_TRANSFORMS
13207      */
13208     size = MAX_PATH;
13209     lstrcpyA(val, "apple");
13210     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13211                             MSIINSTALLCONTEXT_MACHINE,
13212                             INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13213     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13214     ok(!lstrcmpA(val, "pack"), "Expected \"pack\", got \"%s\"\n", val);
13215     ok(size == 4, "Expected 4, got %d\n", size);
13216 
13217     /* UserData is sufficient for all properties
13218      * except INSTALLPROPERTY_TRANSFORMS
13219      */
13220     size = MAX_PATH;
13221     lstrcpyA(val, "apple");
13222     r = pMsiGetPatchInfoExA(patchcode, prodcode, NULL,
13223                             MSIINSTALLCONTEXT_MACHINE,
13224                             INSTALLPROPERTY_TRANSFORMSA, val, &size);
13225     ok(r == ERROR_UNKNOWN_PATCH, "Expected ERROR_UNKNOWN_PATCH, got %d\n", r);
13226     ok(!lstrcmpA(val, "apple"), "Expected \"apple\", got \"%s\"\n", val);
13227     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
13228 
13229     RegDeleteValueA(udpatch, "LocalPackage");
13230     delete_key(udpatch, "", access & KEY_WOW64_64KEY);
13231     RegCloseKey(udpatch);
13232     delete_key(hpatch, "", access & KEY_WOW64_64KEY);
13233     RegCloseKey(hpatch);
13234     delete_key(patches, "", access & KEY_WOW64_64KEY);
13235     RegCloseKey(patches);
13236     delete_key(props, "", access & KEY_WOW64_64KEY);
13237     RegCloseKey(props);
13238     delete_key(udprod, "", access & KEY_WOW64_64KEY);
13239     RegCloseKey(udprod);
13240     LocalFree(usersid);
13241 }
13242 
13243 static void test_MsiGetPatchInfo(void)
13244 {
13245     UINT r;
13246     char prod_code[MAX_PATH], prod_squashed[MAX_PATH], val[MAX_PATH];
13247     char patch_code[MAX_PATH], patch_squashed[MAX_PATH], keypath[MAX_PATH];
13248     WCHAR valW[MAX_PATH], patch_codeW[MAX_PATH];
13249     HKEY hkey_product, hkey_patch, hkey_patches, hkey_udprops, hkey_udproduct;
13250     HKEY hkey_udpatch, hkey_udpatches, hkey_udproductpatches, hkey_udproductpatch;
13251     DWORD size;
13252     LONG res;
13253     REGSAM access = KEY_ALL_ACCESS;
13254 
13255     create_test_guid(patch_code, patch_squashed);
13256     create_test_guid(prod_code, prod_squashed);
13257     MultiByteToWideChar(CP_ACP, 0, patch_code, -1, patch_codeW, MAX_PATH);
13258 
13259     if (is_wow64)
13260         access |= KEY_WOW64_64KEY;
13261 
13262     r = MsiGetPatchInfoA(NULL, NULL, NULL, NULL);
13263     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
13264 
13265     r = MsiGetPatchInfoA(patch_code, NULL, NULL, NULL);
13266     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
13267 
13268     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, NULL, NULL);
13269     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
13270 
13271     size = 0;
13272     r = MsiGetPatchInfoA(patch_code, NULL, NULL, &size);
13273     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
13274 
13275     r = MsiGetPatchInfoA(patch_code, "", NULL, &size);
13276     ok(r == ERROR_UNKNOWN_PROPERTY, "expected ERROR_UNKNOWN_PROPERTY, got %u\n", r);
13277 
13278     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
13279     lstrcatA(keypath, prod_squashed);
13280 
13281     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey_product, NULL);
13282     if (res == ERROR_ACCESS_DENIED)
13283     {
13284         skip("Not enough rights to perform tests\n");
13285         return;
13286     }
13287     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13288 
13289     /* product key exists */
13290     size = MAX_PATH;
13291     lstrcpyA(val, "apple");
13292     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13293     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13294     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged, got \"%s\"\n", val);
13295     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
13296 
13297     res = RegCreateKeyExA(hkey_product, "Patches", 0, NULL, 0, access, NULL, &hkey_patches, NULL);
13298     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13299 
13300     /* patches key exists */
13301     size = MAX_PATH;
13302     lstrcpyA(val, "apple");
13303     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13304     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13305     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
13306     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
13307 
13308     res = RegCreateKeyExA(hkey_patches, patch_squashed, 0, NULL, 0, access, NULL, &hkey_patch, NULL);
13309     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13310 
13311     /* patch key exists */
13312     size = MAX_PATH;
13313     lstrcpyA(val, "apple");
13314     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13315     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13316     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
13317     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
13318 
13319     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
13320     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Products\\");
13321     lstrcatA(keypath, prod_squashed);
13322 
13323     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey_udproduct, NULL);
13324     if (res == ERROR_ACCESS_DENIED)
13325     {
13326         skip("Not enough rights to perform tests\n");
13327         goto done;
13328     }
13329     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
13330 
13331     /* UserData product key exists */
13332     size = MAX_PATH;
13333     lstrcpyA(val, "apple");
13334     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13335     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13336     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
13337     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
13338 
13339     res = RegCreateKeyExA(hkey_udproduct, "InstallProperties", 0, NULL, 0, access, NULL, &hkey_udprops, NULL);
13340     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13341 
13342     /* InstallProperties key exists */
13343     size = MAX_PATH;
13344     lstrcpyA(val, "apple");
13345     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13346     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13347     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged, got \"%s\"\n", val);
13348     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
13349 
13350     res = RegCreateKeyExA(hkey_udproduct, "Patches", 0, NULL, 0, access, NULL, &hkey_udpatches, NULL);
13351     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13352 
13353     /* UserData Patches key exists */
13354     size = MAX_PATH;
13355     lstrcpyA(val, "apple");
13356     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13357     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13358     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
13359     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
13360 
13361     res = RegCreateKeyExA(hkey_udproduct, "Patches", 0, NULL, 0, access, NULL, &hkey_udproductpatches, NULL);
13362     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13363 
13364     res = RegCreateKeyExA(hkey_udproductpatches, patch_squashed, 0, NULL, 0, access, NULL, &hkey_udproductpatch, NULL);
13365     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
13366 
13367     /* UserData product patch key exists */
13368     size = MAX_PATH;
13369     lstrcpyA(val, "apple");
13370     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13371     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r);
13372     ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val);
13373     ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size);
13374 
13375     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
13376     lstrcatA(keypath, "\\UserData\\S-1-5-18\\Patches\\");
13377     lstrcatA(keypath, patch_squashed);
13378 
13379     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey_udpatch, NULL);
13380     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13381 
13382     res = RegSetValueExA(hkey_udpatch, "LocalPackage", 0, REG_SZ, (const BYTE *)"c:\\test.msp", 12);
13383     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res);
13384 
13385     /* UserData Patch key exists */
13386     size = 0;
13387     lstrcpyA(val, "apple");
13388     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13389     ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", r);
13390     ok(!lstrcmpA(val, "apple"), "expected \"apple\", got \"%s\"\n", val);
13391     ok(size == 11, "expected 11 got %u\n", size);
13392 
13393     size = MAX_PATH;
13394     lstrcpyA(val, "apple");
13395     r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size);
13396     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS got %u\n", r);
13397     ok(!lstrcmpA(val, "c:\\test.msp"), "expected \"c:\\test.msp\", got \"%s\"\n", val);
13398     ok(size == 11, "expected 11 got %u\n", size);
13399 
13400     size = 0;
13401     valW[0] = 0;
13402     r = MsiGetPatchInfoW(patch_codeW, INSTALLPROPERTY_LOCALPACKAGEW, valW, &size);
13403     ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", r);
13404     ok(!valW[0], "expected 0 got %u\n", valW[0]);
13405     ok(size == 11, "expected 11 got %u\n", size);
13406 
13407     size = MAX_PATH;
13408     valW[0] = 0;
13409     r = MsiGetPatchInfoW(patch_codeW, INSTALLPROPERTY_LOCALPACKAGEW, valW, &size);
13410     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS got %u\n", r);
13411     ok(valW[0], "expected > 0 got %u\n", valW[0]);
13412     ok(size == 11, "expected 11 got %u\n", size);
13413 
13414     delete_key(hkey_udproductpatch, "", access & KEY_WOW64_64KEY);
13415     RegCloseKey(hkey_udproductpatch);
13416     delete_key(hkey_udproductpatches, "", access & KEY_WOW64_64KEY);
13417     RegCloseKey(hkey_udproductpatches);
13418     delete_key(hkey_udpatch, "", access & KEY_WOW64_64KEY);
13419     RegCloseKey(hkey_udpatch);
13420     delete_key(hkey_udpatches, "", access & KEY_WOW64_64KEY);
13421     RegCloseKey(hkey_udpatches);
13422     delete_key(hkey_udprops, "", access & KEY_WOW64_64KEY);
13423     RegCloseKey(hkey_udprops);
13424     delete_key(hkey_udproduct, "", access & KEY_WOW64_64KEY);
13425     RegCloseKey(hkey_udproduct);
13426 
13427 done:
13428     delete_key(hkey_patches, "", access & KEY_WOW64_64KEY);
13429     RegCloseKey(hkey_patches);
13430     delete_key(hkey_product, "", access & KEY_WOW64_64KEY);
13431     RegCloseKey(hkey_product);
13432     delete_key(hkey_patch, "", access & KEY_WOW64_64KEY);
13433     RegCloseKey(hkey_patch);
13434 }
13435 
13436 static void test_MsiEnumProducts(void)
13437 {
13438     UINT r;
13439     BOOL found1, found2, found3;
13440     DWORD index;
13441     char product1[39], product2[39], product3[39], guid[39];
13442     char product_squashed1[33], product_squashed2[33], product_squashed3[33];
13443     char keypath1[MAX_PATH], keypath2[MAX_PATH], keypath3[MAX_PATH];
13444     char *usersid;
13445     HKEY key1, key2, key3;
13446     REGSAM access = KEY_ALL_ACCESS;
13447 
13448     create_test_guid(product1, product_squashed1);
13449     create_test_guid(product2, product_squashed2);
13450     create_test_guid(product3, product_squashed3);
13451     usersid = get_user_sid();
13452 
13453     if (is_wow64)
13454         access |= KEY_WOW64_64KEY;
13455 
13456     strcpy(keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
13457     strcat(keypath2, usersid);
13458     strcat(keypath2, "\\Installer\\Products\\");
13459     strcat(keypath2, product_squashed2);
13460 
13461     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL);
13462     if (r == ERROR_ACCESS_DENIED)
13463     {
13464         skip("Not enough rights to perform tests\n");
13465         LocalFree(usersid);
13466         return;
13467     }
13468     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13469 
13470     strcpy(keypath1, "Software\\Classes\\Installer\\Products\\");
13471     strcat(keypath1, product_squashed1);
13472 
13473     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL);
13474     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13475 
13476     strcpy(keypath3, "Software\\Microsoft\\Installer\\Products\\");
13477     strcat(keypath3, product_squashed3);
13478 
13479     r = RegCreateKeyA(HKEY_CURRENT_USER, keypath3, &key3);
13480     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13481 
13482     index = 0;
13483     r = MsiEnumProductsA(index, guid);
13484     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13485 
13486     r = MsiEnumProductsA(index, NULL);
13487     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
13488 
13489     index = 2;
13490     r = MsiEnumProductsA(index, guid);
13491     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
13492 
13493     index = 0;
13494     r = MsiEnumProductsA(index, guid);
13495     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13496 
13497     found1 = found2 = found3 = FALSE;
13498     while ((r = MsiEnumProductsA(index, guid)) == ERROR_SUCCESS)
13499     {
13500         if (!strcmp(product1, guid)) found1 = TRUE;
13501         if (!strcmp(product2, guid)) found2 = TRUE;
13502         if (!strcmp(product3, guid)) found3 = TRUE;
13503         index++;
13504     }
13505     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %u\n", r);
13506     ok(found1, "product1 not found\n");
13507     ok(found2, "product2 not found\n");
13508     ros_skip_flaky
13509     ok(found3, "product3 not found\n");
13510 
13511     delete_key(key1, "", access & KEY_WOW64_64KEY);
13512     delete_key(key2, "", access & KEY_WOW64_64KEY);
13513     RegDeleteKeyA(key3, "");
13514     RegCloseKey(key1);
13515     RegCloseKey(key2);
13516     RegCloseKey(key3);
13517     LocalFree(usersid);
13518 }
13519 
13520 static void test_MsiGetFileSignatureInformation(void)
13521 {
13522     HRESULT hr;
13523     const CERT_CONTEXT *cert;
13524     DWORD len;
13525 
13526     hr = MsiGetFileSignatureInformationA( NULL, 0, NULL, NULL, NULL );
13527     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13528 
13529     hr = MsiGetFileSignatureInformationA( NULL, 0, NULL, NULL, &len );
13530     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13531 
13532     hr = MsiGetFileSignatureInformationA( NULL, 0, &cert, NULL, &len );
13533     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13534 
13535     hr = MsiGetFileSignatureInformationA( "", 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, NULL );
13539     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13540 
13541     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, &len );
13542     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13543 
13544     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, &cert, NULL, &len );
13545     todo_wine ok(hr == CRYPT_E_FILE_ERROR, "expected CRYPT_E_FILE_ERROR got 0x%08x\n", hr);
13546 
13547     create_file( "signature.bin", "signature", sizeof("signature") );
13548 
13549     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, NULL );
13550     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13551 
13552     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, &len );
13553     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
13554 
13555     cert = (const CERT_CONTEXT *)0xdeadbeef;
13556     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, &cert, NULL, &len );
13557     todo_wine ok(hr == HRESULT_FROM_WIN32(ERROR_FUNCTION_FAILED), "got 0x%08x\n", hr);
13558     ok(cert == NULL, "got %p\n", cert);
13559 
13560     DeleteFileA( "signature.bin" );
13561 }
13562 
13563 static void test_MsiEnumProductsEx(void)
13564 {
13565     UINT r;
13566     DWORD len, index;
13567     MSIINSTALLCONTEXT context;
13568     char product0[39], product1[39], product2[39], product3[39], guid[39], sid[128];
13569     char product_squashed1[33], product_squashed2[33], product_squashed3[33];
13570     char keypath1[MAX_PATH], keypath2[MAX_PATH], keypath3[MAX_PATH];
13571     HKEY key1 = NULL, key2 = NULL, key3 = NULL;
13572     REGSAM access = KEY_ALL_ACCESS;
13573     char *usersid = get_user_sid();
13574 
13575     if (!pMsiEnumProductsExA)
13576     {
13577         win_skip("MsiEnumProductsExA not implemented\n");
13578         return;
13579     }
13580 
13581     create_test_guid( product0, NULL );
13582     create_test_guid( product1, product_squashed1 );
13583     create_test_guid( product2, product_squashed2 );
13584     create_test_guid( product3, product_squashed3 );
13585 
13586     if (is_wow64) access |= KEY_WOW64_64KEY;
13587 
13588     strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\" );
13589     strcat( keypath2, usersid );
13590     strcat( keypath2, "\\Installer\\Products\\" );
13591     strcat( keypath2, product_squashed2 );
13592 
13593     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
13594     if (r == ERROR_ACCESS_DENIED)
13595     {
13596         skip( "insufficient rights\n" );
13597         goto done;
13598     }
13599     ok( r == ERROR_SUCCESS, "got %u\n", r );
13600 
13601     strcpy( keypath1, "Software\\Classes\\Installer\\Products\\" );
13602     strcat( keypath1, product_squashed1 );
13603 
13604     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
13605     ok( r == ERROR_SUCCESS, "got %u\n", r );
13606 
13607     strcpy( keypath3, usersid );
13608     strcat( keypath3, "\\Software\\Microsoft\\Installer\\Products\\" );
13609     strcat( keypath3, product_squashed3 );
13610 
13611     r = RegCreateKeyExA( HKEY_USERS, keypath3, 0, NULL, 0, access, NULL, &key3, NULL );
13612     ok( r == ERROR_SUCCESS, "got %u\n", r );
13613 
13614     r = pMsiEnumProductsExA( NULL, NULL, 0, 0, NULL, NULL, NULL, NULL );
13615     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13616 
13617     len = sizeof(sid);
13618     r = pMsiEnumProductsExA( NULL, NULL, 0, 0, NULL, NULL, NULL, &len );
13619     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13620     ok( len == sizeof(sid), "got %u\n", len );
13621 
13622     r = pMsiEnumProductsExA( NULL, NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, NULL, NULL );
13623     ok( r == ERROR_SUCCESS, "got %u\n", r );
13624 
13625     sid[0] = 0;
13626     len = sizeof(sid);
13627     r = pMsiEnumProductsExA( product0, NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, &len );
13628     ok( r == ERROR_NO_MORE_ITEMS, "got %u\n", r );
13629     ok( len == sizeof(sid), "got %u\n", len );
13630     ok( !sid[0], "got %s\n", sid );
13631 
13632     sid[0] = 0;
13633     len = sizeof(sid);
13634     r = pMsiEnumProductsExA( product0, usersid, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, &len );
13635     ok( r == ERROR_NO_MORE_ITEMS, "got %u\n", r );
13636     ok( len == sizeof(sid), "got %u\n", len );
13637     ok( !sid[0], "got %s\n", sid );
13638 
13639     sid[0] = 0;
13640     len = 0;
13641     r = pMsiEnumProductsExA( NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, 0, NULL, NULL, sid, &len );
13642     ok( r == ERROR_MORE_DATA, "got %u\n", r );
13643     ok( len, "length unchanged\n" );
13644     ok( !sid[0], "got %s\n", sid );
13645 
13646     guid[0] = 0;
13647     context = 0xdeadbeef;
13648     sid[0] = 0;
13649     len = sizeof(sid);
13650     r = pMsiEnumProductsExA( NULL, NULL, MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
13651     ok( r == ERROR_SUCCESS, "got %u\n", r );
13652     ok( guid[0], "empty guid\n" );
13653     ok( context != 0xdeadbeef, "context unchanged\n" );
13654     ok( !len, "got %u\n", len );
13655     ok( !sid[0], "got %s\n", sid );
13656 
13657     guid[0] = 0;
13658     context = 0xdeadbeef;
13659     sid[0] = 0;
13660     len = sizeof(sid);
13661     r = pMsiEnumProductsExA( NULL, usersid, MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
13662     ok( r == ERROR_SUCCESS, "got %u\n", r );
13663     ok( guid[0], "empty guid\n" );
13664     ok( context != 0xdeadbeef, "context unchanged\n" );
13665     ok( !len, "got %u\n", len );
13666     ok( !sid[0], "got %s\n", sid );
13667 
13668     guid[0] = 0;
13669     context = 0xdeadbeef;
13670     sid[0] = 0;
13671     len = sizeof(sid);
13672     r = pMsiEnumProductsExA( NULL, "S-1-1-0", MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
13673     if (r == ERROR_ACCESS_DENIED)
13674     {
13675         skip( "insufficient rights\n" );
13676         goto done;
13677     }
13678     ok( r == ERROR_SUCCESS, "got %u\n", r );
13679     ok( guid[0], "empty guid\n" );
13680     ok( context != 0xdeadbeef, "context unchanged\n" );
13681     ok( !len, "got %u\n", len );
13682     ok( !sid[0], "got %s\n", sid );
13683 
13684     index = 0;
13685     guid[0] = 0;
13686     context = 0xdeadbeef;
13687     sid[0] = 0;
13688     len = sizeof(sid);
13689     while (!pMsiEnumProductsExA( NULL, "S-1-1-0", MSIINSTALLCONTEXT_ALL, index, guid, &context, sid, &len ))
13690     {
13691         if (!strcmp( product1, guid ))
13692         {
13693             ok( context == MSIINSTALLCONTEXT_MACHINE, "got %u\n", context );
13694             ok( !sid[0], "got \"%s\"\n", sid );
13695             ok( !len, "unexpected length %u\n", len );
13696         }
13697         else if (!strcmp( product2, guid ))
13698         {
13699             ok( context == MSIINSTALLCONTEXT_USERMANAGED, "got %u\n", context );
13700             ok( sid[0], "empty sid\n" );
13701             ok( len == strlen(sid), "unexpected length %u\n", len );
13702         }
13703         else if (!strcmp( product3, guid ))
13704         {
13705             ok( context == MSIINSTALLCONTEXT_USERUNMANAGED, "got %u\n", context );
13706             ok( sid[0], "empty sid\n" );
13707             ok( len == strlen(sid), "unexpected length %u\n", len );
13708         }
13709         else
13710         {
13711             trace("Unexpected guid: %s (have %s | %s | %s)\n", guid, product1, product2, product3);
13712             ok(context != MSIINSTALLCONTEXT_NONE, "got %u\n", context);
13713             ok(sid[0], "empty sid\n");
13714             ok(len == strlen(sid), "unexpected length %u\n", len);
13715         }
13716         index++;
13717         guid[0] = 0;
13718         context = 0xdeadbeef;
13719         sid[0] = 0;
13720         len = sizeof(sid);
13721     }
13722 
13723 done:
13724     delete_key( key1, "", access );
13725     delete_key( key2, "", access );
13726     delete_key( key3, "", access );
13727     RegCloseKey( key1 );
13728     RegCloseKey( key2 );
13729     RegCloseKey( key3 );
13730     LocalFree( usersid );
13731 }
13732 
13733 static void test_MsiEnumComponents(void)
13734 {
13735     UINT r;
13736     BOOL found1, found2;
13737     DWORD index;
13738     char comp1[39], comp2[39], guid[39];
13739     char comp_squashed1[33], comp_squashed2[33];
13740     char keypath1[MAX_PATH], keypath2[MAX_PATH];
13741     REGSAM access = KEY_ALL_ACCESS;
13742     char *usersid = get_user_sid();
13743     HKEY key1 = NULL, key2 = NULL;
13744 
13745     create_test_guid( comp1, comp_squashed1 );
13746     create_test_guid( comp2, comp_squashed2 );
13747 
13748     if (is_wow64) access |= KEY_WOW64_64KEY;
13749 
13750     strcpy( keypath1, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
13751     strcat( keypath1, "S-1-5-18\\Components\\" );
13752     strcat( keypath1, comp_squashed1 );
13753 
13754     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
13755     if (r == ERROR_ACCESS_DENIED)
13756     {
13757         skip( "insufficient rights\n" );
13758         goto done;
13759     }
13760     ok( r == ERROR_SUCCESS, "got %u\n", r );
13761 
13762     strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
13763     strcat( keypath2, usersid );
13764     strcat( keypath2, "\\Components\\" );
13765     strcat( keypath2, comp_squashed2 );
13766 
13767     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
13768     if (r == ERROR_ACCESS_DENIED)
13769     {
13770         skip( "insufficient rights\n" );
13771         goto done;
13772     }
13773 
13774     r = MsiEnumComponentsA( 0, NULL );
13775     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13776 
13777     index = 0;
13778     guid[0] = 0;
13779     found1 = found2 = FALSE;
13780     while (!MsiEnumComponentsA( index, guid ))
13781     {
13782         if (!strcmp( guid, comp1 )) found1 = TRUE;
13783         if (!strcmp( guid, comp2 )) found2 = TRUE;
13784         ok( guid[0], "empty guid\n" );
13785         guid[0] = 0;
13786         index++;
13787     }
13788     ok( found1, "comp1 not found\n" );
13789     ok( found2, "comp2 not found\n" );
13790 
13791 done:
13792     delete_key( key1, "", access );
13793     delete_key( key2, "", access );
13794     RegCloseKey( key1 );
13795     RegCloseKey( key2 );
13796     LocalFree( usersid );
13797 }
13798 
13799 static void test_MsiEnumComponentsEx(void)
13800 {
13801     UINT r;
13802     BOOL found1, found2;
13803     DWORD len, index;
13804     MSIINSTALLCONTEXT context;
13805     char comp1[39], comp2[39], guid[39], sid[128];
13806     char comp_squashed1[33], comp_squashed2[33];
13807     char keypath1[MAX_PATH], keypath2[MAX_PATH];
13808     HKEY key1 = NULL, key2 = NULL;
13809     REGSAM access = KEY_ALL_ACCESS;
13810     char *usersid = get_user_sid();
13811 
13812     if (!pMsiEnumComponentsExA)
13813     {
13814         win_skip( "MsiEnumComponentsExA not implemented\n" );
13815         return;
13816     }
13817     create_test_guid( comp1, comp_squashed1 );
13818     create_test_guid( comp2, comp_squashed2 );
13819 
13820     if (is_wow64) access |= KEY_WOW64_64KEY;
13821 
13822     strcpy( keypath1, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
13823     strcat( keypath1, "S-1-5-18\\Components\\" );
13824     strcat( keypath1, comp_squashed1 );
13825 
13826     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
13827     if (r == ERROR_ACCESS_DENIED)
13828     {
13829         skip( "insufficient rights\n" );
13830         goto done;
13831     }
13832     ok( r == ERROR_SUCCESS, "got %u\n", r );
13833 
13834     strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
13835     strcat( keypath2, usersid );
13836     strcat( keypath2, "\\Components\\" );
13837     strcat( keypath2, comp_squashed2 );
13838 
13839     r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
13840     if (r == ERROR_ACCESS_DENIED)
13841     {
13842         skip( "insufficient rights\n" );
13843         goto done;
13844     }
13845     ok( r == ERROR_SUCCESS, "got %u\n", r );
13846     r = RegSetValueExA( key2, comp_squashed2, 0, REG_SZ, (const BYTE *)"c:\\doesnotexist",
13847                         sizeof("c:\\doesnotexist"));
13848     ok( r == ERROR_SUCCESS, "got %u\n", r );
13849 
13850     index = 0;
13851     guid[0] = 0;
13852     context = 0xdeadbeef;
13853     sid[0] = 0;
13854     len = sizeof(sid);
13855     found1 = found2 = FALSE;
13856     while (!pMsiEnumComponentsExA( "S-1-1-0", MSIINSTALLCONTEXT_ALL, index, guid, &context, sid, &len ))
13857     {
13858         if (!strcmp( comp1, guid ))
13859         {
13860             ok( context == MSIINSTALLCONTEXT_MACHINE, "got %u\n", context );
13861             ok( !sid[0], "got \"%s\"\n", sid );
13862             ok( !len, "unexpected length %u\n", len );
13863             found1 = TRUE;
13864         }
13865         if (!strcmp( comp2, guid ))
13866         {
13867             ok( context == MSIINSTALLCONTEXT_USERUNMANAGED, "got %u\n", context );
13868             ok( sid[0], "empty sid\n" );
13869             ok( len == strlen(sid), "unexpected length %u\n", len );
13870             found2 = TRUE;
13871         }
13872         index++;
13873         guid[0] = 0;
13874         context = 0xdeadbeef;
13875         sid[0] = 0;
13876         len = sizeof(sid);
13877     }
13878     ok( found1, "comp1 not found\n" );
13879     ok( found2, "comp2 not found\n" );
13880 
13881     r = pMsiEnumComponentsExA( NULL, 0, 0, NULL, NULL, NULL, NULL );
13882     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13883 
13884     r = pMsiEnumComponentsExA( NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, NULL );
13885     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
13886 
13887 done:
13888     RegDeleteValueA( key2, comp_squashed2 );
13889     delete_key( key1, "", access );
13890     delete_key( key2, "", access );
13891     RegCloseKey( key1 );
13892     RegCloseKey( key2 );
13893     LocalFree( usersid );
13894 }
13895 
13896 static void test_MsiConfigureProductEx(void)
13897 {
13898     UINT r;
13899     LONG res;
13900     DWORD type, size;
13901     HKEY props, source;
13902     CHAR keypath[MAX_PATH * 2], localpackage[MAX_PATH], packagename[MAX_PATH];
13903     REGSAM access = KEY_ALL_ACCESS;
13904 
13905     if (is_process_limited())
13906     {
13907         skip("process is limited\n");
13908         return;
13909     }
13910 
13911     CreateDirectoryA("msitest", NULL);
13912     create_file("msitest\\hydrogen", "hydrogen", 500);
13913     create_file("msitest\\helium", "helium", 500);
13914     create_file("msitest\\lithium", "lithium", 500);
13915 
13916     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
13917 
13918     if (is_wow64)
13919         access |= KEY_WOW64_64KEY;
13920 
13921     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
13922 
13923     /* NULL szProduct */
13924     r = MsiConfigureProductExA(NULL, INSTALLLEVEL_DEFAULT,
13925                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
13926     ok(r == ERROR_INVALID_PARAMETER,
13927        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
13928 
13929     /* empty szProduct */
13930     r = MsiConfigureProductExA("", INSTALLLEVEL_DEFAULT,
13931                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
13932     ok(r == ERROR_INVALID_PARAMETER,
13933        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
13934 
13935     /* garbage szProduct */
13936     r = MsiConfigureProductExA("garbage", INSTALLLEVEL_DEFAULT,
13937                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
13938     ok(r == ERROR_INVALID_PARAMETER,
13939        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
13940 
13941     /* guid without brackets */
13942     r = MsiConfigureProductExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
13943                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13944                                "PROPVAR=42");
13945     ok(r == ERROR_INVALID_PARAMETER,
13946        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
13947 
13948     /* guid with brackets */
13949     r = MsiConfigureProductExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
13950                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13951                                "PROPVAR=42");
13952     ok(r == ERROR_UNKNOWN_PRODUCT,
13953        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
13954 
13955     /* same length as guid, but random */
13956     r = MsiConfigureProductExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
13957                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13958                                "PROPVAR=42");
13959     ok(r == ERROR_UNKNOWN_PRODUCT,
13960        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
13961 
13962     /* product not installed yet */
13963     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
13964                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13965                                "PROPVAR=42");
13966     ok(r == ERROR_UNKNOWN_PRODUCT,
13967        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
13968 
13969     /* install the product, per-user unmanaged */
13970     r = MsiInstallProductA(msifile, "INSTALLLEVEL=10 PROPVAR=42");
13971     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
13972     {
13973         skip("Not enough rights to perform tests\n");
13974         goto error;
13975     }
13976     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13977     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
13978     ok(pf_exists("msitest\\helium"), "File not installed\n");
13979     ok(pf_exists("msitest\\lithium"), "File not installed\n");
13980     ok(pf_exists("msitest"), "File not installed\n");
13981 
13982     /* product is installed per-user managed, remove it */
13983     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13984                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
13985                                "PROPVAR=42");
13986     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
13987     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
13988     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
13989     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
13990     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
13991 
13992     /* product has been removed */
13993     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
13994                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
13995                                "PROPVAR=42");
13996     ok(r == ERROR_UNKNOWN_PRODUCT,
13997        "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
13998 
13999     /* install the product, machine */
14000     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
14001     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14002     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
14003     ok(pf_exists("msitest\\helium"), "File not installed\n");
14004     ok(pf_exists("msitest\\lithium"), "File not installed\n");
14005     ok(pf_exists("msitest"), "File not installed\n");
14006 
14007     /* product is installed machine, remove it */
14008     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
14009                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
14010                                "PROPVAR=42");
14011     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
14012     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
14013     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
14014     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
14015     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
14016 
14017     /* product has been removed */
14018     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
14019                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
14020                                "PROPVAR=42");
14021     ok(r == ERROR_UNKNOWN_PRODUCT,
14022        "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14023 
14024     /* install the product, machine */
14025     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
14026     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14027     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
14028     ok(pf_exists("msitest\\helium"), "File not installed\n");
14029     ok(pf_exists("msitest\\lithium"), "File not installed\n");
14030     ok(pf_exists("msitest"), "File not installed\n");
14031 
14032     DeleteFileA(msifile);
14033 
14034     /* msifile is removed */
14035     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
14036                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
14037                                "PROPVAR=42");
14038     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
14039     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
14040     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
14041     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
14042     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
14043 
14044     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
14045 
14046     /* install the product, machine */
14047     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
14048     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14049     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
14050     ok(pf_exists("msitest\\helium"), "File not installed\n");
14051     ok(pf_exists("msitest\\lithium"), "File not installed\n");
14052     ok(pf_exists("msitest"), "File not installed\n");
14053 
14054     DeleteFileA(msifile);
14055 
14056     lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
14057     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
14058     lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\InstallProperties");
14059 
14060     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &props);
14061     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14062 
14063     type = REG_SZ;
14064     size = MAX_PATH;
14065     res = RegQueryValueExA(props, "LocalPackage", NULL, &type,
14066                            (LPBYTE)localpackage, &size);
14067     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14068 
14069     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
14070                          (const BYTE *)"C:\\idontexist.msi", 18);
14071     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14072 
14073     /* LocalPackage is used to find the cached msi package */
14074     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
14075                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
14076                                "PROPVAR=42");
14077     ok(r == ERROR_INSTALL_SOURCE_ABSENT,
14078        "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
14079     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
14080     ok(pf_exists("msitest\\helium"), "File not installed\n");
14081     ok(pf_exists("msitest\\lithium"), "File not installed\n");
14082     ok(pf_exists("msitest"), "File not installed\n");
14083 
14084     RegCloseKey(props);
14085     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
14086 
14087     /* LastUsedSource can be used as a last resort */
14088     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
14089                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
14090                                "PROPVAR=42");
14091     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
14092     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
14093     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
14094     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
14095     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
14096     DeleteFileA( localpackage );
14097 
14098     /* install the product, machine */
14099     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
14100     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14101     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
14102     ok(pf_exists("msitest\\helium"), "File not installed\n");
14103     ok(pf_exists("msitest\\lithium"), "File not installed\n");
14104     ok(pf_exists("msitest"), "File not installed\n");
14105 
14106     lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
14107     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
14108     lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\InstallProperties");
14109 
14110     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &props);
14111     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14112 
14113     type = REG_SZ;
14114     size = MAX_PATH;
14115     res = RegQueryValueExA(props, "LocalPackage", NULL, &type,
14116                            (LPBYTE)localpackage, &size);
14117     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14118 
14119     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
14120                          (const BYTE *)"C:\\idontexist.msi", 18);
14121     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14122 
14123     lstrcpyA(keypath, "SOFTWARE\\Classes\\Installer\\Products\\");
14124     lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\SourceList");
14125 
14126     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &source);
14127     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14128 
14129     type = REG_SZ;
14130     size = MAX_PATH;
14131     res = RegQueryValueExA(source, "PackageName", NULL, &type,
14132                            (LPBYTE)packagename, &size);
14133     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14134 
14135     res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
14136                          (const BYTE *)"idontexist.msi", 15);
14137     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14138 
14139     /* SourceList is altered */
14140     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
14141                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
14142                                "PROPVAR=42");
14143     ok(r == ERROR_INSTALL_SOURCE_ABSENT,
14144        "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
14145     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
14146     ok(pf_exists("msitest\\helium"), "File not installed\n");
14147     ok(pf_exists("msitest\\lithium"), "File not installed\n");
14148     ok(pf_exists("msitest"), "File not installed\n");
14149 
14150     /* restore PackageName */
14151     res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
14152                          (const BYTE *)packagename, lstrlenA(packagename) + 1);
14153     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14154 
14155     /* restore LocalPackage */
14156     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
14157                          (const BYTE *)localpackage, lstrlenA(localpackage) + 1);
14158     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
14159 
14160     /* finally remove the product */
14161     r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
14162                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
14163                                "PROPVAR=42");
14164     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
14165     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
14166     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
14167     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
14168     ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
14169 
14170     RegCloseKey(source);
14171     RegCloseKey(props);
14172 
14173 error:
14174     DeleteFileA("msitest\\hydrogen");
14175     DeleteFileA("msitest\\helium");
14176     DeleteFileA("msitest\\lithium");
14177     RemoveDirectoryA("msitest");
14178     DeleteFileA(msifile);
14179 }
14180 
14181 static void test_MsiSetFeatureAttributes(void)
14182 {
14183     UINT r;
14184     DWORD attrs;
14185     char path[MAX_PATH];
14186     MSIHANDLE package;
14187 
14188     if (is_process_limited())
14189     {
14190         skip("process is limited\n");
14191         return;
14192     }
14193     create_database( msifile, tables, sizeof(tables) / sizeof(tables[0]) );
14194 
14195     strcpy( path, CURR_DIR );
14196     strcat( path, "\\" );
14197     strcat( path, msifile );
14198 
14199     r = MsiOpenPackageA( path, &package );
14200     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14201     {
14202         skip("Not enough rights to perform tests\n");
14203         DeleteFileA( msifile );
14204         return;
14205     }
14206     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14207 
14208     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
14209     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %u\n", r);
14210 
14211     r = MsiDoActionA( package, "CostInitialize" );
14212     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14213 
14214     r = MsiSetFeatureAttributesA( 0, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
14215     ok(r == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", r);
14216 
14217     r = MsiSetFeatureAttributesA( package, "", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
14218     ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
14219 
14220     r = MsiSetFeatureAttributesA( package, NULL, INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
14221     ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
14222 
14223     r = MsiSetFeatureAttributesA( package, "One", 0 );
14224     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14225 
14226     attrs = 0xdeadbeef;
14227     r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL );
14228     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14229     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL,
14230        "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got 0x%08x\n", attrs);
14231 
14232     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
14233     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14234 
14235     attrs = 0;
14236     r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL );
14237     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14238     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL,
14239        "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got 0x%08x\n", attrs);
14240 
14241     r = MsiDoActionA( package, "FileCost" );
14242     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14243 
14244     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORSOURCE );
14245     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14246 
14247     attrs = 0;
14248     r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL );
14249     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14250     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORSOURCE,
14251        "expected INSTALLFEATUREATTRIBUTE_FAVORSOURCE, got 0x%08x\n", attrs);
14252 
14253     r = MsiDoActionA( package, "CostFinalize" );
14254     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14255 
14256     r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL );
14257     ok(r == ERROR_FUNCTION_FAILED, "expected ERROR_FUNCTION_FAILED, got %u\n", r);
14258 
14259     MsiCloseHandle( package );
14260     DeleteFileA( msifile );
14261 }
14262 
14263 static void test_MsiGetFeatureInfo(void)
14264 {
14265     UINT r;
14266     MSIHANDLE package;
14267     char title[32], help[32], path[MAX_PATH];
14268     DWORD attrs, title_len, help_len;
14269 
14270     if (is_process_limited())
14271     {
14272         skip("process is limited\n");
14273         return;
14274     }
14275     create_database( msifile, tables, sizeof(tables) / sizeof(tables[0]) );
14276 
14277     strcpy( path, CURR_DIR );
14278     strcat( path, "\\" );
14279     strcat( path, msifile );
14280 
14281     r = MsiOpenPackageA( path, &package );
14282     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14283     {
14284         skip("Not enough rights to perform tests\n");
14285         DeleteFileA( msifile );
14286         return;
14287     }
14288     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14289 
14290     r = MsiGetFeatureInfoA( 0, NULL, NULL, NULL, NULL, NULL, NULL );
14291     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
14292 
14293     r = MsiGetFeatureInfoA( package, NULL, NULL, NULL, NULL, NULL, NULL );
14294     ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
14295 
14296     r = MsiGetFeatureInfoA( package, "", NULL, NULL, NULL, NULL, NULL );
14297     ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
14298 
14299     r = MsiGetFeatureInfoA( package, "One", NULL, NULL, NULL, NULL, NULL );
14300     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14301 
14302     r = MsiGetFeatureInfoA( 0, "One", NULL, NULL, NULL, NULL, NULL );
14303     ok(r == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", r);
14304 
14305     title_len = help_len = 0;
14306     r = MsiGetFeatureInfoA( package, "One", NULL, NULL, &title_len, NULL, &help_len );
14307     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14308     ok(title_len == 3, "expected 3, got %u\n", title_len);
14309     ok(help_len == 3, "expected 3, got %u\n", help_len);
14310 
14311     title[0] = help[0] = 0;
14312     title_len = help_len = 0;
14313     r = MsiGetFeatureInfoA( package, "One", NULL, title, &title_len, help, &help_len );
14314     ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %u\n", r);
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 
14318     attrs = 0;
14319     title[0] = help[0] = 0;
14320     title_len = sizeof(title);
14321     help_len = sizeof(help);
14322     r = MsiGetFeatureInfoA( package, "One", &attrs, title, &title_len, help, &help_len );
14323     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14324     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %u\n", attrs);
14325     ok(title_len == 3, "expected 3, got %u\n", title_len);
14326     ok(help_len == 3, "expected 3, got %u\n", help_len);
14327     ok(!strcmp(title, "One"), "expected \"One\", got \"%s\"\n", title);
14328     ok(!strcmp(help, "One"), "expected \"One\", got \"%s\"\n", help);
14329 
14330     attrs = 0;
14331     title[0] = help[0] = 0;
14332     title_len = sizeof(title);
14333     help_len = sizeof(help);
14334     r = MsiGetFeatureInfoA( package, "Two", &attrs, title, &title_len, help, &help_len );
14335     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14336     ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %u\n", attrs);
14337     ok(!title_len, "expected 0, got %u\n", title_len);
14338     ok(!help_len, "expected 0, got %u\n", help_len);
14339     ok(!title[0], "expected \"\", got \"%s\"\n", title);
14340     ok(!help[0], "expected \"\", got \"%s\"\n", help);
14341 
14342     MsiCloseHandle( package );
14343     DeleteFileA( msifile );
14344 }
14345 
14346 static INT CALLBACK handler_a(LPVOID context, UINT type, LPCSTR msg)
14347 {
14348     return IDOK;
14349 }
14350 
14351 static INT CALLBACK handler_w(LPVOID context, UINT type, LPCWSTR msg)
14352 {
14353     return IDOK;
14354 }
14355 
14356 static INT CALLBACK handler_record(LPVOID context, UINT type, MSIHANDLE record)
14357 {
14358     return IDOK;
14359 }
14360 
14361 static void test_MsiSetInternalUI(void)
14362 {
14363     INSTALLUILEVEL level;
14364 
14365     level = MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
14366     ok(level == INSTALLUILEVEL_DEFAULT, "expected INSTALLUILEVEL_DEFAULT, got %d\n", level);
14367 
14368     level = MsiSetInternalUI(INSTALLUILEVEL_DEFAULT, NULL);
14369     ok(level == INSTALLUILEVEL_FULL, "expected INSTALLUILEVEL_FULL, got %d\n", level);
14370 
14371     level = MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE, NULL);
14372     ok(level == INSTALLUILEVEL_DEFAULT, "expected INSTALLUILEVEL_DEFAULT, got %d\n", level);
14373 
14374     level = MsiSetInternalUI(0xdeadbeef, NULL);
14375     ok(level == INSTALLUILEVEL_NOCHANGE, "expected INSTALLUILEVEL_NOCHANGE, got %d\n", level);
14376 }
14377 
14378 static void test_MsiSetExternalUI(void)
14379 {
14380     INSTALLUI_HANDLERA ret_a;
14381     INSTALLUI_HANDLERW ret_w;
14382     INSTALLUI_HANDLER_RECORD prev;
14383     UINT error;
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_a = MsiSetExternalUIA(NULL, 0, NULL);
14389     ok(ret_a == handler_a, "expected %p, got %p\n", handler_a, ret_a);
14390 
14391     /* Not present before Installer 3.1 */
14392     if (!pMsiSetExternalUIRecord) {
14393         win_skip("MsiSetExternalUIRecord is not available\n");
14394         return;
14395     }
14396 
14397     error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, &prev);
14398     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14399     ok(prev == NULL, "expected NULL, got %p\n", prev);
14400 
14401     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
14402     error = pMsiSetExternalUIRecord(NULL, INSTALLLOGMODE_ERROR, NULL, &prev);
14403     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14404     ok(prev == handler_record, "expected %p, got %p\n", handler_record, prev);
14405 
14406     ret_w = MsiSetExternalUIW(handler_w, INSTALLLOGMODE_ERROR, NULL);
14407     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
14408 
14409     ret_w = MsiSetExternalUIW(NULL, 0, NULL);
14410     ok(ret_w == handler_w, "expected %p, got %p\n", handler_w, ret_w);
14411 
14412     ret_a = MsiSetExternalUIA(handler_a, INSTALLLOGMODE_ERROR, NULL);
14413     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
14414 
14415     ret_w = MsiSetExternalUIW(handler_w, INSTALLLOGMODE_ERROR, NULL);
14416     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
14417 
14418     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
14419     error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, &prev);
14420     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14421     ok(prev == NULL, "expected NULL, got %p\n", prev);
14422 
14423     ret_a = MsiSetExternalUIA(NULL, 0, NULL);
14424     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
14425 
14426     ret_w = MsiSetExternalUIW(NULL, 0, NULL);
14427     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
14428 
14429     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
14430     error = pMsiSetExternalUIRecord(NULL, 0, NULL, &prev);
14431     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14432     ok(prev == handler_record, "expected %p, got %p\n", handler_record, prev);
14433 
14434     error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, NULL);
14435     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14436 
14437     error = pMsiSetExternalUIRecord(NULL, 0, NULL, NULL);
14438     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
14439 }
14440 
14441 static void test_lastusedsource(void)
14442 {
14443     static const char prodcode[] = "{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}";
14444     char value[MAX_PATH], path[MAX_PATH];
14445     DWORD size;
14446     UINT r;
14447 
14448     if (!pMsiSourceListGetInfoA)
14449     {
14450         win_skip("MsiSourceListGetInfoA is not available\n");
14451         return;
14452     }
14453 
14454     CreateDirectoryA("msitest", NULL);
14455     create_file("maximus", "maximus", 500);
14456     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
14457     DeleteFileA("maximus");
14458 
14459     create_database("msifile0.msi", lus0_tables, sizeof(lus0_tables) / sizeof(msi_table));
14460     create_database("msifile1.msi", lus1_tables, sizeof(lus1_tables) / sizeof(msi_table));
14461     create_database("msifile2.msi", lus2_tables, sizeof(lus2_tables) / sizeof(msi_table));
14462 
14463     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
14464 
14465     /* no cabinet file */
14466 
14467     size = MAX_PATH;
14468     lstrcpyA(value, "aaa");
14469     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14470                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14471     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14472     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
14473 
14474     r = MsiInstallProductA("msifile0.msi", "PUBLISH_PRODUCT=1");
14475     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14476     {
14477         skip("Not enough rights to perform tests\n");
14478         goto error;
14479     }
14480     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14481 
14482     lstrcpyA(path, CURR_DIR);
14483     lstrcatA(path, "\\");
14484 
14485     size = MAX_PATH;
14486     lstrcpyA(value, "aaa");
14487     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14488                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14489     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14490     ok(!lstrcmpA(value, path), "expected \"%s\", got \"%s\"\n", path, value);
14491     ok(size == lstrlenA(path), "expected %d, got %d\n", lstrlenA(path), size);
14492 
14493     r = MsiInstallProductA("msifile0.msi", "REMOVE=ALL");
14494     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14495 
14496     /* separate cabinet file */
14497 
14498     size = MAX_PATH;
14499     lstrcpyA(value, "aaa");
14500     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14501                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14502     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14503     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
14504 
14505     r = MsiInstallProductA("msifile1.msi", "PUBLISH_PRODUCT=1");
14506     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14507 
14508     lstrcpyA(path, CURR_DIR);
14509     lstrcatA(path, "\\");
14510 
14511     size = MAX_PATH;
14512     lstrcpyA(value, "aaa");
14513     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14514                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14515     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14516     ok(!lstrcmpA(value, path), "expected \"%s\", got \"%s\"\n", path, value);
14517     ok(size == lstrlenA(path), "expected %d, got %d\n", lstrlenA(path), size);
14518 
14519     r = MsiInstallProductA("msifile1.msi", "REMOVE=ALL");
14520     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14521 
14522     size = MAX_PATH;
14523     lstrcpyA(value, "aaa");
14524     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14525                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14526     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14527     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
14528 
14529     /* embedded cabinet stream */
14530 
14531     add_cabinet_storage("msifile2.msi", "test1.cab");
14532 
14533     r = MsiInstallProductA("msifile2.msi", "PUBLISH_PRODUCT=1");
14534     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14535 
14536     size = MAX_PATH;
14537     lstrcpyA(value, "aaa");
14538     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14539                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14540     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14541     ok(!lstrcmpA(value, path), "expected \"%s\", got \"%s\"\n", path, value);
14542     ok(size == lstrlenA(path), "expected %d, got %d\n", lstrlenA(path), size);
14543 
14544     r = MsiInstallProductA("msifile2.msi", "REMOVE=ALL");
14545     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
14546 
14547     size = MAX_PATH;
14548     lstrcpyA(value, "aaa");
14549     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
14550                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEA, value, &size);
14551     ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
14552     ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
14553 
14554 error:
14555     delete_cab_files();
14556     DeleteFileA("msitest\\maximus");
14557     RemoveDirectoryA("msitest");
14558     DeleteFileA("msifile0.msi");
14559     DeleteFileA("msifile1.msi");
14560     DeleteFileA("msifile2.msi");
14561 }
14562 
14563 static void test_setpropertyfolder(void)
14564 {
14565     UINT r;
14566     CHAR path[MAX_PATH];
14567     DWORD attr;
14568 
14569     if (is_process_limited())
14570     {
14571         skip("process is limited\n");
14572         return;
14573     }
14574 
14575     lstrcpyA(path, PROG_FILES_DIR);
14576     lstrcatA(path, "\\msitest\\added");
14577 
14578     CreateDirectoryA("msitest", NULL);
14579     create_file("msitest\\maximus", "msitest\\maximus", 500);
14580 
14581     create_database(msifile, spf_tables, sizeof(spf_tables) / sizeof(msi_table));
14582 
14583     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
14584 
14585     r = MsiInstallProductA(msifile, NULL);
14586     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14587     {
14588         skip("Not enough rights to perform tests\n");
14589         goto error;
14590     }
14591     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14592     attr = GetFileAttributesA(path);
14593     if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY))
14594     {
14595         ok(delete_pf("msitest\\added\\maximus", TRUE), "File not installed\n");
14596         ok(delete_pf("msitest\\added", FALSE), "Directory not created\n");
14597         ok(delete_pf("msitest", FALSE), "Directory not created\n");
14598     }
14599     else
14600     {
14601         trace("changing folder property not supported\n");
14602         ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
14603         ok(delete_pf("msitest", FALSE), "Directory not created\n");
14604     }
14605 
14606 error:
14607     DeleteFileA(msifile);
14608     DeleteFileA("msitest\\maximus");
14609     RemoveDirectoryA("msitest");
14610 }
14611 
14612 static void test_sourcedir_props(void)
14613 {
14614     UINT r;
14615 
14616     if (is_process_limited())
14617     {
14618         skip("process is limited\n");
14619         return;
14620     }
14621 
14622     create_test_files();
14623     create_file("msitest\\sourcedir.txt", "msitest\\sourcedir.txt", 1000);
14624     create_database(msifile, sd_tables, sizeof(sd_tables) / sizeof(msi_table));
14625 
14626     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
14627 
14628     /* full UI, no ResolveSource action */
14629     r = MsiInstallProductA(msifile, NULL);
14630     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14631 
14632     r = MsiInstallProductA(msifile, "REMOVE=ALL");
14633     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14634 
14635     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
14636     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
14637 
14638     /* full UI, ResolveSource action */
14639     r = MsiInstallProductA(msifile, "ResolveSource=1");
14640     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14641 
14642     r = MsiInstallProductA(msifile, "REMOVE=ALL");
14643     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14644 
14645     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
14646     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
14647 
14648     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
14649 
14650     /* no UI, no ResolveSource action */
14651     r = MsiInstallProductA(msifile, NULL);
14652     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14653 
14654     r = MsiInstallProductA(msifile, "REMOVE=ALL");
14655     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14656 
14657     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
14658     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
14659 
14660     /* no UI, ResolveSource action */
14661     r = MsiInstallProductA(msifile, "ResolveSource=1");
14662     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14663 
14664     r = MsiInstallProductA(msifile, "REMOVE=ALL");
14665     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14666 
14667     ok(!delete_pf("msitest\\sourcedir.txt", TRUE), "file not removed\n");
14668     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
14669 
14670     DeleteFileA("msitest\\sourcedir.txt");
14671     delete_test_files();
14672     DeleteFileA(msifile);
14673 }
14674 
14675 static void test_concurrentinstall(void)
14676 {
14677     UINT r;
14678     CHAR path[MAX_PATH];
14679 
14680     if (is_process_limited())
14681     {
14682         skip("process is limited\n");
14683         return;
14684     }
14685 
14686     CreateDirectoryA("msitest", NULL);
14687     CreateDirectoryA("msitest\\msitest", NULL);
14688     create_file("msitest\\maximus", "msitest\\maximus", 500);
14689     create_file("msitest\\msitest\\augustus", "msitest\\msitest\\augustus", 500);
14690 
14691     create_database(msifile, ci_tables, sizeof(ci_tables) / sizeof(msi_table));
14692 
14693     lstrcpyA(path, CURR_DIR);
14694     lstrcatA(path, "\\msitest\\concurrent.msi");
14695     create_database(path, ci2_tables, sizeof(ci2_tables) / sizeof(msi_table));
14696 
14697     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
14698 
14699     r = MsiInstallProductA(msifile, NULL);
14700     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
14701     {
14702         skip("Not enough rights to perform tests\n");
14703         goto error;
14704     }
14705     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14706     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
14707     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
14708     ok(delete_pf("msitest", FALSE), "Directory not created\n");
14709 
14710     r = MsiConfigureProductA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", INSTALLLEVEL_DEFAULT,
14711                              INSTALLSTATE_ABSENT);
14712     ok(r == ERROR_SUCCESS, "got %u\n", r);
14713 
14714     r = MsiConfigureProductA("{FF4AFE9C-6AC2-44F9-A060-9EA6BD16C75E}", INSTALLLEVEL_DEFAULT,
14715                              INSTALLSTATE_ABSENT);
14716     ok(r == ERROR_SUCCESS, "got %u\n", r);
14717 
14718 error:
14719     DeleteFileA(path);
14720     DeleteFileA(msifile);
14721     DeleteFileA("msitest\\msitest\\augustus");
14722     DeleteFileA("msitest\\maximus");
14723     RemoveDirectoryA("msitest\\msitest");
14724     RemoveDirectoryA("msitest");
14725 }
14726 
14727 static void test_command_line_parsing(void)
14728 {
14729     UINT r;
14730     const char *cmd;
14731 
14732     if (is_process_limited())
14733     {
14734         skip("process is limited\n");
14735         return;
14736     }
14737 
14738     create_test_files();
14739     create_database(msifile, cl_tables, sizeof(cl_tables)/sizeof(msi_table));
14740 
14741     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
14742 
14743     cmd = " ";
14744     r = MsiInstallProductA(msifile, cmd);
14745     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14746 
14747     cmd = "=";
14748     r = MsiInstallProductA(msifile, cmd);
14749     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14750 
14751     cmd = "==";
14752     r = MsiInstallProductA(msifile, cmd);
14753     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14754 
14755     cmd = "one";
14756     r = MsiInstallProductA(msifile, cmd);
14757     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14758 
14759     cmd = "=one";
14760     r = MsiInstallProductA(msifile, cmd);
14761     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14762 
14763     cmd = "P=";
14764     r = MsiInstallProductA(msifile, cmd);
14765     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14766 
14767     cmd = "  P=";
14768     r = MsiInstallProductA(msifile, cmd);
14769     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14770 
14771     cmd = "P=  ";
14772     r = MsiInstallProductA(msifile, cmd);
14773     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14774 
14775     cmd = "P=\"";
14776     r = MsiInstallProductA(msifile, cmd);
14777     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14778 
14779     cmd = "P=\"\"";
14780     r = MsiInstallProductA(msifile, cmd);
14781     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14782 
14783     cmd = "P=\"\"\"";
14784     r = MsiInstallProductA(msifile, cmd);
14785     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14786 
14787     cmd = "P=\"\"\"\"";
14788     r = MsiInstallProductA(msifile, cmd);
14789     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14790 
14791     cmd = "P=\" ";
14792     r = MsiInstallProductA(msifile, cmd);
14793     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14794 
14795     cmd = "P= \"";
14796     r = MsiInstallProductA(msifile, cmd);
14797     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14798 
14799     cmd = "P= \"\" ";
14800     r = MsiInstallProductA(msifile, cmd);
14801     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14802 
14803     cmd = "P=\"  \"";
14804     r = MsiInstallProductA(msifile, cmd);
14805     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14806 
14807     cmd = "P=one";
14808     r = MsiInstallProductA(msifile, cmd);
14809     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14810 
14811     cmd = "P= one";
14812     r = MsiInstallProductA(msifile, cmd);
14813     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14814 
14815     cmd = "P=\"one";
14816     r = MsiInstallProductA(msifile, cmd);
14817     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14818 
14819     cmd = "P=one\"";
14820     r = MsiInstallProductA(msifile, cmd);
14821     todo_wine ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14822 
14823     cmd = "P=\"one\"";
14824     r = MsiInstallProductA(msifile, cmd);
14825     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14826 
14827     cmd = "P= \"one\" ";
14828     r = MsiInstallProductA(msifile, cmd);
14829     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14830 
14831     cmd = "P=\"one\"\"";
14832     r = MsiInstallProductA(msifile, cmd);
14833     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14834 
14835     cmd = "P=\"\"one\"";
14836     r = MsiInstallProductA(msifile, cmd);
14837     ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14838 
14839     cmd = "P=\"\"one\"\"";
14840     r = MsiInstallProductA(msifile, cmd);
14841     todo_wine ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
14842 
14843     cmd = "P=\"one two\"";
14844     r = MsiInstallProductA(msifile, cmd);
14845     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14846 
14847     cmd = "P=\"\"\"one\"\" two\"";
14848     r = MsiInstallProductA(msifile, cmd);
14849     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14850 
14851     cmd = "P=\"\"\"one\"\" two\" Q=three";
14852     r = MsiInstallProductA(msifile, cmd);
14853     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14854 
14855     cmd = "P=\"\" Q=\"two\"";
14856     r = MsiInstallProductA(msifile, cmd);
14857     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14858 
14859     cmd = "P=\"one\" Q=\"two\"";
14860     r = MsiInstallProductA(msifile, cmd);
14861     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14862 
14863     cmd = "P=\"one=two\"";
14864     r = MsiInstallProductA(msifile, cmd);
14865     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14866 
14867     cmd = "Q=\"\" P=\"one\"";
14868     r = MsiInstallProductA(msifile, cmd);
14869     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
14870 
14871     cmd = "P=\"\"\"one\"\"\" Q=\"two\"";
14872     r = MsiInstallProductA(msifile, cmd);
14873     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14874 
14875     cmd = "P=\"one \"\"two\"\"\" Q=\"three\"";
14876     r = MsiInstallProductA(msifile, cmd);
14877     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14878 
14879     cmd = "P=\"\"\"one\"\" two\" Q=\"three\"";
14880     r = MsiInstallProductA(msifile, cmd);
14881     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
14882 
14883     DeleteFileA(msifile);
14884     delete_test_files();
14885 }
14886 
14887 START_TEST(msi)
14888 {
14889     DWORD len;
14890     char temp_path[MAX_PATH], prev_path[MAX_PATH];
14891 
14892 #ifdef __REACTOS__
14893     if (!winetest_interactive &&
14894         !strcmp(winetest_platform, "windows"))
14895     {
14896         skip("ROSTESTS-180: Skipping msi_winetest:msi because it hangs on WHS-Testbot. Set winetest_interactive to run it anyway.\n");
14897         return;
14898     }
14899 #endif
14900 
14901     init_functionpointers();
14902 
14903     if (pIsWow64Process)
14904         pIsWow64Process(GetCurrentProcess(), &is_wow64);
14905 
14906     GetCurrentDirectoryA(MAX_PATH, prev_path);
14907     GetTempPathA(MAX_PATH, temp_path);
14908     SetCurrentDirectoryA(temp_path);
14909 
14910     lstrcpyA(CURR_DIR, temp_path);
14911     len = lstrlenA(CURR_DIR);
14912 
14913     if(len && (CURR_DIR[len - 1] == '\\'))
14914         CURR_DIR[len - 1] = 0;
14915 
14916     ok(get_system_dirs(), "failed to retrieve system dirs\n");
14917 
14918     test_usefeature();
14919     test_null();
14920     test_getcomponentpath();
14921     test_MsiGetFileHash();
14922     test_MsiSetInternalUI();
14923 
14924     if (!pConvertSidToStringSidA)
14925         win_skip("ConvertSidToStringSidA not implemented\n");
14926     else
14927     {
14928         /* These tests rely on get_user_sid that needs ConvertSidToStringSidA */
14929         test_MsiQueryProductState();
14930         test_MsiQueryFeatureState();
14931         test_MsiQueryComponentState();
14932         test_MsiGetComponentPath();
14933         test_MsiGetComponentPathEx();
14934         test_MsiProvideComponent();
14935         test_MsiGetProductCode();
14936         test_MsiEnumClients();
14937         test_MsiGetProductInfo();
14938         test_MsiGetProductInfoEx();
14939         test_MsiGetUserInfo();
14940         test_MsiOpenProduct();
14941         test_MsiEnumPatchesEx();
14942         test_MsiEnumPatches();
14943         test_MsiGetPatchInfoEx();
14944         test_MsiGetPatchInfo();
14945         test_MsiEnumProducts();
14946         test_MsiEnumProductsEx();
14947         test_MsiEnumComponents();
14948         test_MsiEnumComponentsEx();
14949     }
14950     test_MsiGetFileVersion();
14951     test_MsiGetFileSignatureInformation();
14952     test_MsiConfigureProductEx();
14953     test_MsiSetFeatureAttributes();
14954     test_MsiGetFeatureInfo();
14955     test_MsiSetExternalUI();
14956     test_lastusedsource();
14957     test_setpropertyfolder();
14958     test_sourcedir_props();
14959     if (pMsiGetComponentPathExA)
14960         test_concurrentinstall();
14961     test_command_line_parsing();
14962     test_MsiProvideQualifiedComponentEx();
14963 
14964     SetCurrentDirectoryA(prev_path);
14965 }
14966