f0bb461fd75632a03c219fb8d618e67f27473425
[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 ci2_property_dat[] =
561 "Property\tValue\n"
562 "s72\tl0\n"
563 "Property\tProperty\n"
564 "INSTALLLEVEL\t3\n"
565 "Manufacturer\tWine\n"
566 "ProductCode\t{FF4AFE9C-6AC2-44F9-A060-9EA6BD16C75E}\n"
567 "ProductName\tMSITEST2\n"
568 "ProductVersion\t1.1.1\n"
569 "UpgradeCode\t{6B60C3CA-B8CA-4FB7-A395-092D98FF5D2A}\n"
570 "MSIFASTINSTALL\t1\n";
571
572 static const char mcp_component_dat[] =
573 "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
574 "s72\tS38\ts72\ti2\tS255\tS72\n"
575 "Component\tComponent\n"
576 "hydrogen\t{C844BD1E-1907-4C00-8BC9-150BD70DF0A1}\tMSITESTDIR\t2\t\thydrogen\n"
577 "helium\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t2\t\thelium\n"
578 "lithium\t{4AF28FFC-71C7-4307-BDE4-B77C5338F56F}\tMSITESTDIR\t2\tPROPVAR=42\tlithium\n";
579
580 static const char mcp_feature_dat[] =
581 "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
582 "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
583 "Feature\tFeature\n"
584 "hydroxyl\t\thydroxyl\thydroxyl\t2\t1\tTARGETDIR\t0\n"
585 "heliox\t\theliox\theliox\t2\t5\tTARGETDIR\t0\n"
586 "lithia\t\tlithia\tlithia\t2\t10\tTARGETDIR\t0";
587
588 static const char mcp_feature_comp_dat[] =
589 "Feature_\tComponent_\n"
590 "s38\ts72\n"
591 "FeatureComponents\tFeature_\tComponent_\n"
592 "hydroxyl\thydrogen\n"
593 "heliox\thelium\n"
594 "lithia\tlithium";
595
596 static const char mcp_file_dat[] =
597 "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
598 "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
599 "File\tFile\n"
600 "hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n"
601 "helium\thelium\thelium\t0\t\t\t8192\t1\n"
602 "lithium\tlithium\tlithium\t0\t\t\t8192\t1";
603
604 static const char lus_component_dat[] =
605 "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
606 "s72\tS38\ts72\ti2\tS255\tS72\n"
607 "Component\tComponent\n"
608 "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
609
610 static const char lus_feature_dat[] =
611 "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
612 "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
613 "Feature\tFeature\n"
614 "feature\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0\n"
615 "montecristo\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0";
616
617 static const char lus_file_dat[] =
618 "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
619 "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
620 "File\tFile\n"
621 "maximus\tmaximus\tmaximus\t500\t\t\t8192\t1";
622
623 static const char lus_feature_comp_dat[] =
624 "Feature_\tComponent_\n"
625 "s38\ts72\n"
626 "FeatureComponents\tFeature_\tComponent_\n"
627 "feature\tmaximus\n"
628 "montecristo\tmaximus";
629
630 static const char lus_install_exec_seq_dat[] =
631 "Action\tCondition\tSequence\n"
632 "s72\tS255\tI2\n"
633 "InstallExecuteSequence\tAction\n"
634 "ValidateProductID\t\t700\n"
635 "CostInitialize\t\t800\n"
636 "FileCost\t\t900\n"
637 "CostFinalize\t\t1000\n"
638 "InstallValidate\t\t1400\n"
639 "InstallInitialize\t\t1500\n"
640 "ProcessComponents\tPROCESS_COMPONENTS=1 Or FULL=1\t1600\n"
641 "UnpublishFeatures\tUNPUBLISH_FEATURES=1 Or FULL=1\t1800\n"
642 "RemoveFiles\t\t3500\n"
643 "InstallFiles\t\t4000\n"
644 "RegisterUser\tREGISTER_USER=1 Or FULL=1\t6000\n"
645 "RegisterProduct\tREGISTER_PRODUCT=1 Or FULL=1\t6100\n"
646 "PublishFeatures\tPUBLISH_FEATURES=1 Or FULL=1\t6300\n"
647 "PublishProduct\tPUBLISH_PRODUCT=1 Or FULL=1\t6400\n"
648 "InstallFinalize\t\t6600";
649
650 static const char lus0_media_dat[] =
651 "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
652 "i2\ti4\tL64\tS255\tS32\tS72\n"
653 "Media\tDiskId\n"
654 "1\t1\t\t\tDISK1\t\n";
655
656 static const char lus1_media_dat[] =
657 "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
658 "i2\ti4\tL64\tS255\tS32\tS72\n"
659 "Media\tDiskId\n"
660 "1\t1\t\ttest1.cab\tDISK1\t\n";
661
662 static const char lus2_media_dat[] =
663 "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
664 "i2\ti4\tL64\tS255\tS32\tS72\n"
665 "Media\tDiskId\n"
666 "1\t1\t\t#test1.cab\tDISK1\t\n";
667
668 static const char spf_custom_action_dat[] =
669 "Action\tType\tSource\tTarget\tISComments\n"
670 "s72\ti2\tS64\tS0\tS255\n"
671 "CustomAction\tAction\n"
672 "SetFolderProp\t51\tMSITESTDIR\t[ProgramFilesFolder]\\msitest\\added\t\n";
673
674 static const char spf_install_exec_seq_dat[] =
675 "Action\tCondition\tSequence\n"
676 "s72\tS255\tI2\n"
677 "InstallExecuteSequence\tAction\n"
678 "CostFinalize\t\t1000\n"
679 "CostInitialize\t\t800\n"
680 "FileCost\t\t900\n"
681 "SetFolderProp\t\t950\n"
682 "InstallFiles\t\t4000\n"
683 "InstallServices\t\t5000\n"
684 "InstallFinalize\t\t6600\n"
685 "InstallInitialize\t\t1500\n"
686 "InstallValidate\t\t1400\n"
687 "LaunchConditions\t\t100";
688
689 static const char spf_install_ui_seq_dat[] =
690 "Action\tCondition\tSequence\n"
691 "s72\tS255\tI2\n"
692 "InstallUISequence\tAction\n"
693 "CostInitialize\t\t800\n"
694 "FileCost\t\t900\n"
695 "CostFinalize\t\t1000\n"
696 "ExecuteAction\t\t1100\n";
697
698 static const char sd_file_dat[] =
699 "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
700 "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
701 "File\tFile\n"
702 "sourcedir.txt\tsourcedir\tsourcedir.txt\t1000\t\t\t8192\t1\n";
703
704 static const char sd_feature_dat[] =
705 "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
706 "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
707 "Feature\tFeature\n"
708 "sourcedir\t\t\tsourcedir feature\t1\t2\tMSITESTDIR\t0\n";
709
710 static const char sd_feature_comp_dat[] =
711 "Feature_\tComponent_\n"
712 "s38\ts72\n"
713 "FeatureComponents\tFeature_\tComponent_\n"
714 "sourcedir\tsourcedir\n";
715
716 static const char sd_component_dat[] =
717 "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
718 "s72\tS38\ts72\ti2\tS255\tS72\n"
719 "Component\tComponent\n"
720 "sourcedir\t{DD422F92-3ED8-49B5-A0B7-F266F98357DF}\tMSITESTDIR\t0\t\tsourcedir.txt\n";
721
722 static const char sd_install_ui_seq_dat[] =
723 "Action\tCondition\tSequence\n"
724 "s72\tS255\tI2\n"
725 "InstallUISequence\tAction\n"
726 "TestSourceDirProp1\tnot SourceDir and not SOURCEDIR and not Installed\t99\n"
727 "AppSearch\t\t100\n"
728 "TestSourceDirProp2\tnot SourceDir and not SOURCEDIR and not Installed\t101\n"
729 "LaunchConditions\tnot Installed \t110\n"
730 "TestSourceDirProp3\tnot SourceDir and not SOURCEDIR and not Installed\t111\n"
731 "FindRelatedProducts\t\t120\n"
732 "TestSourceDirProp4\tnot SourceDir and not SOURCEDIR and not Installed\t121\n"
733 "CCPSearch\t\t130\n"
734 "TestSourceDirProp5\tnot SourceDir and not SOURCEDIR and not Installed\t131\n"
735 "RMCCPSearch\t\t140\n"
736 "TestSourceDirProp6\tnot SourceDir and not SOURCEDIR and not Installed\t141\n"
737 "ValidateProductID\t\t150\n"
738 "TestSourceDirProp7\tnot SourceDir and not SOURCEDIR and not Installed\t151\n"
739 "CostInitialize\t\t800\n"
740 "TestSourceDirProp8\tnot SourceDir and not SOURCEDIR and not Installed\t801\n"
741 "FileCost\t\t900\n"
742 "TestSourceDirProp9\tnot SourceDir and not SOURCEDIR and not Installed\t901\n"
743 "IsolateComponents\t\t1000\n"
744 "TestSourceDirProp10\tnot SourceDir and not SOURCEDIR and not Installed\t1001\n"
745 "CostFinalize\t\t1100\n"
746 "TestSourceDirProp11\tnot SourceDir and not SOURCEDIR and not Installed\t1101\n"
747 "MigrateFeatureStates\t\t1200\n"
748 "TestSourceDirProp12\tnot SourceDir and not SOURCEDIR and not Installed\t1201\n"
749 "ExecuteAction\t\t1300\n"
750 "TestSourceDirProp13\tnot SourceDir and not SOURCEDIR and not Installed\t1301\n";
751
752 static const char sd_install_exec_seq_dat[] =
753 "Action\tCondition\tSequence\n"
754 "s72\tS255\tI2\n"
755 "InstallExecuteSequence\tAction\n"
756 "TestSourceDirProp14\tSourceDir and SOURCEDIR and not Installed\t99\n"
757 "LaunchConditions\t\t100\n"
758 "TestSourceDirProp15\tSourceDir and SOURCEDIR and not Installed\t101\n"
759 "ValidateProductID\t\t700\n"
760 "TestSourceDirProp16\tSourceDir and SOURCEDIR and not Installed\t701\n"
761 "CostInitialize\t\t800\n"
762 "TestSourceDirProp17\tSourceDir and SOURCEDIR and not Installed\t801\n"
763 "ResolveSource\tResolveSource and not Installed\t850\n"
764 "TestSourceDirProp18\tResolveSource and not SourceDir and not SOURCEDIR and not Installed\t851\n"
765 "TestSourceDirProp19\tnot ResolveSource and SourceDir and SOURCEDIR and not Installed\t852\n"
766 "FileCost\t\t900\n"
767 "TestSourceDirProp20\tSourceDir and SOURCEDIR and not Installed\t901\n"
768 "IsolateComponents\t\t1000\n"
769 "TestSourceDirProp21\tSourceDir and SOURCEDIR and not Installed\t1001\n"
770 "CostFinalize\t\t1100\n"
771 "TestSourceDirProp22\tSourceDir and SOURCEDIR and not Installed\t1101\n"
772 "MigrateFeatureStates\t\t1200\n"
773 "TestSourceDirProp23\tSourceDir and SOURCEDIR and not Installed\t1201\n"
774 "InstallValidate\t\t1400\n"
775 "TestSourceDirProp24\tSourceDir and SOURCEDIR and not Installed\t1401\n"
776 "InstallInitialize\t\t1500\n"
777 "TestSourceDirProp25\tSourceDir and SOURCEDIR and not Installed\t1501\n"
778 "ProcessComponents\t\t1600\n"
779 "TestSourceDirProp26\tnot SourceDir and not SOURCEDIR and not Installed\t1601\n"
780 "UnpublishFeatures\t\t1800\n"
781 "TestSourceDirProp27\tnot SourceDir and not SOURCEDIR and not Installed\t1801\n"
782 "RemoveFiles\t\t3500\n"
783 "TestSourceDirProp28\tnot SourceDir and not SOURCEDIR and not Installed\t3501\n"
784 "InstallFiles\t\t4000\n"
785 "TestSourceDirProp29\tnot SourceDir and not SOURCEDIR and not Installed\t4001\n"
786 "RegisterUser\t\t6000\n"
787 "TestSourceDirProp30\tnot SourceDir and not SOURCEDIR and not Installed\t6001\n"
788 "RegisterProduct\t\t6100\n"
789 "TestSourceDirProp31\tnot SourceDir and not SOURCEDIR and not Installed\t6101\n"
790 "PublishFeatures\t\t6300\n"
791 "TestSourceDirProp32\tnot SourceDir and not SOURCEDIR and not Installed\t6301\n"
792 "PublishProduct\t\t6400\n"
793 "TestSourceDirProp33\tnot SourceDir and not SOURCEDIR and not Installed\t6401\n"
794 "InstallExecute\t\t6500\n"
795 "TestSourceDirProp34\tnot SourceDir and not SOURCEDIR and not Installed\t6501\n"
796 "InstallFinalize\t\t6600\n"
797 "TestSourceDirProp35\tnot SourceDir and not SOURCEDIR and not Installed\t6601\n";
798
799 static const char sd_custom_action_dat[] =
800 "Action\tType\tSource\tTarget\tISComments\n"
801 "s72\ti2\tS64\tS0\tS255\n"
802 "CustomAction\tAction\n"
803 "TestSourceDirProp1\t19\t\tTest 1 failed\t\n"
804 "TestSourceDirProp2\t19\t\tTest 2 failed\t\n"
805 "TestSourceDirProp3\t19\t\tTest 3 failed\t\n"
806 "TestSourceDirProp4\t19\t\tTest 4 failed\t\n"
807 "TestSourceDirProp5\t19\t\tTest 5 failed\t\n"
808 "TestSourceDirProp6\t19\t\tTest 6 failed\t\n"
809 "TestSourceDirProp7\t19\t\tTest 7 failed\t\n"
810 "TestSourceDirProp8\t19\t\tTest 8 failed\t\n"
811 "TestSourceDirProp9\t19\t\tTest 9 failed\t\n"
812 "TestSourceDirProp10\t19\t\tTest 10 failed\t\n"
813 "TestSourceDirProp11\t19\t\tTest 11 failed\t\n"
814 "TestSourceDirProp12\t19\t\tTest 12 failed\t\n"
815 "TestSourceDirProp13\t19\t\tTest 13 failed\t\n"
816 "TestSourceDirProp14\t19\t\tTest 14 failed\t\n"
817 "TestSourceDirProp15\t19\t\tTest 15 failed\t\n"
818 "TestSourceDirProp16\t19\t\tTest 16 failed\t\n"
819 "TestSourceDirProp17\t19\t\tTest 17 failed\t\n"
820 "TestSourceDirProp18\t19\t\tTest 18 failed\t\n"
821 "TestSourceDirProp19\t19\t\tTest 19 failed\t\n"
822 "TestSourceDirProp20\t19\t\tTest 20 failed\t\n"
823 "TestSourceDirProp21\t19\t\tTest 21 failed\t\n"
824 "TestSourceDirProp22\t19\t\tTest 22 failed\t\n"
825 "TestSourceDirProp23\t19\t\tTest 23 failed\t\n"
826 "TestSourceDirProp24\t19\t\tTest 24 failed\t\n"
827 "TestSourceDirProp25\t19\t\tTest 25 failed\t\n"
828 "TestSourceDirProp26\t19\t\tTest 26 failed\t\n"
829 "TestSourceDirProp27\t19\t\tTest 27 failed\t\n"
830 "TestSourceDirProp28\t19\t\tTest 28 failed\t\n"
831 "TestSourceDirProp29\t19\t\tTest 29 failed\t\n"
832 "TestSourceDirProp30\t19\t\tTest 30 failed\t\n"
833 "TestSourceDirProp31\t19\t\tTest 31 failed\t\n"
834 "TestSourceDirProp32\t19\t\tTest 32 failed\t\n"
835 "TestSourceDirProp33\t19\t\tTest 33 failed\t\n"
836 "TestSourceDirProp34\t19\t\tTest 34 failed\t\n"
837 "TestSourceDirProp35\t19\t\tTest 35 failed\t\n";
838
839 static const char ci_install_exec_seq_dat[] =
840 "Action\tCondition\tSequence\n"
841 "s72\tS255\tI2\n"
842 "InstallExecuteSequence\tAction\n"
843 "CostInitialize\t\t800\n"
844 "FileCost\t\t900\n"
845 "CostFinalize\t\t1000\n"
846 "InstallValidate\t\t1400\n"
847 "InstallInitialize\t\t1500\n"
848 "RunInstall\tnot Installed\t1550\n"
849 "ProcessComponents\t\t1600\n"
850 "UnpublishFeatures\t\t1800\n"
851 "RemoveFiles\t\t3500\n"
852 "InstallFiles\t\t4000\n"
853 "RegisterProduct\t\t6100\n"
854 "PublishFeatures\t\t6300\n"
855 "PublishProduct\t\t6400\n"
856 "InstallFinalize\t\t6600\n";
857
858 static const char ci_custom_action_dat[] =
859 "Action\tType\tSource\tTarget\tISComments\n"
860 "s72\ti2\tS64\tS0\tS255\n"
861 "CustomAction\tAction\n"
862 "RunInstall\t23\tmsitest\\concurrent.msi\tMYPROP=[UILevel]\t\n";
863
864 static const char ci_component_dat[] =
865 "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
866 "s72\tS38\ts72\ti2\tS255\tS72\n"
867 "Component\tComponent\n"
868 "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
869
870 static const char ci2_component_dat[] =
871 "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
872 "s72\tS38\ts72\ti2\tS255\tS72\n"
873 "Component\tComponent\n"
874 "augustus\t\tMSITESTDIR\t0\tUILevel=3 AND MYPROP=5\taugustus\n";
875
876 static const char ci2_feature_comp_dat[] =
877 "Feature_\tComponent_\n"
878 "s38\ts72\n"
879 "FeatureComponents\tFeature_\tComponent_\n"
880 "feature\taugustus";
881
882 static const char ci2_file_dat[] =
883 "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
884 "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
885 "File\tFile\n"
886 "augustus\taugustus\taugustus\t500\t\t\t8192\t1";
887
888 static const char cl_custom_action_dat[] =
889 "Action\tType\tSource\tTarget\tISComments\n"
890 "s72\ti2\tS64\tS0\tS255\n"
891 "CustomAction\tAction\n"
892 "TestCommandlineProp\t19\t\tTest1\t\n";
893
894 static const char cl_install_exec_seq_dat[] =
895 "Action\tCondition\tSequence\n"
896 "s72\tS255\tI2\n"
897 "InstallExecuteSequence\tAction\n"
898 "LaunchConditions\t\t100\n"
899 "ValidateProductID\t\t700\n"
900 "CostInitialize\t\t800\n"
901 "FileCost\t\t900\n"
902 "CostFinalize\t\t1000\n"
903 "TestCommandlineProp\tP=\"one\"\t1100\n"
904 "InstallInitialize\t\t1500\n"
905 "ProcessComponents\t\t1600\n"
906 "InstallValidate\t\t1400\n"
907 "InstallFinalize\t\t5000\n";
908
909 typedef struct _msi_table
910 {
911 const CHAR *filename;
912 const CHAR *data;
913 int size;
914 } msi_table;
915
916 #define ADD_TABLE(x) {#x".idt", x##_dat, sizeof(x##_dat)}
917
918 static const msi_table tables[] =
919 {
920 ADD_TABLE(directory),
921 ADD_TABLE(component),
922 ADD_TABLE(feature),
923 ADD_TABLE(feature_comp),
924 ADD_TABLE(file),
925 ADD_TABLE(install_exec_seq),
926 ADD_TABLE(media),
927 ADD_TABLE(property),
928 };
929
930 static const msi_table mcp_tables[] =
931 {
932 ADD_TABLE(directory),
933 ADD_TABLE(mcp_component),
934 ADD_TABLE(mcp_feature),
935 ADD_TABLE(mcp_feature_comp),
936 ADD_TABLE(mcp_file),
937 ADD_TABLE(install_exec_seq),
938 ADD_TABLE(media),
939 ADD_TABLE(property)
940 };
941
942 static const msi_table lus0_tables[] =
943 {
944 ADD_TABLE(lus_component),
945 ADD_TABLE(directory),
946 ADD_TABLE(lus_feature),
947 ADD_TABLE(lus_feature_comp),
948 ADD_TABLE(lus_file),
949 ADD_TABLE(lus_install_exec_seq),
950 ADD_TABLE(lus0_media),
951 ADD_TABLE(property)
952 };
953
954 static const msi_table lus1_tables[] =
955 {
956 ADD_TABLE(lus_component),
957 ADD_TABLE(directory),
958 ADD_TABLE(lus_feature),
959 ADD_TABLE(lus_feature_comp),
960 ADD_TABLE(lus_file),
961 ADD_TABLE(lus_install_exec_seq),
962 ADD_TABLE(lus1_media),
963 ADD_TABLE(property)
964 };
965
966 static const msi_table lus2_tables[] =
967 {
968 ADD_TABLE(lus_component),
969 ADD_TABLE(directory),
970 ADD_TABLE(lus_feature),
971 ADD_TABLE(lus_feature_comp),
972 ADD_TABLE(lus_file),
973 ADD_TABLE(lus_install_exec_seq),
974 ADD_TABLE(lus2_media),
975 ADD_TABLE(property)
976 };
977
978 static const msi_table spf_tables[] =
979 {
980 ADD_TABLE(lus_component),
981 ADD_TABLE(directory),
982 ADD_TABLE(lus_feature),
983 ADD_TABLE(lus_feature_comp),
984 ADD_TABLE(lus_file),
985 ADD_TABLE(lus0_media),
986 ADD_TABLE(property),
987 ADD_TABLE(spf_custom_action),
988 ADD_TABLE(spf_install_exec_seq),
989 ADD_TABLE(spf_install_ui_seq)
990 };
991
992 static const msi_table sd_tables[] =
993 {
994 ADD_TABLE(directory),
995 ADD_TABLE(sd_component),
996 ADD_TABLE(sd_feature),
997 ADD_TABLE(sd_feature_comp),
998 ADD_TABLE(sd_file),
999 ADD_TABLE(sd_install_exec_seq),
1000 ADD_TABLE(sd_install_ui_seq),
1001 ADD_TABLE(sd_custom_action),
1002 ADD_TABLE(media),
1003 ADD_TABLE(property)
1004 };
1005
1006 static const msi_table ci_tables[] =
1007 {
1008 ADD_TABLE(ci_component),
1009 ADD_TABLE(directory),
1010 ADD_TABLE(lus_feature),
1011 ADD_TABLE(lus_feature_comp),
1012 ADD_TABLE(lus_file),
1013 ADD_TABLE(ci_install_exec_seq),
1014 ADD_TABLE(lus0_media),
1015 ADD_TABLE(property),
1016 ADD_TABLE(ci_custom_action),
1017 };
1018
1019 static const msi_table ci2_tables[] =
1020 {
1021 ADD_TABLE(ci2_component),
1022 ADD_TABLE(directory),
1023 ADD_TABLE(lus_feature),
1024 ADD_TABLE(ci2_feature_comp),
1025 ADD_TABLE(ci2_file),
1026 ADD_TABLE(install_exec_seq),
1027 ADD_TABLE(lus0_media),
1028 ADD_TABLE(ci2_property),
1029 };
1030
1031 static const msi_table cl_tables[] =
1032 {
1033 ADD_TABLE(component),
1034 ADD_TABLE(directory),
1035 ADD_TABLE(feature),
1036 ADD_TABLE(feature_comp),
1037 ADD_TABLE(file),
1038 ADD_TABLE(cl_custom_action),
1039 ADD_TABLE(cl_install_exec_seq),
1040 ADD_TABLE(media),
1041 ADD_TABLE(property)
1042 };
1043
1044 static void write_file(const CHAR *filename, const char *data, int data_size)
1045 {
1046 DWORD size;
1047
1048 HANDLE hf = CreateFileA(filename, GENERIC_WRITE, 0, NULL,
1049 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1050 WriteFile(hf, data, data_size, &size, NULL);
1051 CloseHandle(hf);
1052 }
1053
1054 static void write_msi_summary_info(MSIHANDLE db, INT version, INT wordcount, const char *template)
1055 {
1056 MSIHANDLE summary;
1057 UINT r;
1058
1059 r = MsiGetSummaryInformationA(db, NULL, 5, &summary);
1060 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1061
1062 r = MsiSummaryInfoSetPropertyA(summary, PID_TEMPLATE, VT_LPSTR, 0, NULL, template);
1063 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1064
1065 r = MsiSummaryInfoSetPropertyA(summary, PID_REVNUMBER, VT_LPSTR, 0, NULL,
1066 "{004757CA-5092-49C2-AD20-28E1CE0DF5F2}");
1067 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1068
1069 r = MsiSummaryInfoSetPropertyA(summary, PID_PAGECOUNT, VT_I4, version, NULL, NULL);
1070 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1071
1072 r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, wordcount, NULL, NULL);
1073 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1074
1075 r = MsiSummaryInfoSetPropertyA(summary, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
1076 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1077
1078 /* write the summary changes back to the stream */
1079 r = MsiSummaryInfoPersist(summary);
1080 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1081
1082 MsiCloseHandle(summary);
1083 }
1084
1085 #define create_database(name, tables, num_tables) \
1086 create_database_wordcount(name, tables, num_tables, 100, 0, ";1033");
1087
1088 #define create_database_template(name, tables, num_tables, version, template) \
1089 create_database_wordcount(name, tables, num_tables, version, 0, template);
1090
1091 static void create_database_wordcount(const CHAR *name, const msi_table *tables,
1092 int num_tables, INT version, INT wordcount,
1093 const char *template)
1094 {
1095 MSIHANDLE db;
1096 UINT r;
1097 WCHAR *nameW;
1098 int j, len;
1099
1100 len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 );
1101 if (!(nameW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return;
1102 MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, len );
1103
1104 r = MsiOpenDatabaseW(nameW, MSIDBOPEN_CREATE, &db);
1105 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1106
1107 /* import the tables into the database */
1108 for (j = 0; j < num_tables; j++)
1109 {
1110 const msi_table *table = &tables[j];
1111
1112 write_file(table->filename, table->data, (table->size - 1) * sizeof(char));
1113
1114 r = MsiDatabaseImportA(db, CURR_DIR, table->filename);
1115 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1116
1117 DeleteFileA(table->filename);
1118 }
1119
1120 write_msi_summary_info(db, version, wordcount, template);
1121
1122 r = MsiDatabaseCommit(db);
1123 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1124
1125 MsiCloseHandle(db);
1126 HeapFree( GetProcessHeap(), 0, nameW );
1127 }
1128
1129 static UINT run_query(MSIHANDLE hdb, const char *query)
1130 {
1131 MSIHANDLE hview = 0;
1132 UINT r;
1133
1134 r = MsiDatabaseOpenViewA(hdb, query, &hview);
1135 if (r != ERROR_SUCCESS)
1136 return r;
1137
1138 r = MsiViewExecute(hview, 0);
1139 if (r == ERROR_SUCCESS)
1140 r = MsiViewClose(hview);
1141 MsiCloseHandle(hview);
1142 return r;
1143 }
1144
1145 static UINT set_summary_info(MSIHANDLE hdb, LPSTR prodcode)
1146 {
1147 UINT res;
1148 MSIHANDLE suminfo;
1149
1150 /* build summary info */
1151 res = MsiGetSummaryInformationA(hdb, NULL, 7, &suminfo);
1152 ok(res == ERROR_SUCCESS, "Failed to open summaryinfo\n");
1153
1154 res = MsiSummaryInfoSetPropertyA(suminfo, 2, VT_LPSTR, 0, NULL,
1155 "Installation Database");
1156 ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1157
1158 res = MsiSummaryInfoSetPropertyA(suminfo, 3, VT_LPSTR, 0, NULL,
1159 "Installation Database");
1160 ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1161
1162 res = MsiSummaryInfoSetPropertyA(suminfo, 4, VT_LPSTR, 0, NULL,
1163 "Wine Hackers");
1164 ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1165
1166 res = MsiSummaryInfoSetPropertyA(suminfo, 7, VT_LPSTR, 0, NULL,
1167 ";1033");
1168 ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1169
1170 res = MsiSummaryInfoSetPropertyA(suminfo, PID_REVNUMBER, VT_LPSTR, 0, NULL,
1171 "{A2078D65-94D6-4205-8DEE-F68D6FD622AA}");
1172 ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1173
1174 res = MsiSummaryInfoSetPropertyA(suminfo, 14, VT_I4, 100, NULL, NULL);
1175 ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1176
1177 res = MsiSummaryInfoSetPropertyA(suminfo, 15, VT_I4, 0, NULL, NULL);
1178 ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
1179
1180 res = MsiSummaryInfoPersist(suminfo);
1181 ok(res == ERROR_SUCCESS, "Failed to make summary info persist\n");
1182
1183 res = MsiCloseHandle(suminfo);
1184 ok(res == ERROR_SUCCESS, "Failed to close suminfo\n");
1185
1186 return res;
1187 }
1188
1189 static MSIHANDLE create_package_db(LPSTR prodcode)
1190 {
1191 MSIHANDLE hdb = 0;
1192 CHAR query[MAX_PATH];
1193 UINT res;
1194
1195 DeleteFileA(msifile);
1196
1197 /* create an empty database */
1198 res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
1199 ok( res == ERROR_SUCCESS , "Failed to create database\n" );
1200 if (res != ERROR_SUCCESS)
1201 return hdb;
1202
1203 res = MsiDatabaseCommit(hdb);
1204 ok(res == ERROR_SUCCESS, "Failed to commit database\n");
1205
1206 set_summary_info(hdb, prodcode);
1207
1208 res = run_query(hdb,
1209 "CREATE TABLE `Directory` ( "
1210 "`Directory` CHAR(255) NOT NULL, "
1211 "`Directory_Parent` CHAR(255), "
1212 "`DefaultDir` CHAR(255) NOT NULL "
1213 "PRIMARY KEY `Directory`)");
1214 ok(res == ERROR_SUCCESS , "Failed to create directory table\n");
1215
1216 res = run_query(hdb,
1217 "CREATE TABLE `Property` ( "
1218 "`Property` CHAR(72) NOT NULL, "
1219 "`Value` CHAR(255) "
1220 "PRIMARY KEY `Property`)");
1221 ok(res == ERROR_SUCCESS , "Failed to create directory table\n");
1222
1223 sprintf(query, "INSERT INTO `Property` "
1224 "(`Property`, `Value`) "
1225 "VALUES( 'ProductCode', '%s' )", prodcode);
1226 res = run_query(hdb, query);
1227 ok(res == ERROR_SUCCESS , "Failed\n");
1228
1229 res = MsiDatabaseCommit(hdb);
1230 ok(res == ERROR_SUCCESS, "Failed to commit database\n");
1231
1232 return hdb;
1233 }
1234
1235 static void test_usefeature(void)
1236 {
1237 INSTALLSTATE r;
1238
1239 if (!pMsiUseFeatureExA)
1240 {
1241 win_skip("MsiUseFeatureExA not implemented\n");
1242 return;
1243 }
1244
1245 r = MsiQueryFeatureStateA(NULL, NULL);
1246 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1247
1248 r = MsiQueryFeatureStateA("{9085040-6000-11d3-8cfe-0150048383c9}" ,NULL);
1249 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1250
1251 r = pMsiUseFeatureExA(NULL,NULL,0,0);
1252 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1253
1254 r = pMsiUseFeatureExA(NULL, "WORDVIEWFiles", -2, 1 );
1255 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1256
1257 r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}",
1258 NULL, -2, 0 );
1259 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1260
1261 r = pMsiUseFeatureExA("{9085040-6000-11d3-8cfe-0150048383c9}",
1262 "WORDVIEWFiles", -2, 0 );
1263 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1264
1265 r = pMsiUseFeatureExA("{0085040-6000-11d3-8cfe-0150048383c9}",
1266 "WORDVIEWFiles", -2, 0 );
1267 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1268
1269 r = pMsiUseFeatureExA("{90850409-6000-11d3-8cfe-0150048383c9}",
1270 "WORDVIEWFiles", -2, 1 );
1271 ok( r == INSTALLSTATE_INVALIDARG, "wrong return val\n");
1272 }
1273
1274 static LONG delete_key( HKEY key, LPCSTR subkey, REGSAM access )
1275 {
1276 if (pRegDeleteKeyExA)
1277 return pRegDeleteKeyExA( key, subkey, access, 0 );
1278 return RegDeleteKeyA( key, subkey );
1279 }
1280
1281 static void test_null(void)
1282 {
1283 MSIHANDLE hpkg;
1284 UINT r;
1285 HKEY hkey;
1286 DWORD dwType, cbData;
1287 LPBYTE lpData = NULL;
1288 INSTALLSTATE state;
1289 REGSAM access = KEY_ALL_ACCESS;
1290
1291 if (is_wow64)
1292 access |= KEY_WOW64_64KEY;
1293
1294 r = pMsiOpenPackageExW(NULL, 0, &hpkg);
1295 ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
1296
1297 state = MsiQueryProductStateW(NULL);
1298 ok( state == INSTALLSTATE_INVALIDARG, "wrong return\n");
1299
1300 r = MsiEnumFeaturesW(NULL,0,NULL,NULL);
1301 ok( r == ERROR_INVALID_PARAMETER,"wrong error\n");
1302
1303 r = MsiConfigureFeatureW(NULL, NULL, 0);
1304 ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
1305
1306 r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000000}", NULL, 0);
1307 ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
1308
1309 r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000001}", "foo", 0);
1310 ok( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
1311
1312 r = MsiConfigureFeatureA("{00000000-0000-0000-0000-000000000002}", "foo", INSTALLSTATE_DEFAULT);
1313 ok( r == ERROR_UNKNOWN_PRODUCT, "wrong error %d\n", r);
1314
1315 /* make sure empty string to MsiGetProductInfo is not a handle to default registry value, saving and restoring the
1316 * necessary registry values */
1317
1318 /* empty product string */
1319 r = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", 0, access, &hkey);
1320 if (r == ERROR_ACCESS_DENIED)
1321 {
1322 skip("Not enough rights to perform tests\n");
1323 return;
1324 }
1325 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1326
1327 r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
1328 ok ( r == ERROR_SUCCESS || r == ERROR_FILE_NOT_FOUND, "wrong error %d\n", r);
1329 if ( r == ERROR_SUCCESS )
1330 {
1331 lpData = HeapAlloc(GetProcessHeap(), 0, cbData);
1332 if (!lpData)
1333 skip("Out of memory\n");
1334 else
1335 {
1336 r = RegQueryValueExA(hkey, NULL, 0, &dwType, lpData, &cbData);
1337 ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
1338 }
1339 }
1340
1341 r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
1342 if (r == ERROR_ACCESS_DENIED)
1343 {
1344 skip("Not enough rights to perform tests\n");
1345 HeapFree(GetProcessHeap(), 0, lpData);
1346 RegCloseKey(hkey);
1347 return;
1348 }
1349 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1350
1351 r = MsiGetProductInfoA("", "", NULL, NULL);
1352 ok ( r == ERROR_INVALID_PARAMETER, "wrong error %d\n", r);
1353
1354 if (lpData)
1355 {
1356 r = RegSetValueExA(hkey, NULL, 0, dwType, lpData, cbData);
1357 ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
1358
1359 HeapFree(GetProcessHeap(), 0, lpData);
1360 }
1361 else
1362 {
1363 r = RegDeleteValueA(hkey, NULL);
1364 ok ( r == ERROR_SUCCESS, "wrong error %d\n", r);
1365 }
1366
1367 r = RegCloseKey(hkey);
1368 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1369
1370 /* empty attribute */
1371 r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}",
1372 0, NULL, 0, access, NULL, &hkey, NULL);
1373 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1374
1375 r = RegSetValueA(hkey, NULL, REG_SZ, "test", strlen("test"));
1376 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1377
1378 r = MsiGetProductInfoA("{F1C3AF50-8B56-4A69-A00C-00773FE42F30}", "", NULL, NULL);
1379 ok ( r == ERROR_UNKNOWN_PROPERTY, "wrong error %d\n", r);
1380
1381 r = RegCloseKey(hkey);
1382 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1383
1384 r = delete_key(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{F1C3AF50-8B56-4A69-A00C-00773FE42F30}",
1385 access & KEY_WOW64_64KEY);
1386 ok( r == ERROR_SUCCESS, "wrong error %d\n", r);
1387 }
1388
1389 static void test_getcomponentpath(void)
1390 {
1391 INSTALLSTATE r;
1392 char buffer[0x100];
1393 DWORD sz;
1394
1395 if(!pMsiGetComponentPathA)
1396 return;
1397
1398 r = pMsiGetComponentPathA( NULL, NULL, NULL, NULL );
1399 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1400
1401 r = pMsiGetComponentPathA( "bogus", "bogus", NULL, NULL );
1402 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1403
1404 r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", NULL, NULL );
1405 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1406
1407 sz = sizeof buffer;
1408 buffer[0]=0;
1409 r = pMsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", buffer, &sz );
1410 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1411
1412 r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C998E7}",
1413 "{00000000-0000-0000-0000-000000000000}", buffer, &sz );
1414 ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
1415
1416 r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
1417 "{00000000-0000-0000-0000-00000000}", buffer, &sz );
1418 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1419
1420 r = pMsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
1421 "{029E403D-A86A-1D11-5B5B0006799C897E}", buffer, &sz );
1422 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
1423
1424 r = pMsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C9987e}",
1425 "{00000000-A68A-11d1-5B5B-0006799C897E}", buffer, &sz );
1426 ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
1427 }
1428
1429 static void create_file(LPCSTR name, LPCSTR data, DWORD size)
1430 {
1431 HANDLE file;
1432 DWORD written;
1433
1434 file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1435 ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
1436 WriteFile(file, data, strlen(data), &written, NULL);
1437
1438 if (size)
1439 {
1440 SetFilePointer(file, size, NULL, FILE_BEGIN);
1441 SetEndOfFile(file);
1442 }
1443
1444 CloseHandle(file);
1445 }
1446
1447 static void create_test_files(void)
1448 {
1449 CreateDirectoryA("msitest", NULL);
1450 create_file("msitest\\one.txt", "msitest\\one.txt", 100);
1451 CreateDirectoryA("msitest\\first", NULL);
1452 create_file("msitest\\first\\two.txt", "msitest\\first\\two.txt", 100);
1453 CreateDirectoryA("msitest\\second", NULL);
1454 create_file("msitest\\second\\three.txt", "msitest\\second\\three.txt", 100);
1455
1456 create_file("four.txt", "four.txt", 100);
1457 create_file("five.txt", "five.txt", 100);
1458 create_cab_file("msitest.cab", MEDIA_SIZE, "four.txt\0five.txt\0");
1459
1460 create_file("msitest\\filename", "msitest\\filename", 100);
1461 create_file("msitest\\service.exe", "msitest\\service.exe", 100);
1462
1463 DeleteFileA("four.txt");
1464 DeleteFileA("five.txt");
1465 }
1466
1467 static void delete_test_files(void)
1468 {
1469 DeleteFileA("msitest.msi");
1470 DeleteFileA("msitest.cab");
1471 DeleteFileA("msitest\\second\\three.txt");
1472 DeleteFileA("msitest\\first\\two.txt");
1473 DeleteFileA("msitest\\one.txt");
1474 DeleteFileA("msitest\\service.exe");
1475 DeleteFileA("msitest\\filename");
1476 RemoveDirectoryA("msitest\\second");
1477 RemoveDirectoryA("msitest\\first");
1478 RemoveDirectoryA("msitest");
1479 }
1480
1481 #define HASHSIZE sizeof(MSIFILEHASHINFO)
1482
1483 static const struct
1484 {
1485 LPCSTR data;
1486 DWORD size;
1487 MSIFILEHASHINFO hash;
1488 } hash_data[] =
1489 {
1490 { "", 0,
1491 { HASHSIZE,
1492 { 0, 0, 0, 0 },
1493 },
1494 },
1495
1496 { "abc", 0,
1497 { HASHSIZE,
1498 { 0x98500190, 0xb04fd23c, 0x7d3f96d6, 0x727fe128 },
1499 },
1500 },
1501
1502 { "C:\\Program Files\\msitest\\caesar\n", 0,
1503 { HASHSIZE,
1504 { 0x2b566794, 0xfd42181b, 0x2514d6e4, 0x5768b4e2 },
1505 },
1506 },
1507
1508 { "C:\\Program Files\\msitest\\caesar\n", 500,
1509 { HASHSIZE,
1510 { 0x58095058, 0x805efeff, 0x10f3483e, 0x0147d653 },
1511 },
1512 },
1513 };
1514
1515 static void test_MsiGetFileHash(void)
1516 {
1517 const char name[] = "msitest.bin";
1518 UINT r;
1519 MSIFILEHASHINFO hash;
1520 DWORD i;
1521
1522 if (!pMsiGetFileHashA)
1523 {
1524 win_skip("MsiGetFileHash not implemented\n");
1525 return;
1526 }
1527
1528 hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
1529
1530 /* szFilePath is NULL */
1531 r = pMsiGetFileHashA(NULL, 0, &hash);
1532 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1533
1534 /* szFilePath is empty */
1535 r = pMsiGetFileHashA("", 0, &hash);
1536 ok(r == ERROR_PATH_NOT_FOUND || r == ERROR_BAD_PATHNAME,
1537 "Expected ERROR_PATH_NOT_FOUND or ERROR_BAD_PATHNAME, got %d\n", r);
1538
1539 /* szFilePath is nonexistent */
1540 r = pMsiGetFileHashA(name, 0, &hash);
1541 ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
1542
1543 /* dwOptions is non-zero */
1544 r = pMsiGetFileHashA(name, 1, &hash);
1545 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1546
1547 /* pHash.dwFileHashInfoSize is not correct */
1548 hash.dwFileHashInfoSize = 0;
1549 r = pMsiGetFileHashA(name, 0, &hash);
1550 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1551
1552 /* pHash is NULL */
1553 r = pMsiGetFileHashA(name, 0, NULL);
1554 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1555
1556 for (i = 0; i < sizeof(hash_data) / sizeof(hash_data[0]); i++)
1557 {
1558 int ret;
1559
1560 create_file(name, hash_data[i].data, hash_data[i].size);
1561
1562 memset(&hash, 0, sizeof(MSIFILEHASHINFO));
1563 hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
1564
1565 r = pMsiGetFileHashA(name, 0, &hash);
1566 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1567
1568 ret = memcmp(&hash, &hash_data[i].hash, HASHSIZE);
1569 ok(!ret, "Hash incorrect\n");
1570
1571 DeleteFileA(name);
1572 }
1573 }
1574
1575 /* copied from dlls/msi/registry.c */
1576 static BOOL squash_guid(LPCWSTR in, LPWSTR out)
1577 {
1578 DWORD i,n=1;
1579 GUID guid;
1580
1581 if (FAILED(CLSIDFromString((LPCOLESTR)in, &guid)))
1582 return FALSE;
1583
1584 for(i=0; i<8; i++)
1585 out[7-i] = in[n++];
1586 n++;
1587 for(i=0; i<4; i++)
1588 out[11-i] = in[n++];
1589 n++;
1590 for(i=0; i<4; i++)
1591 out[15-i] = in[n++];
1592 n++;
1593 for(i=0; i<2; i++)
1594 {
1595 out[17+i*2] = in[n++];
1596 out[16+i*2] = in[n++];
1597 }
1598 n++;
1599 for( ; i<8; i++)
1600 {
1601 out[17+i*2] = in[n++];
1602 out[16+i*2] = in[n++];
1603 }
1604 out[32]=0;
1605 return TRUE;
1606 }
1607
1608 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
1609 {
1610 WCHAR guidW[MAX_PATH];
1611 WCHAR squashedW[MAX_PATH];
1612 GUID guid;
1613 HRESULT hr;
1614 int size;
1615
1616 hr = CoCreateGuid(&guid);
1617 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
1618
1619 size = StringFromGUID2(&guid, guidW, MAX_PATH);
1620 ok(size == 39, "Expected 39, got %d\n", hr);
1621
1622 WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
1623 if (squashed)
1624 {
1625 squash_guid(guidW, squashedW);
1626 WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
1627 }
1628 }
1629
1630 static char *get_user_sid(void)
1631 {
1632 HANDLE token;
1633 DWORD size = 0;
1634 TOKEN_USER *user;
1635 char *usersid = NULL;
1636
1637 OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
1638 GetTokenInformation(token, TokenUser, NULL, size, &size);
1639
1640 user = HeapAlloc(GetProcessHeap(), 0, size);
1641 GetTokenInformation(token, TokenUser, user, size, &size);
1642 pConvertSidToStringSidA(user->User.Sid, &usersid);
1643 HeapFree(GetProcessHeap(), 0, user);
1644
1645 CloseHandle(token);
1646 return usersid;
1647 }
1648
1649 static void test_MsiQueryProductState(void)
1650 {
1651 CHAR prodcode[MAX_PATH];
1652 CHAR prod_squashed[MAX_PATH];
1653 CHAR keypath[MAX_PATH*2];
1654 LPSTR usersid;
1655 INSTALLSTATE state;
1656 LONG res;
1657 HKEY userkey, localkey, props;
1658 HKEY prodkey;
1659 DWORD data, error;
1660 REGSAM access = KEY_ALL_ACCESS;
1661
1662 create_test_guid(prodcode, prod_squashed);
1663 usersid = get_user_sid();
1664
1665 if (is_wow64)
1666 access |= KEY_WOW64_64KEY;
1667
1668 /* NULL prodcode */
1669 SetLastError(0xdeadbeef);
1670 state = MsiQueryProductStateA(NULL);
1671 error = GetLastError();
1672 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1673 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1674
1675 /* empty prodcode */
1676 SetLastError(0xdeadbeef);
1677 state = MsiQueryProductStateA("");
1678 error = GetLastError();
1679 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1680 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1681
1682 /* garbage prodcode */
1683 SetLastError(0xdeadbeef);
1684 state = MsiQueryProductStateA("garbage");
1685 error = GetLastError();
1686 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1687 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1688
1689 /* guid without brackets */
1690 SetLastError(0xdeadbeef);
1691 state = MsiQueryProductStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D");
1692 error = GetLastError();
1693 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
1694 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1695
1696 /* guid with brackets */
1697 SetLastError(0xdeadbeef);
1698 state = MsiQueryProductStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}");
1699 error = GetLastError();
1700 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1701 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1702 "expected ERROR_SUCCESS, got %u\n", error);
1703
1704 /* same length as guid, but random */
1705 SetLastError(0xdeadbeef);
1706 state = MsiQueryProductStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93");
1707 error = GetLastError();
1708 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1709 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
1710
1711 /* MSIINSTALLCONTEXT_USERUNMANAGED */
1712
1713 SetLastError(0xdeadbeef);
1714 state = MsiQueryProductStateA(prodcode);
1715 error = GetLastError();
1716 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1717 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1718 "expected ERROR_SUCCESS, got %u\n", error);
1719
1720 lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
1721 lstrcatA(keypath, prod_squashed);
1722
1723 res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
1724 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1725
1726 /* user product key exists */
1727 SetLastError(0xdeadbeef);
1728 state = MsiQueryProductStateA(prodcode);
1729 error = GetLastError();
1730 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1731 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1732 "expected ERROR_SUCCESS, got %u\n", error);
1733
1734 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
1735 lstrcatA(keypath, prodcode);
1736
1737 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1738 if (res == ERROR_ACCESS_DENIED)
1739 {
1740 skip("Not enough rights to perform tests\n");
1741 RegDeleteKeyA(userkey, "");
1742 RegCloseKey(userkey);
1743 LocalFree(usersid);
1744 return;
1745 }
1746 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1747
1748 /* local uninstall key exists */
1749 SetLastError(0xdeadbeef);
1750 state = MsiQueryProductStateA(prodcode);
1751 error = GetLastError();
1752 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1753 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1754 "expected ERROR_SUCCESS, got %u\n", error);
1755
1756 data = 1;
1757 res = RegSetValueExA(localkey, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1758 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1759
1760 /* WindowsInstaller value exists */
1761 SetLastError(0xdeadbeef);
1762 state = MsiQueryProductStateA(prodcode);
1763 error = GetLastError();
1764 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1765 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1766 "expected ERROR_SUCCESS, got %u\n", error);
1767
1768 RegDeleteValueA(localkey, "WindowsInstaller");
1769 delete_key(localkey, "", access & KEY_WOW64_64KEY);
1770
1771 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1772 lstrcatA(keypath, usersid);
1773 lstrcatA(keypath, "\\Products\\");
1774 lstrcatA(keypath, prod_squashed);
1775
1776 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1777 if (res == ERROR_ACCESS_DENIED)
1778 {
1779 skip("Not enough rights to perform tests\n");
1780 RegDeleteKeyA(userkey, "");
1781 RegCloseKey(userkey);
1782 LocalFree(usersid);
1783 return;
1784 }
1785 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1786
1787 /* local product key exists */
1788 SetLastError(0xdeadbeef);
1789 state = MsiQueryProductStateA(prodcode);
1790 error = GetLastError();
1791 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1792 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1793 "expected ERROR_SUCCESS, got %u\n", error);
1794
1795 res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1796 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1797
1798 /* install properties key exists */
1799 SetLastError(0xdeadbeef);
1800 state = MsiQueryProductStateA(prodcode);
1801 error = GetLastError();
1802 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1803 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1804 "expected ERROR_SUCCESS, got %u\n", error);
1805
1806 data = 1;
1807 res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1808 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1809
1810 /* WindowsInstaller value exists */
1811 SetLastError(0xdeadbeef);
1812 state = MsiQueryProductStateA(prodcode);
1813 error = GetLastError();
1814 ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1815 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1816 "expected ERROR_SUCCESS, got %u\n", error);
1817
1818 data = 2;
1819 res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1820 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1821
1822 /* WindowsInstaller value is not 1 */
1823 SetLastError(0xdeadbeef);
1824 state = MsiQueryProductStateA(prodcode);
1825 error = GetLastError();
1826 ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1827 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1828 "expected ERROR_SUCCESS, got %u\n", error);
1829
1830 RegDeleteKeyA(userkey, "");
1831
1832 /* user product key does not exist */
1833 SetLastError(0xdeadbeef);
1834 state = MsiQueryProductStateA(prodcode);
1835 error = GetLastError();
1836 ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
1837 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
1838 "expected ERROR_SUCCESS, got %u\n", error);
1839
1840 RegDeleteValueA(props, "WindowsInstaller");
1841 delete_key(props, "", access & KEY_WOW64_64KEY);
1842 RegCloseKey(props);
1843 delete_key(localkey, "", access & KEY_WOW64_64KEY);
1844 RegCloseKey(localkey);
1845 RegDeleteKeyA(userkey, "");
1846 RegCloseKey(userkey);
1847
1848 /* MSIINSTALLCONTEXT_USERMANAGED */
1849
1850 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
1851 lstrcatA(keypath, usersid);
1852 lstrcatA(keypath, "\\Installer\\Products\\");
1853 lstrcatA(keypath, prod_squashed);
1854
1855 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
1856 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1857
1858 state = MsiQueryProductStateA(prodcode);
1859 ok(state == INSTALLSTATE_ADVERTISED,
1860 "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1861
1862 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1863 lstrcatA(keypath, usersid);
1864 lstrcatA(keypath, "\\Products\\");
1865 lstrcatA(keypath, prod_squashed);
1866
1867 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1868 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1869
1870 state = MsiQueryProductStateA(prodcode);
1871 ok(state == INSTALLSTATE_ADVERTISED,
1872 "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1873
1874 res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1875 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1876
1877 state = MsiQueryProductStateA(prodcode);
1878 ok(state == INSTALLSTATE_ADVERTISED,
1879 "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1880
1881 data = 1;
1882 res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1883 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1884
1885 /* WindowsInstaller value exists */
1886 state = MsiQueryProductStateA(prodcode);
1887 ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1888
1889 RegDeleteValueA(props, "WindowsInstaller");
1890 delete_key(props, "", access & KEY_WOW64_64KEY);
1891 RegCloseKey(props);
1892 delete_key(localkey, "", access & KEY_WOW64_64KEY);
1893 RegCloseKey(localkey);
1894 delete_key(prodkey, "", access & KEY_WOW64_64KEY);
1895 RegCloseKey(prodkey);
1896
1897 /* MSIINSTALLCONTEXT_MACHINE */
1898
1899 lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
1900 lstrcatA(keypath, prod_squashed);
1901
1902 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
1903 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1904
1905 state = MsiQueryProductStateA(prodcode);
1906 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1907
1908 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
1909 lstrcatA(keypath, "S-1-5-18\\Products\\");
1910 lstrcatA(keypath, prod_squashed);
1911
1912 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
1913 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1914
1915 state = MsiQueryProductStateA(prodcode);
1916 ok(state == INSTALLSTATE_ADVERTISED,
1917 "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1918
1919 res = RegCreateKeyExA(localkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
1920 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1921
1922 state = MsiQueryProductStateA(prodcode);
1923 ok(state == INSTALLSTATE_ADVERTISED,
1924 "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1925
1926 data = 1;
1927 res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
1928 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1929
1930 /* WindowsInstaller value exists */
1931 state = MsiQueryProductStateA(prodcode);
1932 ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1933
1934 RegDeleteValueA(props, "WindowsInstaller");
1935 delete_key(props, "", access & KEY_WOW64_64KEY);
1936 RegCloseKey(props);
1937 delete_key(localkey, "", access & KEY_WOW64_64KEY);
1938 RegCloseKey(localkey);
1939 delete_key(prodkey, "", access & KEY_WOW64_64KEY);
1940 RegCloseKey(prodkey);
1941
1942 LocalFree(usersid);
1943 }
1944
1945 static const char table_enc85[] =
1946 "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
1947 "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
1948 "yz{}~";
1949
1950 /*
1951 * Encodes a base85 guid given a GUID pointer
1952 * Caller should provide a 21 character buffer for the encoded string.
1953 */
1954 static void encode_base85_guid( GUID *guid, LPWSTR str )
1955 {
1956 unsigned int x, *p, i;
1957
1958 p = (unsigned int*) guid;
1959 for( i=0; i<4; i++ )
1960 {
1961 x = p[i];
1962 *str++ = table_enc85[x%85];
1963 x = x/85;
1964 *str++ = table_enc85[x%85];
1965 x = x/85;
1966 *str++ = table_enc85[x%85];
1967 x = x/85;
1968 *str++ = table_enc85[x%85];
1969 x = x/85;
1970 *str++ = table_enc85[x%85];
1971 }
1972 *str = 0;
1973 }
1974
1975 static void compose_base85_guid(LPSTR component, LPSTR comp_base85, LPSTR squashed)
1976 {
1977 WCHAR guidW[MAX_PATH];
1978 WCHAR base85W[MAX_PATH];
1979 WCHAR squashedW[MAX_PATH];
1980 GUID guid;
1981 HRESULT hr;
1982 int size;
1983
1984 hr = CoCreateGuid(&guid);
1985 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
1986
1987 size = StringFromGUID2(&guid, guidW, MAX_PATH);
1988 ok(size == 39, "Expected 39, got %d\n", hr);
1989
1990 WideCharToMultiByte(CP_ACP, 0, guidW, size, component, MAX_PATH, NULL, NULL);
1991 encode_base85_guid(&guid, base85W);
1992 WideCharToMultiByte(CP_ACP, 0, base85W, -1, comp_base85, MAX_PATH, NULL, NULL);
1993 squash_guid(guidW, squashedW);
1994 WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
1995 }
1996
1997 static void test_MsiQueryFeatureState(void)
1998 {
1999 HKEY userkey, localkey, compkey, compkey2;
2000 CHAR prodcode[MAX_PATH];
2001 CHAR prod_squashed[MAX_PATH];
2002 CHAR component[MAX_PATH];
2003 CHAR comp_base85[MAX_PATH];
2004 CHAR comp_squashed[MAX_PATH], comp_squashed2[MAX_PATH];
2005 CHAR keypath[MAX_PATH*2];
2006 INSTALLSTATE state;
2007 LPSTR usersid;
2008 LONG res;
2009 REGSAM access = KEY_ALL_ACCESS;
2010 DWORD error;
2011
2012 create_test_guid(prodcode, prod_squashed);
2013 compose_base85_guid(component, comp_base85, comp_squashed);
2014 compose_base85_guid(component, comp_base85 + 20, comp_squashed2);
2015 usersid = get_user_sid();
2016
2017 if (is_wow64)
2018 access |= KEY_WOW64_64KEY;
2019
2020 /* NULL prodcode */
2021 SetLastError(0xdeadbeef);
2022 state = MsiQueryFeatureStateA(NULL, "feature");
2023 error = GetLastError();
2024 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2025 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2026
2027 /* empty prodcode */
2028 SetLastError(0xdeadbeef);
2029 state = MsiQueryFeatureStateA("", "feature");
2030 error = GetLastError();
2031 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2032 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2033
2034 /* garbage prodcode */
2035 SetLastError(0xdeadbeef);
2036 state = MsiQueryFeatureStateA("garbage", "feature");
2037 error = GetLastError();
2038 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2039 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2040
2041 /* guid without brackets */
2042 SetLastError(0xdeadbeef);
2043 state = MsiQueryFeatureStateA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", "feature");
2044 error = GetLastError();
2045 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2046 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2047
2048 /* guid with brackets */
2049 SetLastError(0xdeadbeef);
2050 state = MsiQueryFeatureStateA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", "feature");
2051 error = GetLastError();
2052 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2053 ok(error == ERROR_SUCCESS || broken(error == ERROR_ALREADY_EXISTS) /* win2k */,
2054 "expected ERROR_SUCCESS, got %u\n", error);
2055
2056 /* same length as guid, but random */
2057 SetLastError(0xdeadbeef);
2058 state = MsiQueryFeatureStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", "feature");
2059 error = GetLastError();
2060 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2061 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2062
2063 /* NULL szFeature */
2064 SetLastError(0xdeadbeef);
2065 state = MsiQueryFeatureStateA(prodcode, NULL);
2066 error = GetLastError();
2067 ok(state == INSTALLSTATE_INVALIDARG, "Expected INSTALLSTATE_INVALIDARG, got %d\n", state);
2068 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2069
2070 /* empty szFeature */
2071 SetLastError(0xdeadbeef);
2072 state = MsiQueryFeatureStateA(prodcode, "");
2073 error = GetLastError();
2074 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2075 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2076 "expected ERROR_SUCCESS, got %u\n", error);
2077
2078 /* feature key does not exist yet */
2079 SetLastError(0xdeadbeef);
2080 state = MsiQueryFeatureStateA(prodcode, "feature");
2081 error = GetLastError();
2082 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2083 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2084 "expected ERROR_SUCCESS, got %u\n", error);
2085
2086 /* MSIINSTALLCONTEXT_USERUNMANAGED */
2087
2088 lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Features\\");
2089 lstrcatA(keypath, prod_squashed);
2090
2091 res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &userkey);
2092 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2093
2094 /* feature key exists */
2095 SetLastError(0xdeadbeef);
2096 state = MsiQueryFeatureStateA(prodcode, "feature");
2097 error = GetLastError();
2098 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2099 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2100 "expected ERROR_SUCCESS, got %u\n", error);
2101
2102 res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 2);
2103 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2104
2105 /* feature value exists */
2106 SetLastError(0xdeadbeef);
2107 state = MsiQueryFeatureStateA(prodcode, "feature");
2108 error = GetLastError();
2109 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2110 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2111 "expected ERROR_SUCCESS, got %u\n", error);
2112
2113 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2114 lstrcatA(keypath, usersid);
2115 lstrcatA(keypath, "\\Products\\");
2116 lstrcatA(keypath, prod_squashed);
2117 lstrcatA(keypath, "\\Features");
2118
2119 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
2120 if (res == ERROR_ACCESS_DENIED)
2121 {
2122 skip("Not enough rights to perform tests\n");
2123 RegDeleteKeyA(userkey, "");
2124 RegCloseKey(userkey);
2125 LocalFree(usersid);
2126 return;
2127 }
2128 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2129
2130 /* userdata features key exists */
2131 SetLastError(0xdeadbeef);
2132 state = MsiQueryFeatureStateA(prodcode, "feature");
2133 error = GetLastError();
2134 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2135 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2136 "expected ERROR_SUCCESS, got %u\n", error);
2137
2138 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
2139 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2140
2141 SetLastError(0xdeadbeef);
2142 state = MsiQueryFeatureStateA(prodcode, "feature");
2143 error = GetLastError();
2144 ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
2145 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2146 "expected ERROR_SUCCESS, got %u\n", error);
2147
2148 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
2149 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2150
2151 SetLastError(0xdeadbeef);
2152 state = MsiQueryFeatureStateA(prodcode, "feature");
2153 error = GetLastError();
2154 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2155 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2156 "expected ERROR_SUCCESS, got %u\n", error);
2157
2158 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
2159 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2160
2161 SetLastError(0xdeadbeef);
2162 state = MsiQueryFeatureStateA(prodcode, "feature");
2163 error = GetLastError();
2164 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2165 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2166 "expected ERROR_SUCCESS, got %u\n", error);
2167
2168 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
2169 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2170
2171 SetLastError(0xdeadbeef);
2172 state = MsiQueryFeatureStateA(prodcode, "feature");
2173 error = GetLastError();
2174 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2175 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2176 "expected ERROR_SUCCESS, got %u\n", error);
2177
2178 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2179 lstrcatA(keypath, usersid);
2180 lstrcatA(keypath, "\\Components\\");
2181 lstrcatA(keypath, comp_squashed);
2182
2183 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2184 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2185
2186 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2187 lstrcatA(keypath, usersid);
2188 lstrcatA(keypath, "\\Components\\");
2189 lstrcatA(keypath, comp_squashed2);
2190
2191 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
2192 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2193
2194 SetLastError(0xdeadbeef);
2195 state = MsiQueryFeatureStateA(prodcode, "feature");
2196 error = GetLastError();
2197 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2198 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2199 "expected ERROR_SUCCESS, got %u\n", error);
2200
2201 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
2202 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2203
2204 SetLastError(0xdeadbeef);
2205 state = MsiQueryFeatureStateA(prodcode, "feature");
2206 error = GetLastError();
2207 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2208 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2209 "expected ERROR_SUCCESS, got %u\n", error);
2210
2211 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
2212 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2213
2214 SetLastError(0xdeadbeef);
2215 state = MsiQueryFeatureStateA(prodcode, "feature");
2216 error = GetLastError();
2217 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2218 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2219 "expected ERROR_SUCCESS, got %u\n", error);
2220
2221 res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
2222 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2223
2224 /* INSTALLSTATE_LOCAL */
2225 SetLastError(0xdeadbeef);
2226 state = MsiQueryFeatureStateA(prodcode, "feature");
2227 error = GetLastError();
2228 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2229 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2230 "expected ERROR_SUCCESS, got %u\n", error);
2231
2232 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01\\", 4);
2233 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2234
2235 /* INSTALLSTATE_SOURCE */
2236 SetLastError(0xdeadbeef);
2237 state = MsiQueryFeatureStateA(prodcode, "feature");
2238 error = GetLastError();
2239 ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2240 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2241 "expected ERROR_SUCCESS, got %u\n", error);
2242
2243 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
2244 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2245
2246 /* bad INSTALLSTATE_SOURCE */
2247 SetLastError(0xdeadbeef);
2248 state = MsiQueryFeatureStateA(prodcode, "feature");
2249 error = GetLastError();
2250 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2251 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2252 "expected ERROR_SUCCESS, got %u\n", error);
2253
2254 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01a", 4);
2255 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2256
2257 /* INSTALLSTATE_SOURCE */
2258 SetLastError(0xdeadbeef);
2259 state = MsiQueryFeatureStateA(prodcode, "feature");
2260 error = GetLastError();
2261 ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2262 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2263 "expected ERROR_SUCCESS, got %u\n", error);
2264
2265 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
2266 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2267
2268 /* bad INSTALLSTATE_SOURCE */
2269 SetLastError(0xdeadbeef);
2270 state = MsiQueryFeatureStateA(prodcode, "feature");
2271 error = GetLastError();
2272 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2273 ok(error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* win2k */,
2274 "expected ERROR_SUCCESS, got %u\n", error);
2275
2276 RegDeleteValueA(compkey, prod_squashed);
2277 RegDeleteValueA(compkey2, prod_squashed);
2278 delete_key(compkey, "", access & KEY_WOW64_64KEY);
2279 delete_key(compkey2, "", access & KEY_WOW64_64KEY);
2280 RegDeleteValueA(localkey, "feature");
2281 RegDeleteValueA(userkey, "feature");
2282 RegDeleteKeyA(userkey, "");
2283 RegCloseKey(compkey);
2284 RegCloseKey(compkey2);
2285 RegCloseKey(localkey);
2286 RegCloseKey(userkey);
2287
2288 /* MSIINSTALLCONTEXT_USERMANAGED */
2289
2290 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
2291 lstrcatA(keypath, usersid);
2292 lstrcatA(keypath, "\\Installer\\Features\\");
2293 lstrcatA(keypath, prod_squashed);
2294
2295 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
2296 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2297
2298 /* feature key exists */
2299 state = MsiQueryFeatureStateA(prodcode, "feature");
2300 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2301
2302 res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 1);
2303 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2304
2305 /* feature value exists */
2306 state = MsiQueryFeatureStateA(prodcode, "feature");
2307 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2308
2309 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2310 lstrcatA(keypath, usersid);
2311 lstrcatA(keypath, "\\Products\\");
2312 lstrcatA(keypath, prod_squashed);
2313 lstrcatA(keypath, "\\Features");
2314
2315 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
2316 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2317
2318 /* userdata features key exists */
2319 state = MsiQueryFeatureStateA(prodcode, "feature");
2320 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2321
2322 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
2323 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2324
2325 state = MsiQueryFeatureStateA(prodcode, "feature");
2326 ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
2327
2328 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
2329 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2330
2331 state = MsiQueryFeatureStateA(prodcode, "feature");
2332 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2333
2334 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
2335 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2336
2337 state = MsiQueryFeatureStateA(prodcode, "feature");
2338 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2339
2340 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
2341 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2342
2343 state = MsiQueryFeatureStateA(prodcode, "feature");
2344 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2345
2346 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2347 lstrcatA(keypath, usersid);
2348 lstrcatA(keypath, "\\Components\\");
2349 lstrcatA(keypath, comp_squashed);
2350
2351 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2352 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2353
2354 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2355 lstrcatA(keypath, usersid);
2356 lstrcatA(keypath, "\\Components\\");
2357 lstrcatA(keypath, comp_squashed2);
2358
2359 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
2360 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2361
2362 state = MsiQueryFeatureStateA(prodcode, "feature");
2363 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2364
2365 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
2366 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2367
2368 state = MsiQueryFeatureStateA(prodcode, "feature");
2369 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2370
2371 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
2372 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2373
2374 state = MsiQueryFeatureStateA(prodcode, "feature");
2375 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2376
2377 res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
2378 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2379
2380 state = MsiQueryFeatureStateA(prodcode, "feature");
2381 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2382
2383 RegDeleteValueA(compkey, prod_squashed);
2384 RegDeleteValueA(compkey2, prod_squashed);
2385 delete_key(compkey, "", access & KEY_WOW64_64KEY);
2386 delete_key(compkey2, "", access & KEY_WOW64_64KEY);
2387 RegDeleteValueA(localkey, "feature");
2388 RegDeleteValueA(userkey, "feature");
2389 delete_key(userkey, "", access & KEY_WOW64_64KEY);
2390 RegCloseKey(compkey);
2391 RegCloseKey(compkey2);
2392 RegCloseKey(localkey);
2393 RegCloseKey(userkey);
2394
2395 /* MSIINSTALLCONTEXT_MACHINE */
2396
2397 lstrcpyA(keypath, "Software\\Classes\\Installer\\Features\\");
2398 lstrcatA(keypath, prod_squashed);
2399
2400 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
2401 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2402
2403 /* feature key exists */
2404 state = MsiQueryFeatureStateA(prodcode, "feature");
2405 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2406
2407 res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 1);
2408 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2409
2410 /* feature value exists */
2411 state = MsiQueryFeatureStateA(prodcode, "feature");
2412 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2413
2414 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2415 lstrcatA(keypath, "S-1-5-18\\Products\\");
2416 lstrcatA(keypath, prod_squashed);
2417 lstrcatA(keypath, "\\Features");
2418
2419 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL);
2420 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2421
2422 /* userdata features key exists */
2423 state = MsiQueryFeatureStateA(prodcode, "feature");
2424 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2425
2426 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20);
2427 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2428
2429 state = MsiQueryFeatureStateA(prodcode, "feature");
2430 ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state);
2431
2432 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21);
2433 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2434
2435 state = MsiQueryFeatureStateA(prodcode, "feature");
2436 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2437
2438 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22);
2439 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2440
2441 state = MsiQueryFeatureStateA(prodcode, "feature");
2442 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2443
2444 res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 41);
2445 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2446
2447 state = MsiQueryFeatureStateA(prodcode, "feature");
2448 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2449
2450 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2451 lstrcatA(keypath, "S-1-5-18\\Components\\");
2452 lstrcatA(keypath, comp_squashed);
2453
2454 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2455 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2456
2457 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2458 lstrcatA(keypath, "S-1-5-18\\Components\\");
2459 lstrcatA(keypath, comp_squashed2);
2460
2461 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey2, NULL);
2462 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2463
2464 state = MsiQueryFeatureStateA(prodcode, "feature");
2465 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2466
2467 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1);
2468 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2469
2470 state = MsiQueryFeatureStateA(prodcode, "feature");
2471 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2472
2473 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 6);
2474 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2475
2476 state = MsiQueryFeatureStateA(prodcode, "feature");
2477 ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2478
2479 res = RegSetValueExA(compkey2, prod_squashed, 0, REG_SZ, (const BYTE *)"orange", 7);
2480 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2481
2482 state = MsiQueryFeatureStateA(prodcode, "feature");
2483 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2484
2485 RegDeleteValueA(compkey, prod_squashed);
2486 RegDeleteValueA(compkey2, prod_squashed);
2487 delete_key(compkey, "", access & KEY_WOW64_64KEY);
2488 delete_key(compkey2, "", access & KEY_WOW64_64KEY);
2489 RegDeleteValueA(localkey, "feature");
2490 RegDeleteValueA(userkey, "feature");
2491 delete_key(userkey, "", access & KEY_WOW64_64KEY);
2492 RegCloseKey(compkey);
2493 RegCloseKey(compkey2);
2494 RegCloseKey(localkey);
2495 RegCloseKey(userkey);
2496 LocalFree(usersid);
2497 }
2498
2499 static void test_MsiQueryComponentState(void)
2500 {
2501 HKEY compkey, prodkey;
2502 CHAR prodcode[MAX_PATH];
2503 CHAR prod_squashed[MAX_PATH];
2504 CHAR component[MAX_PATH];
2505 CHAR comp_base85[MAX_PATH];
2506 CHAR comp_squashed[MAX_PATH];
2507 CHAR keypath[MAX_PATH];
2508 INSTALLSTATE state;
2509 LPSTR usersid;
2510 LONG res;
2511 UINT r;
2512 REGSAM access = KEY_ALL_ACCESS;
2513 DWORD error;
2514
2515 static const INSTALLSTATE MAGIC_ERROR = 0xdeadbeef;
2516
2517 if (!pMsiQueryComponentStateA)
2518 {
2519 win_skip("MsiQueryComponentStateA not implemented\n");
2520 return;
2521 }
2522
2523 create_test_guid(prodcode, prod_squashed);
2524 compose_base85_guid(component, comp_base85, comp_squashed);
2525 usersid = get_user_sid();
2526
2527 if (is_wow64)
2528 access |= KEY_WOW64_64KEY;
2529
2530 /* NULL szProductCode */
2531 state = MAGIC_ERROR;
2532 SetLastError(0xdeadbeef);
2533 r = pMsiQueryComponentStateA(NULL, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2534 error = GetLastError();
2535 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2536 ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2537 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2538
2539 /* empty szProductCode */
2540 state = MAGIC_ERROR;
2541 SetLastError(0xdeadbeef);
2542 r = pMsiQueryComponentStateA("", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2543 error = GetLastError();
2544 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2545 ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2546 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2547
2548 /* random szProductCode */
2549 state = MAGIC_ERROR;
2550 SetLastError(0xdeadbeef);
2551 r = pMsiQueryComponentStateA("random", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2552 error = GetLastError();
2553 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2554 ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2555 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2556
2557 /* GUID-length szProductCode */
2558 state = MAGIC_ERROR;
2559 SetLastError(0xdeadbeef);
2560 r = pMsiQueryComponentStateA("DJANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KDE", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2561 error = GetLastError();
2562 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2563 ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2564 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2565
2566 /* GUID-length with brackets */
2567 state = MAGIC_ERROR;
2568 SetLastError(0xdeadbeef);
2569 r = pMsiQueryComponentStateA("{JANE93KNDNAS-2KN2NR93KMN3LN13=L1N3KD}", NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2570 error = GetLastError();
2571 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2572 ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2573 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2574
2575 /* actual GUID */
2576 state = MAGIC_ERROR;
2577 SetLastError(0xdeadbeef);
2578 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2579 error = GetLastError();
2580 ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2581 ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2582 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2583
2584 state = MAGIC_ERROR;
2585 SetLastError(0xdeadbeef);
2586 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2587 error = GetLastError();
2588 ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2589 ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2590 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2591
2592 lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
2593 lstrcatA(keypath, prod_squashed);
2594
2595 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2596 if (res == ERROR_ACCESS_DENIED)
2597 {
2598 skip("Not enough rights to perform tests\n");
2599 LocalFree(usersid);
2600 return;
2601 }
2602 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2603
2604 state = MAGIC_ERROR;
2605 SetLastError(0xdeadbeef);
2606 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2607 error = GetLastError();
2608 ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2609 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2610 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2611
2612 delete_key(prodkey, "", access & KEY_WOW64_64KEY);
2613 RegCloseKey(prodkey);
2614
2615 /* create local system product key */
2616 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\");
2617 lstrcatA(keypath, prod_squashed);
2618 lstrcatA(keypath, "\\InstallProperties");
2619
2620 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
2621 if (res == ERROR_ACCESS_DENIED)
2622 {
2623 skip("Not enough rights to perform tests\n");
2624 LocalFree(usersid);
2625 return;
2626 }
2627 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2628
2629 /* local system product key exists */
2630 state = MAGIC_ERROR;
2631 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2632 error = GetLastError();
2633 ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2634 ok(state == MAGIC_ERROR, "Expected 0xdeadbeef, got %d\n", state);
2635 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2636
2637 res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
2638 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2639
2640 /* LocalPackage value exists */
2641 state = MAGIC_ERROR;
2642 SetLastError(0xdeadbeef);
2643 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2644 error = GetLastError();
2645 ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2646 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2647 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2648
2649 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\");
2650 lstrcatA(keypath, comp_squashed);
2651
2652 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
2653 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2654
2655 /* component key exists */
2656 state = MAGIC_ERROR;
2657 SetLastError(0xdeadbeef);
2658 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2659 error = GetLastError();
2660 ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2661 ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2662 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2663
2664 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 0);
2665 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2666
2667 /* component\product exists */
2668 state = MAGIC_ERROR;
2669 SetLastError(0xdeadbeef);
2670 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2671 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2672 error = GetLastError();
2673 ok(state == INSTALLSTATE_NOTUSED || state == INSTALLSTATE_LOCAL,
2674 "Expected INSTALLSTATE_NOTUSED or INSTALLSTATE_LOCAL, got %d\n", state);
2675 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2676
2677 /* NULL component, product exists */
2678 state = MAGIC_ERROR;
2679 SetLastError(0xdeadbeef);
2680 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, NULL, &state);
2681 error = GetLastError();
2682 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2683 ok(state == MAGIC_ERROR, "Expected state not changed, got %d\n", state);
2684 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2685
2686 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"hi", 2);
2687 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2688
2689 /* INSTALLSTATE_LOCAL */
2690 state = MAGIC_ERROR;
2691 SetLastError(0xdeadbeef);
2692 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2693 error = GetLastError();
2694 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2695 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2696 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2697
2698 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01\\", 4);
2699 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2700
2701 /* INSTALLSTATE_SOURCE */
2702 state = MAGIC_ERROR;
2703 SetLastError(0xdeadbeef);
2704 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2705 error = GetLastError();
2706 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2707 ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2708 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2709
2710 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
2711 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2712
2713 /* bad INSTALLSTATE_SOURCE */
2714 state = MAGIC_ERROR;
2715 SetLastError(0xdeadbeef);
2716 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2717 error = GetLastError();
2718 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2719 ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2720 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2721
2722 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01a", 4);
2723 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2724
2725 /* INSTALLSTATE_SOURCE */
2726 state = MAGIC_ERROR;
2727 SetLastError(0xdeadbeef);
2728 r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
2729 error = GetLastError();
2730 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2731 ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
2732 ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
2733
2734 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01:", 4);
2735 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d<