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