[MSI_WINETEST] Sync with Wine Staging 1.7.55. CORE-10536
[reactos.git] / rostests / winetests / msi / msi.c
1 /*
2 * tests for Microsoft Installer functionality
3 *
4 * Copyright 2005 Mike McCormack for CodeWeavers
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #define _WIN32_MSI 300
22 #define COBJMACROS
23
24 #include <stdio.h>
25 #include <windows.h>
26 #include <msi.h>
27 #include <msiquery.h>
28 #include <msidefs.h>
29 #include <sddl.h>
30 #include <fci.h>
31
32 #include "wine/test.h"
33
34 static BOOL is_wow64;
35 static const char msifile[] = "winetest.msi";
36 static const WCHAR msifileW[] = {'w','i','n','e','t','e','s','t','.','m','s','i',0};
37 static char CURR_DIR[MAX_PATH];
38 static char PROG_FILES_DIR[MAX_PATH];
39 static char PROG_FILES_DIR_NATIVE[MAX_PATH];
40 static char COMMON_FILES_DIR[MAX_PATH];
41 static char WINDOWS_DIR[MAX_PATH];
42
43 static BOOL (WINAPI *pCheckTokenMembership)(HANDLE,PSID,PBOOL);
44 static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
45 static BOOL (WINAPI *pOpenProcessToken)( HANDLE, DWORD, PHANDLE );
46 static LONG (WINAPI *pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD);
47 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
48
49 static INSTALLSTATE (WINAPI *pMsiGetComponentPathA)
50 (LPCSTR, LPCSTR, LPSTR, DWORD*);
51 static INSTALLSTATE (WINAPI *pMsiGetComponentPathExA)
52 (LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPSTR, LPDWORD);
53 static INSTALLSTATE (WINAPI *pMsiProvideComponentA)
54 (LPCSTR, LPCSTR, LPCSTR, DWORD, LPSTR, LPDWORD);
55 static INSTALLSTATE (WINAPI *pMsiProvideComponentW)
56 (LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPWSTR, LPDWORD);
57 static UINT (WINAPI *pMsiGetFileHashA)
58 (LPCSTR, DWORD, PMSIFILEHASHINFO);
59 static UINT (WINAPI *pMsiGetProductInfoExA)
60 (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, LPSTR, LPDWORD);
61 static UINT (WINAPI *pMsiOpenPackageExA)
62 (LPCSTR, DWORD, MSIHANDLE*);
63 static UINT (WINAPI *pMsiOpenPackageExW)
64 (LPCWSTR, DWORD, MSIHANDLE*);
65 static UINT (WINAPI *pMsiEnumPatchesExA)
66 (LPCSTR, LPCSTR, DWORD, DWORD, DWORD, LPSTR, LPSTR,
67 MSIINSTALLCONTEXT*, LPSTR, LPDWORD);
68 static UINT (WINAPI *pMsiQueryComponentStateA)
69 (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, INSTALLSTATE*);
70 static INSTALLSTATE (WINAPI *pMsiUseFeatureExA)
71 (LPCSTR, LPCSTR ,DWORD, DWORD);
72 static UINT (WINAPI *pMsiGetPatchInfoExA)
73 (LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, LPSTR, DWORD *);
74 static UINT (WINAPI *pMsiEnumProductsExA)
75 (LPCSTR, LPCSTR, DWORD, DWORD, CHAR[39], MSIINSTALLCONTEXT *, LPSTR, LPDWORD);
76 static UINT (WINAPI *pMsiEnumComponentsExA)
77 (LPCSTR, DWORD, DWORD, CHAR[39], MSIINSTALLCONTEXT *, LPSTR, LPDWORD);
78 static UINT (WINAPI *pMsiSetExternalUIRecord)
79 (INSTALLUI_HANDLER_RECORD, DWORD, LPVOID, PINSTALLUI_HANDLER_RECORD);
80 static UINT (WINAPI *pMsiSourceListGetInfoA)
81 (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, LPSTR, LPDWORD);
82
83 static void init_functionpointers(void)
84 {
85 HMODULE hmsi = GetModuleHandleA("msi.dll");
86 HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
87 HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
88
89 #define GET_PROC(dll, func) \
90 p ## func = (void *)GetProcAddress(dll, #func); \
91 if(!p ## func) \
92 trace("GetProcAddress(%s) failed\n", #func);
93
94 GET_PROC(hmsi, MsiGetComponentPathA)
95 GET_PROC(hmsi, MsiGetComponentPathExA);
96 GET_PROC(hmsi, MsiProvideComponentA)
97 GET_PROC(hmsi, MsiProvideComponentW)
98 GET_PROC(hmsi, MsiGetFileHashA)
99 GET_PROC(hmsi, MsiGetProductInfoExA)
100 GET_PROC(hmsi, MsiOpenPackageExA)
101 GET_PROC(hmsi, MsiOpenPackageExW)
102 GET_PROC(hmsi, MsiEnumPatchesExA)
103 GET_PROC(hmsi, MsiQueryComponentStateA)
104 GET_PROC(hmsi, MsiSetExternalUIRecord)
105 GET_PROC(hmsi, MsiUseFeatureExA)
106 GET_PROC(hmsi, MsiGetPatchInfoExA)
107 GET_PROC(hmsi, MsiEnumProductsExA)
108 GET_PROC(hmsi, MsiEnumComponentsExA)
109 GET_PROC(hmsi, MsiSourceListGetInfoA)
110
111 GET_PROC(hadvapi32, CheckTokenMembership);
112 GET_PROC(hadvapi32, ConvertSidToStringSidA)
113 GET_PROC(hadvapi32, OpenProcessToken);
114 GET_PROC(hadvapi32, RegDeleteKeyExA)
115 GET_PROC(hkernel32, IsWow64Process)
116
117 #undef GET_PROC
118 }
119
120 static BOOL get_system_dirs(void)
121 {
122 HKEY hkey;
123 DWORD type, size;
124
125 if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", &hkey))
126 return FALSE;
127
128 size = MAX_PATH;
129 if (RegQueryValueExA(hkey, "ProgramFilesDir (x86)", 0, &type, (LPBYTE)PROG_FILES_DIR, &size) &&
130 RegQueryValueExA(hkey, "ProgramFilesDir", 0, &type, (LPBYTE)PROG_FILES_DIR, &size))
131 {
132 RegCloseKey(hkey);
133 return FALSE;
134 }
135 size = MAX_PATH;
136 if (RegQueryValueExA(hkey, "CommonFilesDir (x86)", 0, &type, (LPBYTE)COMMON_FILES_DIR, &size) &&
137 RegQueryValueExA(hkey, "CommonFilesDir", 0, &type, (LPBYTE)COMMON_FILES_DIR, &size))
138 {
139 RegCloseKey(hkey);
140 return FALSE;
141 }
142 size = MAX_PATH;
143 if (RegQueryValueExA(hkey, "ProgramFilesDir", 0, &type, (LPBYTE)PROG_FILES_DIR_NATIVE, &size))
144 {
145 RegCloseKey(hkey);
146 return FALSE;
147 }
148 RegCloseKey(hkey);
149 if (!GetWindowsDirectoryA(WINDOWS_DIR, MAX_PATH)) return FALSE;
150 return TRUE;
151 }
152
153 static BOOL file_exists(const char *file)
154 {
155 return GetFileAttributesA(file) != INVALID_FILE_ATTRIBUTES;
156 }
157
158 static BOOL pf_exists(const char *file)
159 {
160 char path[MAX_PATH];
161
162 lstrcpyA(path, PROG_FILES_DIR);
163 lstrcatA(path, "\\");
164 lstrcatA(path, file);
165 return file_exists(path);
166 }
167
168 static BOOL delete_pf(const char *rel_path, BOOL is_file)
169 {
170 char path[MAX_PATH];
171
172 lstrcpyA(path, PROG_FILES_DIR);
173 lstrcatA(path, "\\");
174 lstrcatA(path, rel_path);
175
176 if (is_file)
177 return DeleteFileA(path);
178 else
179 return RemoveDirectoryA(path);
180 }
181
182 static BOOL is_process_limited(void)
183 {
184 SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
185 PSID Group = NULL;
186 BOOL IsInGroup;
187 HANDLE token;
188
189 if (!pCheckTokenMembership || !pOpenProcessToken) return FALSE;
190
191 if (!AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
192 DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &Group) ||
193 !pCheckTokenMembership(NULL, Group, &IsInGroup))
194 {
195 trace("Could not check if the current user is an administrator\n");
196 FreeSid(Group);
197 return FALSE;
198 }
199 FreeSid(Group);
200
201 if (!IsInGroup)
202 {
203 /* Only administrators have enough privileges for these tests */
204 return TRUE;
205 }
206
207 if (pOpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
208 {
209 BOOL ret;
210 TOKEN_ELEVATION_TYPE type = TokenElevationTypeDefault;
211 DWORD size;
212
213 ret = GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &size);
214 CloseHandle(token);
215 return (ret && type == TokenElevationTypeLimited);
216 }
217 return FALSE;
218 }
219
220 /* cabinet definitions */
221
222 /* make the max size large so there is only one cab file */
223 #define MEDIA_SIZE 0x7FFFFFFF
224 #define FOLDER_THRESHOLD 900000
225
226 /* the FCI callbacks */
227
228 static void * CDECL mem_alloc(ULONG cb)
229 {
230 return HeapAlloc(GetProcessHeap(), 0, cb);
231 }
232
233 static void CDECL mem_free(void *memory)
234 {
235 HeapFree(GetProcessHeap(), 0, memory);
236 }
237
238 static BOOL CDECL get_next_cabinet(PCCAB pccab, ULONG cbPrevCab, void *pv)
239 {
240 sprintf(pccab->szCab, pv, pccab->iCab);
241 return TRUE;
242 }
243
244 static LONG CDECL progress(UINT typeStatus, ULONG cb1, ULONG cb2, void *pv)
245 {
246 return 0;
247 }
248
249 static int CDECL file_placed(PCCAB pccab, char *pszFile, LONG cbFile,
250 BOOL fContinuation, void *pv)
251 {
252 return 0;
253 }
254
255 static INT_PTR CDECL fci_open(char *pszFile, int oflag, int pmode, int *err, void *pv)
256 {
257 HANDLE handle;
258 DWORD dwAccess = 0;
259 DWORD dwShareMode = 0;
260 DWORD dwCreateDisposition = OPEN_EXISTING;
261
262 dwAccess = GENERIC_READ | GENERIC_WRITE;
263 /* FILE_SHARE_DELETE is not supported by Windows Me/98/95 */
264 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
265
266 if (GetFileAttributesA(pszFile) != INVALID_FILE_ATTRIBUTES)
267 dwCreateDisposition = OPEN_EXISTING;
268 else
269 dwCreateDisposition = CREATE_NEW;
270
271 handle = CreateFileA(pszFile, dwAccess, dwShareMode, NULL,
272 dwCreateDisposition, 0, NULL);
273
274 ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszFile);
275
276 return (INT_PTR)handle;
277 }
278
279 static UINT CDECL fci_read(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
280 {
281 HANDLE handle = (HANDLE)hf;
282 DWORD dwRead;
283 BOOL res;
284
285 res = ReadFile(handle, memory, cb, &dwRead, NULL);
286 ok(res, "Failed to ReadFile\n");
287
288 return dwRead;
289 }
290
291 static UINT CDECL fci_write(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
292 {
293 HANDLE handle = (HANDLE)hf;
294 DWORD dwWritten;
295 BOOL res;
296
297 res = WriteFile(handle, memory, cb, &dwWritten, NULL);
298 ok(res, "Failed to WriteFile\n");
299
300 return dwWritten;
301 }
302
303 static int CDECL fci_close(INT_PTR hf, int *err, void *pv)
304 {
305 HANDLE handle = (HANDLE)hf;
306 ok(CloseHandle(handle), "Failed to CloseHandle\n");
307
308 return 0;
309 }
310
311 static LONG CDECL fci_seek(INT_PTR hf, LONG dist, int seektype, int *err, void *pv)
312 {
313 HANDLE handle = (HANDLE)hf;
314 DWORD ret;
315
316 ret = SetFilePointer(handle, dist, NULL, seektype);
317 ok(ret != INVALID_SET_FILE_POINTER, "Failed to SetFilePointer\n");
318
319 return ret;
320 }
321
322 static int CDECL fci_delete(char *pszFile, int *err, void *pv)
323 {
324 BOOL ret = DeleteFileA(pszFile);
325 ok(ret, "Failed to DeleteFile %s\n", pszFile);
326
327 return 0;
328 }
329
330 static BOOL CDECL get_temp_file(char *pszTempName, int cbTempName, void *pv)
331 {
332 LPSTR tempname;
333
334 tempname = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
335 GetTempFileNameA(".", "xx", 0, tempname);
336
337 if (tempname && (strlen(tempname) < (unsigned)cbTempName))
338 {
339 lstrcpyA(pszTempName, tempname);
340 HeapFree(GetProcessHeap(), 0, tempname);
341 return TRUE;
342 }
343
344 HeapFree(GetProcessHeap(), 0, tempname);
345
346 return FALSE;
347 }
348
349 static INT_PTR CDECL get_open_info(char *pszName, USHORT *pdate, USHORT *ptime,
350 USHORT *pattribs, int *err, void *pv)
351 {
352 BY_HANDLE_FILE_INFORMATION finfo;
353 FILETIME filetime;
354 HANDLE handle;
355 DWORD attrs;
356 BOOL res;
357
358 handle = CreateFileA(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
359 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
360 ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszName);
361
362 res = GetFileInformationByHandle(handle, &finfo);
363 ok(res, "Expected GetFileInformationByHandle to succeed\n");
364
365 FileTimeToLocalFileTime(&finfo.ftLastWriteTime, &filetime);
366 FileTimeToDosDateTime(&filetime, pdate, ptime);
367
368 attrs = GetFileAttributesA(pszName);
369 ok(attrs != INVALID_FILE_ATTRIBUTES, "Failed to GetFileAttributes\n");
370
371 return (INT_PTR)handle;
372 }
373
374 static BOOL add_file(HFCI hfci, const char *file, TCOMP compress)
375 {
376 char path[MAX_PATH];
377 char filename[MAX_PATH];
378
379 lstrcpyA(path, CURR_DIR);
380 lstrcatA(path, "\\");
381 lstrcatA(path, file);
382
383 lstrcpyA(filename, file);
384
385 return FCIAddFile(hfci, path, filename, FALSE, get_next_cabinet,
386 progress, get_open_info, compress);
387 }
388
389 static void set_cab_parameters(PCCAB pCabParams, const CHAR *name, DWORD max_size)
390 {
391 ZeroMemory(pCabParams, sizeof(CCAB));
392
393 pCabParams->cb = max_size;
394 pCabParams->cbFolderThresh = FOLDER_THRESHOLD;
395 pCabParams->setID = 0xbeef;
396 pCabParams->iCab = 1;
397 lstrcpyA(pCabParams->szCabPath, CURR_DIR);
398 lstrcatA(pCabParams->szCabPath, "\\");
399 lstrcpyA(pCabParams->szCab, name);
400 }
401
402 static void create_cab_file(const CHAR *name, DWORD max_size, const CHAR *files)
403 {
404 CCAB cabParams;
405 LPCSTR ptr;
406 HFCI hfci;
407 ERF erf;
408 BOOL res;
409
410 set_cab_parameters(&cabParams, name, max_size);
411
412 hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
413 fci_read, fci_write, fci_close, fci_seek, fci_delete,
414 get_temp_file, &cabParams, NULL);
415
416 ok(hfci != NULL, "Failed to create an FCI context\n");
417
418 ptr = files;
419 while (*ptr)
420 {
421 res = add_file(hfci, ptr, tcompTYPE_MSZIP);
422 ok(res, "Failed to add file: %s\n", ptr);
423 ptr += lstrlenA(ptr) + 1;
424 }
425
426 res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
427 ok(res, "Failed to flush the cabinet\n");
428
429 res = FCIDestroy(hfci);
430 ok(res, "Failed to destroy the cabinet\n");
431 }
432
433 static BOOL add_cabinet_storage(LPCSTR db, LPCSTR cabinet)
434 {
435 WCHAR dbW[MAX_PATH], cabinetW[MAX_PATH];
436 IStorage *stg;
437 IStream *stm;
438 HRESULT hr;
439 HANDLE handle;
440
441 MultiByteToWideChar(CP_ACP, 0, db, -1, dbW, MAX_PATH);
442 hr = StgOpenStorage(dbW, NULL, STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
443 if (FAILED(hr))
444 return FALSE;
445
446 MultiByteToWideChar(CP_ACP, 0, cabinet, -1, cabinetW, MAX_PATH);
447 hr = IStorage_CreateStream(stg, cabinetW, STGM_WRITE|STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
448 if (FAILED(hr))
449 {
450 IStorage_Release(stg);
451 return FALSE;
452 }
453
454 handle = CreateFileW(cabinetW, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
455 if (handle != INVALID_HANDLE_VALUE)
456 {
457 DWORD count;
458 char buffer[1024];
459 if (ReadFile(handle, buffer, sizeof(buffer), &count, NULL))
460 IStream_Write(stm, buffer, count, &count);
461 CloseHandle(handle);
462 }
463
464 IStream_Release(stm);
465 IStorage_Release(stg);
466
467 return TRUE;
468 }
469
470 static void delete_cab_files(void)
471 {
472 SHFILEOPSTRUCTA shfl;
473 CHAR path[MAX_PATH+10];
474
475 lstrcpyA(path, CURR_DIR);
476 lstrcatA(path, "\\*.cab");
477 path[strlen(path) + 1] = '\0';
478
479 shfl.hwnd = NULL;
480 shfl.wFunc = FO_DELETE;
481 shfl.pFrom = path;
482 shfl.pTo = NULL;
483 shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
484
485 SHFileOperationA(&shfl);
486 }
487
488 /* msi database data */
489
490 static const char directory_dat[] =
491 "Directory\tDirectory_Parent\tDefaultDir\n"
492 "s72\tS72\tl255\n"
493 "Directory\tDirectory\n"
494 "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
495 "ProgramFilesFolder\tTARGETDIR\t.\n"
496 "TARGETDIR\t\tSourceDir";
497
498 static const char component_dat[] =
499 "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
500 "s72\tS38\ts72\ti2\tS255\tS72\n"
501 "Component\tComponent\n"
502 "One\t{8F5BAEEF-DD92-40AC-9397-BE3CF9F97C81}\tMSITESTDIR\t2\tNOT REINSTALL\tone.txt\n";
503
504 static const char feature_dat[] =
505 "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
506 "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
507 "Feature\tFeature\n"
508 "One\t\tOne\tOne\t1\t3\tMSITESTDIR\t0\n"
509 "Two\t\t\t\t2\t1\tTARGETDIR\t0\n";
510
511 static const char feature_comp_dat[] =
512 "Feature_\tComponent_\n"
513 "s38\ts72\n"
514 "FeatureComponents\tFeature_\tComponent_\n"
515 "One\tOne\n";
516
517 static const char file_dat[] =
518 "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
519 "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
520 "File\tFile\n"
521 "one.txt\tOne\tone.txt\t1000\t\t\t0\t1\n";
522
523 static const char install_exec_seq_dat[] =
524 "Action\tCondition\tSequence\n"
525 "s72\tS255\tI2\n"
526 "InstallExecuteSequence\tAction\n"
527 "ValidateProductID\t\t700\n"
528 "CostInitialize\t\t800\n"
529 "FileCost\t\t900\n"
530 "CostFinalize\t\t1000\n"
531 "InstallValidate\t\t1400\n"
532 "InstallInitialize\t\t1500\n"
533 "ProcessComponents\t\t1600\n"
534 "UnpublishFeatures\t\t1800\n"
535 "RemoveFiles\t\t3500\n"
536 "InstallFiles\t\t4000\n"
537 "RegisterProduct\t\t6100\n"
538 "PublishFeatures\t\t6300\n"
539 "PublishProduct\t\t6400\n"
540 "InstallFinalize\t\t6600";
541
542 static const char media_dat[] =
543 "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
544 "i2\ti4\tL64\tS255\tS32\tS72\n"
545 "Media\tDiskId\n"
546 "1\t1\t\t\tDISK1\t\n";
547
548 static const char property_dat[] =
549 "Property\tValue\n"
550 "s72\tl0\n"
551 "Property\tProperty\n"
552 "INSTALLLEVEL\t3\n"
553 "Manufacturer\tWine\n"
554 "ProductCode\t{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}\n"
555 "ProductName\tMSITEST\n"
556 "ProductVersion\t1.1.1\n"
557 "UpgradeCode\t{9574448F-9B86-4E07-B6F6-8D199DA12127}\n"
558 "MSIFASTINSTALL\t1\n";
559
560 static const char mcp_component_dat[] =
561 "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
562 "s72\tS38\ts72\ti2\tS255\tS72\n"
563 "Component\tComponent\n"
564 "hydrogen\t{C844BD1E-1907-4C00-8BC9-150BD70DF0A1}\tMSITESTDIR\t2\t\thydrogen\n"
565 "helium\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t2\t\thelium\n"
566 "lithium\t{4AF28FFC-71C7-4307-BDE4-B77C5338F56F}\tMSITESTDIR\t2\tPROPVAR=42\tlithium\n";
567
568 static const char mcp_feature_dat[] =
569 "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
570 "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
571 "Feature\tFeature\n"
572 "hydroxyl\t\thydroxyl\thydroxyl\t2\t1\tTARGETDIR\t0\n"
573 "heliox\t\theliox\theliox\t2\t5\tTARGETDIR\t0\n"
574 "lithia\t\tlithia\tlithia\t2\t10\tTARGETDIR\t0";
575
576 static const char mcp_feature_comp_dat[] =
577 "Feature_\tComponent_\n"
578 "s38\ts72\n"
579 "FeatureComponents\tFeature_\tComponent_\n"
580 "hydroxyl\thydrogen\n"
581 "heliox\thelium\n"
582 "lithia\tlithium";
583
584 static const char mcp_file_dat[] =
585 "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
586 "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
587 "File\tFile\n"
588 "hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n"
589 "helium\thelium\thelium\t0\t\t\t8192\t1\n"
590 "lithium\tlithium\tlithium\t0\t\t\t8192\t1";
591
592 static const char lus_component_dat[] =
593 "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
594 "s72\tS38\ts72\ti2\tS255\tS72\n"
595 "Component\tComponent\n"
596 "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
597
598 static const char lus_feature_dat[] =
599 "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
600 "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
601 "Feature\tFeature\n"
602 "feature\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0\n"
603 "montecristo\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0";
604
605 static const char lus_file_dat[] =
606 "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
607 "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
608 "File\tFile\n"
609 "maximus\tmaximus\tmaximus\t500\t\t\t8192\t1";
610
611 static const char lus_feature_comp_dat[] =
612 "Feature_\tComponent_\n"
613 "s38\ts72\n"
614 "FeatureComponents\tFeature_\tComponent_\n"
615 "feature\tmaximus\n"
616 "montecristo\tmaximus";
617
618 static const char lus_install_exec_seq_dat[] =
619 "Action\tCondition\tSequence\n"
620 "s72\tS255\tI2\n"
621 "InstallExecuteSequence\tAction\n"
622 "ValidateProductID\t\t700\n"
623 "CostInitialize\t\t800\n"
624 "FileCost\t\t900\n"
625 "CostFinalize\t\t1000\n"
626 "InstallValidate\t\t1400\n"
627 "InstallInitialize\t\t1500\n"
628 "ProcessComponents\tPROCESS_COMPONENTS=1 Or FULL=1\t1600\n"
629 "UnpublishFeatures\tUNPUBLISH_FEATURES=1 Or FULL=1\t1800\n"
630 "RemoveFiles\t\t3500\n"
631 "InstallFiles\t\t4000\n"
632 "RegisterUser\tREGISTER_USER=1 Or FULL=1\t6000\n"
633 "RegisterProduct\tREGISTER_PRODUCT=1 Or FULL=1\t6100\n"
634 "PublishFeatures\tPUBLISH_FEATURES=1 Or FULL=1\t6300\n"
635 "PublishProduct\tPUBLISH_PRODUCT=1 Or FULL=1\t6400\n"
636 "InstallFinalize\t\t6600";
637
638 static const char lus0_media_dat[] =
639 "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
640 "i2\ti4\tL64\tS255\tS32\tS72\n"
641 "Media\tDiskId\n"
642 "1\t1\t\t\tDISK1\t\n";
643
644 static const char lus1_media_dat[] =
645 "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
646 "i2\ti4\tL64\tS255\tS32\tS72\n"
647 "Media\tDiskId\n"
648 "1\t1\t\ttest1.cab\tDISK1\t\n";
649
650 static const char lus2_media_dat[] =
651 "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
652 "i2\ti4\tL64\tS255\tS32\tS72\n"
653 "Media\tDiskId\n"
654 "1\t1\t\t#test1.cab\tDISK1\t\n";
655
656 static const char spf_custom_action_dat[] =
657 "Action\tType\tSource\tTarget\tISComments\n"
658 "s72\ti2\tS64\tS0\tS255\n"
659 "CustomAction\tAction\n"
660 "SetFolderProp\t51\tMSITESTDIR\t[ProgramFilesFolder]\\msitest\\added\t\n";
661
662 static const char spf_install_exec_seq_dat[] =
663 "Action\tCondition\tSequence\n"
664 "s72\tS255\tI2\n"
665 "InstallExecuteSequence\tAction\n"
666 "CostFinalize\t\t1000\n"
667 "CostInitialize\t\t800\n"
668 "FileCost\t\t900\n"
669 "SetFolderProp\t\t950\n"
670 "InstallFiles\t\t4000\n"
671 "InstallServices\t\t5000\n"
672 "InstallFinalize\t\t6600\n"
673 "InstallInitialize\t\t1500\n"
674 "InstallValidate\t\t1400\n"
675 "LaunchConditions\t\t100";
676
677 static const char spf_install_ui_seq_dat[] =
678 "Action\tCondition\tSequence\n"
679 "s72\tS255\tI2\n"
680 "InstallUISequence\tAction\n"
681 "CostInitialize\t\t800\n"
682 "FileCost\t\t900\n"
683 "CostFinalize\t\t1000\n"
684 "ExecuteAction\t\t1100\n";
685
686 static const char sd_file_dat[] =
687 "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
688 "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
689 "File\tFile\n"
690 "sourcedir.txt\tsourcedir\tsourcedir.txt\t1000\t\t\t8192\t1\n";
691
692 static const char sd_feature_dat[] =
693 "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
694 "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
695 "Feature\tFeature\n"
696 "sourcedir\t\t\tsourcedir feature\t1\t2\tMSITESTDIR\t0\n";
697
698 static const char sd_feature_comp_dat[] =
699 "Feature_\tComponent_\n"
700 "s38\ts72\n"
701 "FeatureComponents\tFeature_\tComponent_\n"
702 "sourcedir\tsourcedir\n";
703
704 static const char sd_component_dat[] =
705 "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
706 "s72\tS38\ts72\ti2\tS255\tS72\n"
707 "Component\tComponent\n"
708 "sourcedir\t{DD422F92-3ED8-49B5-A0B7-F266F98357DF}\tMSITESTDIR\t0\t\tsourcedir.txt\n";
709
710 static const char sd_install_ui_seq_dat[] =
711 "Action\tCondition\tSequence\n"
712 "s72\tS255\tI2\n"
713 "InstallUISequence\tAction\n"
714 "TestSourceDirProp1\tnot SourceDir and not SOURCEDIR and not Installed\t99\n"
715 "AppSearch\t\t100\n"
716 "TestSourceDirProp2\tnot SourceDir and not SOURCEDIR and not Installed\t101\n"
717 "LaunchConditions\tnot Installed \t110\n"
718 "TestSourceDirProp3\tnot SourceDir and not SOURCEDIR and not Installed\t111\n"
719 "FindRelatedProducts\t\t120\n"
720 "TestSourceDirProp4\tnot SourceDir and not SOURCEDIR and not Installed\t121\n"
721 "CCPSearch\t\t130\n"
722 "TestSourceDirProp5\tnot SourceDir and not SOURCEDIR and not Installed\t131\n"
723 "RMCCPSearch\t\t140\n"
724 "TestSourceDirProp6\tnot SourceDir and not SOURCEDIR and not Installed\t141\n"
725 "ValidateProductID\t\t150\n"
726 "TestSourceDirProp7\tnot SourceDir and not SOURCEDIR and not Installed\t151\n"
727 "CostInitialize\t\t800\n"
728 "TestSourceDirProp8\tnot SourceDir and not SOURCEDIR and not Installed\t801\n"
729 "FileCost\t\t900\n"
730 "TestSourceDirProp9\tnot SourceDir and not SOURCEDIR and not Installed\t901\n"
731 "IsolateComponents\t\t1000\n"
732 "TestSourceDirProp10\tnot SourceDir and not SOURCEDIR and not Installed\t1001\n"
733 "CostFinalize\t\t1100\n"
734 "TestSourceDirProp11\tnot SourceDir and not SOURCEDIR and not Installed\t1101\n"
735 "MigrateFeatureStates\t\t1200\n"
736 "TestSourceDirProp12\tnot SourceDir and not SOURCEDIR and not Installed\t1201\n"
737 "ExecuteAction\t\t1300\n"
738 "TestSourceDirProp13\tnot SourceDir and not SOURCEDIR and not Installed\t1301\n";
739
740 static const char sd_install_exec_seq_dat[] =
741 "Action\tCondition\tSequence\n"
742 "s72\tS255\tI2\n"
743 "InstallExecuteSequence\tAction\n"
744 "TestSourceDirProp14\tSourceDir and SOURCEDIR and not Installed\t99\n"
745 "LaunchConditions\t\t100\n"
746 "TestSourceDirProp15\tSourceDir and SOURCEDIR and not Installed\t101\n"
747 "ValidateProductID\t\t700\n"
748 "TestSourceDirProp16\tSourceDir and SOURCEDIR and not Installed\t701\n"
749 "CostInitialize\t\t800\n"
750 "TestSourceDirProp17\tSourceDir and SOURCEDIR and not Installed\t801\n"
751 "ResolveSource\tResolveSource and not Installed\t850\n"
752 "TestSourceDirProp18\tResolveSource and not SourceDir and not SOURCEDIR and not Installed\t851\n"
753 "TestSourceDirProp19\tnot ResolveSource and SourceDir and SOURCEDIR and not Installed\t852\n"
754 "FileCost\t\t900\n"
755 "TestSourceDirProp20\tSourceDir and SOURCEDIR and not Installed\t901\n"
756 "IsolateComponents\t\t1000\n"
757 "TestSourceDirProp21\tSourceDir and SOURCEDIR and not Installed\t1001\n"
758 "CostFinalize\t\t1100\n"
759 "TestSourceDirProp22\tSourceDir and SOURCEDIR and not Installed\t1101\n"
760 "MigrateFeatureStates\t\t1200\n"
761 "TestSourceDirProp23\tSourceDir and SOURCEDIR and not Installed\t1201\n"
762 "InstallValidate\t\t1400\n"
763 "TestSourceDirProp24\tSourceDir and SOURCEDIR and not Installed\t1401\n"
764 "InstallInitialize\t\t1500\n"
765 "TestSourceDirProp25\tSourceDir and SOURCEDIR and not Installed\t1501\n"
766 "ProcessComponents\t\t1600\n"
767 "TestSourceDirProp26\tnot SourceDir and not SOURCEDIR and not Installed\t1601\n"
768 "UnpublishFeatures\t\t1800\n"
769 "TestSourceDirProp27\tnot SourceDir and not SOURCEDIR and not Installed\t1801\n"
770 "RemoveFiles\t\t3500\n"
771 "TestSourceDirProp28\tnot SourceDir and not SOURCEDIR and not Installed\t3501\n"
772 "InstallFiles\t\t4000\n"
773 "TestSourceDirProp29\tnot SourceDir and not SOURCEDIR and not Installed\t4001\n"
774 "RegisterUser\t\t6000\n"
775 "TestSourceDirProp30\tnot SourceDir and not SOURCEDIR and not Installed\t6001\n"
776 "RegisterProduct\t\t6100\n"
777 "TestSourceDirProp31\tnot SourceDir and not SOURCEDIR and not Installed\t6101\n"
778 "PublishFeatures\t\t6300\n"
779 "TestSourceDirProp32\tnot SourceDir and not SOURCEDIR and not Installed\t6301\n"
780 "PublishProduct\t\t6400\n"
781 "TestSourceDirProp33\tnot SourceDir and not SOURCEDIR and not Installed\t6401\n"
782 "InstallExecute\t\t6500\n"
783 "TestSourceDirProp34\tnot SourceDir and not SOURCEDIR and not Installed\t6501\n"
784 "InstallFinalize\t\t6600\n"
785 "TestSourceDirProp35\tnot SourceDir and not SOURCEDIR and not Installed\t6601\n";
786
787 static const char sd_custom_action_dat[] =
788 "Action\tType\tSource\tTarget\tISComments\n"
789 "s72\ti2\tS64\tS0\tS255\n"
790 "CustomAction\tAction\n"
791 "TestSourceDirProp1\t19\t\tTest 1 failed\t\n"
792 "TestSourceDirProp2\t19\t\tTest 2 failed\t\n"
793 "TestSourceDirProp3\t19\t\tTest 3 failed\t\n"
794 "TestSourceDirProp4\t19\t\tTest 4 failed\t\n"
795 "TestSourceDirProp5\t19\t\tTest 5 failed\t\n"
796 "TestSourceDirProp6\t19\t\tTest 6 failed\t\n"
797 "TestSourceDirProp7\t19\t\tTest 7 failed\t\n"
798 "TestSourceDirProp8\t19\t\tTest 8 failed\t\n"
799 "TestSourceDirProp9\t19\t\tTest 9 failed\t\n"
800 "TestSourceDirProp10\t19\t\tTest 10 failed\t\n"
801 "TestSourceDirProp11\t19\t\tTest 11 failed\t\n"
802 "TestSourceDirProp12\t19\t\tTest 12 failed\t\n"
803 "TestSourceDirProp13\t19\t\tTest 13 failed\t\n"
804 "TestSourceDirProp14\t19\t\tTest 14 failed\t\n"
805 "TestSourceDirProp15\t19\t\tTest 15 failed\t\n"
806 "TestSourceDirProp16\t19\t\tTest 16 failed\t\n"
807 "TestSourceDirProp17\t19\t\tTest 17 failed\t\n"
808 "TestSourceDirProp18\t19\t\tTest 18 failed\t\n"
809 "TestSourceDirProp19\t19\t\tTest 19 failed\t\n"
810 "TestSourceDirProp20\t19\t\tTest 20 failed\t\n"
811 "TestSourceDirProp21\t19\t\tTest 21 failed\t\n"
812 "TestSourceDirProp22\t19\t\tTest 22 failed\t\n"
813 "TestSourceDirProp23\t19\t\tTest 23 failed\t\n"
814 "TestSourceDirProp24\t19\t\tTest 24 failed\t\n"
815 "TestSourceDirProp25\t19\t\tTest 25 failed\t\n"
816 "TestSourceDirProp26\t19\t\tTest 26 failed\t\n"
817 "TestSourceDirProp27\t19\t\tTest 27 failed\t\n"
818 "TestSourceDirProp28\t19\t\tTest 28 failed\t\n"
819 "TestSourceDirProp29\t19\t\tTest 29 failed\t\n"
820 "TestSourceDirProp30\t19\t\tTest 30 failed\t\n"
821 "TestSourceDirProp31\t19\t\tTest 31 failed\t\n"
822 "TestSourceDirProp32\t19\t\tTest 32 failed\t\n"
823 "TestSourceDirProp33\t19\t\tTest 33 failed\t\n"
824 "TestSourceDirProp34\t19\t\tTest 34 failed\t\n"
825 "TestSourceDirProp35\t19\t\tTest 35 failed\t\n";
826
827 static const char ci_install_exec_seq_dat[] =
828 "Action\tCondition\tSequence\n"
829 "s72\tS255\tI2\n"
830 "InstallExecuteSequence\tAction\n"
831 "CostFinalize\t\t1000\n"
832 "CostInitialize\t\t800\n"
833 "FileCost\t\t900\n"
834 "InstallFiles\t\t4000\n"
835 "InstallServices\t\t5000\n"
836 "InstallFinalize\t\t6600\n"
837 "InstallInitialize\t\t1500\n"
838 "RunInstall\t\t1600\n"
839 "InstallValidate\t\t1400\n"
840 "LaunchConditions\t\t100";
841
842 static const char ci_custom_action_dat[] =
843 "Action\tType\tSource\tTarget\tISComments\n"
844 "s72\ti2\tS64\tS0\tS255\n"
845 "CustomAction\tAction\n"
846 "RunInstall\t87\tmsitest\\concurrent.msi\tMYPROP=[UILevel]\t\n";
847
848 static const char ci_component_dat[] =
849 "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
850 "s72\tS38\ts72\ti2\tS255\tS72\n"
851 "Component\tComponent\n"
852 "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
853
854 static const char ci2_component_dat[] =
855 "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
856 "s72\tS38\ts72\ti2\tS255\tS72\n"
857 "Component\tComponent\n"
858 "augustus\t\tMSITESTDIR\t0\tUILevel=3 AND MYPROP=5\taugustus\n";
859
860 static const char ci2_feature_comp_dat[] =
861 "Feature_\tComponent_\n"
862 "s38\ts72\n"
863 "FeatureComponents\tFeature_\tComponent_\n"
864 "feature\taugustus";
865
866 static const char ci2_file_dat[] =
867 "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
868 "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
869 "File\tFile\n"
870 "augustus\taugustus\taugustus\t500\t\t\t8192\t1";
871
872 static const char cl_custom_action_dat[] =
873 "Action\tType\tSource\tTarget\tISComments\n"
874 "s72\ti2\tS64\tS0\tS255\n"
875 "CustomAction\tAction\n"
876 "TestCommandlineProp\t19\t\tTest1\t\n";
877
878 static const char cl_install_exec_seq_dat[] =
879 "Action\tCondition\tSequence\n"
880 "s72\tS255\tI2\n"
881 "InstallExecuteSequence\tAction\n"
882 "LaunchConditions\t\t100\n"
883 "ValidateProductID\t\t700\n"
884 "CostInitialize\t\t800\n"
885 "FileCost\t\t900\n"
886 "CostFinalize\t\t1000\n"
887 "TestCommandlineProp\tP=\"one\"\t1100\n"
888 "InstallInitialize\t\t1500\n"
889 "ProcessComponents\t\t1600\n"
890 "InstallValidate\t\t1400\n"
891 "InstallFinalize\t\t5000\n";
892
893 typedef struct _msi_table
894 {
895 const CHAR *filename;
896 const CHAR *data;
897 int size;
898 } msi_table;
899
900 #define ADD_TABLE(x) {#x".idt", x##_dat, sizeof(x##_dat)}
901
902 static const msi_table tables[] =
903 {
904 ADD_TABLE(directory),
905 ADD_TABLE(component),
906 ADD_TABLE(feature),
907 ADD_TABLE(feature_comp),
908 ADD_TABLE(file),
909 ADD_TABLE(install_exec_seq),
910 ADD_TABLE(media),
911 ADD_TABLE(property),
912 };
913
914 static const msi_table mcp_tables[] =
915 {
916 ADD_TABLE(directory),
917 ADD_TABLE(mcp_component),
918 ADD_TABLE(mcp_feature),
919 ADD_TABLE(mcp_feature_comp),
920 ADD_TABLE(mcp_file),
921 ADD_TABLE(install_exec_seq),
922 ADD_TABLE(media),
923 ADD_TABLE(property)
924 };
925
926 static const msi_table lus0_tables[] =
927 {
928 ADD_TABLE(lus_component),
929 ADD_TABLE(directory),
930 ADD_TABLE(lus_feature),
931 ADD_TABLE(lus_feature_comp),
932 ADD_TABLE(lus_file),
933 ADD_TABLE(lus_install_exec_seq),
934 ADD_TABLE(lus0_media),
935 ADD_TABLE(property)
936 };
937
938 static const msi_table lus1_tables[] =
939 {
940 ADD_TABLE(lus_component),
941 ADD_TABLE(directory),
942 ADD_TABLE(lus_feature),
943 ADD_TABLE(lus_feature_comp),
944 ADD_TABLE(lus_file),
945 ADD_TABLE(lus_install_exec_seq),
946 ADD_TABLE(lus1_media),
947 ADD_TABLE(property)
948 };
949
950 static const msi_table lus2_tables[] =
951 {
952 ADD_TABLE(lus_component),
953 ADD_TABLE(directory),
954 ADD_TABLE(lus_feature),
955 ADD_TABLE(lus_feature_comp),
956 ADD_TABLE(lus_file),
957 ADD_TABLE(lus_install_exec_seq),
958 ADD_TABLE(lus2_media),
959 ADD_TABLE(property)
960 };
961
962 static const msi_table spf_tables[] =
963 {
964 ADD_TABLE(lus_component),
965 ADD_TABLE(directory),
966 ADD_TABLE(lus_feature),
967 ADD_TABLE(lus_feature_comp),
968 ADD_TABLE(lus_file),
969 ADD_TABLE(lus0_media),
970 ADD_TABLE(property),
971 ADD_TABLE(spf_custom_action),
972 ADD_TABLE(spf_install_exec_seq),
973 ADD_TABLE(spf_install_ui_seq)
974 };
975
976 static const msi_table sd_tables[] =
977 {
978 ADD_TABLE(directory),
979 ADD_TABLE(sd_component),
980 ADD_TABLE(sd_feature),
981 ADD_TABLE(sd_feature_comp),
982 ADD_TABLE(sd_file),
983 ADD_TABLE(sd_install_exec_seq),
984 ADD_TABLE(sd_install_ui_seq),
985 ADD_TABLE(sd_custom_action),
986 ADD_TABLE(media),
987 ADD_TABLE(property)
988 };
989
990 static const msi_table ci_tables[] =
991 {
992 ADD_TABLE(ci_component),
993 ADD_TABLE(directory),
994 ADD_TABLE(lus_feature),
995 ADD_TABLE(lus_feature_comp),
996 ADD_TABLE(lus_file),
997 ADD_TABLE(ci_install_exec_seq),
998 ADD_TABLE(lus0_media),
999 ADD_TABLE(property),
1000 ADD_TABLE(ci_custom_action),
1001 };
1002
1003 static const msi_table ci2_tables[] =
1004 {
1005 ADD_TABLE(ci2_component),
1006 ADD_TABLE(directory),
1007 ADD_TABLE(lus_feature),
1008 ADD_TABLE(ci2_feature_comp),
1009 ADD_TABLE(ci2_file),
1010 ADD_TABLE(install_exec_seq),
1011 ADD_TABLE(lus0_media),
1012 ADD_TABLE(property),
1013 };
1014
1015 static const msi_table cl_tables[] =
1016 {
1017 ADD_TABLE(component),
1018 ADD_TABLE(directory),
1019 ADD_TABLE(feature),
1020 ADD_TABLE(feature_comp),
1021 ADD_TABLE(file),
1022 ADD_TABLE(cl_custom_action),
1023 ADD_TABLE(cl_install_exec_seq),
1024 ADD_TABLE(media),
1025 ADD_TABLE(property)
1026 };
1027
1028 static void write_file(const CHAR *filename, const char *data, int data_size)
1029 {
1030 DWORD size;
1031
1032 HANDLE hf = CreateFileA(filename, GENERIC_WRITE, 0, NULL,
1033 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1034 WriteFile(hf, data, data_size, &size, NULL);
1035 CloseHandle(hf);
1036 }
1037
1038 static void write_msi_summary_info(MSIHANDLE db, INT version, INT wordcount, const char *template)
1039 {
1040 MSIHANDLE summary;
1041 UINT r;
1042
1043 r = MsiGetSummaryInformationA(db, NULL, 5, &summary);
1044 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1045
1046 r = MsiSummaryInfoSetPropertyA(summary, PID_TEMPLATE, VT_LPSTR, 0, NULL, template);
1047 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1048
1049 r = MsiSummaryInfoSetPropertyA(summary, PID_REVNUMBER, VT_LPSTR, 0, NULL,
1050 "{004757CA-5092-49C2-AD20-28E1CE0DF5F2}");
1051 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1052
1053 r = MsiSummaryInfoSetPropertyA(summary, PID_PAGECOUNT, VT_I4, version, NULL, NULL);
1054 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1055
1056 r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, wordcount, NULL, NULL);
1057 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1058
1059 r = MsiSummaryInfoSetPropertyA(summary, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
1060 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1061
1062 /* write the summary changes back to the stream */
1063 r = MsiSummaryInfoPersist(summary);
1064 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1065
1066 MsiCloseHandle(summary);
1067 }
1068
1069 #define create_database(name, tables, num_tables) \
1070 create_database_wordcount(name, tables, num_tables, 100, 0, ";1033");
1071
1072 #define create_database_template(name, tables, num_tables, version, template) \
1073 create_database_wordcount(name, tables, num_tables, version, 0, template);
1074
1075 static void create_database_wordcount(const CHAR *name, const msi_table *tables,
1076 int num_tables, INT version, INT wordcount,
1077 const char *template)
1078 {
1079 MSIHANDLE db;
1080 UINT r;
1081 WCHAR *nameW;
1082 int j, len;
1083
1084 len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 );
1085 if (!(nameW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return;
1086 MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, len );
1087
1088 r = MsiOpenDatabaseW(nameW, MSIDBOPEN_CREATE, &db);
1089 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1090
1091 /* import the tables into the database */
1092 for (j = 0; j < num_tables; j++)
1093 {
1094 const msi_table *table = &tables[j];
1095
1096 write_file(table->filename, table->data, (table->size - 1) * sizeof(char));
1097
1098 r = MsiDatabaseImportA(db, CURR_DIR, table->filename);
1099 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1100
1101 DeleteFileA(table->filename);
1102 }
1103
1104 write_msi_summary_info(db, version, wordcount, template);
1105
1106 r = MsiDatabaseCommit(db);
1107 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1108
1109 MsiCloseHandle(db);
1110 HeapFree( GetProcessHeap(), 0, nameW );
1111 }
1112
1113 static UINT run_query(MSIHANDLE hdb, const char *query)
1114 {
1115 MSIHANDLE hview = 0;
1116 UINT r;
1117
1118 r = MsiDatabaseOpenViewA(hdb, query, &hview);
1119 if (r != ERROR_SUCCESS)
1120 return r;
1121
1122 r = MsiViewExecute(hview, 0);
1123 if (r == ERROR_SUCCESS)
1124 r = MsiViewClose(hview);
1125 MsiCloseHandle(hview);
1126 return r;
1127 }
1128
1129 static UINT set_summary_info(MSIHANDLE hdb, LPSTR prodcode)
1130 {
1131 UINT res;
1132 MSIHANDLE suminfo;
1133
1134 /* build summary info */
1135 res = MsiGetSummaryInformationA(hdb, NULL, 7, &suminfo);
1136 ok(res == ERROR_SUCCESS, "Failed to open summaryinfo\n");
1137
1138 res = MsiSummaryInfoSetPropertyA(suminfo, 2, VT_LPSTR, 0, NULL,
1139 "Installation Database");
1140 ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1141
1142 res = MsiSummaryInfoSetPropertyA(suminfo, 3, VT_LPSTR, 0, NULL,
1143 "Installation Database");
1144 ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1145
1146 res = MsiSummaryInfoSetPropertyA(suminfo, 4, VT_LPSTR, 0, NULL,
1147 "Wine Hackers");
1148 ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1149
1150 res = MsiSummaryInfoSetPropertyA(suminfo, 7, VT_LPSTR, 0, NULL,
1151 ";1033");
1152 ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1153
1154 res = MsiSummaryInfoSetPropertyA(suminfo, PID_REVNUMBER, VT_LPSTR, 0, NULL,
1155 "{A2078D65-94D6-4205-8DEE-F68D6FD622AA}");
1156 ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1157
1158 res = MsiSummaryInfoSetPropertyA(suminfo, 14, VT_I4, 100, NULL, NULL);
1159 ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1160
1161 res = MsiSummaryInfoSetPropertyA(suminfo, 15, VT_I4, 0, NULL, NULL);
1162 ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1163
1164 res = MsiSummaryInfoPersist(suminfo);
1165 ok(res == ERROR_SUCCESS, "Failed to make summary info persist\n");
1166
1167 res = MsiCloseHandle(suminfo);
1168 ok(res == ERROR_SUCCESS, "Failed to close suminfo\n");
1169
1170 return res;
1171 }
1172
1173 static MSIHANDLE create_package_db(LPSTR prodcode)
1174 {
1175 MSIHANDLE hdb = 0;
1176 CHAR query[MAX_PATH];
1177 UINT res;
1178
1179 DeleteFileA(msifile);
1180
1181 /* create an empty database */
1182 res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
1183 ok( res == ERROR_SUCCESS , "Failed to create database\n" );
1184 if (res != ERROR_SUCCESS)
1185 return hdb;
1186
1187 res = MsiDatabaseCommit(hdb);
1188 ok(res == ERROR_SUCCESS, "Failed to commit database\n");
1189
1190 set_summary_info(hdb, prodcode);
1191
1192 res = run_query(hdb,
1193 "CREATE TABLE `Directory` ( "
1194 "`Directory` CHAR(255) NOT NULL, "
1195 "`Directory_Parent` CHAR(255), "
1196 "`DefaultDir` CHAR(255) NOT NULL "
1197 "PRIMARY KEY `Directory`)");
1198 ok(res == ERROR_SUCCESS , "Failed to create directory table\n");
1199
1200 res = run_query(hdb,
1201 "CREATE TABLE `Property` ( "
1202 "`Property` CHAR(72) NOT NULL, "
1203 "`Value` CHAR(255) "
1204 "PRIMARY KEY `Property`)");
1205 ok(res == ERROR_SUCCESS , "Failed to create directory table\n");
1206
1207 sprintf(query, "INSERT INTO `Property` "
1208 "(`Property`, `Value`) "
1209 "VALUES( 'ProductCode', '%s' )", prodcode);
1210 res = run_query(hdb, query);
1211 ok(res == ERROR_SUCCESS , "Failed\n");
1212
1213 res = MsiDatabaseCommit(hdb);
1214 ok(res == ERROR_SUCCESS, "Failed to commit database\n");
1215
1216 return hdb;
1217 }
1218
1219 static void test_usefeature(void)
1220 {
1221 INSTALLSTATE r;
1222
1223 if (!pMsiUseFeatureExA)
1224 {
1225 win_skip("MsiUseFeatureExA not implemented\n");
1226 return;
1227 }
1228
1229 r = MsiQueryFeatureStateA(NULL, NULL);
1230 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1231
1232 r = MsiQueryFeatureStateA("{9085040-6000-11d3-8cfe-0150048383c9}" ,NULL);
1233 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1234
1235 r = pMsiUseFeatureExA(NULL,NULL,0,0);
1236 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1237
1238 r = pMsiUseFeatureExA(NULL, "WORDVIEWFiles", -2, 1 );
1239 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1240
1241 r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}",
1242 NULL, -2, 0 );
1243 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1244
1245 r = pMsiUseFeatureExA("{9085040-6000-11d3-8cfe-0150048383c9}",
1246 "WORDVIEWFiles", -2, 0 );
1247 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1248
1249 r = pMsiUseFeatureExA("{0085040-6000-11d3-8cfe-0150048383c9}",
1250 "WORDVIEWFiles", -2, 0 );
1251 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1252
1253 r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}",
1254 "WORDVIEWFiles", -2, 1 );
1255 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1256 }
1257
1258 static LONG delete_key( HKEY key, LPCSTR subkey, REGSAM access )
1259 {
1260 if (pRegDeleteKeyExA)
1261 return pRegDeleteKeyExA( key, subkey, access, 0 );
1262 return RegDeleteKeyA( key, subkey );
1263 }
1264
1265 static void test_null(void)
1266 {
1267 MSIHANDLE hpkg;
1268 UINT r;
1269 HKEY hkey;
1270 DWORD dwType, cbData;
1271 LPBYTE lpData = NULL;
1272 INSTALLSTATE state;
1273 REGSAM access = KEY_ALL_ACCESS;
1274
1275 if (is_wow64)
1276 access |= KEY_WOW64_64KEY;
1277
1278 r = pMsiOpenPackageExW(NULL, 0, &hpkg);
1279 ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
1280
1281 state = MsiQueryProductStateW(NULL);
1282 ok( state == INSTALLSTATE_INVALIDARG, "wrong return\n");
1283
1284 r = MsiEnumFeaturesW(NULL,0,NULL,NULL);
1285 ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
1286
1287 r = MsiConfigureFeatureW(NULL, NULL, 0);
1288 ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
1289
1290 r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", NULL, 0);
1291 ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
1292
1293 r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000001}", "foo", 0);
1294 ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
1295
1296 r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000002}", "foo", INSTALLSTATE_DEFAULT);
1297 ok( r == ERROR_UNKNOWN_PRODUCT, "wrong error %d\n", r);
1298
1299 /* make sure empty string to MsiGetProductInfo is not a handle to default registry value, saving and restoring the
1300 * necessary registry values */
1301
1302 /* empty product string */
1303 r = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", 0, access, &hkey);
1304 if (r == ERROR_ACCESS_DENIED)
1305 {
1306 skip("Not enough rights to perform tests\n");
1307 return;
1308 }
1309 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1310
1311 r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
1312 ok ( r == ERROR_SUCCESS || r == ERROR_FILE_NOT_FOUND, "wrong error %d\n", r);
1313 if ( r == ERROR_SUCCESS )
1314 {
1315 lpData = HeapAlloc(GetProcessHeap(), 0, cbData);
1316 if (!lpData)
1317 skip("Out of memory\n");
1318 else
1319 {
1320 r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
1321 ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
1322 }
1323 }
1324
1325 r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
1326 if (r == ERROR_ACCESS_DENIED)
1327 {
1328 skip("Not enough rights to perform tests\n");
1329 HeapFree(GetProcessHeap(), 0, lpData);
1330 RegCloseKey(hkey);
1331 return;
1332 }
1333 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1334
1335 r = MsiGetProductInfoA("", "", NULL, NULL);
1336 ok ( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
1337
1338 if (lpData)
1339 {
1340 r = RegSetValueExA(hkey, NULL, 0, dwType, lpData, cbData);
1341 ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
1342
1343 HeapFree(GetProcessHeap(), 0, lpData);
1344 }
1345 else
1346 {
1347 r = RegDeleteValueA(hkey, NULL);
1348 ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
1349 }
1350
1351 r = RegCloseKey(hkey);
1352 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1353
1354 /* empty attribute */
1355 r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}",
1356 0, NULL, 0, access, NULL, &hkey, NULL);
1357 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1358
1359 r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
1360 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1361
1362 r = MsiGetProductInfoA("{F1C3AF50-8B56-4A69-A00C-00773FE42F30}", "", NULL, NULL);
1363 ok ( r == ERROR_UNKNOWN_PROPERTY, "wrong error %d\n", r);
1364
1365 r = RegCloseKey(hkey);
1366 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1367
1368 r = delete_key(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}",
1369 access & KEY_WOW64_64KEY);
1370 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1371 }
1372
1373 static void test_getcomponentpath(void)
1374 {
1375 INSTALLSTATE r;
1376 char buffer[0x100];
1377 DWORD sz;
1378
1379 if(!pMsiGetComponentPathA)
1380 return;
1381
1382 r = pMsiGetComponentPathA( NULL, NULL, NULL, NULL );
1383 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1384
1385 r = pMsiGetComponentPathA( "bogus", "bogus", NULL, NULL );
1386 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1387
1388 r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", NULL, NULL );
1389 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1390
1391 sz = sizeof buffer;
1392 buffer[0]=0;
1393 r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", buffer, &sz );
1394 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1395
1396 r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C998E7}",
1397 "{00000000-0000-0000-0000-000000000000}", buffer, &sz );
1398 ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
1399
1400 r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
1401 "{00000000-0000-0000-0000-00000000}", buffer, &sz );
1402 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1403
1404 r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
1405 "{029E403D-A86A-1D11-5B5B0006799C897E}", buffer, &sz );
1406 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1407
1408 r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C9987e}",
1409 "{00000000-A68A-11d1-5B5B-0006799C897E}", buffer, &sz );
1410 ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
1411 }
1412
1413 static void create_file(LPCSTR name, LPCSTR data, DWORD size)
1414 {
1415 HANDLE file;
1416 DWORD written;
1417
1418 file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1419 ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
1420 WriteFile(file, data, strlen(data), &written, NULL);
1421
1422 if (size)
1423 {
1424 SetFilePointer(file, size, NULL, FILE_BEGIN);
1425 SetEndOfFile(file);
1426 }
1427
1428 CloseHandle(file);
1429 }
1430
1431 static void create_test_files(void)
1432 {
1433 CreateDirectoryA("msitest", NULL);
1434 create_file("msitest\\one.txt", "msitest\\one.txt", 100);
1435 CreateDirectoryA("msitest\\first", NULL);
1436 create_file("msitest\\first\\two.txt", "msitest\\first\\two.txt", 100);
1437 CreateDirectoryA("msitest\\second", NULL);
1438 create_file("msitest\\second\\three.txt", "msitest\\second\\three.txt", 100);
1439
1440 create_file("four.txt", "four.txt", 100);
1441 create_file("five.txt", "five.txt", 100);
1442 create_cab_file("msitest.cab", MEDIA_SIZE, "four.txt\0five.txt\0");
1443
1444 create_file("msitest\\filename", "msitest\\filename", 100);
1445 create_file("msitest\\service.exe", "msitest\\service.exe", 100);
1446
1447 DeleteFileA("four.txt");
1448 DeleteFileA("five.txt");
1449 }
1450
1451 static void delete_test_files(void)
1452 {
1453 DeleteFileA("msitest.msi");
1454 DeleteFileA("msitest.cab");
1455 DeleteFileA("msitest\\second\\three.txt");
1456 DeleteFileA("msitest\\first\\two.txt");
1457 DeleteFileA("msitest\\one.txt");
1458 DeleteFileA("msitest\\service.exe");
1459 DeleteFileA("msitest\\filename");
1460 RemoveDirectoryA("msitest\\second");
1461 RemoveDirectoryA("msitest\\first");
1462 RemoveDirectoryA("msitest");
1463 }
1464
1465 #define HASHSIZE sizeof(MSIFILEHASHINFO)
1466
1467 static const struct
1468 {
1469 LPCSTR data;
1470 DWORD size;
1471 MSIFILEHASHINFO hash;
1472 } hash_data[] =
1473 {
1474 { "", 0,
1475 { HASHSIZE,
1476 { 0, 0, 0, 0 },
1477 },
1478 },
1479
1480 { "abc", 0,
1481 { HASHSIZE,
1482 { 0x98500190, 0xb04fd23c, 0x7d3f96d6, 0x727fe128 },
1483 },
1484 },
1485
1486 { "C:\\Program Files\\msitest\\caesar\n", 0,
1487 { HASHSIZE,
1488 { 0x2b566794, 0xfd42181b, 0x2514d6e4, 0x5768b4e2 },
1489 },
1490 },
1491
1492 { "C:\\Program Files\\msitest\\caesar\n", 500,
1493 { HASHSIZE,
1494 { 0x58095058, 0x805efeff, 0x10f3483e, 0x0147d653 },
1495 },
1496 },
1497 };
1498
1499 static void test_MsiGetFileHash(void)
1500 {
1501 const char name[] = "msitest.bin";
1502 UINT r;
1503 MSIFILEHASHINFO hash;
1504 DWORD i;
1505
1506 if (!pMsiGetFileHashA)
1507 {
1508 win_skip("MsiGetFileHash not implemented\n");
1509 return;
1510 }
1511
1512 hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
1513
1514 /* szFilePath is NULL */
1515 r = pMsiGetFileHashA(NULL, 0, &hash);
1516 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1517
1518 /* szFilePath is empty */
1519 r = pMsiGetFileHashA("", 0, &hash);
1520 ok(r == ERROR_PATH_NOT_FOUND || r == ERROR_BAD_PATHNAME,
1521 "Expected ERROR_PATH_NOT_FOUND or ERROR_BAD_PATHNAME, got %d\n", r);
1522
1523 /* szFilePath is nonexistent */
1524 r = pMsiGetFileHashA(name, 0, &hash);
1525 ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
1526
1527 /* dwOptions is non-zero */
1528 r = pMsiGetFileHashA(name, 1, &hash);
1529 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1530
1531 /* pHash.dwFileHashInfoSize is not correct */
1532 hash.dwFileHashInfoSize = 0;
1533 r = pMsiGetFileHashA(name, 0, &hash);
1534 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1535
1536 /* pHash is NULL */
1537 r = pMsiGetFileHashA(name, 0, NULL);
1538 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1539
1540 for (i = 0; i < sizeof(hash_data) / sizeof(hash_data[0]); i++)
1541 {
1542 int ret;
1543
1544 create_file(name, hash_data[i].data, hash_data[i].size);
1545
1546 memset(&hash, 0, sizeof(MSIFILEHASHINFO));
1547 hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
1548
1549 r = pMsiGetFileHashA(name, 0, &hash);
1550 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1551
1552 ret = memcmp(&hash, &hash_data[i].hash, HASHSIZE);
1553 ok(!ret, "Hash incorrect\n");
1554
1555 DeleteFileA(name);
1556 }
1557 }
1558
1559 /* copied from dlls/msi/registry.c */
1560 static BOOL squash_guid(LPCWSTR in, LPWSTR out)
1561 {
1562 DWORD i,n=1;
1563 GUID guid;
1564
1565 if (FAILED(CLSIDFromString((LPCOLESTR)in, &guid)))
1566 return FALSE;
1567
1568 for(i=0; i<8; i++)
1569 out[7-i] = in[n++];
1570 n++;
1571 for(i=0; i<4; i++)
1572 out[11-i] = in[n++];
1573 n++;
1574 for(i=0; i<4; i++)
1575 out[15-i] = in[n++];
1576 n++;
1577 for(i=0; i<2; i++)
1578 {
1579 out[17+i*2] = in[n++];
1580 out[16+i*2] = in[n++];
1581 }
1582 n++;
1583 for( ; i<8; i++)
1584 {
1585 out[17+i*2] = in[n++];
1586 out[16+i*2] = in[n++];
1587 }
1588 out[32]=0;
1589 return TRUE;
1590 }
1591
1592 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
1593 {
1594 WCHAR guidW[MAX_PATH];
1595 WCHAR squashedW[MAX_PATH];
1596 GUID guid;
1597 HRESULT hr;
1598 int size;
1599
1600 hr = CoCreateGuid(&guid);
1601 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
1602
1603 size = StringFromGUID2(&guid, guidW, MAX_PATH);
1604 ok(size == 39, "Expected 39, got %d\n", hr);
1605
1606 WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
1607 if (squashed)
1608 {
1609 squash_guid(guidW, squashedW);
1610 WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
1611 }
1612 }
1613
1614 static char *get_user_sid(void)
1615 {
1616 HANDLE token;
1617 DWORD size = 0;
1618 TOKEN_USER *user;
1619 char *usersid = NULL;
1620
1621 OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
1622 GetTokenInformation(token, TokenUser, NULL, size, &size);
1623
1624 user = HeapAlloc(GetProcessHeap(), 0, size);
1625 GetTokenInformation(token, TokenUser, user, size, &size);
1626 pConvertSidToStringSidA(user->User.Sid, &usersid);
1627 HeapFree(GetProcessHeap(), 0, user);
1628
1629 CloseHandle(token);
1630 return usersid;
1631 }
1632
1633 static void test_MsiQueryProductState(void)
1634 {
1635 CHAR prodcode[MAX_PATH];
1636 CHAR prod_squashed[MAX_PATH];
1637 CHAR keypath[MAX_PATH*2];
1638 LPSTR usersid;
1639 INSTALLSTATE state;
1640 LONG res;
1641 HKEY userkey, localkey, props;
1642 HKEY prodkey;
1643 DWORD data, error;
1644 REGSAM access = KEY_ALL_ACCESS;
1645
1646 create_test_guid(prodcode, prod_squashed);
1647 usersid = get_user_sid();
1648
1649 if (is_wow64)
1650 access |= KEY_WOW64_64KEY;
1651
1652 /* NULL prodcode */
1653 SetLastError(0xdeadbeef);
1654 state = MsiQueryProductStateA(NULL);
1655 error = GetLastError();
1656 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1657 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1658
1659 /* empty prodcode */
1660 SetLastError(0xdeadbeef);
1661 state = MsiQueryProductStateA("");
1662 error = GetLastError();
1663 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1664 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1665
1666 /* garbage prodcode */
1667 SetLastError(0xdeadbeef);
1668 state = MsiQueryProductStateA("garbage");
1669 error = GetLastError();
1670 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1671 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1672
1673 /* guid without brackets */
1674 SetLastError(0xdeadbeef);
1675 state = MsiQueryProductStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D");
1676 error = GetLastError();
1677 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1678 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1679
1680 /* guid with brackets */
1681 SetLastError(0xdeadbeef);
1682 state = MsiQueryProductStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}");
1683 error = GetLastError();
1684 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1685 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1686 "expected ERROR_SUCCESS, got %u\n", error);
1687
1688 /* same length as guid, but random */
1689 SetLastError(0xdeadbeef);
1690 state = MsiQueryProductStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93");
1691 error = GetLastError();
1692 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1693 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1694
1695 /* MSIINSTALLCONTEXT_USERUNMANAGED */
1696
1697 SetLastError(0xdeadbeef);
1698 state = MsiQueryProductStateA(prodcode);
1699 error = GetLastError();
1700 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1701 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1702 "expected ERROR_SUCCESS, got %u\n", error);
1703
1704 lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
1705 lstrcatA(keypath, prod_squashed);
1706
1707 res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
1708 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1709
1710 /* user product key exists */
1711 SetLastError(0xdeadbeef);
1712 state = MsiQueryProductStateA(prodcode);
1713 error = GetLastError();
1714 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1715 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1716 "expected ERROR_SUCCESS, got %u\n", error);
1717
1718 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
1719 lstrcatA(keypath, prodcode);
1720
1721 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1722 if (res == ERROR_ACCESS_DENIED)
1723 {
1724 skip("Not enough rights to perform tests\n");
1725 RegDeleteKeyA(userkey, "");
1726 RegCloseKey(userkey);
1727 LocalFree(usersid);
1728 return;
1729 }
1730 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1731
1732 /* local uninstall key exists */
1733 SetLastError(0xdeadbeef);
1734 state = MsiQueryProductStateA(prodcode);
1735 error = GetLastError();
1736 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1737 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1738 "expected ERROR_SUCCESS, got %u\n", error);
1739
1740 data = 1;
1741 res = RegSetValueExA(localkey, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1742 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1743
1744 /* WindowsInstaller value exists */
1745 SetLastError(0xdeadbeef);
1746 state = MsiQueryProductStateA(prodcode);
1747 error = GetLastError();
1748 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1749 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1750 "expected ERROR_SUCCESS, got %u\n", error);
1751
1752 RegDeleteValueA(localkey, "WindowsInstaller");
1753 delete_key(localkey, "", access & KEY_WOW64_64KEY);
1754
1755 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1756 lstrcatA(keypath, usersid);
1757 lstrcatA(keypath, "\\Products\\");
1758 lstrcatA(keypath, prod_squashed);
1759
1760 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1761 if (res == ERROR_ACCESS_DENIED)
1762 {
1763 skip("Not enough rights to perform tests\n");
1764 RegDeleteKeyA(userkey, "");
1765 RegCloseKey(userkey);
1766 LocalFree(usersid);
1767 return;
1768 }
1769 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1770
1771 /* local product key exists */
1772 SetLastError(0xdeadbeef);
1773 state = MsiQueryProductStateA(prodcode);
1774 error = GetLastError();
1775 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1776 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1777 "expected ERROR_SUCCESS, got %u\n", error);
1778
1779 res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1780 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1781
1782 /* install properties key exists */
1783 SetLastError(0xdeadbeef);
1784 state = MsiQueryProductStateA(prodcode);
1785 error = GetLastError();
1786 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1787 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1788 "expected ERROR_SUCCESS, got %u\n", error);
1789
1790 data = 1;
1791 res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1792 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1793
1794 /* WindowsInstaller value exists */
1795 SetLastError(0xdeadbeef);
1796 state = MsiQueryProductStateA(prodcode);
1797 error = GetLastError();
1798 ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1799 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1800 "expected ERROR_SUCCESS, got %u\n", error);
1801
1802 data = 2;
1803 res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1804 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1805
1806 /* WindowsInstaller value is not 1 */
1807 SetLastError(0xdeadbeef);
1808 state = MsiQueryProductStateA(prodcode);
1809 error = GetLastError();
1810 ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1811 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1812 "expected ERROR_SUCCESS, got %u\n", error);
1813
1814 RegDeleteKeyA(userkey, "");
1815
1816 /* user product key does not exist */
1817 SetLastError(0xdeadbeef);
1818 state = MsiQueryProductStateA(prodcode);
1819 error = GetLastError();
1820 ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1821 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1822 "expected ERROR_SUCCESS, got %u\n", error);
1823
1824 RegDeleteValueA(props, "WindowsInstaller");
1825 delete_key(props, "", access & KEY_WOW64_64KEY);
1826 RegCloseKey(props);
1827 delete_key(localkey, "", access & KEY_WOW64_64KEY);
1828 RegCloseKey(localkey);
1829 RegDeleteKeyA(userkey, "");
1830 RegCloseKey(userkey);
1831
1832 /* MSIINSTALLCONTEXT_USERMANAGED */
1833
1834 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
1835 lstrcatA(keypath, usersid);
1836 lstrcatA(keypath, "\\Installer\\Products\\");
1837 lstrcatA(keypath, prod_squashed);
1838
1839 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
1840 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1841
1842 state = MsiQueryProductStateA(prodcode);
1843 ok(state == INSTALLSTATE_ADVERTISED,
1844 "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1845
1846 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1847 lstrcatA(keypath, usersid);
1848 lstrcatA(keypath, "\\Products\\");
1849 lstrcatA(keypath, prod_squashed);
1850
1851 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1852 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1853
1854 state = MsiQueryProductStateA(prodcode);
1855 ok(state == INSTALLSTATE_ADVERTISED,
1856 "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1857
1858 res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1859 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1860
1861 state = MsiQueryProductStateA(prodcode);
1862 ok(state == INSTALLSTATE_ADVERTISED,
1863 "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1864
1865 data = 1;
1866 res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1867 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1868
1869 /* WindowsInstaller value exists */
1870 state = MsiQueryProductStateA(prodcode);
1871 ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1872
1873 RegDeleteValueA(props, "WindowsInstaller");
1874 delete_key(props, "", access & KEY_WOW64_64KEY);
1875 RegCloseKey(props);
1876 delete_key(localkey, "", access & KEY_WOW64_64KEY);
1877 RegCloseKey(localkey);
1878 delete_key(prodkey, "", access & KEY_WOW64_64KEY);
1879 RegCloseKey(prodkey);
1880
1881 /* MSIINSTALLCONTEXT_MACHINE */
1882
1883 lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
1884 lstrcatA(keypath, prod_squashed);
1885
1886 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
1887 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1888
1889 state = MsiQueryProductStateA(prodcode);
1890 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1891
1892 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1893 lstrcatA(keypath, "S-1-5-18\\Products\\");
1894 lstrcatA(keypath, prod_squashed);
1895
1896 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1897 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1898
1899 state = MsiQueryProductStateA(prodcode);
1900 ok(state == INSTALLSTATE_ADVERTISED,
1901 "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1902
1903 res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1904 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1905
1906 state = MsiQueryProductStateA(prodcode);
1907 ok(state == INSTALLSTATE_ADVERTISED,
1908 "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1909
1910 data = 1;
1911 res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1912 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1913
1914 /* WindowsInstaller value exists */
1915 state = MsiQueryProductStateA(prodcode);
1916 ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1917
1918 RegDeleteValueA(props, "WindowsInstaller");
1919 delete_key(props, "", access & KEY_WOW64_64KEY);
1920 RegCloseKey(props);
1921 delete_key(localkey, "", access & KEY_WOW64_64KEY);
1922 RegCloseKey(localkey);
1923 delete_key(prodkey, "", access & KEY_WOW64_64KEY);
1924 RegCloseKey(prodkey);
1925
1926 LocalFree(usersid);
1927 }
1928
1929 static const char table_enc85[] =
1930 "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
1931 "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
1932 "yz{}~";
1933
1934 /*
1935 * Encodes a base85 guid given a GUID pointer
1936 * Caller should provide a 21 character buffer for the encoded string.
1937 */
1938 static void encode_base85_guid( GUID *guid, LPWSTR str )
1939 {
1940 unsigned int x, *p, i;
1941
1942 p = (unsigned int*) guid;
1943 for( i=0; i<4; i++ )
1944 {
1945 x = p[i];
1946 *str++ = table_enc85[x%85];
1947 x = x/85;
1948 *str++ = table_enc85[x%85];
1949 x = x/85;
1950 *str++ = table_enc85[x%85];
1951 x = x/85;
1952 *str++ = table_enc85[x%85];
1953 x = x/85;
1954 *str++ = table_enc85[x%85];
1955 }
1956 *str = 0;
1957 }
1958
1959 static void compose_base85_guid(LPSTR component, LPSTR comp_base85, LPSTR squashed)
1960 {
1961 WCHAR guidW[MAX_PATH];
1962 WCHAR base85W[MAX_PATH];
1963 WCHAR squashedW[MAX_PATH];
1964 GUID guid;
1965 HRESULT hr;
1966 int size;
1967
1968 hr = CoCreateGuid(&guid);
1969 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
1970
1971 size = StringFromGUID2(&guid, guidW, MAX_PATH);
1972 ok(size == 39, "Expected 39, got %d\n", hr);
1973
1974 WideCharToMultiByte(CP_ACP, 0, guidW, size, component, MAX_PATH, NULL, NULL);
1975 encode_base85_guid(&guid, base85W);
1976 WideCharToMultiByte(CP_ACP, 0, base85W, -1, comp_base85, MAX_PATH, NULL, NULL);
1977 squash_guid(guidW, squashedW);
1978 WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
1979 }
1980
1981 static void test_MsiQueryFeatureState(void)
1982 {
1983 HKEY userkey, localkey, compkey, compkey2;
1984 CHAR prodcode[MAX_PATH];
1985 CHAR prod_squashed[MAX_PATH];
1986 CHAR component[MAX_PATH];
1987 CHAR comp_base85[MAX_PATH];
1988 CHAR comp_squashed[MAX_PATH], comp_squashed2[MAX_PATH];
1989 CHAR keypath[MAX_PATH*2];
1990 INSTALLSTATE state;
1991 LPSTR usersid;
1992 LONG res;
1993 REGSAM access = KEY_ALL_ACCESS;
1994 DWORD error;
1995
1996 create_test_guid(prodcode, prod_squashed);
1997 compose_base85_guid(component, comp_base85, comp_squashed);
1998 compose_base85_guid(component, comp_base85 + 20, comp_squashed2);
1999 usersid = get_user_sid();
2000
2001 if (is_wow64)
2002 access |= KEY_WOW64_64KEY;
2003
2004 /* NULL prodcode */
2005 SetLastError(0xdeadbeef);
2006 state = MsiQueryFeatureStateA(NULL, "feature");
2007 error = GetLastError();
2008 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2009 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2010
2011 /* empty prodcode */
2012 SetLastError(0xdeadbeef);
2013 state = MsiQueryFeatureStateA("", "feature");
2014 error = GetLastError();
2015 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2016 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2017
2018 /* garbage prodcode */
2019 SetLastError(0xdeadbeef);
2020 state = MsiQueryFeatureStateA("garbage", "feature");
2021 error = GetLastError();
2022 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2023 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2024
2025 /* guid without brackets */
2026 SetLastError(0xdeadbeef);
2027 state = MsiQueryFeatureStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", "feature");
2028 error = GetLastError();
2029 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2030 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2031
2032 /* guid with brackets */
2033 SetLastError(0xdeadbeef);
2034 state = MsiQueryFeatureStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", "feature");
2035 error = GetLastError();
2036 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2037 ok(error == ERROR_SUCCESS || broken(error == ERROR_ALREADY_EXISTS) /* win2k */,
2038 "expected ERROR_SUCCESS, got %u\n", error);
2039
2040 /* same length as guid, but random */
2041 SetLastError(0xdeadbeef);
2042 state = MsiQueryFeatureStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", "feature");
2043 error = GetLastError();
2044 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2045 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2046
2047 /* NULL szFeature */
2048 SetLastError(0xdeadbeef);
2049 state = MsiQueryFeatureStateA(prodcode, NULL);
2050 error = GetLastError();
2051 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2052 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2053
2054 /* empty szFeature */
2055 SetLastError(0xdeadbeef);
2056 state = MsiQueryFeatureStateA(prodcode, "");
2057 error = GetLastError();
2058 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2059 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2060 "expected ERROR_SUCCESS, got %u\n", error);
2061
2062 /* feature key does not exist yet */
2063 SetLastError(0xdeadbeef);
2064 state = MsiQueryFeatureStateA(prodcode, "feature");
2065 error = GetLastError();
2066 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2067 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2068 "expected ERROR_SUCCESS, got %u\n", error);
2069
2070 /* MSIINSTALLCONTEXT_USERUNMANAGED */
2071
2072 lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Features\\");
2073 lstrcatA(keypath, prod_squashed);
2074
2075 res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
2076 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2077
2078 /* feature key exists */
2079 SetLastError(0xdeadbeef);
2080 state = MsiQueryFeatureStateA(prodcode, "feature");
2081 error = GetLastError();
2082 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2083 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2084 "expected ERROR_SUCCESS, got %u\n", error);
2085
2086 res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 2);
2087 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2088
2089 /* feature value exists */
2090 SetLastError(0xdeadbeef);
2091 state = MsiQueryFeatureStateA(prodcode, "feature");
2092 error = GetLastError();
2093 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2094 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2095 "expected ERROR_SUCCESS, got %u\n", error);
2096
2097 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2098 lstrcatA(keypath, usersid);
2099 lstrcatA(keypath, "\\Products\\");
2100 lstrcatA(keypath, prod_squashed);
2101 lstrcatA(keypath, "\\Features");
2102
2103 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
2104 if (res == ERROR_ACCESS_DENIED)
2105 {
2106 skip("Not enough rights to perform tests\n");
2107 RegDeleteKeyA(userkey, "");
2108 RegCloseKey(userkey);
2109 LocalFree(usersid);
2110 return;
2111 }
2112 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2113
2114 /* userdata features key exists */
2115 SetLastError(0xdeadbeef);
2116 state = MsiQueryFeatureStateA(prodcode, "feature");
2117 error = GetLastError();
2118 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2119 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2120 "expected ERROR_SUCCESS, got %u\n", error);
2121
2122 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
2123 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2124
2125 SetLastError(0xdeadbeef);
2126 state = MsiQueryFeatureStateA(prodcode, "feature");
2127 error = GetLastError();
2128 ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
2129 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2130 "expected ERROR_SUCCESS, got %u\n", error);
2131
2132 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
2133 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2134
2135 SetLastError(0xdeadbeef);
2136 state = MsiQueryFeatureStateA(prodcode, "feature");
2137 error = GetLastError();
2138 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2139 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2140 "expected ERROR_SUCCESS, got %u\n", error);
2141
2142 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
2143 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2144
2145 SetLastError(0xdeadbeef);
2146 state = MsiQueryFeatureStateA(prodcode, "feature");
2147 error = GetLastError();
2148 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2149 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2150 "expected ERROR_SUCCESS, got %u\n", error);
2151
2152 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
2153 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2154
2155 SetLastError(0xdeadbeef);
2156 state = MsiQueryFeatureStateA(prodcode, "feature");
2157 error = GetLastError();
2158 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2159 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2160 "expected ERROR_SUCCESS, got %u\n", error);
2161
2162 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2163 lstrcatA(keypath, usersid);
2164 lstrcatA(keypath, "\\Components\\");
2165 lstrcatA(keypath, comp_squashed);
2166
2167 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2168 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2169
2170 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2171 lstrcatA(keypath, usersid);
2172 lstrcatA(keypath, "\\Components\\");
2173 lstrcatA(keypath, comp_squashed2);
2174
2175 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
2176 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2177
2178 SetLastError(0xdeadbeef);
2179 state = MsiQueryFeatureStateA(prodcode, "feature");
2180 error = GetLastError();
2181 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2182 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2183 "expected ERROR_SUCCESS, got %u\n", error);
2184
2185 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
2186 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2187
2188 SetLastError(0xdeadbeef);
2189 state = MsiQueryFeatureStateA(prodcode, "feature");
2190 error = GetLastError();
2191 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2192 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2193 "expected ERROR_SUCCESS, got %u\n", error);
2194
2195 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
2196 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2197
2198 SetLastError(0xdeadbeef);
2199 state = MsiQueryFeatureStateA(prodcode, "feature");
2200 error = GetLastError();
2201 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2202 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2203 "expected ERROR_SUCCESS, got %u\n", error);
2204
2205 res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
2206 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2207
2208 /* INSTALLSTATE_LOCAL */
2209 SetLastError(0xdeadbeef);
2210 state = MsiQueryFeatureStateA(prodcode, "feature");
2211 error = GetLastError();
2212 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2213 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2214 "expected ERROR_SUCCESS, got %u\n", error);
2215
2216 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01\\", 4);
2217 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2218
2219 /* INSTALLSTATE_SOURCE */
2220 SetLastError(0xdeadbeef);
2221 state = MsiQueryFeatureStateA(prodcode, "feature");
2222 error = GetLastError();
2223 ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2224 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2225 "expected ERROR_SUCCESS, got %u\n", error);
2226
2227 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
2228 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2229
2230 /* bad INSTALLSTATE_SOURCE */
2231 SetLastError(0xdeadbeef);
2232 state = MsiQueryFeatureStateA(prodcode, "feature");
2233 error = GetLastError();
2234 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2235 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2236 "expected ERROR_SUCCESS, got %u\n", error);
2237
2238 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01a", 4);
2239 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2240
2241 /* INSTALLSTATE_SOURCE */
2242 SetLastError(0xdeadbeef);
2243 state = MsiQueryFeatureStateA(prodcode, "feature");
2244 error = GetLastError();
2245 ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2246 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2247 "expected ERROR_SUCCESS, got %u\n", error);
2248
2249 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
2250 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2251
2252 /* bad INSTALLSTATE_SOURCE */
2253 SetLastError(0xdeadbeef);
2254 state = MsiQueryFeatureStateA(prodcode, "feature");
2255 error = GetLastError();
2256 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2257 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2258 "expected ERROR_SUCCESS, got %u\n", error);
2259
2260 RegDeleteValueA(compkey, prod_squashed);
2261 RegDeleteValueA(compkey2, prod_squashed);
2262 delete_key(compkey, "", access & KEY_WOW64_64KEY);
2263 delete_key(compkey2, "", access & KEY_WOW64_64KEY);
2264 RegDeleteValueA(localkey, "feature");
2265 RegDeleteValueA(userkey, "feature");
2266 RegDeleteKeyA(userkey, "");
2267 RegCloseKey(compkey);
2268 RegCloseKey(compkey2);
2269 RegCloseKey(localkey);
2270 RegCloseKey(userkey);
2271
2272 /* MSIINSTALLCONTEXT_USERMANAGED */
2273
2274 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
2275 lstrcatA(keypath, usersid);
2276 lstrcatA(keypath, "\\Installer\\Features\\");
2277 lstrcatA(keypath, prod_squashed);
2278
2279 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
2280 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2281
2282 /* feature key exists */
2283 state = MsiQueryFeatureStateA(prodcode, "feature");
2284 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2285
2286 res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 1);
2287 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2288
2289 /* feature value exists */
2290 state = MsiQueryFeatureStateA(prodcode, "feature");
2291 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2292
2293 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2294 lstrcatA(keypath, usersid);
2295 lstrcatA(keypath, "\\Products\\");
2296 lstrcatA(keypath, prod_squashed);
2297 lstrcatA(keypath, "\\Features");
2298
2299 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
2300 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2301
2302 /* userdata features key exists */
2303 state = MsiQueryFeatureStateA(prodcode, "feature");
2304 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2305
2306 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
2307 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2308
2309 state = MsiQueryFeatureStateA(prodcode, "feature");
2310 ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
2311
2312 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
2313 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2314
2315 state = MsiQueryFeatureStateA(prodcode, "feature");
2316 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2317
2318 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
2319 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2320
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 *)comp_base85, 41);
2325 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2326
2327 state = MsiQueryFeatureStateA(prodcode, "feature");
2328 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2329
2330 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2331 lstrcatA(keypath, usersid);
2332 lstrcatA(keypath, "\\Components\\");
2333 lstrcatA(keypath, comp_squashed);
2334
2335 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2336 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2337
2338 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2339 lstrcatA(keypath, usersid);
2340 lstrcatA(keypath, "\\Components\\");
2341 lstrcatA(keypath, comp_squashed2);
2342
2343 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
2344 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2345
2346 state = MsiQueryFeatureStateA(prodcode, "feature");
2347 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2348
2349 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
2350 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2351
2352 state = MsiQueryFeatureStateA(prodcode, "feature");
2353 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2354
2355 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
2356 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2357
2358 state = MsiQueryFeatureStateA(prodcode, "feature");
2359 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2360
2361 res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
2362 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2363
2364 state = MsiQueryFeatureStateA(prodcode, "feature");
2365 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2366
2367 RegDeleteValueA(compkey, prod_squashed);
2368 RegDeleteValueA(compkey2, prod_squashed);
2369 delete_key(compkey, "", access & KEY_WOW64_64KEY);
2370 delete_key(compkey2, "", access & KEY_WOW64_64KEY);
2371 RegDeleteValueA(localkey, "feature");
2372 RegDeleteValueA(userkey, "feature");
2373 delete_key(userkey, "", access & KEY_WOW64_64KEY);
2374 RegCloseKey(compkey);
2375 RegCloseKey(compkey2);
2376 RegCloseKey(localkey);
2377 RegCloseKey(userkey);
2378
2379 /* MSIINSTALLCONTEXT_MACHINE */
2380
2381 lstrcpyA(keypath, "Software\\Classes\\Installer\\Features\\");
2382 lstrcatA(keypath, prod_squashed);
2383
2384 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
2385 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2386
2387 /* feature key exists */
2388 state = MsiQueryFeatureStateA(prodcode, "feature");
2389 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2390
2391 res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 1);
2392 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2393
2394 /* feature value exists */
2395 state = MsiQueryFeatureStateA(prodcode, "feature");
2396 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2397
2398 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2399 lstrcatA(keypath, "S-1-5-18\\Products\\");
2400 lstrcatA(keypath, prod_squashed);
2401 lstrcatA(keypath, "\\Features");
2402
2403 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
2404 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2405
2406 /* userdata features key exists */
2407 state = MsiQueryFeatureStateA(prodcode, "feature");
2408 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2409
2410 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
2411 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2412
2413 state = MsiQueryFeatureStateA(prodcode, "feature");
2414 ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
2415
2416 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
2417 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2418
2419 state = MsiQueryFeatureStateA(prodcode, "feature");
2420 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2421
2422 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
2423 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2424
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 *)comp_base85, 41);
2429 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2430
2431 state = MsiQueryFeatureStateA(prodcode, "feature");
2432 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2433
2434 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2435 lstrcatA(keypath, "S-1-5-18\\Components\\");
2436 lstrcatA(keypath, comp_squashed);
2437
2438 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2439 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2440
2441 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2442 lstrcatA(keypath, "S-1-5-18\\Components\\");
2443 lstrcatA(keypath, comp_squashed2);
2444
2445 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
2446 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2447
2448 state = MsiQueryFeatureStateA(prodcode, "feature");
2449 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2450
2451 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
2452 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2453
2454 state = MsiQueryFeatureStateA(prodcode, "feature");
2455 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2456
2457 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
2458 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2459
2460 state = MsiQueryFeatureStateA(prodcode, "feature");
2461 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2462
2463 res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
2464 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2465
2466 state = MsiQueryFeatureStateA(prodcode, "feature");
2467 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2468
2469 RegDeleteValueA(compkey, prod_squashed);
2470 RegDeleteValueA(compkey2, prod_squashed);
2471 delete_key(compkey, "", access & KEY_WOW64_64KEY);
2472 delete_key(compkey2, "", access & KEY_WOW64_64KEY);
2473 RegDeleteValueA(localkey, "feature");
2474 RegDeleteValueA(userkey, "feature");
2475 delete_key(userkey, "", access & KEY_WOW64_64KEY);
2476 RegCloseKey(compkey);
2477 RegCloseKey(compkey2);
2478 RegCloseKey(localkey);
2479 RegCloseKey(userkey);
2480 LocalFree(usersid);
2481 }
2482
2483 static void test_MsiQueryComponentState(void)
2484 {
2485 HKEY compkey, prodkey;
2486 CHAR prodcode[MAX_PATH];
2487 CHAR prod_squashed[MAX_PATH];
2488 CHAR component[MAX_PATH];
2489 CHAR comp_base85[MAX_PATH];
2490 CHAR comp_squashed[MAX_PATH];
2491 CHAR keypath[MAX_PATH];
2492 INSTALLSTATE state;
2493 LPSTR usersid;
2494 LONG res;
2495 UINT r;
2496 REGSAM access = KEY_ALL_ACCESS;
2497 DWORD error;
2498
2499 static const INSTALLSTATE MAGIC_ERROR = 0xdeadbeef;
2500
2501 if (!pMsiQueryComponentStateA)
2502 {
2503 win_skip("MsiQueryComponentStateA not implemented\n");
2504 return;
2505 }
2506
2507 create_test_guid(prodcode, prod_squashed);
2508 compose_base85_guid(component, comp_base85, comp_squashed);
2509 usersid = get_user_sid();
2510
2511 if (is_wow64)
2512 access |= KEY_WOW64_64KEY;
2513
2514 /* NULL szProductCode */
2515 state = MAGIC_ERROR;
2516 SetLastError(0xdeadbeef);
2517 r = pMsiQueryComponentStateA(NULL, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2518 error = GetLastError();
2519 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2520 ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2521 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2522
2523 /* empty szProductCode */
2524 state = MAGIC_ERROR;
2525 SetLastError(0xdeadbeef);
2526 r = pMsiQueryComponentStateA("", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2527 error = GetLastError();
2528 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2529 ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2530 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2531
2532 /* random szProductCode */
2533 state = MAGIC_ERROR;
2534 SetLastError(0xdeadbeef);
2535 r = pMsiQueryComponentStateA("random", 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 /* GUID-length szProductCode */
2542 state = MAGIC_ERROR;
2543 SetLastError(0xdeadbeef);
2544 r = pMsiQueryComponentStateA("DJANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KDE", 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 /* GUID-length with brackets */
2551 state = MAGIC_ERROR;
2552 SetLastError(0xdeadbeef);
2553 r = pMsiQueryComponentStateA("{JANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KD}", 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 /* actual GUID */
2560 state = MAGIC_ERROR;
2561 SetLastError(0xdeadbeef);
2562 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2563 error = GetLastError();
2564 ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, 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 state = MAGIC_ERROR;
2569 SetLastError(0xdeadbeef);
2570 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2571 error = GetLastError();
2572 ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2573 ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2574 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2575
2576 lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
2577 lstrcatA(keypath, prod_squashed);
2578
2579 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2580 if (res == ERROR_ACCESS_DENIED)
2581 {
2582 skip("Not enough rights to perform tests\n");
2583 LocalFree(usersid);
2584 return;
2585 }
2586 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2587
2588 state = MAGIC_ERROR;
2589 SetLastError(0xdeadbeef);
2590 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2591 error = GetLastError();
2592 ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2593 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2594 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2595
2596 delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2597 RegCloseKey(prodkey);
2598
2599 /* create local system product key */
2600 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\");
2601 lstrcatA(keypath, prod_squashed);
2602 lstrcatA(keypath, "\\InstallProperties");
2603
2604 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2605 if (res == ERROR_ACCESS_DENIED)
2606 {
2607 skip("Not enough rights to perform tests\n");
2608 LocalFree(usersid);
2609 return;
2610 }
2611 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2612
2613 /* local system product key exists */
2614 state = MAGIC_ERROR;
2615 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2616 error = GetLastError();
2617 ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2618 ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2619 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2620
2621 res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2622 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2623
2624 /* LocalPackage value exists */
2625 state = MAGIC_ERROR;
2626 SetLastError(0xdeadbeef);
2627 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2628 error = GetLastError();
2629 ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2630 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2631 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2632
2633 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\");
2634 lstrcatA(keypath, comp_squashed);
2635
2636 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2637 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2638
2639 /* component key exists */
2640 state = MAGIC_ERROR;
2641 SetLastError(0xdeadbeef);
2642 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2643 error = GetLastError();
2644 ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2645 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2646 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2647
2648 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
2649 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2650
2651 /* component\product exists */
2652 state = MAGIC_ERROR;
2653 SetLastError(0xdeadbeef);
2654 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2655 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2656 error = GetLastError();
2657 ok(state == INSTALLSTATE_NOTUSED || state == INSTALLSTATE_LOCAL,
2658 "Expected INSTALLSTATE_NOTUSED or INSTALLSTATE_LOCAL, got %d\n", state);
2659 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2660
2661 /* NULL component, product exists */
2662 state = MAGIC_ERROR;
2663 SetLastError(0xdeadbeef);
2664 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, NULL, &state);
2665 error = GetLastError();
2666 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2667 ok(state == MAGIC_ERROR, "Expected state not changed, got %d\n", state);
2668 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2669
2670 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
2671 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2672
2673 /* INSTALLSTATE_LOCAL */
2674 state = MAGIC_ERROR;
2675 SetLastError(0xdeadbeef);
2676 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2677 error = GetLastError();
2678 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2679 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2680 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2681
2682 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01\\", 4);
2683 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2684
2685 /* INSTALLSTATE_SOURCE */
2686 state = MAGIC_ERROR;
2687 SetLastError(0xdeadbeef);
2688 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2689 error = GetLastError();
2690 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2691 ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2692 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2693
2694 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
2695 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2696
2697 /* bad INSTALLSTATE_SOURCE */
2698 state = MAGIC_ERROR;
2699 SetLastError(0xdeadbeef);
2700 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2701 error = GetLastError();
2702 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2703 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2704 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2705
2706 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01a", 4);
2707 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2708
2709 /* INSTALLSTATE_SOURCE */
2710 state = MAGIC_ERROR;
2711 SetLastError(0xdeadbeef);
2712 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2713 error = GetLastError();
2714 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2715 ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2716 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2717
2718 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01:", 4);
2719 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2720
2721 /* registry component */
2722 state = MAGIC_ERROR;
2723 SetLastError(0xdeadbeef);
2724 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2725 error = GetLastError();
2726 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2727 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2728 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2729
2730 RegDeleteValueA(prodkey, "LocalPackage");
2731 delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2732 RegDeleteValueA(compkey,